first commit
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
# 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.
|
||||
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
sudo install -m 0755 svc-proxy /usr/local/sbin/svc-proxy
|
||||
```
|
||||
|
||||
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 |
|
||||
|
||||
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.
|
||||
|
||||
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://`.
|
||||
|
||||
---
|
||||
|
||||
## 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ü
|
||||
|
||||
```bash
|
||||
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).
|
||||
|
||||
### 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 | Proxy-Typ wählen (beim Dienst 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 |
|
||||
|
||||
- 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 |
|
||||
|
||||
Mit `--config-dir`/`--systemd-dir` läuft das Skript auch ohne root. Das ist
|
||||
praktisch zum Testen, z.B. zusammen mit `--no-reload`.
|
||||
|
||||
---
|
||||
|
||||
## Beispiele
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
# 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
|
||||
Modus: eigene Werte (leere Felder = global)
|
||||
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)
|
||||
|
||||
```yaml
|
||||
- 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
|
||||
|
||||
```bash
|
||||
systemctl cat docker.service # zeigt das Drop-in
|
||||
sudo cat /proc/$(systemctl show -p MainPID --value docker)/environ | tr '\0' '\n' | grep -i proxy
|
||||
```
|
||||
|
||||
## Deinstallation
|
||||
|
||||
```bash
|
||||
sudo svc-proxy unset --all --restart
|
||||
sudo rm -rf /etc/svc-proxy /usr/local/sbin/svc-proxy
|
||||
```
|
||||
Binary file not shown.
Reference in New Issue
Block a user