#!/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')