Tutorial: Linking servers

This page explains how to securely link two (or more) UnrealIRCd servers so you have a multi-server network. This tutorial applies to both UnrealIRCd 4 and the older UnrealIRCd 3.2.x (and mixing both).

Step 1: use SSL
You should be using SSL/TLS for all your server links. Why? Because sensitive data will travel between server links, including passwords, private messages and more.

UnrealIRCd 4 has SSL/TLS enabled by default and on initial installation has prompted you to create a certificate. So, you're all set.

On UnrealIRCd 3.2.x on the other hand you must enable it explicitly during ./Config on *NIX (and then re-compile) while on Windows you must use the SSL version of UnrealIRCd (we offer both on our site).

Unsure if you have SSL enabled? Type '/VERSION' as IRCOp(!) and if it outputs a line like 'OpenSSL X.Y.Z xxxxxxx' (among other things) then your server has SSL support enabled.

Step 2: open up a dedicated server port
You probably have opened up port 6667 for clients on your server already. You should open up a dedicated servers-only SSL port as well.

This can be as simple as: listen *:6900 { options { ssl; serversonly; }; };

Or, if you use a shell provider then you may have to specify the IP that got assigned to you: listen 1.2.3.4:6900 { options { ssl; serversonly; }; };

Step 3: set up a special server class
If you haven't done already then set up a class { } block for your servers now, like: class servers {   pingfreq 60; connfreq 30; maxclients 10; sendq 5M; };

Step 4: grab the SSL fingerprint of your servers
We will need this in next step. Do this on both servers and write them down.

Run the following command on the shell. In UnrealIRCd 4 you run this from the ~/unrealircd/conf/ssl directory (or wherever you installed UnrealIRCd to), on 3.2.x you run it from Unreal3.2.X (or your installation target): openssl x509 -sha256 -fingerprint -noout -in server.cert.pem

This will output something like: SHA256 Fingerprint=EB:1F:5C:B0:E6:EE:DF:AE:A7:56:83:87:A1:8A:AE:E2:D2:B4:70:AF:D8:DD:C2:19:30:18:75:B0:CE:EF:D6:12

Here, EB:1F:5C:B0:E6:EE:DF:AE:A7:56:83:87:A1:8A:AE:E2:D2:B4:70:AF:D8:DD:C2:19:30:18:75:B0:CE:EF:D6:12 is the actual fingerprint.

TODO: make easier!!

Step 5: setting up link blocks
In the example below we assume you have two servers. One is named alpha.test.net and the other one is called beta.test.net. Simply replace the names with the actual names of your server.

Now, please jump to the section that applies to you below:
 * UnrealIRCd 4 (New)
 * UnrealIRCd 3.2.x (Old)
 * UnrealIRCd 4 to 3.2.x (New to Old)
 * UnrealIRCd 3.2.x to 4 (Old to New)

Trouble choosing between the latter two (if you have mixed 3.2.x/4.x)? It's just the linking direction (4.x connecting to 3.2.x or 3.2.x connecting to 4.x). Just choose one, it doesn't matter much!

UnrealIRCd 4 (New)
In the unrealircd.conf on alpha.test.net you add a link block to link with beta.test.net: link beta.test.net { incoming { mask *; };   outgoing { bind-ip *; /* or explicitly an IP if you have a shell provider, as mentioned in step 2 */ hostname beta.test.net; /* or if 'beta.test.net' does not exist then you can use an IP or something like 'beta.dyndns.org' */ port 6900; /* the special SSL server port we opened up earlier */ options { ssl; }; };   password "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF"; /* put the SSL fingerprint of beta.test.net here */ hub *; class servers; };

Similarly, on beta.test.net configure the block to link with alpha.test.net: link alpha.test.net { incoming { mask *; };   outgoing { bind-ip *; /* or explicitly an IP if you have a shell provider, as mentioned in step 2 */ hostname alpha.test.net; /* or if 'alpha.test.net' does not exist then you can use an IP or something like 'alpha.dyndns.org' */ port 6900; /* the special SSL server port we opened up earlier */ options { ssl; autoconnect; }; };   password "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF"; /* put the SSL fingerprint of alpha.test.net here */ hub *; class servers; };

UnrealIRCd 3.2.x (Old)
In the unrealircd.conf on alpha.test.net you add a link block to link with beta.test.net: link beta.test.net { username *; hostname *; bind-ip *; /* or explicitly an IP if you have a shell provider, as mentioned in step 2 */ port 6900; /* the special SSL server port we opened up earlier */ password-connect "*"; password-receive "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF" { sslclientcertfp; }; /* replace 00:11etc.. with the SSL fingerprint of beta.test.net */ hub *; class servers; options { ssl; }; };

Similarly, on beta.test.net configure the block to link with alpha.test.net: link alpha.test.net { username *; hostname alpha.test.net; /* or if 'alpha.test.net' does not exist then you can use an IP or something like 'alpha.dyndns.org' */ bind-ip *; /* or explicitly an IP if you have a shell provider, as mentioned in step 2 */ port 6900; /* the special SSL server port we opened up earlier */ password-connect "*"; password-receive "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF" { sslclientcertfp; }; /* replace 00:11etc.. with the SSL fingerprint of beta.test.net */ hub *; class servers; options { ssl; }; };

