Open jfly opened 10 months ago
Really cool you're looking into this! I've been playing a bit with it, and I don't consider the systemd-resolved implementation complete at the moment.
First of all, yes the update-systemd-resolved
script to be used via the OpenVPN 2.x script-hooks. This can't work with OpenVPN 3 Linux without some wrappers triggering this script on D-Bus signals.
When you import the configuration (openvpn3 config-import --persistent
), you can easily set the DNS scope to tunnel
. That should set the default-route
flag to false
, as the systemd document talks about.
What currently does not happen, is the ~
prefixing. And I've long wondered if that is really needed or not. It seems to work without, but I may have misunderstood the details here. It would be cool if you can experiment a little bit here; if you find that this ~
prefix is important or not - and what it changes.
There are several things to beware of. OpenVPN 3 Linux considers DNS settings for all running VPN sessions it manages. It isn't just a single VPN tunnel being set. So all DNS settings from the VPN client process goes through the DNS::SettingsManager
in the Network Configuration service. When one of the tunnels requires some DNS changes, all the collected information (kept in DNS::ResolveSettings
objects; one per VPN session) are being traversed (in DNS::SettingsManager::Apply()
). Up until this point, the information is "backend agnostic". The information collected here does not know or know about anything about the DNS resolver backend being used.
When the systemd-resolved
backend is used, the DNS::SystemdResolved::Apply()
method receives all the information collected above and queues it, extracting the needed information for the systemd-resolved
service. The information it collects here is the information for all the VPN sessions. And that is being "activated" once the SystemdResolved::Commit()
method is called (from SettingsManager::ApplySettings()
, line 70).
The reason is that all changes needs to be queued up once again in the DNS::SystemdResolved
implementation is that all the information need to be per-device. The SystemdResolved::updateQueueEntry
struct keeps the DNS resolver settings and a link to the systemd-resolved interface the change is going to bound to. And the final SystemdResolved::Commit()
just calls the relevant D-Bus methods for the relevant VPN interfaces with the needed details.
That's generally how these pieces belongs together.
Oh, one more important detail. The VPN server must push some information to the client, with DNS information. The needed info is either dhcp-option DNS $IP_ADDRESS
+ dhcp-option DOMAIN corp.domain.example.org
... or it can facilitate the new dns
option available from OpenVPN 3 Linux v20 and OpenVPN 2.6. The --dns
option is documented in the 2.6 man page
The reason for the new --dns
option is purely that there many dhcp-option
implementations for DNS settings - where they may behave very differently across platforms and implementations. That was mostly due to poor documentation - or lack of details. The new option tries to resolve that. IIRC, a server can push both, and then the --dns
options should take precedence.
@dsommers, thank you for the detailed response! Sorry for the long delay here, I finally found some time today to try this out. After a couple of time consuming distractions*, I was able to get this to work by following the instructions you wrote up (config-import ...
, config-manage ... --dns-scope tunnel
).
When you import the configuration (
openvpn3 config-import --persistent
), you can easily set the DNS scope totunnel
Is there some way of setting this DNS scope without having to import and override my configuration? Can I configure my openvpn server in a way such that it will set some client option that will change the DNS scope from global to tunnel?
What currently does not happen, is the ~ prefixing. And I've long wondered if that is really needed or not.
Not having the ~ prefixing seems to work fine for me (I'll report back if it causes any issues). https://systemd.io/RESOLVED-VPNS/ just says that "in many cases the qualifying of single-label names is not desirable (since security-sensitive)". I'm not really sure what the security implications are here.
*Notes about the distractions:
dns-scope
seems to have only just come out with v21 of openvpn3-linux. At least, I couldn't get it to do anything for me with v20. I think https://github.com/OpenVPN/openvpn3-linux/commit/e720b79bcca600a529fbc962aa919b95bb3886a3 is the relevant commit that adds support for this, and it landed in v21.dhcp-option DNS $IP_ADDRESS
+ dhcp-option DOMAIN corp.domain.example.org
or with the new --dns
option) to get used by openvpn3-linux v21. Switching back to openvpn3-linux v20 without any other changes would cause the search domains to work (but would break my ability to tweak the dns-scope, see previous comment). After a lot of debugging, I eventually traced it to this line of code in OpenVPN/openvpn3 (we appear to only call tun_builder_add_search_domain
if dns_options.servers
is empty, which is not the case for me). I then rebuilt using OpenVPN/openvpn3 release/3.8.3 with that commit reverted, and things (finally) work. It looks like this logic was recently changed in https://github.com/OpenVPN/openvpn3/commit/6f538ca0fd84fd0454a3de06786d6c68968ab0cf, which seems pretty suspicious to me.
@dsommers, any advice for me here? Thanks!
Hey, @jfly! Sorry, this fell through my cracks.
So the DNS setup, as you're experiencing, is a trick thing to configure. And to be honest, I don't think we're done getting things right. And yes, the commit you found for v21 - that's a fix we realised was needed. Configuring DNS turns out to be chasing a moving target, as there are subtle differences in systemd-resolved
versions (and how distributions have configured it) and the cross-platform behaviour is even worse in consistent behaviour with the --dhcp-options
; that's why we decided to start clean with the new --dns
option - to work towards a consistent behaviour across all platforms. But there might still be some cross-Linux-distro challenges which we can't solve yet (that ties into how /etc/nsswitch.conf
is configured).
I'm pulling in @d12fk into this discussion now, as he has done the work for the new --dns
option in the Core library. He have better insight in what the Core should, shoudn't or doesn't do. We're having some issues on the Windows side as well, hence the commit you spotted there.
One important difference between v20 and v21; the former ships with Core 3.7.2 while v21 ships with Core 3.8.2. I vaguely remember that we had some DNS fixes in the Core 3.8, but forgot what that was about.
In regards to setting dns-scope
. Currently, the openvpn3 config-import
approach is the only way. We have discussed internally possibilities to push or have some of these behaviours defined as options in configuration files. Ideally the Core library should "detect" this through the --dns
options being used and how they are set up. The openvpn3 config-import
approach is more or less a Linux hack to get started testing out split-DNS.
These days I'm deep into GH issue 171 (glib2-2.76 compatibility issues) and doing a massive overhaul of the D-Bus implementation (this will be a v22_dev release); that will take most of my focus. The needed changes to improve DNS will most likely be slated for a v23+ release - unless this DNS issue is so critical it need to be put into a v21 hotfix. But split DNS is something being requested more and more these days, and our Access Server and Cloud Connexa service are both setting the stage to enable this possibility. Your interest, testing and help on this topic will help us get find a better solution; we're grateful for that!
Thanks again for the detailed response!
unless this DNS issue is so critical it need to be put into a v21 hotfix
Not sure if you were asking me, but this is not a critical issue for me. This has just turned into a side project where I want to see if it's possible to get my corp DNS playing alongside nicely with my home DNS.
But split DNS is something being requested more and more these days, and our Access Server and Cloud Connexa service are both setting the stage to enable this possibility. Your interest, testing and help on this topic will help us get find a better solution; we're grateful for that!
Awesome! If it's useful to know, my company is a customer (we use Access Server), and I'd love to get this configured correctly internally once all the knobs are in place (where the server can push the split DNS to the client).
Let me know if there's anything I can do in terms of testing out changes.
I'm quite new to all of this. Some context:
I believe
SystemdResolved::Apply
is the relevant code, and it doesn't look like it has support for "Routing domains".I see support for this over on
jonathanio/update-systemd-resolved
, but I believe that's a tool specific for openvpn2.