Neben den Proxy-Variablen (env) kann pro Dienst jetzt der Modus proxychains gewählt werden: proxychains-ng wird per LD_PRELOAD geladen und leitet alle ausgehenden TCP-Verbindungen über den Proxy, auch bei Programmen ohne Proxy-Unterstützung (z.B. Kerio Connect SMTP/POP3). - eigene proxychains-Konfiguration je Dienst unter /etc/svc-proxy/proxychains/ - localhost, private Netze, DNS und IP-Einträge aus No-Proxy gehen direkt - Proxy-Hostname wird zu IPv4 aufgelöst, Kennwort-Datei an User= des Dienstes - Modus-Auswahl im ncurses-Formular, --mode für set, Anzeige in list/show - README und --help ergänzt - __pycache__ aus dem Repo entfernt, .gitignore angelegt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
14 KiB
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 nichtEnvironment=? Werte ausEnvironment=kann jeder Benutzer mitsystemctl 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.socks5hwird wiesocks5behandelt. Einenhttps-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 applyausfü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. BeiDynamicUser=yesgeht 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 Modusenv. Prüfen mitldd /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) |
| 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 |
| 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 |
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
setundglobalwerden nur die angegebenen Felder geändert, der Rest bleibt. - Leerer Wert leert ein Feld:
--user "". set DIENST --resetleert 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
.serviceangehä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.
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
# 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