Kresd: automatically use vpn dns server for internsl domains

Hi,

When I connect to a VPN server, I want kresd to automatically resolve internal (vpn) domains using the vpn dns server (while keeping resolving other domains as before). The problem is that I enabled TLS DNS forwarding to Cloudflare using Foris, and it looks like in this mode it does not read /tmp/resolv.conf.auto.
I know how to hardcode that in configuration for a specific domain and dns server IP (Kresd configuration: how to forward a specific internal domain to another DNS), but can I make it work automatically as without TLS forwarding to cloudflare?
I am using kresd 3.2.1.

config resolver 'common'
        list interface '0.0.0.0'
        list interface '::0'
        option port '53'
        option keyfile '/etc/root.keys'
        option verbose '0'
        option msg_buffer_size '4096'
        option msg_cache_size '20M'
        option net_ipv6 '1'
        option net_ipv4 '1'
        option forward_upstream '1'
        option prefered_resolver 'kresd'
        option ignore_root_key '0'
        option prefetch 'yes'
        option static_domains '1'
        option dynamic_domains '1'
        option forward_custom '99_cloudflare'

config resolver 'kresd'
        option rundir '/tmp/kresd'
        option log_stderr '1'
        option log_stdout '1'
        option forks '1'
        option keep_cache '1'

P.S. Auto reverse PTR would be good as well :slight_smile:

And how should kresd know which domains are internal? (I’m curious; it’s meant positively.)

That is a good question…
Honestly I don’t know.
What script writes the contents of /tmp/resolv.conf.auto? It should definitely have the domain zone, since it adds “search domainzone” string to it:

# Interface openconnect
nameserver 172.30.1.1
nameserver 172.30.1.2
search vpn
# Interface wan
nameserver 77.37.251.33
nameserver 77.37.255.30
# Interface wan6
nameserver 2a02:2168:208:1::1
nameserver 2a02:2168:208:2::1

Probably we could enhance that script instead

I know very little about VPNs, so probably someone else can help, but I think the usual DNS setup is to send all requests through the VPN. (Assuming people want DNS-specific names to work.) That way the VPN’s DNS decides what names are special and when they get all requests anyway, it’s easiest (and fastest) to let them provide all answers as well, i.e. even those from public DNS.

Still, there are many ways of using a VPN. You may not need any special names (just route some IP ranges elsewhere), or all of them may be within a few known sub-trees which you forward to VPN and resolve the rest “normally”…

My use case is to access office resources from home. And I don’t want to forward other DNS requests to the VPN DNS server because it does not support TLS and DNSSEC. I am not sure if my use case is common or not, but currently I need to add a kresd policy to a custom configuration file, and monitor any (rare but possible) changes to the remote network configuration manually.

I assume you use OpenVPN?

OpenVPN allows you to call a script if an OpenVPN interface goes up or down. I use this to change a custom kresd config file on VPN connect/disconnect, so that kresd forwards all dns traffic to my VPN DNS Server once connected to my VPN (it disables kresd forwarding configuration set in foris using uci and then sets up forwarding using the custom kresd config file). You can alter $kresdCustomConfig to your needs (e.g. so that kresd forwards only specific domains to your VPN DNS Server, as you described in your initial post). If you specified your VPN DNS Server in your VPN client config OpenVPN will pass it as an enviornment var to the script and the script will read it and save it into its var $dnsServer.

/etc/openvpn/vpnclient.sh:

#!/bin/sh
kresdCustomConfigFile="/tmp/kresd.custom.conf"

dnsServer="${foreign_option_1##* }"
kresdCustomConfig="policy.add(policy.all(policy.FORWARD({
        '$dnsServer'
})))
"

case "${script_type}" in
        up)
                uci set resolver.common.forward_upstream=0
                uci commit
                echo "$kresdCustomConfig" > "$kresdCustomConfigFile"
        ;;
        down)
                uci set resolver.common.forward_upstream=1
                uci commit
                echo "" > "$kresdCustomConfigFile"
        ;;
esac

echo "cache.clear()" | socat - /tmp/kresd/tty/*
/etc/init.d/resolver restart &

add to your client vpn config file:

script-security 2
up /etc/openvpn/vpnclient.sh
down /etc/openvpn/vpnclient.sh

Unfortunately no, I use openconnect.

Well, my main point was to understand if it was some standard feature that was supposed to work out of the box but is broken in my case.

I think I can leave with hardcoded IP addresses in my config.

https://www.infradead.org/openconnect/vpnc-script.html

openconnect seems to have some “script-calling-feature”, too. I’m not familiar with openconnect at all but maybe you can use it to disable forwarding to Cloudflare on demand as I wrote.

Good look :slight_smile:

1 Like

It should be possible to use also https://openwrt.org/docs/guide-user/base-system/hotplug

If there’s a good way to recognize the office names, say they all end in office.ma-domena.cz, you don’t even need any script to switch – kresd will always try to forward it and it will work or it won’t.

EDIT: it can be a short-enough list of specific names that you maintain manually.