|
|
6 일 전 | |
|---|---|---|
| bash | 6 일 전 | |
| .gitignore | 6 일 전 | |
| LICENSE | 6 일 전 | |
| README.md | 6 일 전 | |
| manage_ipset.conf | 6 일 전 | |
| manage_ipset.py | 6 일 전 |
Keep Proxmox cluster firewall IPSets in sync with DNS.
Hostnames are resolved repeatedly (A and AAAA) until no new IP addresses show up, so that all IPs behind a round-robin or anycast DNS record are collected. Afterwards the IPSet is synchronized: IPs that are gone are deleted, new IPs are added. Only the difference is written — no flush-and-refill.
One script, one config file. Python 3 standard library only — no pip
installs needed. Requires pvesh (from pve-manager) and dig
(from dnsutils) on the host.
Copy the script and the config to a Proxmox host (or any host with
pvesh access to the cluster).
Note: /etc/pve is Proxmox's cluster filesystem (pmxcfs). It syncs
its files to every node, but does not support chmod — scripts
there cannot be made executable. Two options:
a) In /etc/pve — cluster-wide, run via python3:
cp manage_ipset.py manage_ipset.conf /etc/pve/
python3 /etc/pve/manage_ipset.py
b) Local and executable — e.g. /usr/local/sbin, per node:
install -m 755 manage_ipset.py /usr/local/sbin/
install -m 644 manage_ipset.conf /etc/
/usr/local/sbin/manage_ipset.py -c /etc/manage_ipset.conf
manage_ipset.conf is looked up next to the script unless -c is
given.
# sync every IPSet from the config
python3 manage_ipset.py
# use a different config file
python3 manage_ipset.py -c /path/to/manage_ipset.conf
# sync a single IPSet directly
python3 manage_ipset.py github github.com github.io
python3 manage_ipset.py docker-io registry-1.docker.io --round 30
# every hour, /etc/pve install
0 * * * * python3 /etc/pve/manage_ipset.py
# local install
0 * * * * /usr/local/sbin/manage_ipset.py -c /etc/manage_ipset.conf
manage_ipset.conf)[defaults]
round=50
stale_after=10
# dns_server=1.1.1.1 # optional, default: system resolver
# timeout=15
golang
host=go.dev
github
host=github.com
host=github.io round=10 stale_after=3
[defaults] section sets the global defaults. Optional.host=... adds a host to the current IPSet.
An IPSet may hold several hosts; their IPs are merged into one set.round, stale_after, dns_server,
timeout.# are comments.| Option | Meaning | Default |
|---|---|---|
round |
max. DNS query rounds per host | 50 |
stale_after |
rounds without a new IP before stopping early | 10 |
dns_server |
resolver to query (dig @server) |
system |
timeout |
dig timeout in seconds |
15 |
Hosts with many rotating IPs (big CDNs, registry-1.docker.io)
benefit from a higher round; round=1 behaves like a single query.
manage_ipset.py reads manage_ipset.conf and groups hosts by
IPSet.dig +short host A / AAAA is run up to round
times. As soon as stale_after consecutive rounds return no new
IP, the loop stops.pvesh get /cluster/firewall/ipset/<name> --output-format json).pvesh create ... --cidr), stale IPs are
removed (pvesh delete .../<ip>).If a host in an IPSet does not resolve, that IPSet is left untouched — a single broken hostname cannot strip the IPs of its siblings.
bash/ directory.GPLv3 — see LICENSE.
Copyright (C) 2026 Paul Klumpp