46 lines
2.0 KiB
Python
46 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Synchronize only the new white proxy vhosts' Cloudflare trust include."""
|
|
import ipaddress
|
|
import os
|
|
import pathlib
|
|
import subprocess
|
|
|
|
target = pathlib.Path('/etc/nginx/white-proxy-cloudflare-realip.conf')
|
|
ranges = []
|
|
for version in (4, 6):
|
|
p = subprocess.run(['curl', '-4', '--fail', '--silent', '--show-error', '--max-time', '30',
|
|
f'https://www.cloudflare.com/ips-v{version}'],
|
|
check=True, capture_output=True, text=True)
|
|
nets = [ipaddress.ip_network(x.strip(), strict=True) for x in p.stdout.splitlines() if x.strip()]
|
|
if not ((5 if version == 4 else 2) <= len(nets) <= 100):
|
|
raise RuntimeError('Unexpected Cloudflare range count')
|
|
if any(n.version != version or n.prefixlen < (8 if version == 4 else 16) for n in nets):
|
|
raise RuntimeError('Invalid or overbroad Cloudflare trust range')
|
|
ranges.extend(str(n) for n in nets)
|
|
if len(ranges) != len(set(ranges)):
|
|
raise RuntimeError('Duplicate Cloudflare ranges')
|
|
data = ('# Managed new white proxy vhosts only; Cloudflare official ranges.\n' +
|
|
''.join(f'set_real_ip_from {n};\n' for n in ranges) +
|
|
'real_ip_header CF-Connecting-IP;\nreal_ip_recursive off;\n').encode()
|
|
old = target.read_bytes() if target.exists() else None
|
|
if old == data:
|
|
print('White proxy Cloudflare trust unchanged')
|
|
raise SystemExit(0)
|
|
temporary = target.with_suffix('.conf.new')
|
|
temporary.write_bytes(data)
|
|
temporary.chmod(0o644)
|
|
os.replace(temporary, target)
|
|
try:
|
|
subprocess.run(['nginx', '-t'], check=True, capture_output=True)
|
|
subprocess.run(['systemctl', 'reload', 'nginx'], check=True)
|
|
except Exception:
|
|
if old is None:
|
|
target.unlink()
|
|
else:
|
|
temporary.write_bytes(old)
|
|
os.replace(temporary, target)
|
|
subprocess.run(['nginx', '-t'], check=True, capture_output=True)
|
|
subprocess.run(['systemctl', 'reload', 'nginx'], check=True)
|
|
raise
|
|
print(f'White proxy Cloudflare trust synchronized: {len(ranges)} ranges')
|