Nspawn - Build A Tor-only IRC Server In Containers
Tor, The Dark Web And Your IRC Chat
The Onion Router (Tor) is presented like the wild-west of the internet.
In reality it's a system for better privacy.
The infrastructure behind it handles the routing and encryption.
Most people think of Tor as the dark web.
Despite Tor being used for shady things - you can use it in an ethical and legal way.
For better privacy. For encryption.
You - and your users - can benefit from Tor without setting a foot on the "dark web".
IRC is fast. IRC is simple.
A text based protocol that runs smoothly even with Tor's latency.
You build a Tor-only IRC server that:
- hides your server's IP from the clients
- hides your clients' IP addresses from the IRC server and from other IRC users
- uses Tor's end-to-end encryption
- uses its own
.onionaddress.
The Plan - Nspawn Container Separation
You've already learnt about Nspawn and container management.
Compartmentalization enhances the flexibility.
Take advantage of cloning and snapshotting.
Create two containers:
- Tor service (10.10.0.10)
- IRC server and services (10.10.0.11)
The two containers must have network connectivity between 10.10.0.10 and 10.10.0.11.
Make sure the IRC container's port 6667 is not exposed outside the container network.
The Plan - Execution
Tor Container
Log in to the Tor container.
Install the Tor service.
sudo apt update sudo apt install tor
In the /etc/tor/torrc file set up your service and the port forwarding to the IRC container.
HiddenServiceDir /var/lib/tor/irc_hidden_service/ HiddenServicePort 6667 10.10.0.11:6667
In the example 10.10.0.11 is the IP address of the IRC container.
The Tor container's IP is 10.10.0.10.
You find your new .onion address in /var/lib/tor/irc_hidden_service/hostname.
sudo cat /var/lib/tor/irc_hidden_service/hostname
Backup the:
- hs_ed25519_public_key
- hs_ed25519_secret_key
- hostname
Take a note of the .onion address.
Verify that the Tor service is running and it listens.
systemctl status tor.service sudo ss -tupln |grep tor
IRC Container
You can use any popular IRC service software in this container, like Ergo chat.
For the flexibility I chose InspIRCd.
InspIRCd 4 is available in current Debian stable and it integrates well with Anope services.
Install InspIRCd and Anope in the container.
sudo apt update sudo apt install inspircd anope
Create a backup of the original configuration file.
sudo mv /etc/inspircd/inspircd.conf /etc/inspircd/inspircd.conf.orig
Create your own IRC configuration in /etc/inspircd/inspircd.conf.
Example config snippet:
<server name="irc.myhiddenchat.onion" description="Myhiddenchat IRC Server" network="MyhiddenchatNetwork"> <admin name="yournick" description="myhiddenchat" email="myhiddenchat@email.me"> <module name="hidechans"> <module name="spanningtree"> <module name="account"> <module name="services"> <module name="conn_umodes"> <module name="sha2"> <module name="cap"> <module name="sasl"> <module name="conn_join"> <module name="password_hash"> <module name="customprefix"> <module name="cloak"> <module name="cloak_user"> <cloak method="account" case="preserve" class="" invalidchar="strip" prefix="HiddenHost/" suffix=""> <bind address="10.10.0.11" port="6667" type="clients"> <connect allow="*" timeout="60" threshold="10" pingfreq="120" hardsendq="262144" softsendq="8192" recvq="8192" localmax="500" globalmax="500" maxchans="20" resolvehostnames="no" modes="+x"> <class name="Shutdown" commands="DIE RESTART REHASH LOADMODULE UNLOADMODULE RELOADMODULE"> <class name="ServerLink" commands="CONNECT SQUIT RCONNECT RSQUIT MKPASSWD"> <class name="BanControl" commands="KILL GLINE KLINE ZLINE QLINE ELINE"> <class name="OperChat" commands="WALLOPS GLOBOPS SETIDLE SPYLIST SPYNAMES"> <class name="HostCloak" commands="SETHOST SETIDENT CHGNAME CHGHOST CHGIDENT"> <class name="ServerStats" commands="STATS" privs="users/auspex channels/auspex servers/auspex users/mass-message users/flood/no-throttle users/flood/increased-buffers"> <type name="NetAdmin" classes="OperChat BanControl HostCloak Shutdown ServerLink ServerStats" host="netadmin.myhiddenchat.onion"> <type name="GlobalOp" classes="OperChat BanControl HostCloak" host="ircop.myhiddenchat.onion"> <type name="Helper" classes="HostCloak" host="helper.myhiddenchat.onion"> <oper name="youropernick" password="YourPW" host="*@*" type="NetAdmin" maxchans="60"> <files motd="/etc/inspircd/inspircd.motd"> <dns timeout="0"> <options prefixquit="Quit: " syntaxhints="no" announcets="yes" hostintopic="yes" pingwarning="15" splitwhois="no" exemptchanops=""> <security hideserver="" userstats="Pu" customversion="" flatlinks="no" hidesplits="no" hideulines="no" hidebans="no" maxtargets="20"> <performance quietbursts="yes" softlimit="1024" somaxconn="128" netbuffersize="10240"> <whowas groupsize="10" maxgroups="100000" maxkeep="3d"> <badnick nick="ChanServ" reason="Reserved For Services"> <badnick nick="NickServ" reason="Reserved For Services"> <badnick nick="OperServ" reason="Reserved For Services"> <badnick nick="MemoServ" reason="Reserved For Services"> <badnick nick="HostServ" reason="Reserved For Services"> <badnick nick="Global" reason="Reserved For Services"> <link name="services.myhiddenchat.onion" ipaddr="127.0.0.1" port="7000" allowmask="127.0.0.0/8" sendpass="passwordForServices" recvpass="passwordForServices"> <uline server="services.myhiddenchat.onion" silent="yes"> <bind address="127.0.0.1" port="7000" type="servers"> <sasl target="services.myhiddenchat.onion" requiressl="no">
- In this example you use, and you trust Tor's own encryption.
- The server listens on port
6667. - SASL authentication is configured and can be used.
- The NetAdmin password must be hashed before production use.
For the Anope services backup the default configuration.
sudo mv /etc/anope/services.conf /etc/anope/services.conf.orig
Create your new config in /etc/anope/services.conf.
Example config:
uplink { host = "127.0.0.1" ipv6 = no ssl = no port = 7000 password = "passwordForServices" } serverinfo { name = "services.myhiddenchat.onion" description = "myhiddenchatNetwork Services" pid = "/run/anope/anope.pid" motd = "services.motd" } module { name = "inspircd3" use_server_side_mlock = yes use_server_side_topiclock = yes } networkinfo { networkname = "myhiddenchatNetwork" nicklen = 31 userlen = 10 hostlen = 64 chanlen = 32 modelistsize = 100 vhost_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-" allow_undotted_vhosts = false disallow_start_or_end = ".-" } options { casemap = "ascii" strictpasswords = yes badpasslimit = 5 badpasstimeout = 1h updatetimeout = 5m expiretimeout = 30m readtimeout = 5s timeoutcheck = 3s retrywait = 60s hideprivilegedcommands = yes hideregisteredcommands = yes languages = "ca_ES.UTF-8 de_DE.UTF-8 el_GR.UTF-8 es_ES.UTF-8 fr_FR.UTF-8 hu_HU.UTF-8 it_IT.UTF-8 nl_NL.UTF-8 pl_PL.UTF-8 pt_PT.UTF-8 ru_RU.UTF-8 tr_TR.UTF-8" } module { name = "enc_sha256" } module { name = "db_flatfile" database = "anope.db" keepbackups = 12 } include { type = "file" name = "nickserv.conf" } include { type = "file" name = "chanserv.conf" } include { type = "file" name = "operserv.conf" } include { type = "file" name = "hostserv.conf" } include { type = "file" name = "memoserv.conf" } include { type = "file" name = "global.conf" } log { target = "services.log" bot = "Global" logage = 3 users = "connect disconnect nick" rawio = no debug = no } module { name = "help" } module { name = "m_sasl" } opertype { name = "ServicesRoot" commands = "*" privileges = "*" } oper { name = "youropernick" type = "ServicesRoot" }
Adjust the following services files for your config:
- nickserv.conf
- chanserv.conf
- operserv.conf
- hostserv.conf
- memoserv.conf
- global.conf
Rewrite the placeholder services host:
sudo sed -i 's/services.host/services.myhiddenchat.onion/g' /etc/anope/*.conf
Start the InspIRCd.
sudo systemctl enable inspircd.service sudo systemctl start inspircd.service
Start the Anope.
sudo systemctl enable anope.service sudo systemctl start anope.service
Check the logs and debug if necessary.
journalctl -u inspircd journalctl -u anope
You can join your IRC server through a SOCKS5 Tor proxy.
More NetAdmin Security
Load the password_hash module in InspIRCd.
Generate a hash for the NetAdmin password.
Use the hash in the configuration file, remove the plain text data.
Don't forget to /rehash the config on your server.
Final Whisper
The design is simple and reproducible.
- You can host your chat for your community.
- Tor provides end-to-end encryption between the clients and the onion service.
- You can snapshot the containers before you make any change.
Treat container snapshots as sensitive data.
They may contain private keys, credentials and chat data.
Build your community. Stay ethical. Stay legal.
DeadSwitch | The Silent Architect
[ Fear the Silence. Fear the Switch. ]