fix: split-tunnel default for peers, port check via wg interface, tunnel mode toggle in UI
- check_port_open now checks if wg0 interface is actually listening (via 'wg show wg0') instead of requiring a live peer handshake. This means the port shows 'Open' whenever WireGuard is running, not only when a peer has connected recently. - get_peer_config defaults to split-tunnel AllowedIPs (10.0.0.0/24, 172.20.0.0/16) so VPN clients only route cell service traffic through the tunnel. Local LAN traffic (192.168.x.x etc.) stays direct, fixing the 60-120ms penalty when pinging local hosts while on VPN. - Peer config modal now uses cell DNS (172.20.0.2) so .cell domains resolve correctly with both split and full tunnel. - Added split/full tunnel toggle in the peer config modal so users can download either config variant. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+21
-21
@@ -237,11 +237,18 @@ class WireGuardManager(BaseServiceManager):
|
||||
self._write_config('\n'.join(new_lines))
|
||||
return True
|
||||
|
||||
# Split-tunnel: only route cell VPN + Docker subnets through WireGuard.
|
||||
# This keeps the client's local LAN traffic (e.g. 192.168.x.x) off the tunnel,
|
||||
# avoiding the internet RTT penalty when pinging local devices.
|
||||
SPLIT_TUNNEL_IPS = '10.0.0.0/24, 172.20.0.0/16'
|
||||
|
||||
def get_peer_config(self, peer_name: str, peer_ip: str,
|
||||
peer_private_key: str,
|
||||
server_endpoint: str = '<SERVER_IP>',
|
||||
allowed_ips: str = '0.0.0.0/0, ::/0') -> str:
|
||||
"""Generate a WireGuard client config string (full-tunnel by default)."""
|
||||
allowed_ips: str = None) -> str:
|
||||
"""Generate a WireGuard client config string (split-tunnel by default)."""
|
||||
if allowed_ips is None:
|
||||
allowed_ips = self.SPLIT_TUNNEL_IPS
|
||||
server_keys = self.get_keys()
|
||||
peer_dns = _resolve_peer_dns()
|
||||
endpoint = server_endpoint if ':' in server_endpoint else f'{server_endpoint}:{DEFAULT_PORT}'
|
||||
@@ -302,11 +309,18 @@ class WireGuardManager(BaseServiceManager):
|
||||
return ip
|
||||
|
||||
def check_port_open(self, port: int = DEFAULT_PORT) -> bool:
|
||||
"""Check if the WireGuard UDP port is reachable from outside."""
|
||||
external_ip = self.get_external_ip()
|
||||
if not external_ip:
|
||||
return False
|
||||
# Check via WireGuard itself: if any peer has a recent handshake the port is open
|
||||
"""Check if WireGuard is running and listening on the UDP port."""
|
||||
# Primary: check if wg0 interface is up (means port IS listening)
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['docker', 'exec', 'cell-wireguard', 'wg', 'show', 'wg0'],
|
||||
capture_output=True, text=True, timeout=5,
|
||||
)
|
||||
if result.returncode == 0 and 'listen port' in result.stdout.lower():
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
# Fallback: recent peer handshake confirms external reachability
|
||||
try:
|
||||
statuses = self.get_all_peer_statuses()
|
||||
for st in statuses.values():
|
||||
@@ -314,20 +328,6 @@ class WireGuardManager(BaseServiceManager):
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
# Try UDP port check APIs that support UDP
|
||||
if _requests is not None:
|
||||
for url, params in [
|
||||
('https://portchecker.io/api/query', {'host': external_ip, 'port': port, 'type': 'udp'}),
|
||||
('https://api.ipquery.io/portcheck', {'ip': external_ip, 'port': port, 'protocol': 'udp'}),
|
||||
]:
|
||||
try:
|
||||
resp = _requests.get(url, params=params, timeout=6)
|
||||
if resp.ok:
|
||||
d = resp.json()
|
||||
if d.get('open') or d.get('isOpen') or d.get('status') == 'open':
|
||||
return True
|
||||
except Exception:
|
||||
continue
|
||||
return False
|
||||
|
||||
def get_server_config(self) -> Dict[str, Any]:
|
||||
|
||||
Reference in New Issue
Block a user