fix: embed DNAT rules in wg0.conf PostUp for persistence + fix dns_ip in server config

DNAT rules applied via docker exec are lost whenever wg-easy reloads the
WireGuard interface (PostDown flushes the nat table then PostUp only
re-adds static rules). Fix: embed DNS (port 53) and service (port 80)
DNAT rules directly in wg0.conf PostUp/PostDown so they reapply on every
interface restart. ensure_postup_dnat() patches existing configs on startup.

get_server_config() now returns the WG server IP (e.g. 10.0.0.1) for
dns_ip instead of the cell-dns container IP (172.20.0.3). This makes the
value consistent with what get_peer_config() writes into the .conf file,
and fixes the stale hint text in Peers.jsx and WireGuard.jsx.

UI: fallback dns_ip changed from 172.20.0.3 to 10.0.0.1; split-tunnel
fallback drops the 172.20.0.0/16 stale range.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-02 04:07:10 -04:00
parent 9a800e3b6b
commit f1666ba19c
5 changed files with 169 additions and 9 deletions
+3 -3
View File
@@ -133,9 +133,9 @@ function Peers() {
const serverPubKey = peer.server_public_key || sc?.public_key || 'SERVER_PUBLIC_KEY_PLACEHOLDER';
const endpoint = peer.server_endpoint || sc?.endpoint || 'YOUR_SERVER_IP:51820';
const address = peer.ip?.includes('/') ? peer.ip : `${peer.ip}/32`;
const splitTunnelIPs = sc?.split_tunnel_ips || `10.0.0.0/24, 172.20.0.0/16`;
const splitTunnelIPs = sc?.split_tunnel_ips || `10.0.0.0/24`;
const allowedIPs = peer.internet_access !== false ? FULL_TUNNEL_IPS : splitTunnelIPs;
const dnsIp = sc?.dns_ip || '172.20.0.3';
const dnsIp = sc?.dns_ip || '10.0.0.1';
return `[Interface]
PrivateKey = ${privateKey}
Address = ${address}
@@ -767,7 +767,7 @@ PersistentKeepalive = ${peer.persistent_keepalive || 25}`;
</div>
)}
<p className="text-xs text-gray-500 mt-2">
DNS is set to <code className="bg-gray-100 px-1 rounded">{serverConf?.dns_ip || '172.20.0.3'}</code> (PIC CoreDNS) — required to resolve <code className="bg-gray-100 px-1 rounded">.{domain}</code> domains.
DNS is set to <code className="bg-gray-100 px-1 rounded">{serverConf?.dns_ip || '10.0.0.1'}</code> (PIC DNS) — required to resolve <code className="bg-gray-100 px-1 rounded">.{domain}</code> domains.
</p>
</div>
+3 -3
View File
@@ -227,9 +227,9 @@ function WireGuard() {
const serverEndpoint = peer.server_endpoint || serverConfig?.endpoint || "YOUR_SERVER_IP:51820";
const privateKey = peer.private_key || 'YOUR_PRIVATE_KEY_HERE';
const peerAddress = peer.ip?.includes('/') ? peer.ip : `${peer.ip}/32`;
const splitTunnelIPs = serverConfig?.split_tunnel_ips || '10.0.0.0/24, 172.20.0.0/16';
const splitTunnelIPs = serverConfig?.split_tunnel_ips || '10.0.0.0/24';
const allowedIPs = mode === 'full' ? FULL_TUNNEL_IPS : splitTunnelIPs;
const dnsIp = serverConfig?.dns_ip || '172.20.0.3';
const dnsIp = serverConfig?.dns_ip || '10.0.0.1';
return `[Interface]
PrivateKey = ${privateKey}
@@ -667,7 +667,7 @@ PersistentKeepalive = ${peer.persistent_keepalive || 25}`;
</div>
<p className="text-xs text-gray-500 mb-3">
{tunnelMode === 'split'
? `Split tunnel: only cell services (${serverConfig?.split_tunnel_ips || '10.0.0.0/24, 172.20.0.0/16'}) route through VPN — local network & internet traffic stay direct.`
? `Split tunnel: only cell services (${serverConfig?.split_tunnel_ips || '10.0.0.0/24'}) route through VPN — local network & internet traffic stay direct.`
: 'Full tunnel: all traffic (internet + local) routes through VPN server.'}
</p>