fix: dnsmasq answers the remote access clients' DNS queries, so they no longer get the router's own host name with all its addresses from systemd-resolved.
Release / release (push) Successful in 13s

This commit is contained in:
slawek committed 2026-10-26 16:53:42 +01:00
1 parent dabe4e8365
commit e14bbe2ba1
13 files changed
+111 -24

No files matched your search

@@ -81,6 +81,9 @@ CADDY_PKI_DIR = pathlib.Path('/etc/caddy/vpn-router-pki')
#: The certificates and keys of the sites of tls file, <site>/cert.pem and key.pem.
CADDY_SITES_DIR = pathlib.Path('/etc/caddy/vpn-router-sites')
#: The unit of dnsmasq, the resolver of the remote access clients.
RESOLVER_UNIT = 'vpn-router-resolver.service'
#: The unit of rclone's WebDAV server of the sites' folders.
WEBDAV_UNIT = 'vpn-router-webdav.service'
@@ -676,6 +679,19 @@ def caddy_address(host, port, tls):
return f'{"http://" if tls == "none" else ""}{host}:{port}'
def manage_resolver(changed):
"""Run dnsmasq, the resolver of the remote access clients, while configure wrote its configuration, restarting it when
that changed, and stop it when not. It starts after systemd-resolved has left the addresses it takes."""
if not vpnrouter.RESOLVER_CONF.exists():
if unit_is_active(RESOLVER_UNIT):
run(['systemctl', 'disable', '--now', RESOLVER_UNIT], check=False)
return
if not unit_is_active(RESOLVER_UNIT):
run(['systemctl', 'enable', '--now', RESOLVER_UNIT], check=False)
elif 'resolver' in changed:
run(['systemctl', 'restart', RESOLVER_UNIT], check=False)
def manage_caddy(cfg, ctx):
"""Run Caddy, the HTTPS proxy of the router's services and the server of the web sites, while either is wanted, and
stop it when not.
@@ -1062,6 +1078,8 @@ def main():
if 'resolved' in changed:
progress('running', 'resolver')
run(['systemctl', 'restart', 'systemd-resolved'], check=False)
progress('running', 'resolver of the remote access clients')
manage_resolver(changed)
progress('running', 'platform module')
run_platform_setup(cfg, ctx)
@@ -36,7 +36,10 @@ TEMPLATE_DIR = pathlib.Path('/usr/share/vpn-router/templates')
SWANCTL_CONF_D = pathlib.Path('/etc/swanctl/conf.d')
SITE_TO_SITE = SWANCTL_CONF_D / 'site-to-site.conf'
ROAD_WARRIOR = SWANCTL_CONF_D / 'road-warrior.conf'
#: The drop-in of systemd-resolved that earlier versions wrote for the remote access clients; removed when found.
P2S_FORWARDER = pathlib.Path('/etc/systemd/resolved.conf.d/p2s-forwarder.conf')
#: The configuration of dnsmasq, the resolver of the remote access clients (vpn-router-resolver.service).
RESOLVER_CONF = pathlib.Path('/etc/vpn-router/dnsmasq.conf')
WG_CONF = pathlib.Path('/etc/wireguard/wg0.conf')
#: The router's WireGuard public key, which setup writes with its private key.
WG_PUBLIC_KEY = pathlib.Path('/etc/wireguard/wg0.pub')
@@ -1172,7 +1175,7 @@ def configure(cfg=None, public_ip=None):
"""Render configuration files and provision PKI.
Returns (ctx, changed) where changed is a set naming what needs reloading:
'swanctl', 'resolved', 'wireguard', 'openvpn'.
'swanctl', 'resolved', 'resolver', 'wireguard', 'openvpn'.
"""
if cfg is None:
cfg = load_config()
@@ -1229,12 +1232,15 @@ def configure(cfg=None, public_ip=None):
elif remove(ROAD_WARRIOR):
changed.add('swanctl')
# The resolver of the remote access clients answers on the addresses of p2s.dns_listen only.
if (p2s_ready(ctx) or openvpn_ready(ctx)) and ctx['p2s_resolver_addrs']:
if render(env, ctx, 'p2s-forwarder.conf.j2', P2S_FORWARDER, 0o644):
changed.add('resolved')
elif remove(P2S_FORWARDER):
# The resolver of the remote access clients is dnsmasq on the addresses of p2s.dns_listen; systemd-resolved keeps
# its loopback stub only, so its records of the router's own name stay on the router.
if remove(P2S_FORWARDER):
changed.add('resolved')
if (p2s_ready(ctx) or openvpn_ready(ctx)) and ctx['p2s_resolver_addrs']:
if render(env, ctx, 'dnsmasq.conf.j2', RESOLVER_CONF, 0o644):
changed.add('resolver')
elif remove(RESOLVER_CONF):
changed.add('resolver')
if wg_ready(ctx):
if render_wg_conf(env, ctx):
@@ -4,8 +4,8 @@ No platform-specific configuration is currently required.
The Azure platform resolver 168.63.129.16 is deliberately *not* advertised to
road-warrior clients and *not* added to the traffic selectors. Clients are
given the router's addresses of p2s.dns_listen as their DNS servers, and the router
forwards through its own systemd-resolved via the p2s-forwarder drop-in. That resolves
given the router's addresses of p2s.dns_listen as their DNS servers, where dnsmasq
forwards to the router's own systemd-resolved. That resolves
Azure-internal names without routing the wireserver address through the tunnel
and without a second resolver in the pool.
"""
+1 -1
View File
@@ -171,7 +171,7 @@ POSTGRESQL_SETTINGS = ('server_version', 'listen_addresses', 'port', 'max_connec
#: The units whose journal /logs/journal shows, besides the whole journal: the package's own and the services it runs.
JOURNAL_UNITS = ('vpn-router-setup', 'vpn-router-web', 'vpn-router-metrics', 'vpn-router-pki', 'vpn-router-backup',
'vpn-router-caddy', 'vpn-router-manager', 'caddy', 'slapd', 'nslcd', 'postgresql', 'strongswan',
'wg-quick@wg0', 'openvpn-server@vpn-router', 'ssh')
'wg-quick@wg0', 'openvpn-server@vpn-router', 'ssh', 'vpn-router-resolver', 'vpn-router-webdav', 'pdns')
#: The most lines /logs answers, the number it answers without lines, and the most bytes it reads from the end of a file.
LOG_LINES_MAX = 1000
@@ -0,0 +1,11 @@
# Written by vpn-router-setup from /etc/vpn-router/vpn-router.json; edits are overwritten.
# The resolver of the remote access clients, on the addresses of p2s.dns_listen, forwarding to systemd-resolved's stub.
{% for address in p2s_resolver_addrs -%}
listen-address={{ address }}
{% endfor -%}
bind-interfaces
no-resolv
server=127.0.0.53
domain-needed
no-hosts
cache-size=1000
@@ -1,4 +0,0 @@
[Resolve]
{% for address in p2s_resolver_addrs -%}
DNSStubListenerExtra={{ address }}
{% endfor -%}