diff --git a/api/wireguard_manager.py b/api/wireguard_manager.py index e133c61..0bf164a 100644 --- a/api/wireguard_manager.py +++ b/api/wireguard_manager.py @@ -22,8 +22,8 @@ except ImportError: logger = logging.getLogger(__name__) -SERVER_ADDRESS = '172.20.0.1/16' -SERVER_NETWORK = '172.20.0.0/16' +SERVER_ADDRESS = '10.0.0.1/24' +SERVER_NETWORK = '10.0.0.0/24' DEFAULT_PORT = 51820 def _resolve_peer_dns() -> str: @@ -109,15 +109,30 @@ class WireGuardManager(BaseServiceManager): def generate_config(self, interface: str = 'wg0', port: int = DEFAULT_PORT) -> str: """Return a WireGuard [Interface] config string for the server.""" keys = self.get_keys() + ext_ip = self.get_external_ip() or '' + # Hairpin DNAT: redirect VPN clients targeting the server's public IP + # to 10.0.0.1 (the VPN interface), avoiding the Docker network loopback. + hairpin = ( + f'iptables -t nat -A PREROUTING -i %i -d {ext_ip} -j DNAT --to-destination 10.0.0.1; ' + if ext_ip else '' + ) + hairpin_down = ( + f'iptables -t nat -D PREROUTING -i %i -d {ext_ip} -j DNAT --to-destination 10.0.0.1; ' + if ext_ip else '' + ) return ( f'[Interface]\n' f'PrivateKey = {keys["private_key"]}\n' f'Address = {SERVER_ADDRESS}\n' f'ListenPort = {port}\n' f'PostUp = iptables -A FORWARD -i %i -j ACCEPT; ' - f'iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE\n' + f'iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ' + f'{hairpin}' + f'sysctl -q net.ipv4.conf.all.rp_filter=0\n' f'PostDown = iptables -D FORWARD -i %i -j ACCEPT; ' - f'iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE\n' + f'iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ' + f'{hairpin_down}' + f'sysctl -q net.ipv4.conf.all.rp_filter=1\n' ) def _config_file(self) -> str: