October 2018: This document may still have some educational value, but it has been superceded by a newer article Building a secure chat infrastructure. It describes Untochat, a chat infrastructure that aims to be both secure and anonymous.
In this tutorial we will show you how to set up a secure private IRC server with Tor support. The server will be suitable for private use only, and it is for instance intended to help oppressed groups of individuals who need to communicate with each other without fear of being monitored. To reiterate, the secure private IRC server described here cannot be a member of any public IRC network - quite on the contrary, it must be totally isolated on one trusted host and it must never speak to other IRC servers.
Some Internet users know that IRC is an old but still a pretty functional Internet chat protocol. It was developed all the way back in 1988 by Jarkko Oikarinen, a Finnish computer scientist and programmer, so as of this writing, IRC protocol is already about 30 years old.
One of the weaknesses of the IRC protocol is that it contains no way to specify character sets for IRC messages or IRC channels. Despite that, it all kind of works and there are still public IRC networks that attract e.g. technically oriented computer users and hardcore hackers. There are people who have been on IRC for literally decades, and they see no reason to give up their habit.
Another well-known weakness is that the original IRC protocol consists of unencrypted plain text data flow. This naturally means that evil eavesdroppers who are in the position to monitor Internet traffic can see other people's IRC conversations. But nowadays some IRC server implementations do support TLS for server authentication and IRC network traffic encryption. Despite that, in this tutorial we will stick with the simple plain text IRC protocol. The reasons for that decision will be explained next.
Why did we choose to demonstrate setting up an IRC server instead of, say, a more modern XMPP/Jabber based Internet chat server? Or an IRC server with TLS enabled? One extremely central reason is simplicity. Setting up a TLS enabled XMPP or IRC server requires having a certificate and a matching private key. XMPP servers also often need to be configured to authenticate clients. They may also require configuring database servers such as MariaDB. We grant that it is not very difficult if you know what you are doing. However, in contrast to that, Next Generation IRC Daemon is much easier to set up even for the pretty inexperienced Unix/Linux users.
It is our goal to help e.g. human rights activists to build a trusted chatting infrastructure that should be difficult for others to monitor and spy on. Those activists may well lack technical skills so things should be made very accessible for them and everyone. In addition, we believe it is in general a pretty good idea to avoid complexity whenever we can. Remember that the famous physicist and philosopher Albert Einstein once said:
Things should be made as simple as possible - but not any simpler.
Our secure private IRC server model places some demands on the users, that is, the regular clients who wish to use the IRC server for chatting and being safe. It turns out that the users only need an SSH client and Tor Network access. They need not worry about installing or updating IRC client programs at all, because the IRC server administrator provides them with a centrally administered IRC client. The downside is that the client proposed here (called
irssi) is terminal-based, i.e. it does not have a flashy and modern GUI that some users might expect. We may be overoptimistic, but we do believe that almost anyone can learn to use
irssi with little practice.
Security-wise, the infrastructure suggested here has one major issue: We allow shell access to the IRC server. This means that malicious users could gain control of the server by applying yet unknown local root exploits. To combat that, we could sandbox and limit the users as much as we can with e.g. Linux security mechanisms such as SELinux. But we have chosen not to do that, because it is our initial assumption that we are here building a strictly private IRC server. That means that we should have only trusted users and no suspicious strangers.
In general, it is evident that allowing shell access to a server in order to access its services is a very bad idea indeed. We humbly suggest the model presented here first because it is a relatively simple solution, and second because the whole concept of having a private IRC server is based on having a group of mutually trusted users. In other words, if you have untrusted users, then this model is not suitable for you.
It seems to us that one considerable advantage of this model could be that it allows clients to easily use operating systems such as Tails. Tails is a special-purpose OS based on Debian Linux. It can be booted using an USB stick and it leaves no traces anywhere on the computer it runs on. All Tails network traffic, including DNS queries, is routed to the Tor Network, providing users good chances of being anonymous. Using Tails, users always have an SSH client and they could contact the secure private IRC server easily without the need to configure IRC clients by themselves. Tor is also automatically available for them.
Using a centrally administered
irssi on the IRC server also eliminates the possibility of someone's IRC client being misconfigured to log conversations on disk. By default
irssi logs no conversations.
Let's get started. First of all, our secure private IRC server will never accept direct connections from the Internet. The IRC daemon
ngircd is bound to
localhost (IPv4 127.0.0.1) only. The origin of this basic idea dates back several years, and we are sure neither of us is the original inventor. We thus make absolutely no claims about originality or invention here. We just wish to spread some privacy related information to those who might benefit from it.
Nevertheless, one of the authors of this article used to run a carefully firewalled OpenBSD operating system on a Sun Ultra 80 Unix workstation working as a trusted Unix server. The Sun Ultra 80 was located in a server room the location of which the author is not willing to discuss, but suffice it to say that the machine ran almost uninterrupted for some years. During that time period, it served many happy IRC chat users who were afraid of surveillance or even persecution.
Older IRC daemon called
ircd was bound to
localhost and all the IRC users had to first login to the Sun Ultra 80 server using Secure Shell (
ssh). After that, they used Irssi (
irssi) IRC client program to connect to the locally running
ircd. The possible outside observers saw only SSH connections, but unless they did network traffic analysis, they could not figure out the SSH connections were used to ultimately use IRC chatting contained inside the destination host. So in our model the basic principle for setting up a secure private IRC server is to take care of two essential things:
localhost(IPv4 127.0.0.1) only. This prevents all IRC connections from the Internet and hides the fact that our host is even running IRC daemon.
In our case, both of the requirements above can be achieved by editing the IRC daemon's configuration file
/etc/ngircd.conf. For additional security and to guard against human errors, it might be good to use firewall rules (
iptables on Linux) to block both incoming and outgoing TCP connections to the usual IRC ports (i.e. 6666-6668). However, we leave firewall configuration up to the reader.
Assume that Alice and Bob want to secretly chat with each other. Then look at the picture below, starting from the left side.
UPDATE July 30th, 2018: WARNING! Unfortunately our original overview picture below is inaccurate and potentially misleading!
Please accept our apologies for messing up the picture. We have left the original here, but the revised overview picture is right below.
The required steps for Alice are pretty straightforward:
localhost. Review the picture if you are unsure. For simplicity, you can ignore the Tor aspects for now. We will explain the related Tor concepts later in this article.
irssiIRC client program. Alice is now ready to join IRC channels. She can also send and receive IRC private messages just like when using a normal, public IRC server. However, this time the IRC protocol is totally contained inside the trusted host, so no outsiders can monitor it unless they:
What about Bob? His steps are exactly identical. Both Alice and Bob must of course have Unix/Linux shell accounts and home directories on the SSH/IRC server. Otherwise they cannot do SSH logins to later access the private IRC server.
It is perhaps worth pointing out explicitly that in this secure chat model, the data flow between IRC client program
irssi and the IRC server
ngircd is totally in plaintext. Why is this so? It does not have to be encrypted, because the IRC protocol runs strictly inside the host machine. SSH protocol encrypts the network traffic between Alice/Bob's personal computer and the SSH server host. In addition to that, the SSH protocol is contained within Tor Network cells (i.e. data packets used in Tor protocol). The Tor cells are also encrypted! That is why using IRC like this should be quite safe.
We used Fedora Linux 28 with Xfce desktop on a QEMU virtual machine for putting the theory into practice. With some effort and creativity, we hope you can adopt the steps described here to other Linux (e.g. Debian GNU/Linux, Ubuntu) and Unix systems such as FreeBSD, NetBSD and OpenBSD. We wanted to stick with Fedora Linux, because we are already familiar with it. It is just a matter of personal preference. We claim no superiority over other systems out there.
Before we continue, we need to deviate a little bit from the main topic. To save our sanity, it is our decision to always install Xfce desktop as the very first thing after Fedora Linux installation. It is up to you if you want to follow us. If you do, find a way to open a terminal (as there are no sensible menus available in the weird default Gnome desktop, we just type "terminal" into the search box) and once you have the shell, then type:
Logging out might well suffice, but to be sure we reboot the machine, wait for the GDM login prompt, and type in the login name. We click the wheel symbol, select "Xfce session" and enter the password. When logged in to Xfce for the first time, we choose the default, and proceed from there according to our taste. For us, the default desktop on Fedora Linux 28 is unfortunately way too confusing and clumsy to be usable at all. But maybe some people like it.
Okay, enough of that digression. We next install Next Generation IRC daemon
ngircd, a terminal-based (it uses
ncurses library) IRC client
irssi and The Onion Router
/etc/skel/ directory is the "skeleton", i.e. the basis, or blueprint, for creating home directory content for new Unix/Linux users.
For the convenience of our future users, we will add a shell alias so that all new users can start
irssi with just typing a simple command
i. So we edit
/etc/skel/.bashrc by adding one line there:
Then we create a test user
We assign a safe password for
Then (using our own password, not the one we just invented for
alice), we switch to
alice user, we verify that the
i shell alias is effective:
We should see a reply resembling the following:
alice user's shell session, we issue command:
That is all there is. We are now done with
irssi configuration. When a user first starts
irssi, it will create directory
~/.irssi for the user. The configuration file will be automatically written there, and it should be fine as it is. We verified that
irssi does not log IRC conversations anywhere by default, and that is exactly what we want.
We start by editing
/etc/ngircd.motd. The abbreviation "motd" stands for "message of the day". It is just a brief greeting message to be displayed when users connect to our IRC server. We use
vim text editor:
Adopting the habit of never wanting to give away any unneeded information, we simply insert a boring text "This is a MOTD" and save the file. Please be aware that Vim can be very confusing and difficult for beginners, so you could use a simpler text editor such as
nano, or whatever you are confident to use.
Now comes the more crucial part. To configure our IRC server, we must edit
/etc/ngircd.conf. Again, feel perfectly free to use your favourite text editor. We do still recommend that you would learn
vim if you plan to do any serious system administration in the long run. It will pay off. We have learned to love
vim and fire it up:
For clarity and extra information, we include some comments taken from the configuration file. If you use a later version of
ngircd.conf, the comments could be slightly different. All comments here start with "#" and they are meant for human administrator's use only. The IRC server itself ignores comments when parsing the configuration.
We define server name:
We add some dummy information so that our IRC daemon will not complain in the system logs during its startup:
This is very important. We now command our IRC daemon to bind to
localhost (IPv4 127.0.0.1) only. This prevents access from outside world:
We allow our users to join as many channels as they like:
This might not be that important, since all our IRC clients come from the
localhost. But we set it anyway:
The following setting overrides the Real Name field with IRC nickname. Again, this is probably not at all important, but we set it to "yes":
But these settings are extremely important. We absolutely never want our private IRC server to connect to other IRC servers. Make sure to set these to "no":
All our IRC clients always come from
localhost, so this setting probably does not matter much. But it makes perfect sense to turn it off to avoid unnecessary DNS lookups. So we set DNS to "no":
Doing IDENT lookups makes no sense in our case. Using IDENT queries, an IRC server will contact a client to verify Unix/Linux username. We do not run IDENT daemon and we know that all our IRC users come from inside our own host. Without hesitation, we turn Ident queries off:
MorePrivacy sounds promising, but probably is not that crucial in our case. But we turn it on:
PAM is a widely used Pluggable Authentication Module framework originally invented by Sun Microsystems, a Unix vendor responsible for Solaris (formerly "SunOS") UNIX Operating System. By the way, Sun Microsystems also created SPARC RISC CPUs. Oracle bought Sun Microsystems many years ago.
In any case, let's get back to business. We do not want PAM authentication here. Why not? Because we know that all our IRC users have already been authenticated during the SSH login phase, so we allow connecting to the IRC daemon with no passwords required. We turn PAM off:
Finally we wish to allow unlimitd amount of connections from the same client IP, because all our clients come from 127.0.0.1 as far as the IRC server sees it:
In case you are wondering why we did not define IRC port anywhere, the explanation is simple. TCP port 6667 is the default in
ngircd distributed with Fedora Linux 28, so we were able to skip over that setting. Our IRC server configuration is now hopefully complete. We save the file and exit the text editor.
ngircd, we want to check that we made no mistakes while editing. We let
ngircd verify its configuration file sanity:
If you see warnings or errors, then go back and edit the configuration file until they are fixed.
It is now time to start
ngircd. We issue command:
If all went well, our secure private IRC daemon should be up and running. We verify that it is:
If you see errors, try to find a way to fix them. Inspecting system logs often proves helpful.
Before connecting to
ngircd, we are paranoid and wish to make sure it is indeed listening
localhost only. The classic Unix/Linux command
netstat is deprecated on Linux, so we try to avoid it, and use the new replacement tool called
ss instead. We give command:
We can be happy because we see the text that we expected:
It indicates that port 6667 is in the listening state and we can be pretty sure that it is
ngircd that is bound to
localhost (IPv4 127.0.0.1) just like we wanted. You could verify that using the PID of
ngircd, but we did not bother to do that.
To finish our
ngircd testing, we temporarily become our test user
alice, we launch
irssi IRC client program using the previously created shell alias
We should see how
irssi successfully connects to the local IRC server. If it worked out, congratulations! Your secure private IRC server is now up and running.
irssi, we just type a familiar IRC command:
Then we quit
alice user's shell session like usual:
There is one final step to be done with respect to our IRC server. We permanently enable
ngircd so that the IRC daemon will always automatically start up when we boot our machine. It is of course up to you whether you want to do this or not. In case you want to enable
ngircd too, then tell that to
systemd by typing command:
In this section we configure
sshd daemon. It will then allow users to login using encrypted SSH protocol.
ListenAddress setting and edit it to be:
Now if you have previous experience with running traditional Unix/Linux network servers, using
ListenAddress 127.0.0.1 for an SSH server will probably feel quite weird. After all, our goal here is to allow SSH logins from the outside world, so why on earth did we bind
sshd to the localhost only (IPv4 127.0.0.1)? Do not worry about this. We will configure a Tor Onion Service later in this tutorial, and in that section this peculiar sounding issue will be explained. So let's move on.
Next we find
PermitRootLogin and disable it:
To restrict SSH access to Unix/Linux group
ircusers, we add the following setting:
After that we verify that it got up and running:
Then we use
ss utility again to verify that 127.0.0.1 TCP port 22 is in listening mode:
If you see text "127.0.0.1:22", you should be fine.
We do a test login using
ssh as user
When asked "Are you sure you want to continue connecting (yes/no)?", we answer "yes". When prompted, we enter
Even though her password is correct, we should receive "Permission denied, please try again.". This is to be expected because
alice is not yet a member of the group
ircusers. So first we create that group:
And then we add
alice to the group:
We try to SSH login again as
This time we do get logged in. To quit
alice's shell session, we just type:
Finally we tell
systemd to always automatically bring up
sshd when booting our machine. It is up to you whether you want to follow us. If you choose to do so, just type:
On Fedora Linux 28 Security-Enhanced_Linux (SELinux for short) is enabled by default. We verify that fact by issuing command:
We should get a response like the following:
So we see that SELinux status is
enabled, mode is
enforcing, and finally the loaded security policy is
targeted. That is all fine, but we must tweak a Tor Onion Service related SELinux boolean variable called
tor_can_onion_services. To see why this is so, we query the status of that variable:
The response we get is:
You probably guessed this means that by default SELinux prevents
tor daemon from creating Tor Onion Services. So we tell SELinux to drop that restriction:
After that we proceed to edit
/etc/tor/torrc to configure
tor daemon. Again, you can use the text editor you want, but we keep on using
Having the file open for editing, we locate the section that deals with Hidden Services. "Hidden Services" is a deprecated name for Onion Services, but for backward compatibility reasons it still survives in the configuration setting names.
Fortunately Tor developers have made things easy for us. All we need to do is add two simple lines:
Those alone are sufficient to define the Tor Onion Service we want to create.
Notice that the second line
HiddenServicePort 22 127.0.0.1:22 maps Tor Onion Service port 22 to our
sshd daemon's listening port
127.0.0.1:22. When offering Onion Services, Tor works in a pretty counter-intuitive way. Instead of listening for incoming connections via a TCP socket,
tor daemon makes a permanent outbound connection to the Tor Network! Using that TCP connection,
tor makes our Onion Services available to Tor Network users! That is indeed clever.
The exact details of this surprising arrangement are pretty complicated to understand and require studying Tor architecture. However, once we accept the fact that we need no public listening TCP sockets, we soon arrive at a very, very important realization: We can easily run our own Tor Onion Services from home, even if our machine is in a private network masked behind a home router that does NAT. On such a computer, we can even run our Tor Onion Services inside isolated virtual machines, because all we need is working outbound TCP connections to the Tor Network! This is just amazing and extremely convenient.
So we tell
systemd to launch
We then wait for a short while, and hoping for the best, proceed to query
tor daemon's status:
We see that is all is well, but how do we figure out how to access our new Tor Onion Service? We have provided no name for the service, but that is perfectly fine. We cannot decide the hostname. Instead Tor works its magic behind the scenes and comes up with a unique hostname for us. Using
cat we can see it:
We should see the Tor Onion Service hostname as something like:
$hash will contain stuff that looks like gibberish to many, but rest assured that it is meaningful in the Tor Network context.
Finally we verify that the newly created Tor Onion Service is indeed available via Tor Network. To do that, we use our test user
alice to make a "torified" (i.e. Tor enabled) SSH connection to our hidden SSH server. We type:
Make sure you remember to replace
$hash.onion with whatever your file
If we did everything right, we should get logged in. However, the interactive SSH connection may feel a bit slower than usual because the network traffic is routed via Tor Network just like we wanted.
Last but not least, we chose not to enable automatic
tor daemon startup. But if you wish to do so, instruct
systemd like this:
This tutorial showed you one possible way of setting up a secure private IRC server. Such a server could be very useful for e.g. activist groups that have mutual trust between their individuals. In practice, this probably implies having a rather small user base.
Our model is easy from the chat user's perspective: The server administrator manages both the IRC server and the IRC client, so regular users need only an SSH client and access to Tor Network. This means that a (nearly) zero-configuration special-purpose security-focused OS such as Tails could be very suitable for chat users. The users could run Tails live system using USB sticks, but any system (e.g. OSX, Windows, BSD, regular Linux) with an SSH client and Tor Network access would be sufficient.
If you have untrusted users, the model presented here is not recommended, because allowing shell access to the shared server could prove catastrophic. Modern operating systems are extremely complicated, with many moving parts, and this implies that users with local access have extra attack vectors compared to the users who are not able to login.
We wish you good luck.