Tip of the day: Consider contributing to make UnrealIRCd even better: reporting bugs, testing, helping out with support, ..

Use TLS

From UnrealIRCd documentation wiki
Jump to navigation Jump to search

This page explains why having port 6667 (or any other plaintext port) open for users to connect to is a bad idea. And how to move your users to SSL/TLS. Slowly step-by-step, or quickly, whatever you prefer.

Why this is a problem

For a long time IRC networks have kept port 6667 (or a similar port) open, which allows unencrypted plaintext connections. Nowadays, everyone should be using SSL/TLS, usually on port 6697.

If you continue to provide port 6667, it means at least some users will use it. The problem is that conversations of the plaintext users travels unencrypted over the internet. It is a long known fact that state actors massively harvest and store these conversations (see e.g. 2013 Snowden leaks) but also more malicious actors could possibly intercept these. As long as you have any users on port 6667 at least some of this traffic will be exposed. This doesn't only affect the few people who use port 6667 but also other people on the same channel or private messaging such individuals. (Of course, in the case of channels, channel members can also log and leak conversations regardless of TLS, but this requires someone actively and visibly being into each channel)

This is similar to how the web has moved from http (which is insecure) to https (which uses SSL/TLS). There is no reason IRC should still be using insecure plaintext connections.

Do you have SSL/TLS properly configured?

Before moving users to TLS you need to check some things:

  • Port 6697 should be open with listen::options::tls (almost everyone has this already)
  • You must have an SSL/TLS certificate that is issued by a trusted Certificate Authority. If you haven't already, then follow the Using Let's Encrypt with UnrealIRCd guide to get one for free.
    • Be sure that your certificate includes all server names that users use to connect to your server. For single-server networks this is normally no issue, but if you have a two-server network with irc1.example.net and irc2.example.net and also a round robin irc.example.net that points to both servers, then server irc1 will need a certificate for both irc1.example.net and irc.example.net, and irc2 will need one for both irc2.example.net and irc.example.net.
  • Don't proceed until you have verified yourself that port 6697 works in your IRC client (without warnings)

Warn your users

This will show a warning to every user that connect to the IRC server. Users may miss it but it's worth a try:

set {
    plaintext-policy {
        user warn;
        user-message "Port 6667 is insecure and will be closed soon. Please connect with SSL/TLS to irc.example.org on port 6697.";
    }
}

At the same time it could be a good idea to deploy Strict Transport Security which automatically redirects users from plaintext port 6667 to TLS on 6697:

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

However, there is an important caveat: your SSL certificate should be valid for all the hostnames that users use to connect to your server. So, if users connect to your server irc2.example.net also via irc.example.net then the certificate must have both names. Read the full Strict Transport Security article in such a case.

Keep the plaintext port open but give an error

set {
    plaintext-policy {
        user deny;
        user-message "Port 6667 is insecure and is closed. Please connect with SSL/TLS to irc.example.org on port 6697.";
    }
}

Now that you have a set::plaintext-policy::user set to 'deny' the best practices advice will no longer be shown, as plaintext users won't be able to connect to your server.

Similarly to previous item, you could also deploy Strict Transport Security which automatically redirects users from plaintext port 6667 to TLS on 6697:

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

The above (plaintext-policy deny with an sts-policy) is what we use at irc.unrealircd.org.

Close the port

Following the advice to Keep the plaintext port open but give an error is already a good start, but in production servers, the ideal approach is to eventually close port 6667 completely.

To do this, simply remove or comment out the listen block for port 6667:

//listen {
//        ip *;
//        port 6667;
//}

You probably have one IRC server that has Services running and connected over localhost on port 6667. You can keep the listener but make it localhost-only:

listen {
        ip 127.0.0.1;
        port 6667;
}

(You won't get a warning about localhost plaintext ports)

Another alternative would be to replace the localhost TCP/IP socket with a Unix Socket. They can provide a cleaner way to link Services without offering the port on lo, which is a tad safer if you run various other processes on the same machine (docker, freebsd jails, etc). If your Services support it (eg: Anope), then you configure a Listen_block using a Unix Socket:

listen {
        file "/var/run/unrealircd.sock";
        mode 0770;
}

See also

  • Moving users to TLS - a background article about our efforts to users to use TLS on IRC, for those interested