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.
|
||||
- `protocol`: nur relevant wenn `ports` gesetzt ist — `tcp` (Default), `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`):
|
||||
|
||||
@@ -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
|
||||
eigener oeffentlicher IP, Geoblocking direkt auf dieser Maschine — der
|
||||
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.
|
||||
|
||||
@@ -40,6 +40,15 @@
|
||||
; protocol: nur relevant wenn "ports" gesetzt ist. tcp (Standard), udp,
|
||||
; oder "tcp,udp" fuer beides. Fuer die meisten Web-/App-Ports
|
||||
; reicht "tcp".
|
||||
;
|
||||
; proxy: optional, HTTP(S)-Proxy-URL, ueber den das Script ipdeny.com
|
||||
; erreicht -- fuer Hosts, die zwar aus dem Internet erreichbar
|
||||
; sind (z.B. hinter Reverse-Proxy/Firewall), selbst aber KEINE
|
||||
; direkte ausgehende Internetverbindung haben.
|
||||
; Format: http://host:port oder mit Auth http://user:pass@host:port
|
||||
; Wird fuer http UND https genutzt (ipdeny liefert per https aus).
|
||||
; Leer lassen (Standard) = direkte Verbindung, kein Proxy.
|
||||
; Beispiel: proxy = http://10.0.0.5:3128
|
||||
|
||||
[geoblock]
|
||||
countries = RU, CN, KP, IR
|
||||
@@ -53,6 +62,8 @@ log_file = /var/log/geoblock/geoblock.log
|
||||
; z.B. "8899" setzen (nur der Testserver wird geblockt, SSH bleibt offen).
|
||||
ports =
|
||||
protocol = tcp
|
||||
; Leer lassen, ausser der Host hat keine direkte Internetverbindung.
|
||||
proxy =
|
||||
|
||||
; --- Test-Webserver (geoblock_testserver.py) --------------------------
|
||||
; Kleiner HTTP-Server ohne Abhaengigkeiten, um Geoblocking-Regeln von aussen
|
||||
|
||||
+26
-4
@@ -20,6 +20,8 @@ VORAUSSETZUNGEN (auf dem Ziel-Host, NICHT im Container):
|
||||
- Pakete installiert: iptables, ipset
|
||||
Debian/Ubuntu: apt install iptables ipset
|
||||
- Internetzugang zum Laden der Zonefiles von ipdeny.com
|
||||
(falls der Host selbst keine direkte Verbindung hat: 'proxy' in der
|
||||
.ini setzen -- siehe README)
|
||||
|
||||
BENUTZUNG:
|
||||
sudo python3 geoblock.py --config geoblock.ini --apply
|
||||
@@ -167,6 +169,7 @@ def load_config(path):
|
||||
"log_file": sec.get("log_file", "").strip(),
|
||||
"ports": ports,
|
||||
"protocols": protocols,
|
||||
"proxy": sec.get("proxy", "").strip(),
|
||||
}
|
||||
|
||||
|
||||
@@ -213,12 +216,31 @@ def _variant_label(variant):
|
||||
return f"{variant['proto']}/{variant['dports']}"
|
||||
|
||||
|
||||
def fetch_country_cidrs(country_code):
|
||||
"""Laedt die CIDR-Liste eines Landes von ipdeny.com. Gibt Liste von Strings zurueck."""
|
||||
def _build_url_opener(proxy):
|
||||
"""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)
|
||||
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:
|
||||
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")
|
||||
except urllib.error.HTTPError as e:
|
||||
raise RuntimeError(
|
||||
@@ -276,7 +298,7 @@ def apply_geoblock(cfg, dry_run=False):
|
||||
# 2) alle CIDRs aller konfigurierten Laender sammeln
|
||||
all_cidrs = []
|
||||
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:
|
||||
raise RuntimeError("Keine IP-Bereiche geladen — Abbruch, um kein leeres Set zu aktivieren")
|
||||
|
||||
Reference in New Issue
Block a user