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.irssi
IRC 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 tor
:
/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 alice
:
We assign a safe password for alice
:
Then (using our own password, not the one we just invented for alice
), we switch to alice
user:
Being now alice
user, we verify that the i
shell alias is effective:
We should see a reply resembling the following:
To exit 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.
Before starting 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
again:
Being now alice
, we launch irssi
IRC client program using the previously created shell alias i
:
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.
To exit 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.
We find 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:
We start sshd
:
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 alice
:
When asked "Are you sure you want to continue connecting (yes/no)?", we answer "yes". When prompted, we enter alice
's password.
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 alice
:
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 vim
:
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 tor
daemon:
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:
Note that $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 /var/lib/tor/hidden_service/hostname
contains!
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.