Tip of the day: If you want to bypass access checks for channels as an IRCOp, use SAMODE or SAJOIN. Or use OperOverride.

Strict Transport Security

From UnrealIRCd documentation wiki
Jump to navigation Jump to search

Strict Transport Security (STS) on IRC can be used to redirect plaintext users to SSL/TLS automatically (redirect from port 6667 to +6697).

Specification

"Strict Transport Security" is an IRCv3 specification. When used, it will:

  1. Redirect users with capable clients to the appropriate SSL/TLS port automatically
  2. Remember this redirection for a period of time. So next time SSL/TLS is used directly, without even trying plaintext first.
  3. Prevent any unsafe certificate popups

It is basically the same as on the web, where people use an http to https redirect (point 1) combined with HSTS (points 2 and 3).

Client support

Strict Transport Security (STS) is supported by the following clients: mIRC, AdiIRC, IRCCloud, The Lounge, Ambassador, GLirc, CoreIRC, BitBot, Limnoria.

If the client does not support STS then it will ignore STS and will continue to connect as usual: if the user told the client to connect to plaintext port 6667 then it will continue to use plaintext on port 6667, if the user told it to use TLS then it will continue using TLS. If this is not what you want then see the end of this article under Blocking plaintext connections

Enabling STS

To enable Strict Transport Security you need to configure two important things:

Step 1: Get a real certificate

You need a 'real' SSL/TLS certificate, not the default / self-signed certificate that many people use. So: get one for free via Let's Encrypt (tutorial) or buy one. But be sure to read below first:

IMPORTANT: Your users must connect to the server with the same hostname as the hostname in the certificate. So if users use /SERVER irc.example.org then even if your server is actually irc2.example.org your server should have a valid certificate for irc.example.org. Possible solutions for this are:

  • wildcard certificates, eg. for *.example.org (this too is possible via Let's Encrypt)
  • multi domain certificates, eg. one certificate that is valid for both irc.example.org and irc2.example.org (again, possibly with Let's Encrypt too).
  • Or multiple separate certificates with a Sni block (rarely used!)

It is very important for the certificate and naming to be correct:

  • without STS some IRC clients may have an Ignore button to ignore an invalid certificate and if you click that you can still connect, but...
  • with STS this is not the case, it is a hard error and the connection is aborted. This is a security measure.

Step 2: Configure the set::tls::sts-policy block

The following will configure a STS policy, redirecting capable clients to port 6697 (which must be SSL/TLS):

set {
    tls {
        sts-policy {
            port 6697;
            duration 1m; /* start low! you can always increase this later */
        };
    };
};

It is very important to start with a low duration, such as 1m in the example above. Of course, you can easily remove the the set::tls::sts-policy block at any time if there are any problems, however any clients that have already connected and seen the sts-policy will cache the setting for up to set::tls::sts-policy::duration time. Only after duration time has passed the client may try plaintext connections again.

You should gradually raise the set::tls::sts-policy::duration time. This to prevent you inadvertently locking users out due to a misconfiguration:

  • Begin with 1 minute (1m) during testing.
  • After a week, consider raising it to a day (1d).
  • After a month, consider raising it to it's final setting, such as half a year (180d)

Be sure to enforce the same STS policy on all servers on your network (unless you are only testing).

Blocking plaintext connections

STS by itself does not prevent all plaintext (port 6667) IRC connections. Clients that don't support STS could still use plaintext.

If you want to deny those users, then set set::plaintext-policy::user to deny:

set {
        plaintext-policy {
                user deny;
                oper deny;
                server deny;
                user-message "Insecure connection. Please reconnect using SSL/TLS on port +6697. See [put some link or useful note here]";
        }
}

If you have this, combined with STS, then clients supporting STS will be redirected automatically to the right port with SSL/TLS, and clients not supporting STS will see the error message.

Closing the plaintext port

You can also close plaintext port 6667 completely and only have port 6697 open (with TLS). If you want to do that, then simply remove the listen block for port 6667.

Pros:

  • Zero traffic is sent over plaintext. Because, as long as you keep the plaintext port open, some clients may still send messages during the initial handshake in plaintext, such as their nick name, before they are denied or redirect to the SSL/TLS port.

Cons:

  • You loose the ability to automatically redirect users from plaintext to SSL/TLS. You have to make clear to your users that they really must connect to SSL/TLS port 6697.

For new networks it is probably fine to have port 6667 closed. For older networks, you may first want to use STS for a while and then, say a year later, consider closing port 6667 completely.