fix: UI always accessible; fix exit-relay AllowedIPs not updating

**PIC UI always accessible (service_access=[])**
Remove the per-peer Caddy:80 ACCEPT/DROP rule from apply_peer_rules.
Service access was enforced at two layers (iptables DROP + CoreDNS ACL),
but the iptables layer also blocked the PIC web UI served through Caddy.
CoreDNS ACL alone is sufficient — DNS blocks service hostnames; the UI
path through Caddy remains reachable regardless of service_access value.

**Exit-relay internet routing (route_via another cell)**
update_peer_ip validated new_ip as a single ip_network, rejecting the
comma-separated '10.0.1.0/24, 0.0.0.0/0' string passed by
update_cell_peer_allowed_ips(add_default_route=True). The AllowedIPs
in wg0.conf was never updated, so WireGuard never routed internet traffic
through the exit cell's tunnel. Fix: validate each CIDR individually and
apply the change live via wg set without a container restart.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-02 05:41:22 -04:00
parent c521fab1cb
commit 1a611e0474
5 changed files with 97 additions and 46 deletions
+23
View File
@@ -231,6 +231,29 @@ class TestWireGuardManager(unittest.TestCase):
with open(self.wg_manager._config_file(), 'r') as f:
config = f.read()
self.assertIn('10.0.0.9/32', config)
def test_update_peer_ip_accepts_comma_separated_cidrs(self):
"""update_peer_ip accepts comma-separated CIDRs for exit-relay AllowedIPs."""
peer_keys = self.wg_manager.generate_peer_keys('exitpeer')
# Use add_cell_peer — cell peers have subnet AllowedIPs, not /32
self.wg_manager.add_cell_peer(
'exitpeer', peer_keys['public_key'], '', '10.0.1.0/24')
success = self.wg_manager.update_peer_ip(
peer_keys['public_key'], '10.0.1.0/24, 0.0.0.0/0')
self.assertTrue(success, 'Should accept comma-separated CIDRs')
with open(self.wg_manager._config_file(), 'r') as f:
config = f.read()
self.assertIn('10.0.1.0/24, 0.0.0.0/0', config)
def test_update_peer_ip_rejects_newlines(self):
"""update_peer_ip rejects strings with newlines (injection guard)."""
peer_keys = self.wg_manager.generate_peer_keys('badpeer')
self.wg_manager.add_peer('badpeer', peer_keys['public_key'], '', '10.0.0.2/32')
success = self.wg_manager.update_peer_ip(peer_keys['public_key'], '10.0.0.9/32\nPostUp=evil')
self.assertFalse(success)
def test_get_peer_config(self):
"""Test generating peer client configuration."""