📜 ⬆️ ⬇️

Several different VPN connections with local DNS servers

Where did the problem come from


Many of you use a VPN connection to a working local network from home.
Thanks to this, connecting VPN you work with a working network “as if being in it”.

What does a typical linux setup look like?
It is written into /etc/resolv.conf (using openresolv or NetworkManager)

search local.company.name nameserver 10.0.20.186 

Where local.company.name is the domain of the company, and 10.0.20.186 is the ip address of the local (on the working network) DNS server.
')
What does work look like?

 root@t510 0 ~ % ping -c 1 cdash-master PING cdash-master.local.company.name (10.0.20.237) 56(84) bytes of data. 64 bytes from 10.0.20.237: icmp_seq=1 ttl=63 time=214 ms ... 

What happened?
  1. search has added a local.company.name suffix to cdash-master
  2. DNS server in the working network converted cdash-master.local.company.name to 10.0.20.237

Everything works fine as long as you have a VPN connection ... one thing.
I wanted to connect at the same time two VPNs and prescribe two DNS - one for the working network, the other for the local network on hetzner, where my virtual machines are spinning.

It would seem, what could be easier? However, the path to the solution was long and winding.

Detailed description of the result


Work network


The local subnet is 10.0.20.0/24 (i.e. 10.0.20. * - from the subnet)
Domain - * .local.company.name
DNS server - 10.0.20.186

 ping - 1 somename 

should define somename as somename.local.company.name, and turn somename.local.company.name into an IP address via DNS 10.0.20.186

If the VPN connection is disabled, the name will not be found.

Personal server on hetzner


It's a bit smarter with him.

Local subnet - 10.10.10.0/24 (i.e. 10.10.10. * - from the subnet)
Domain - * .my.domain
Local DNS server - 10.10.10.253

The my.domain server has a white IP address and is accessible from the outside.
The server hosts nginx, which proxies requests of the form subdomain.my.domain to machines from the local subnet.

On the one hand, if the user went to the subdomain.my.domain by the browser, the registrar's DNS server will return the white IP address my.domain, the browser will send an HTTP request to this IP address, and then nginx will figure out where to proxy it.

On the other hand, when VPN is enabled, my connections are:

 ssh subdomain 

should go directly to the machine from the local subnet.
What for?

I feel so comfortable. I once set up a working machine, and transparently walk around the work network and personal network. Outside on * .my.domain, users see exactly one server (which is part-time and VPN) and do not have access to local machines. I can directly connect via ssh to both the machines from the working network and from the personal one.

“Wait,” the user will tell me.
“I will just prescribe /etc/resolv.conf”:

 search local.company.name my.domain 

"And everything will work."

Will not be. For each zone - local.company.name and my.domain, you need to register your DNS server. Through resolv.conf, openresolv this problem is not solved.

Decision


I had to torment Google and familiar admins for hours to find a solution.
My post is designed to save your time.

So, first you need to put bind. I have a working machine on Arch Linux:

 pacman -S bind systemctl enable named 

Further we configure / etc / named.conf, adds there:

 zone "local.company.name" IN { type forward; forwarders { 10.0.20.186; }; }; include "/usr/share/openvpn/named.conf.my.domain"; zone "." IN { type forward; forwarders { 8.8.8.8; 8.8.4.4; }; }; 

Configure NetworkManager or edit /etc/resolv.conf. The result in both cases should be:
root @ t510 0 / usr / share / openvpn # cat /etc/resolv.conf

 # Generated by NetworkManager search local.company.name my.domain nameserver 127.0.0.1 

In the openvpn script for my.domain add:

 up "/usr/share/openvpn/update-dns-my.domain" down "/usr/share/openvpn/update-dns-my.domain" 

Add the /usr/share/openvpn/update-dns-my.domain script that will update the bind settings and restart it after establishing the VPN connection:

 #!/bin/bash set -eu NAME=/usr/share/openvpn/named.conf.my.domain TEMPLATE=${NAME}.template function restart_bind () { /usr/bin/systemctl restart named } case $script_type in up) cat ${TEMPLATE} > ${NAME} restart_bind ;; down) cat /dev/null > ${NAME} restart_bind ;; esac 


Add /usr/share/openvpn/named.conf.my.domain.template
 zone "my.domain" IN { type forward; forwarders { 10.10.10.253; }; }; 

How it works?

When establishing a VPN connection to a personal server:
  1. openvpn runs the script /usr/share/openvpn/update-dns-my.domain
  2. the script in the /usr/share/openvpn/named.conf.my.domain file writes the contents of /usr/share/openvpn/named.conf.my.domain.template
  3. script restarts bind
  4. bind reads my.domain zone settings from the updated file.
  5. my.domain zone is now resolved by DNS server from local network (available via VPN)


When disconnecting a VPN connection
  1. openvpn runs the script /usr/share/openvpn/update-dns-my.domain
  2. the script clears the contents of /usr/share/openvpn/named.conf.my.domain
  3. script restarts bind
  4. bind reads the my.domain zone settings from the updated file (forgets about the zone)
  5. my.domain zone is now resolvable by public DNS


How does it look in practice?

 root@t510 0 /usr/share/openvpn # systemctl start named #    bind root@t510 0 /usr/share/openvpn # systemctl start openvpn@waltham #   root@t510 0 /usr/share/openvpn # systemctl start openvpn@hetzner #   root@t510 0 /usr/share/openvpn # ping -c 1 cdash-master PING cdash-master.local.company.name (10.0.20.237) 56(84) bytes of data. 64 bytes from 10.0.20.237: icmp_seq=1 ttl=63 time=214 ms ... root@t510 0 /usr/share/openvpn # ping -c 1 db PING db.my.domain (10.10.10.200) 56(84) bytes of data. 64 bytes from 10.10.10.200: icmp_seq=1 ttl=63 time=233 ms ... root@t510 0 /usr/share/openvpn # systemctl stop openvpn@hetzner root@t510 0 /usr/share/openvpn # ping -c 1 db PING db.my.domain (white-ip-address) 56(84) bytes of data. 64 bytes from my.domain (white-ip-address): icmp_seq=1 ttl=55 time=124 ms ... root@t510 0 /usr/share/openvpn # systemctl start openvpn@hetzner root@t510 0 /usr/share/openvpn # ping -c 1 db PING db.my.domain (10.10.10.200) 56(84) bytes of data. 64 bytes from 10.10.10.200: icmp_seq=1 ttl=63 time=118 ms ... 

It's funny that to get such a simple behavior, you had to do so much work.

Source: https://habr.com/ru/post/182924/


All Articles