duffyduckandClaude Opus 5.5 9270994e82 Verbindungstest für Proxys hinzufügen
Neuer Befehl 'svc-proxy test [DIENST]' sowie Taste 't' in der Liste und
Schaltfläche/F3 im Formular (testet ungespeicherte Werte).

- prüft Erreichbarkeit, Handshake und Anmeldung für SOCKS5/SOCKS4/HTTP(S)
  mit klaren Meldungen (Kennwort falsch, Proxy-Typ vertauscht, Port gesperrt)
- baut Tunnel zu Testzielen auf und liest die Begrüßung (SMTP, POP3, IMAP,
  HTTP), TLS für 443/465/993/995
- --target HOST:PORT, --mail (SMTP 25/587/465, POP3S, IMAPS), --timeout
- im proxychains-Modus zusätzlicher Test über die proxychains-Bibliothek
  mit der Konfiguration des Dienstes
- Ad-hoc-Test mit --proxy ohne root und ohne Speichern
- Hilfe und README ergänzt, Version 1.2.0

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 14:34:44 +02:00

svc-proxy – Proxy für systemd-Dienste

svc-proxy legt fest, über welchen Proxy ein systemd-Dienst seine Verbindungen aufbaut. Bedienen lässt es sich auf zwei Wegen:

  • ncurses-Menü: listet alle Dienste auf. Man wählt einen aus und trägt die Daten bequem ein.
  • Kommandozeile: für Skripte, Ansible, Provisionierung usw.

Pro Dienst wählt man den Modus:

Modus Wirkung Geeignet für
env – Proxy-Variablen (Standard) setzt http_proxy, https_proxy, … Programme, die diese Variablen beachten (curl, apt, Docker, Python, Go, …)
proxychains leitet alle ausgehenden TCP-Verbindungen des Dienstes über den Proxy Programme ohne Proxy-Unterstützung, z.B. Kerio Connect (SMTP, POP3, IMAP)

Es gibt einen globalen Proxy. Alle Felder, die man bei einem Dienst leer lässt, übernehmen den globalen Wert. Explizit gesetzte Werte beim Dienst gelten vorrangig. Benutzername und Kennwort sind optional; ohne sie wird der Proxy ohne Anmeldung genutzt.

Abhängigkeiten: nur python3 (≥ 3.6) mit den Standardmodulen. curses ist bei Debian/Ubuntu/RHEL im Python-Paket enthalten. Für den Modus proxychains zusätzlich proxychains4 (Debian/Ubuntu) bzw. proxychains-ng (RHEL/Fedora).


Installation

sudo install -m 0755 svc-proxy /usr/local/sbin/svc-proxy
sudo apt install proxychains4      # nur für den Modus proxychains nötig

Danach sudo svc-proxy (Menü) oder svc-proxy --help (Hilfe).


Funktionsweise

Für jeden konfigurierten Dienst werden zwei Dateien erzeugt:

Datei Inhalt Rechte
/etc/systemd/system/<dienst>.d/50-svc-proxy.conf Drop-in mit EnvironmentFile= 0644
/etc/svc-proxy/env/<dienst>.env die eigentlichen Proxy-Variablen 0600

Im Modus proxychains kommt eine dritte Datei dazu:

Datei Inhalt Rechte
/etc/svc-proxy/proxychains/<dienst>.conf proxychains-Konfiguration 0644, mit Kennwort 0600

Die Konfiguration selbst (global + alle Dienste) liegt in /etc/svc-proxy/config.json (0600). Die Drop-ins und Env-Dateien werden daraus generiert und sollten nicht von Hand bearbeitet werden.

Modus env (Proxy-Variablen)

Gesetzt werden die Variablen

http_proxy  https_proxy  ftp_proxy  all_proxy  no_proxy
HTTP_PROXY  HTTPS_PROXY  FTP_PROXY  ALL_PROXY  NO_PROXY

Warum EnvironmentFile= und nicht Environment=? Werte aus Environment= kann jeder Benutzer mit systemctl show <dienst> auslesen, also auch ein Proxy-Kennwort. Die Env-Datei ist nur für root lesbar.

Sonderzeichen in Benutzername/Kennwort (z.B. @, :, /) werden automatisch URL-kodiert.

Wichtige Einschränkung

