IRC ist tot, lang lebe IRC. Während der Rest der Welt durch Messenger-Silos zieht, hänge ich nach wie vor gern in ein paar IRC-Kanälen ab — und damit mir dabei keine Zeile entgeht, betreibe ich einen Bouncer. Bei mir ist das ZNC , läuft auf Kubernetes und erreicht seine Upstream-Netze nicht direkt, sondern als Onion-Services über Tor.
Wozu ein Bouncer?
Ein IRC-Client ist nur verbunden, solange er läuft. Schließt man ihn, ist man weg — und alles, was in der Zwischenzeit geschah, verpasst. Ein Bouncer sitzt dauerhaft im Netz, hält die Verbindung und die Kanäle offen, puffert das Geschehen und spielt es dem Client beim nächsten Verbinden nach. ZNC ist der Klassiker dafür: Es hält pro Netzwerk persistente Buffer, terminiert TLS für die Clients (IRC auf 6697, das Webinterface auf 8443) und überlebt als Pod jeden Client-Neustart.
Der Clou: Upstream über Tor
Der eigentlich interessante Teil ist, wie ZNC die öffentlichen Netze erreicht. Sowohl Libera.Chat als auch hackint bieten ihre Server als Onion-Services an. Ich nutze das konsequent: Der Verkehr verlässt den Cluster nur durch Tor, inklusive obfs4-Bridges gegen Netzwerk-Zensur. Mein ISP sieht nicht einmal, dass dort IRC gesprochen wird.
Im Pod laufen dafür neben ZNC zwei kleine Sidecars. Der erste ist ein client-only Tor:
ClientOnly 1
SocksPort 127.0.0.1:9050
UseBridges 1
ClientTransportPlugin obfs4 exec /usr/bin/lyrebird
%include /config/bridges
MapAddress palladium.libera.chat libera75jm6of4...onion
MapAddress guybrush.hackint.org dtlbunzs5b7s5...onion
Das Problem: ZNC selbst hat keinen SOCKS-Client. Deshalb übernimmt ein zweiter Sidecar mit socat die Übersetzung — er wartet, bis Tor zu 100 % gebootstrappt ist, und legt dann lokale TCP-Brücken in die Onion-Services:
socat "TCP4-LISTEN:6671,fork,bind=127.0.0.1" \
"SOCKS4A:127.0.0.1:dtlbunzs5b7s5...onion:6697,socksport=9050" &
socat "TCP4-LISTEN:6672,fork,bind=127.0.0.1" \
"SOCKS4A:127.0.0.1:libera75jm6of4...onion:6697,socksport=9050" &
ZNC verbindet sich daraufhin ganz banal gegen 127.0.0.1 — die Tor-Magie passiert eine Schicht tiefer:
<Network hackint>
Server = 127.0.0.1 +6671
</Network>
<Network libera>
Server = 127.0.0.1 +6672
</Network>
<Network local>
Server = inspircd.irc.svc.cluster.local +6697
</Network>
Der vollständige Pfad einer Nachricht sieht damit so aus:
local, zeigt auf einen eigenen InspIRCd im selben Namespace. Dieser interne IRCd ist mein privates Netz für clusterinterne Benachrichtigungen und Spielereien — kein Federation-Gedöns, einfach ein sauberer, schlanker IRC-Server, der nur innerhalb des Clusters erreichbar ist.Ein Wort zu BitlBee
Früher hing an meinem IRC-Setup noch BitlBee — ein Gateway, das fremde Messenger (XMPP, ICQ, später diverse) als ganz normale IRC-Kanäle und -Queries erscheinen ließ. Man saß in seinem gewohnten IRC-Client und chattete nebenbei mit Kontakten aus völlig anderen Netzen, alles in derselben Oberfläche. Das war geniale Software: ein Protokoll-Übersetzer, der die Komplexität der Messenger-Welt hinter der wunderbar simplen IRC-Semantik versteckte. Ich nutze es heute nicht mehr aktiv, aber als Stück Software-Ästhetik hat es bei mir bis heute einen Ehrenplatz.
Fazit
Der Bouncer ist die kleine, unscheinbare Komponente, die IRC für mich überhaupt erst alltagstauglich macht: immer online, nichts verpasst, und der gesamte Upstream-Verkehr verschwindet sauber in Tor. Dass daneben ein eigener InspIRCd läuft, ist Luxus — aber genau für solchen Luxus betreibt man ja ein Lab.
