Resolve names on OpenVPN server side?

6,895

Solution 1

I'm not sure if that "push" is necessary, as I don't use DHCP client-side.

OpenVPN already receives its IP address and other configuration from the server, so it understands certain "DHCP options" itself even if they're not technically sent via DHCP.

I presume I must set up my (VPN) server to also be a DNS server in order for that to work. But is that necessary?

Yes, it is. (Specifically you need a resolver – Unbound, dnsmasq, Bind9 will work, but NSD will not as it's authoritative-only.)

Why can't the VPN server handle forwarded DNS queries via it's resolv.conf (without being a DNS server, just as it handles everything else without being an everything else server)?

That's not even close to the same thing – the VPN server doesn't handle "everything else", it merely forwards the IP packets.

For example, if a client connects to Google, or uses 8.8.8.8 as your DNS server, the VPN server only sees that it's an IPv4 packet for someone else's IP address. So the VPN server doesn't try to understand the packet's contents – just sends it towards the next router, and so on, until the packet eventually reaches the real destination.

But if you want the VPN server to honor its resolv.conf, then it must understand how it's related to the packets it receives, and what replies should be generated – and it needs two things for that:

  • For a start, your clients must use the VPN server's own address as their "DNS server", so that the server would see itself as the packets' final destination and actually interpret their contents (as UDP) rather than forwarding them somewhere else.

    (That means "Client-side resolv.conf (manually set, never changes)" is a problem. If you push the dns-server option, the OpenVPN client will understand it and it should try to update the client's resolv.conf, but that depends on the system.)

  • Now the VPN server is receiving packets to UDP port 53, but it still doesn't automagically understand what data they contain. Just like you need a web server to understand HTTP requests, you also need a DNS server to understand DNS requests and to properly reply to them.


Technically, you can get around the 1st requirement by using iptables on the VPN server to redirect all UDP/53 packets to itself – I think that's called "transparent proxy" or -j REDIRECT in various tutorials.

But I suggest only doing that once you have a good grasp on the distinction between your server forwarding packets and handling them itself. Otherwise it would only add to the confusion.

Solution 2

You need to use a suitable shell script to interface the options passed to you by OpenVPN (the two push dhcp-options..., which are perfectly fine) with the resolv.conf file via the resolvconf package, which you should have installed by default.

I have, in /etc/openvpn on the client, a file (not my work!) called /etc/openvpn/update-resolv-conf, which is invoked in the client's configuration file as follows:

 script-security 2
 up /etc/openvpn/update-resolv-conf
 down /etc/openvpn/update-resolv-conf

I am sure the shell script is widely available online, but should you be unable to locate it, here it goes:

#!/bin/bash
# 
# Parses DHCP options from openvpn to update resolv.conf
# To use set as 'up' and 'down' script in your openvpn *.conf:
# up /etc/openvpn/update-resolv-conf
# down /etc/openvpn/update-resolv-conf
#
# Used snippets of resolvconf script by Thomas Hood and Chris Hanson.
# Licensed under the GNU GPL.  See /usr/share/common-licenses/GPL. 
# 
# Example envs set from openvpn:
#
#     foreign_option_1='dhcp-option DNS 193.43.27.132'
#     foreign_option_2='dhcp-option DNS 193.43.27.133'
#     foreign_option_3='dhcp-option DOMAIN be.bnc.ch'
#

[ -x /sbin/resolvconf ] || exit 0
[ "$script_type" ] || exit 0
[ "$dev" ] || exit 0

split_into_parts()
{
    part1="$1"
    part2="$2"
    part3="$3"
}

case "$script_type" in
   up)
        NMSRVRS=""
        SRCHS=""
        for optionvarname in ${!foreign_option_*} ; do
            option="${!optionvarname}"
            echo "$option"
            split_into_parts $option
            if [ "$part1" = "dhcp-option" ] ; then
                if [ "$part2" = "DNS" ] ; then
                    NMSRVRS="${NMSRVRS:+$NMSRVRS }$part3"
                elif [ "$part2" = "DOMAIN" ] ; then
                    SRCHS="${SRCHS:+$SRCHS }$part3"
                fi
            fi
        done
        R=""
        [ "$SRCHS" ] && R="search $SRCHS
"
        for NS in $NMSRVRS ; do
              R="${R}nameserver $NS
"
        done
        echo -n "$R" | /sbin/resolvconf -a "${dev}.openvpn"
  ;;
  down)
  /sbin/resolvconf -d "${dev}.openvpn"
  ;;