NOTE: Since 3.2.x is a little less flexible, above we set it up so beta.test.net will always link to alpha.test.net and never the other way around.

UnrealIRCd 4 to 3.2.x (New to Old)
On your UnrealIRCd 4 server alpha.test.net you add a link block to link with beta.test.net: link beta.test.net { incoming { mask *; };   outgoing { bind-ip *; /* or explicitly an IP if you have a shell provider, as mentioned in step 2 */ hostname beta.test.net; /* or if 'beta.test.net' does not exist then you can use an IP or something like 'beta.dyndns.org' */ port 6900; /* the special SSL server port we opened up earlier */ options { ssl; }; };   password "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF"; /* put the SSL fingerprint of beta.test.net here */ hub *; class servers; };

Similarly, on your UnrealIRCd 3.2.x server beta.test.net you add a link block to link with alpha.test.net: link alpha.test.net { username *; hostname alpha.test.net; /* or if 'alpha.test.net' does not exist then you can use an IP or something like 'alpha.dyndns.org' */ bind-ip *; /* or explicitly an IP if you have a shell provider, as mentioned in step 2 */ port 6900; /* the special SSL server port we opened up earlier */ password-connect "*"; password-receive "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF" { sslclientcertfp; }; /* replace 00:11etc.. with the SSL fingerprint of beta.test.net */ hub *; class servers; options { ssl; }; };

NOTE: Since 3.2.x is a little less flexible, above we set it up so beta.test.net will always link to alpha.test.net and never the other way around.

UnrealIRCd 3.2.x to 4 (Old to New)
On your UnrealIRCd 3.2.x server alpha.test.net you add a link block to link with beta.test.net: link beta.test.net { username *; hostname *; bind-ip *; /* or explicitly an IP if you have a shell provider, as mentioned in step 2 */ port 6900; /* the special SSL server port we opened up earlier */ password-connect "*"; password-receive "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF" { sslclientcertfp; }; /* replace 00:11etc.. with the SSL fingerprint of beta.test.net */ hub *; class servers; options { ssl; }; };

Similarly, on your UnrealIRCd 4 server beta.test.net you add a link block to link with alpha.test.net: link alpha.test.net { incoming { mask *; };   outgoing { bind-ip *; /* or explicitly an IP if you have a shell provider, as mentioned in step 2 */ hostname alpha.test.net; /* or if 'alpha.test.net' does not exist then you can use an IP or something like 'alpha.dyndns.org' */ port 6900; /* the special SSL server port we opened up earlier */ options { ssl; autoconnect; }; };   password "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF"; /* put the SSL fingerprint of alpha.test.net here */ hub *; class servers; };

Autoconnect
In the example of above we added autoconnect (in link::outgoing::options) in beta.test.net's config. This means beta will automatically try to link to alpha every class::connfreq seconds (configured in step 3: every 30 seconds). You can also choose to autoconnect the other way around or not to autoconnect at all. While it's also possible to autoconnect from both sides (especially in UnrealIRCd 4) we generally don't recommend it.

Step 6: Rehash
Rehash both servers (or restart them if you are lazy and you have no users on them). We recommend to rehash a server as IRCOp by executing '/REHASH' on IRC.

If you restarted or did the '/REHASH' as an IRCOp you should see directly if there are any warnings or errors in your configuration. If so, fix them now.

Step 7: Link!
In step 4 we added 'autoconnect'. If everything works well then you should see the servers automatically linking (they will try every 30 seconds, based on class::connfreq).

You can see if the other server is linked by executing the IRC command '/MAP' to see the network map.

As an IRCOp you will be informed when servers try to link and if there are any errors. '''Do you see any errors? Check out Troubleshooting: linking servers'''

You can always tell UnrealIRCd to try to link the servers right now by executing (as IRCOp) /CONNECT name.of.other.server. This can be used if you disabled autoconnect, or simply if you don't want to wait ;)

Step 8: Restricting by IP (optional)
What if someone manages to read all contents of your unrealircd/conf directory? Your configuration file would be exposed, your SSL private key, etc. Or maybe you made a backup (good!) and forgot to restrict access to it (bad!). Such a breach of security would be a real problem. Among other things, it would allow the hacker / stealer to link up a server to your network and acquire all sensitive information and become IRCOp.. etc...

To help prevent against such a malicious linked server UnrealIRCd allows you to add another restriction to link blocks, namely to restrict by IP.

Earlier we configured the link block like this: link alpha.test.net { incoming { mask *; };

The mask * here specifies that any IP is permitted. You can restrict to mask 1.2.3.4 or a range like mask 1.2.*.

We consider this step optional as it's basically security-in-depth. If your SSL private key really gets stolen it means an attacker can decode all client and server SSL traffic (but only IF he has access to all such network traffic) so you're in a very bad situation already.

Step 9: Impose topology restrictions (optional)
In our examples we permit any server to introduce other servers. If this is not what you want, for example if you want to be absolutely sure that a remote link is always 'alone' and has no servers behind it (this is called a leaf) then you can impose this restriction.

If you have a small standard network with just two servers plus a services server and trust each other then this isn't terribly important.

TODO: explain how

Step 10: Advanced toplogy restrictions (optional)
deny link { } allow you to enforce some rather advanced topology restrictions. This is generally only used on medium- and large networks.

TODO: explain how