Der Proxy wirkt nur bei Programmen, die die Proxy-Umgebungsvariablen auswerten. Das tun die meisten (curl, wget, apt, pip, Python requests/urllib, Go, Node mit passenden Libs, Docker-Daemon, containerd, Git, ...). Programme, die die Variablen ignorieren (z.B. viele Java-Anwendungen ohne -Dhttp.proxyHost), müssen anders konfiguriert werden. Eine Netzwerk-Sperre ist das nicht: Ein Programm kann den Proxy umgehen.

SOCKS-Proxys (socks5://, socks5h://) werden ebenfalls in alle Variablen geschrieben. Das funktioniert z.B. mit curl und Go. Manche Programme verstehen in http_proxy aber nur http://. Für solche Fälle gibt es den Modus proxychains.

Modus proxychains (alle TCP-Verbindungen)

proxychains-ng wird per LD_PRELOAD in den Dienst geladen. Die Bibliothek fängt jeden connect()-Aufruf ab und baut die Verbindung stattdessen über den Proxy auf. Das Programm selbst muss nichts von einem Proxy wissen. Das ist dasselbe wie proxychains4 programm, nur fest im Dienst eingetragen. Die Env-Datei enthält dann:

LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libproxychains.so.4"
PROXYCHAINS_CONF_FILE="/etc/svc-proxy/proxychains/<dienst>.conf"
PROXYCHAINS_QUIET_MODE="1"

Direkt (ohne Proxy) verbunden werden immer:

  • localhost (127.0.0.0/8, ::1)
  • private Netze: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, fc00::/7, fe80::/10
  • DNS (Port 53, jedes Ziel), damit z.B. MX-Abfragen normal funktionieren
  • alle IP-Adressen und Netze aus der No-Proxy-Liste (z.B. 192.0.2.0/24). Hostnamen/Domains aus No-Proxy kann proxychains nicht berücksichtigen.

Hinweise:

  • Proxy-Typen: http (CONNECT), socks4, socks5. socks5h wird wie socks5 behandelt. Einen https-Proxy kann proxychains nicht.
  • proxychains braucht für den Proxy eine IPv4-Adresse. Ein Hostname wird beim Speichern aufgelöst und die IP fest eingetragen. Ändert sich die IP des Proxys, einmal svc-proxy apply ausführen.
  • Benutzer/Kennwort dürfen hier keine Leerzeichen enthalten.
  • Läuft der Dienst unter einem eigenen Benutzer (User=), bekommt dieser die Datei mit dem Kennwort zugewiesen. Bei DynamicUser=yes geht das nicht, dann einen Proxy ohne Anmeldung verwenden.
  • Nur TCP wird umgeleitet, UDP nicht. Eingehende Verbindungen (z.B. MX-Empfang) sind nicht betroffen.
  • Statisch gelinkte Programme (z.B. viele Go-Binaries) ignorieren LD_PRELOAD. Für die gibt es meist den Modus env. Prüfen mit ldd /pfad/zum/programm.
  • Der Modus wird nicht vom globalen Proxy geerbt, er gilt immer nur für den jeweiligen Dienst (Standard: env).

Beispiel: Kerio Connect

Kerio beachtet keine Proxy-Variablen, und der Proxy in den Kerio-Einstellungen gilt nur für Updates und Antivirus. Mit proxychains laufen auch SMTP-Versand und POP3/IMAP-Abruf über den Proxy:

sudo apt install proxychains4
ldd /opt/kerio/mailserver/mailserver | grep libc      # muss dynamisch gelinkt sein
sudo svc-proxy global --proxy socks5://192.168.1.50:1080
sudo svc-proxy set kerio-connect --mode proxychains --restart

Beim Mailversand über einen Proxy gilt: Empfänger sehen die IP des Proxys. Diese muss im SPF-Eintrag stehen und einen passenden Reverse-DNS haben, und der Proxy muss ausgehend Port 25 erlauben. Alternativ in Kerio einen SMTP-Relay (Smarthost, Port 587 mit Anmeldung) eintragen. Die Verbindung dorthin läuft dann ebenfalls über den Proxy.


Vererbung: Dienst ↔ global

Felder: Typ, Host, Port, Benutzer, Kennwort, No-Proxy

Feld beim Dienst Ergebnis
Typ / Host / Port / No-Proxy leer globaler Wert
Typ / Host / Port / No-Proxy gesetzt Wert des Dienstes
Benutzer leer und Host leer globale Zugangsdaten
Benutzer leer, eigener Host Proxy ohne Anmeldung
Benutzer gesetzt Benutzer + Kennwort des Dienstes

Die Sonderregel für Benutzer/Kennwort verhindert, dass globale Zugangsdaten an einen fremden Proxy geschickt werden.

Ändert man den globalen Proxy, werden alle Dienste, die ihn ganz oder teilweise erben, automatisch neu geschrieben. Wird der globale Proxy gelöscht, verlieren Dienste ohne eigenen Host ihren Proxy. Ihre Konfiguration bleibt aber gespeichert und wird wieder aktiv, sobald ein globaler Proxy gesetzt ist.


ncurses-Menü

sudo svc-proxy
 svc-proxy 1.0.0 – Proxy für systemd-Dienste
 Global: http://max:****@proxy.firma.local:3128   No-Proxy: localhost,127.0.0.1,::1
 220 Dienste
    Dienst                         Status     Proxy
 G  cron.service                   active     global → http://max:****@proxy.firma.local:3128
 E* docker.service                 active     eigen  → socks5h://10.1.1.1:1080
    nginx.service                  inactive
 ...
 ↑↓ Wählen  Enter Bearbeiten  g Global  Entf Proxy entfernen  / Filter  c Nur konfigurierte ...

Markierungen: G = nutzt globalen Proxy, E = eigene Werte, * = in dieser Sitzung geändert (Neustart noch offen), [proxychains] = Modus proxychains.

Tasten in der Liste

Taste Funktion
↑ ↓ / Bild↑ Bild↓ / Pos1 Ende Dienst wählen
Enter Proxy des Dienstes bearbeiten
g globalen Proxy bearbeiten
Entf / d Proxy vom Dienst entfernen
/ Filter (Name oder Beschreibung), Esc löscht den Filter
c nur konfigurierte Dienste anzeigen (an/aus)
t Verbindungstest für den gewählten Dienst (ohne Proxy: globaler Proxy)
r gewählten Dienst sofort neu starten
F5 Dienstliste neu einlesen
F1 / ? Hilfe
q / F10 Beenden

Tasten im Formular

Taste Funktion
Tab / ↑ ↓ Feld wechseln
← → / Leertaste Modus bzw. Proxy-Typ wählen (beim Typ gibt es zusätzlich „global“)
Enter nächstes Feld bzw. Schaltfläche auslösen
F2 Speichern
F3 / „Testen“ Verbindungstest mit den eingegebenen, noch nicht gespeicherten Werten
Strg+U Feld leeren
Esc Abbrechen

Leere Felder zeigen grau den globalen Wert an. Unter dem Formular steht live die Proxy-URL, die sich ergibt. Ungültige Eingaben werden nicht gespeichert.

Nach jedem Speichern läuft systemctl daemon-reload. Beim Beenden erscheint eine Liste der geänderten Dienste: Diese kann man an- und abwählen und neu starten lassen.


Kommandozeile

svc-proxy [BEFEHL] [OPTIONEN]
Befehl Beschreibung
(keiner) / tui Menü starten
list [--all] konfigurierte Dienste (mit --all: alle Dienste)
show [DIENST] effektive Werte eines Dienstes inkl. Herkunft; ohne DIENST: global
global [FELDER] globalen Proxy setzen/ändern; ohne FELDER: anzeigen
global --clear globalen Proxy löschen
set DIENST... [FELDER] [--reset] Proxy für Dienst(e) setzen/ändern
unset DIENST... / unset --all Proxy entfernen
apply alle Drop-ins aus der Konfiguration neu erzeugen
test [DIENST] [--target H:P] [--mail] Verbindungstest über den Proxy (siehe unten)
help, -h, --help Hilfe mit Beispielen

Felder

Option Bedeutung
--proxy URL komplette URL, z.B. http://user:pass@proxy:3128; setzt Typ, Host, Port, Benutzer, Kennwort
--type TYP http, https, socks5, socks5h, socks4
--host HOST Hostname / IP
--port PORT 1–65535
--user NAME Benutzername
--password PW Kennwort (in ps sichtbar!)
--password-stdin Kennwort aus der Standardeingabe lesen (empfohlen)
--no-proxy LISTE Ausnahmen, kommagetrennt
--mode MODUS nur bei set: env (Standard) oder proxychains
  • Bei set und global werden nur die angegebenen Felder geändert, der Rest bleibt.
  • Leerer Wert leert ein Feld: --user "".
  • set DIENST --reset leert vorher alle Felder, der Dienst nutzt danach komplett den globalen Proxy.
  • Ein neuer Dienst ohne Felder (set DIENST) nutzt den globalen Proxy.
  • Dienstnamen ohne Endung bekommen automatisch .service angehängt.
  • Beim ersten Setzen des globalen Proxys ist No-Proxy standardmäßig localhost,127.0.0.1,::1.

Neustart und Reload

Option Wirkung
(nichts) im Terminal Nachfrage [j/N]; ohne Terminal (Cron, Skript) kein Neustart
--restart geänderte Dienste ohne Nachfrage neu starten
--no-restart nicht neu starten, nicht fragen
--no-reload kein systemctl daemon-reload

Neu gestartet wird mit systemctl try-restart, also nur Dienste, die gerade laufen. Gestoppte Dienste werden nicht gestartet.

Weitere Optionen

Option Bedeutung
--config-dir DIR anderes Konfigurationsverzeichnis (Standard /etc/svc-proxy)
--systemd-dir DIR anderes Ziel für Drop-ins (Standard /etc/systemd/system)
-V, --version Version

Umgebungsvariable SVC_PROXY_PROXYCHAINS_LIB: Pfad zur proxychains-Bibliothek, falls sie nicht automatisch gefunden wird.

Mit --config-dir/--systemd-dir läuft das Skript auch ohne root. Das ist praktisch zum Testen, z.B. zusammen mit --no-reload.


Verbindungstest

sudo svc-proxy test kerio-connect --mail
Verbindungstest: Dienst kerio-connect.service
         Proxy: socks5://max:****@192.168.1.50:1080  [proxychains]
[ OK ]   Proxy erreichbar: 192.168.1.50:1080 (1 ms)
[FEHLER] gmail-smtp-in.l.google.com:25 → Proxy meldet: vom Regelwerk des Proxys nicht erlaubt (Port/Ziel gesperrt?)
[ OK ]   smtp.gmail.com:587 → Antwort: 220 smtp.gmail.com ESMTP ... (46 ms)
[ OK ]   smtp.gmail.com:465 → TLS ok, Antwort: 220 smtp.gmail.com ESMTP ... (61 ms)
[ OK ]   pop.gmail.com:995 → TLS ok, Antwort: +OK Gpop ready for requests ... (67 ms)
[ OK ]   imap.gmail.com:993 → TLS ok, Antwort: * OK Gimap ready for requests ... (105 ms)
         Test über proxychains (so verbindet der Dienst):
[FEHLER] proxychains: gmail-smtp-in.l.google.com:25 → Verbindung abgelehnt
[ OK ]   proxychains: smtp.gmail.com:587 → Antwort: 220 smtp.gmail.com ESMTP ...
...
Ergebnis: 2 Test(s) fehlgeschlagen.

Ablauf:

  1. Proxy erreichbar? TCP-Verbindung zum Proxy.
  2. Handshake und Anmeldung: SOCKS5, SOCKS4 oder HTTP CONNECT (auch https-Proxy). Verständliche Meldungen z.B. bei falschem Kennwort, fehlender Anmeldung, falschem Proxy-Typ (socks/http vertauscht) oder einem vom Proxy gesperrten Port.
  3. Ziele: Tunnel zu jedem Ziel aufbauen und die Begrüßung lesen. Das zeigt, dass wirklich Daten fließen (SMTP 220, POP3 +OK, IMAP * OK, HTTP-Status). Die Ports 443, 465, 993 und 995 werden per TLS angesprochen (ohne Zertifikatsprüfung, es geht nur um die Verbindung).
  4. Nur im Modus proxychains: Derselbe Test läuft noch einmal als normales Programm über die proxychains-Bibliothek mit der Konfiguration des Dienstes. Damit ist der komplette Weg geprüft, den auch der Dienst nimmt.
Option Bedeutung
--target HOST:PORT Testziel, mehrfach möglich (Standard: example.com:80, example.com:443)
--mail Mail-Ziele: SMTP 25/587/465, POP3S 995, IMAPS 993 (Gmail)
--timeout SEK Zeitlimit pro Schritt (Standard 6 s)
--proxy, --host, … Werte nur für den Test überschreiben, nichts wird gespeichert

Ohne DIENST wird der globale Proxy getestet. Mit --proxy URL (ohne DIENST) läuft der Test auch ohne root und ohne gespeicherte Konfiguration. So lässt sich ein Proxy prüfen, bevor man ihn einträgt. Rückgabewert: 0 = alles ok, 1 = mindestens ein Test fehlgeschlagen, praktisch für Monitoring-Skripte.

Hinweis zu Port 25: Viele Proxys und Provider sperren ausgehend Port 25. Der Test zeigt genau das. Abhilfe ist ein SMTP-Relay (Smarthost) auf Port 587 oder 465.


Beispiele

# Menü
sudo svc-proxy

# Globaler Proxy ohne Anmeldung
sudo svc-proxy global --proxy http://proxy.firma.local:3128

# Globaler Proxy mit Anmeldung, Kennwort nicht in der Prozessliste
echo 'geheim' | sudo svc-proxy global --proxy http://proxy:3128 --user max --password-stdin
# oder aus einer Datei / einem Secret-Store
sudo svc-proxy global --user max --password-stdin < /root/proxy.pw

# Ausnahmen für den globalen Proxy
sudo svc-proxy global --no-proxy localhost,127.0.0.1,::1,.firma.local,10.0.0.0/8

# Mehrere Dienste nutzen den globalen Proxy, sofort neu starten
sudo svc-proxy set docker containerd nginx --restart

# Eigener SOCKS-Proxy ohne Anmeldung für einen Dienst
sudo svc-proxy set myapp --proxy socks5h://10.1.1.1:1080

# Nur anderer Host, Port/Typ/No-Proxy kommen vom globalen Proxy,
# keine Anmeldung (eigener Host ohne Benutzer)
sudo svc-proxy set backup --host proxy2.firma.local

# Kerio Connect: alle Mail-Verbindungen über den (globalen) SOCKS5-Proxy
sudo svc-proxy set kerio-connect --mode proxychains --restart

# Eigener Proxy mit Anmeldung im proxychains-Modus, Netz 192.0.2.0/24 direkt
echo 'geheim' | sudo svc-proxy set kerio-connect --mode proxychains \
     --proxy socks5://192.0.2.10:1080 --user max --password-stdin --no-proxy 192.0.2.0/24

# Zurück zu den Proxy-Variablen
sudo svc-proxy set kerio-connect --mode env

# Nur den Port ändern
sudo svc-proxy set myapp --port 1081 --no-restart

# Zurück auf den globalen Proxy
sudo svc-proxy set myapp --reset

# Entfernen
sudo svc-proxy unset myapp --restart
sudo svc-proxy unset --all --no-restart

# Verbindungstests
sudo svc-proxy test                                     # globaler Proxy
sudo svc-proxy test kerio-connect --mail                # Mail-Ports über Kerios Proxy
sudo svc-proxy test kerio-connect --target mx.example.com:25 --target pop.example.com:995
svc-proxy test --proxy socks5://192.0.2.10:1080 --mail  # ad hoc, ohne Speichern, ohne root

# Anzeigen
sudo svc-proxy list
sudo svc-proxy list --all
sudo svc-proxy show docker
sudo svc-proxy show            # globaler Proxy

Beispielausgabe von show:

Dienst:    ssh.service
Status:    active
Herkunft:  eigene Werte (leere Felder = global)
Modus:     Proxy-Variablen
  Proxy-Typ  http                                (global)
  Host       other.proxy                         (dienst)
  Port       3128                                (global)
  Benutzer   -                                   (dienst)
  Kennwort   -                                   (dienst)
  No-Proxy   localhost,127.0.0.1,::1             (global)
Proxy-URL: http://other.proxy:3128

Automatisierung (z.B. Ansible)

- name: Proxy für Docker setzen
  ansible.builtin.shell: >
    svc-proxy global --proxy http://proxy.firma.local:3128 --no-restart &&
    svc-proxy set docker.service --restart

Rückgabewert: 0 bei Erfolg, 1 bei Fehler (ungültige Eingabe, fehlende Rechte, fehlgeschlagener Neustart).


Prüfen, ob es wirkt

systemctl cat docker.service              # zeigt das Drop-in
sudo cat /proc/$(systemctl show -p MainPID --value docker)/environ | tr '\0' '\n' | grep -i proxy

# proxychains-Modus: ist die Bibliothek im Prozess geladen?
sudo grep proxychains /proc/$(systemctl show -p MainPID --value kerio-connect)/maps | head -1
# laufende Verbindungen des Dienstes: Ziel sollte der Proxy sein
sudo ss -tnp | grep mailserver

Deinstallation

sudo svc-proxy unset --all --restart
sudo rm -rf /etc/svc-proxy /usr/local/sbin/svc-proxy
S
Description
No description provided
Readme
192 KiB
Languages
Python 100%