Tor-Dienst auf autorisierte Clients begrenzen

Dienste die man im Tor-Netzwerk bereit stellt, können bei Bedarf ausschließlich autorisierten Gegenstellen verfügbar gemacht werden.

Alle Befehle dieser Anleitung werden am Client-Rechner ausgeführt. Einerseits vereinfacht dies die Erläuterungen, andererseits wird vermieden den privaten Schlüssel an weiteren Orten zwischen zu speichern.

Voraussetzungen

  • Es wird davon ausgegangen, dass SSH-Zugriffe zum Server als root möglich sind.
  • Der versteckte Dienst muss bereits am Server eingerichtet und aktiv sein (siehe HiddenServiceDir in /etc/tor/torrc).
  • Am Client muss PyNaCl vorhanden sein. Unter Void Linux wird es beispielsweise via xbps-install -Su python3-pynacl installiert.
  • Am Client muss der Befehl openbsd-nc vorhanden sein. Unter Void Linux installiert man das entsprechende Paket beispielsweise via xbps-install -Su openbsd-netcat.

Umgebung definieren

Diese Konstanten müssen im Verlauf der gesamten Anleitung korrekt gesetzt sein.

# Diese Konstanten entsprechend der eigenen Umgebung deklarieren
SERVER=203.0.113.2
TOR_SERVICE_PATH=/var/lib/tor/hidden_service
NETCAT_CMD="openbsd-nc -X 5 -x 127.0.0.1:9050 %h %p"

# Die Werte dieser Konstanten werden vom Server geholt
SERVERNAME=`ssh root@${SERVER} hostname`
ONION=`ssh root@${SERVER} cat ${TOR_SERVICE_PATH}/hostname`

Schlüsselpaar generieren

Zum Generieren des Schlüsselpaars wird ein einfaches Python-Skript verwendet, dessen Inhalt zumindest auf verdächtige Auffälligkeiten geprüft werden sollte.

# Skript laden
curl -O https://raw.githubusercontent.com/pastly/python-snippits/7ea7cb7fd3fea47dcf723edec2e52775aee43b0a/src/tor/x25519-gen.py

# Inhalt des Skripts zur Überprüfung ausgeben
cat x25519-gen.py

# Schlüssel generieren und einlesen
TMP=`mktemp --tmpdir keypair-XXX`
python ./x25519-gen.py | sed 's#\: *#=#g' > "$TMP"
. "$TMP" && rm -f "$TMP"

# Schlüssel prüfen
echo "$public"  | grep -E '.{52}' >/dev/null ||
    echo "Öffentlicher Schlüssel '$public' ungültig!" >&2
echo "$private" | grep -E '.{52}' >/dev/null ||
    echo "Privater Schlüssel '$private' ungültig!" >&2

Öffentlichen Schlüssel zu Server kopieren

echo "descriptor:x25519:$public" |
    ssh root@${SERVER} tee "$TOR_SERVICE_PATH/authorized_clients/$HOST.auth"

Privaten Schlüssel am Client hinterlegen

CAUTH_PATH=/var/lib/tor/onion_auth
sudo mkdir -p "$CAUTH_PATH"
echo "${ONION%%.onion}:descriptor:x25519:$private" |
    sudo tee "$CAUTH_PATH"/$SERVERNAME.auth_private

echo "ClientOnionAuthDir $CAUTH_PATH" |
    sudo tee /etc/tor/torrc

Vorgenommene Änderungen in Tor übernehmen

Wichtig: Man sollte eine neue Konfiguration sehr vorsichtig übernehmen. Schränkt man hier beispielsweise den Zugang zu SSH-über-Tor ein, sollte sicher gestellt sein, dass auch von Tor unabhängig eine SSH-Verbindung aufgebaut werden kann.

Test vor dem Einschränken

Da vor dem Neustart der Dienste die Client Authorization noch inaktiv ist, muss die Verbindung an dieser Stelle noch möglich sein.

ssh -o ProxyCommand="$NETCAT_CMD" root@${ONION} &&
    echo 'OK: Verbindung ist wie erwartet noch möglich!'

Server-Konfiguration neu laden

Der Befehl hierzu hängt von der verwendeten Diensteverwaltung ab.

# Beispiel: Server mit Alpine Linux / OpenRC
ssh root@${SERVER} service tor reload

Test nach dem Einschränken

Da der Server nun bereits auf autorisierte Gegenstellen begrenzt ist, muss an dieser Stelle jeder Verbindungsversuch scheitern:

ssh -o ProxyCommand="$NETCAT_CMD" root@${ONION} ||
    echo 'OK: Verbindungsaufbau ist wie erwartet fehlgeschlagen!'

Client-Konfiguration neu laden

Der Befehl hierzu hängt von der verwendeten Diensteverwaltung ab.

# Beispiel: Client mit Void Linux / Runit
sudo sv reload tor

Test nach Aktivieren des Client-Schlüssels

Da sich der Client dem Server gegenüber nun ordnungsgemäß authentifiziert, muss an dieser Stelle die Verbindung wieder möglich sein:

ssh -o ProxyCommand="$NETCAT_CMD" root@${ONION} &&
    echo 'OK: Verbindung ist wie erwartet wieder möglich!'

Quellen