Proxy-Option fuer Zonefile-Abruf (Host ohne direkte Internetverbindung)
This commit is contained in:
@@ -245,6 +245,11 @@ Siehe Kommentare in der Datei selbst — kurz:
|
|||||||
einzelner Ports" unten.
|
einzelner Ports" unten.
|
||||||
- `protocol`: nur relevant wenn `ports` gesetzt ist — `tcp` (Default), `udp`
|
- `protocol`: nur relevant wenn `ports` gesetzt ist — `tcp` (Default), `udp`
|
||||||
oder `tcp,udp`
|
oder `tcp,udp`
|
||||||
|
- `proxy`: optional, HTTP(S)-Proxy fuer den Abruf der Zonefiles von ipdeny.com
|
||||||
|
(z.B. `http://10.0.0.5:3128`, mit Auth `http://user:pass@host:port`). Nur
|
||||||
|
noetig, wenn der Host selbst keine direkte Internetverbindung hat, aber
|
||||||
|
ueber einen Proxy raus kann. Leer lassen = direkte Verbindung (Standard).
|
||||||
|
Siehe Abschnitt "Proxy fuer den Zonefile-Abruf" unten.
|
||||||
|
|
||||||
Abschnitt `[testserver]` (fuer `geoblock_testserver.py`):
|
Abschnitt `[testserver]` (fuer `geoblock_testserver.py`):
|
||||||
|
|
||||||
@@ -295,3 +300,35 @@ Fuer einen sauberen End-to-End-Test der iptables-Regeln selbst (ohne Fragen
|
|||||||
zu Proxy-Ketten/CDN reinzumischen) ist Variante 1 — Testmaschine direkt mit
|
zu Proxy-Ketten/CDN reinzumischen) ist Variante 1 — Testmaschine direkt mit
|
||||||
eigener oeffentlicher IP, Geoblocking direkt auf dieser Maschine — der
|
eigener oeffentlicher IP, Geoblocking direkt auf dieser Maschine — der
|
||||||
einfachste und eindeutigste Weg.
|
einfachste und eindeutigste Weg.
|
||||||
|
|
||||||
|
## Proxy fuer den Zonefile-Abruf (`proxy` in `geoblock.ini`)
|
||||||
|
|
||||||
|
**Wichtig — das ist ein ANDERES Thema als der Reverse-Proxy-Abschnitt oben.**
|
||||||
|
Dort ging es darum, wo die *eingehende* Client-Verbindung ankommt. Hier geht
|
||||||
|
es darum, wie `geoblock.py` selbst *ausgehend* die Zonefiles von ipdeny.com
|
||||||
|
laedt.
|
||||||
|
|
||||||
|
**Wann noetig:** Manche Hosts sind zwar aus dem Internet erreichbar (z.B.
|
||||||
|
ueber einen vorgelagerten Reverse-Proxy oder eine Firewall mit Portweiterleitung),
|
||||||
|
haben aber selbst **keine direkte ausgehende Internetverbindung** — nur einen
|
||||||
|
Weg ueber einen internen HTTP(S)-Proxy nach draussen. Ohne diesen Proxy kann
|
||||||
|
`geoblock.py` `https://www.ipdeny.com/...` nicht erreichen und bricht mit
|
||||||
|
einem URL-Fehler ab.
|
||||||
|
|
||||||
|
**Konfiguration** in `geoblock.ini`, Abschnitt `[geoblock]`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[geoblock]
|
||||||
|
countries = de
|
||||||
|
proxy = http://10.0.0.5:3128
|
||||||
|
; mit Basic-Auth am Proxy:
|
||||||
|
; proxy = http://user:pass@10.0.0.5:3128
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Proxy wird sowohl fuer HTTP- als auch HTTPS-Abrufe genutzt (ipdeny liefert
|
||||||
|
per HTTPS aus). Leer lassen (Standard) = das Script verbindet sich direkt,
|
||||||
|
ohne Proxy — das ist der Normalfall auf den meisten Servern.
|
||||||
|
|
||||||
|
Betroffen ist **nur** der Abruf der Zonefiles beim Ausfuehren von
|
||||||
|
`--apply`/`--update`. iptables/ipset selbst und der Testserver brauchen dafuer
|
||||||
|
keinen Proxy — die filtern nur lokal am Kernel-Paketfilter.
|
||||||
|
|||||||
+27
-5
@@ -20,6 +20,8 @@ VORAUSSETZUNGEN (auf dem Ziel-Host, NICHT im Container):
|
|||||||
- Pakete installiert: iptables, ipset
|
- Pakete installiert: iptables, ipset
|
||||||
Debian/Ubuntu: apt install iptables ipset
|
Debian/Ubuntu: apt install iptables ipset
|
||||||
- Internetzugang zum Laden der Zonefiles von ipdeny.com
|
- Internetzugang zum Laden der Zonefiles von ipdeny.com
|
||||||
|
(falls der Host selbst keine direkte Verbindung hat: 'proxy' in der
|
||||||
|
.ini setzen -- siehe README)
|
||||||
|
|
||||||
BENUTZUNG:
|
BENUTZUNG:
|
||||||
sudo python3 geoblock.py --config geoblock.ini --apply
|
sudo python3 geoblock.py --config geoblock.ini --apply
|
||||||
@@ -167,6 +169,7 @@ def load_config(path):
|
|||||||
"log_file": sec.get("log_file", "").strip(),
|
"log_file": sec.get("log_file", "").strip(),
|
||||||
"ports": ports,
|
"ports": ports,
|
||||||
"protocols": protocols,
|
"protocols": protocols,
|
||||||
|
"proxy": sec.get("proxy", "").strip(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -213,12 +216,31 @@ def _variant_label(variant):
|
|||||||
return f"{variant['proto']}/{variant['dports']}"
|
return f"{variant['proto']}/{variant['dports']}"
|
||||||
|
|
||||||
|
|
||||||
def fetch_country_cidrs(country_code):
|
def _build_url_opener(proxy):
|
||||||
"""Laedt die CIDR-Liste eines Landes von ipdeny.com. Gibt Liste von Strings zurueck."""
|
"""Baut einen urllib-Opener. Mit 'proxy' gesetzt (z.B. 'http://host:3128' oder
|
||||||
|
'http://user:pass@host:3128') wird dieser fuer http UND https genutzt -- fuer
|
||||||
|
Server, die selbst keine direkte Internetverbindung haben und nur ueber
|
||||||
|
einen Vorgelagerten Proxy raus koennen."""
|
||||||
|
if not proxy:
|
||||||
|
return urllib.request.build_opener()
|
||||||
|
handler = urllib.request.ProxyHandler({"http": proxy, "https": proxy})
|
||||||
|
return urllib.request.build_opener(handler)
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_country_cidrs(country_code, proxy=""):
|
||||||
|
"""Laedt die CIDR-Liste eines Landes von ipdeny.com. Gibt Liste von Strings zurueck.
|
||||||
|
|
||||||
|
'proxy' (optional): HTTP(S)-Proxy-URL, falls der Server selbst keine direkte
|
||||||
|
Internetverbindung hat und ipdeny.com nur ueber einen Proxy erreichen kann.
|
||||||
|
"""
|
||||||
url = ZONE_URL_TMPL.format(cc=country_code)
|
url = ZONE_URL_TMPL.format(cc=country_code)
|
||||||
log(f"Lade IP-Ranges fuer '{country_code}' von {url}")
|
if proxy:
|
||||||
|
log(f"Lade IP-Ranges fuer '{country_code}' von {url} (ueber Proxy {proxy})")
|
||||||
|
else:
|
||||||
|
log(f"Lade IP-Ranges fuer '{country_code}' von {url}")
|
||||||
|
opener = _build_url_opener(proxy)
|
||||||
try:
|
try:
|
||||||
with urllib.request.urlopen(url, timeout=20) as resp:
|
with opener.open(url, timeout=20) as resp:
|
||||||
text = resp.read().decode("utf-8", errors="ignore")
|
text = resp.read().decode("utf-8", errors="ignore")
|
||||||
except urllib.error.HTTPError as e:
|
except urllib.error.HTTPError as e:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
@@ -276,7 +298,7 @@ def apply_geoblock(cfg, dry_run=False):
|
|||||||
# 2) alle CIDRs aller konfigurierten Laender sammeln
|
# 2) alle CIDRs aller konfigurierten Laender sammeln
|
||||||
all_cidrs = []
|
all_cidrs = []
|
||||||
for cc in cfg["countries"]:
|
for cc in cfg["countries"]:
|
||||||
all_cidrs.extend(fetch_country_cidrs(cc))
|
all_cidrs.extend(fetch_country_cidrs(cc, proxy=cfg.get("proxy", "")))
|
||||||
|
|
||||||
if not all_cidrs and not dry_run:
|
if not all_cidrs and not dry_run:
|
||||||
raise RuntimeError("Keine IP-Bereiche geladen — Abbruch, um kein leeres Set zu aktivieren")
|
raise RuntimeError("Keine IP-Bereiche geladen — Abbruch, um kein leeres Set zu aktivieren")
|
||||||
|
|||||||
Reference in New Issue
Block a user