From 8da711e3662e86b35c5276bb6ca09b0bac2136d1 Mon Sep 17 00:00:00 2001 From: Dmitrii Iurco Date: Sat, 6 Jun 2026 07:14:55 -0400 Subject: [PATCH] fix: DNAT and forward port 443 (HTTPS) to Caddy from WireGuard peers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ensure_service_dnat() only wired port 80 → cell-caddy, so HTTPS was silently dropped: no DNAT rule redirected 443 to the Caddy container, and the FORWARD chain had no ACCEPT for dport 443. Refactored the function to loop over both 80 and 443 so both are DNAT'd and forwarded. Co-Authored-By: Claude Sonnet 4.6 --- api/firewall_manager.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/api/firewall_manager.py b/api/firewall_manager.py index 3c59800..f315402 100644 --- a/api/firewall_manager.py +++ b/api/firewall_manager.py @@ -569,7 +569,7 @@ def ensure_dns_dnat() -> bool: def ensure_service_dnat() -> bool: - """DNAT wg0:80 (scoped to WG server IP) → cell-caddy:80. + """DNAT wg0:80 and wg0:443 (scoped to WG server IP) → cell-caddy. Service DNS names resolve to the WG server IP. DNAT is scoped with -d {server_ip} so that cross-cell HTTP traffic destined for another cell passes through unmodified. @@ -583,21 +583,22 @@ def ensure_service_dnat() -> bool: if not caddy_ip: logger.warning('ensure_service_dnat: cell-caddy not found') return False - dnat_check = ['-t', 'nat', '-C', 'PREROUTING', '-i', 'wg0', '-d', server_ip, - '-p', 'tcp', '--dport', '80', - '-j', 'DNAT', '--to-destination', f'{caddy_ip}:80'] - dnat_add = ['-t', 'nat', '-A', 'PREROUTING', '-i', 'wg0', '-d', server_ip, - '-p', 'tcp', '--dport', '80', - '-j', 'DNAT', '--to-destination', f'{caddy_ip}:80'] - if _wg_exec(['iptables'] + dnat_check).returncode != 0: - _wg_exec(['iptables'] + dnat_add) - fwd_check = ['-C', 'FORWARD', '-i', 'wg0', '-o', 'eth0', - '-p', 'tcp', '--dport', '80', '-j', 'ACCEPT'] - fwd_add = ['-I', 'FORWARD', '-i', 'wg0', '-o', 'eth0', - '-p', 'tcp', '--dport', '80', '-j', 'ACCEPT'] - if _wg_exec(['iptables'] + fwd_check).returncode != 0: - _wg_exec(['iptables'] + fwd_add) - logger.info(f'ensure_service_dnat: wg0:{server_ip}:80 → {caddy_ip}:80') + for port in ('80', '443'): + dnat_check = ['-t', 'nat', '-C', 'PREROUTING', '-i', 'wg0', '-d', server_ip, + '-p', 'tcp', '--dport', port, + '-j', 'DNAT', '--to-destination', f'{caddy_ip}:{port}'] + dnat_add = ['-t', 'nat', '-A', 'PREROUTING', '-i', 'wg0', '-d', server_ip, + '-p', 'tcp', '--dport', port, + '-j', 'DNAT', '--to-destination', f'{caddy_ip}:{port}'] + if _wg_exec(['iptables'] + dnat_check).returncode != 0: + _wg_exec(['iptables'] + dnat_add) + fwd_check = ['-C', 'FORWARD', '-i', 'wg0', '-o', 'eth0', + '-p', 'tcp', '--dport', port, '-j', 'ACCEPT'] + fwd_add = ['-I', 'FORWARD', '-i', 'wg0', '-o', 'eth0', + '-p', 'tcp', '--dport', port, '-j', 'ACCEPT'] + if _wg_exec(['iptables'] + fwd_check).returncode != 0: + _wg_exec(['iptables'] + fwd_add) + logger.info(f'ensure_service_dnat: wg0:{server_ip}:80+443 → {caddy_ip}') return True except Exception as e: logger.error(f'ensure_service_dnat: {e}')