esac
Share:
6,895

Related videos on Youtube

Alex
Author by

Alex

Updated on September 18, 2022

Comments

  • Alex
    Alex over 1 year

    I installed OpenVPN on my server via this auto install script and copied the generated config file to my client, also running OpenVPN. I want to route all client traffic through the VPN, and I want the names to be resolved server-side. All traffic seems to be routed successfully, but the names are resolved by whatever DNS server I specify in the client's resolv.conf. How can I make it so they are resolved server-side? Relevant server-side configuration:

    root@marius:~# cat /etc/openvpn/server.conf | grep dhcp
    push "redirect-gateway def1 bypass-dhcp"
    push "dhcp-option DNS 8.8.8.8"
    push "dhcp-option DNS 8.8.4.4"
    

    I'm not familiar with VPN servers, I'm not sure if that "push" is necessary, as I don't use DHCP client-side. Client-side resolv.conf (manually set, never changes):

    domain domain.name
    search domain.name
    # Local cache (dnsmasq)
    nameserver 127.0.0.1
    # VPN (doesn't work)
    #nameserver 10.8.0.1
    # ISP (doesn't work with VPN)
    #nameserver 200.175.89.139
    #nameserver 200.175.5.139
    # Google (works with VPN)
    nameserver 8.8.8.8
    nameserver 8.8.4.4
    

    According to OpenVPN's official HOWTO:

    When redirect-gateway is used, OpenVPN clients will route DNS queries through the VPN, and the VPN server will need handle them. This can be accomplished by pushing a DNS server address to connecting clients which will replace their normal DNS server settings during the time that the VPN is active. For example:

    push "dhcp-option DNS 10.8.0.1"
    

    will configure Windows clients (or non-Windows clients with some extra server-side scripting) to use 10.8.0.1 as their DNS server. Any address which is reachable from clients may be used as the DNS server address.

    But that doesn't seem to work, as aforementioned. I presume I must set up my (VPN) server to also be a DNS server in order for that to work. But is that necessary? Why can't the VPN server handle forwarded DNS queries via it's resolv.conf (without being a DNS server, just as it handles everything else without being an everything else server)? I'm a bit lost here.

    I can provide any additional configuration files if necessary.

  • Alex
    Alex over 8 years
    I see. I don't need to use the server's resolv.conf, although I mentioned that on the OP. Since I have control to both the client's and the server's resolv.conf, either one is fine, as long as the DNS query leaves to the DNS server from my VPN. I.e. I'm okay with the VPN just forwarding the queries. Now, as a final question, why do DNS queries require special treatment? I mean, there is no interpretation required from the VPN, shouldn't the queries be forwarded along with everything else when I set up my client's resolv.conf to some DNS server's address (not my VPN's address)?
  • user1686
    user1686 over 8 years
    They don't – see your own quote, "Any address which is reachable from clients may be used as the DNS server address." It is merely common to use the VPN server as a local cache.
  • Alex
    Alex over 8 years
    Oh, I see now. I was confusing things. I thought the names ware being locally resolved because it failed with my ISP's DNS servers, and when I changes the client's resolv.conf to Google's it worked. In fact the queries were being forwarded to the VPN just as intended, but my ISP only accepts queries from its clients (which the VPN is not). I should have checked that with Wireshark sooner. Thanks, I might actually use the VPN as a local cache with dnsmasq, though it seems to work fine the cache being in the client (also with dnsmasq).