Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to still use VPN DNS servers for anything that doesn't resolve via original DNS servers? #15

Open
marcosscriven opened this issue May 9, 2019 · 9 comments
Labels
fancy-split-DNS Feature requests related to splitting/masquerading DNS

Comments

@marcosscriven
Copy link

I've got split tunnelling working with:

openconnect -b vpn.myvpn.com  -s 'vpn-slice 10.0.0.0/8'

Then I can successfully ping 10.n.n.n, while also not affecting other traffic.

The only thing I can't get working though is to still be able to use remote/internal DNS server?

So that I could ping myserver.mycompany.com, without explicitly adding it to the vpn-slice args?

I did confirm I had access via:

dig @<my internal DNS> myserver.mycompany.com

And it resolved - so I installed resolvconf, and added:

nameserver <my internal DNS>
search <my company domain>

to /etc/resolvconf/resolv.conf.d/tail.

After restarting resolv.conf, I see the right thing in /etc/resolv.conf, but it still won't resolvd internal domains.

My ideal would be for the usual local domain server to be tried first, and only if that failed to try the internal one.

Any ideas how to do this please? Perhaps I need dnsmasq?

@dlenski
Copy link
Owner

dlenski commented May 11, 2019

My ideal would be for the usual local domain server to be tried first, and only if that failed to try the internal one.

Assuming "usual local domain server" means the DNS server of your main Internet-connection, and "internal one" means the VPN's DNS server… keep in mind that (a) this will leak all of your VPN-internal DNS queries to the outside internet and (b) if the VPN DNS servers alias any "public" domain names — and a lot of corporate networks do this — then it will take you to the public one rather than the one inside the VPN.

Might not matter for your use cases, but keep in mind.

Any ideas how to do this please? Perhaps I need dnsmasq?

Yeah, most likely dnsmasq is a necessary building block for a solution. See #4 (comment) for some more discussion.

Personally I have little-to-no use for such a feature. I normally only access a small and finite set of servers inside a VPN, and when I need to add another one, I use a little hostify helper script to do it manually, e.g. hostify tun0 host.i.need.to.add other.host.company.com:

#!/bin/bash

if [[ $# < 2 ]]; then {
    p="$(basename $0)"
    echo "usage:  $p [vpn_name] [domain1] ..."
    echo
    echo "This script does the following:"
    echo "  1) Looks up the named domain(s) on the DNS servers for a VPN connection created"
    echo "     with the help of vpn-slice"
    echo "  2) Adds the ones that are found to /etc/hosts"
    echo "  3) Routes traffic to those hosts via the named VPN connection"
    echo
    echo "In other words, it does what vpn-slice WOULD HAVE DONE if you'd listed these"
    echo "specific hostnames in its command line as invoked AT CONNECTION TIME."
    echo
    echo "THESE CHANGES ARE TEMPORARY and won't persist past the lifetime of the VPN connection"
    exit 1;
} >&2
fi

vpn="$1"
shift 1

#####

BLOB=$(grep -oP "\bdns\d+\.$vpn\b.+\#.+" /etc/hosts|cut -d\# -f2|tail -n1)
declare -a DNS=( $(grep -oP "\bdns\d+\.$vpn" /etc/hosts|sort|uniq) )
if [[ ! "$DNS[*]" ]]; then
    echo "ERROR: can't find dnsX.${vpn} in /etc/hosts -- is ${vpn} VPN up?" >&2
    exit 1;
fi

for hostname in "$@"; do
    ip=$(dig +short ${DNS[@]/#/@} "$hostname" | tail -n1)
    if [[ ! "$?" || -z "$ip" ]]; then
        echo "ERROR: couldn't find $hostname on $vpn DNS servers" >&2
    else
        echo "Found $hostname at IP address $ip on $vpn DNS servers" >&2
     sudo ip route add "$ip" dev "tun_${vpn}" &&
            echo "$ip $hostname $BLOB" | sudo tee -a /etc/hosts >/dev/null
        if [[ ! "$?" ]]; then
            echo "ERROR: couldn't configure $hostname properly" >&2
        fi
    fi
done

Perhaps it'd be useful for me to integrate this behavior into vpn-slice? (Even if it doesn't address your exact use case.)

@dlenski dlenski added the fancy-split-DNS Feature requests related to splitting/masquerading DNS label May 11, 2019
@dlenski dlenski changed the title How to still use remote DNS for anything that doesn't resolve locally? How to still use VPN DNS servers for anything that doesn't resolve via original DNS servers? May 11, 2019
@marcosscriven
Copy link
Author

@dlenski - thanks for the responses, and also making the requirement clearer.

I do like the idea of hostify a lot, making it simple to quickly add the entries to /etc/hosts, and as you say, leaking corporate DNS queries to the outside world is a bad idea.

@sjuxax
Copy link

sjuxax commented May 31, 2019

dnsmasq is the answer here. It's very flexible and allows all kinds of different setups for this, including directing specific domains to specific DNS upstreams. Since most corporate networks rely on a small handful of primary domains, this usually works fine, and it's simple to setup without polluting your local hosts file.

The configuration directive is something like:

server=/example.com/10.0.0.0

Then, any requests for example.com or its subdomains will be forwarded to 10.0.0.0. Setting more than one server for the same domain will use them in order, so another line with server=/example.com/8.8.4.4 will use Google DNS if the internal DNS lookup fails. Makes it fairly seamless.

Note that NXDOMAIN isn't a failure, it's an authoritative "there's nothing there". There are additional configuration parameters that can be set to make dnsmasq cascade on NXDOMAIN values. Check out the manual: http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html

@marcosscriven
Copy link
Author

Thanks @sjuxax

I think I'm convinced by @dlenski's argument that it's better to just add hosts as and when needed.

@kKdH
Copy link

kKdH commented Jul 24, 2020

Here is another solution using systemd-resolved.

@rikardev
Copy link
Contributor

@dlenski Any further plans to include hostify into vpn-slice? I think it would be a great addition.

@dlenski
Copy link
Owner

dlenski commented Mar 19, 2021

@dlenski Any further plans to include hostify into vpn-slice? I think it would be a great addition.

The code for my working bash version is above.

If you want to rewrite it in Python and include it in this package, I'll gratefully accept a PR for that :-)

@pozsa
Copy link

pozsa commented Sep 20, 2021

My ideal would be for the usual local domain server to be tried first, and only if that failed to try the internal one.

Assuming "usual local domain server" means the DNS server of your main Internet-connection, and "internal one" means the VPN's DNS server… keep in mind that (a) this will leak all of your VPN-internal DNS queries to the outside internet and (b) if the VPN DNS servers alias any "public" domain names — and a lot of corporate networks do this — then it will take you to the public one rather than the one inside the VPN.

Might not matter for your use cases, but keep in mind.

Any ideas how to do this please? Perhaps I need dnsmasq?

Yeah, most likely dnsmasq is a necessary building block for a solution. See #4 (comment) for some more discussion.

Personally I have little-to-no use for such a feature. I normally only access a small and finite set of servers inside a VPN, and when I need to add another one, I use a little hostify helper script to do it manually, e.g. hostify tun0 host.i.need.to.add other.host.company.com:

#!/bin/bash

if [[ $# < 2 ]]; then {
    p="$(basename $0)"
    echo "usage:  $p [vpn_name] [domain1] ..."
    echo
    echo "This script does the following:"
    echo "  1) Looks up the named domain(s) on the DNS servers for a VPN connection created"
    echo "     with the help of vpn-slice"
    echo "  2) Adds the ones that are found to /etc/hosts"
    echo "  3) Routes traffic to those hosts via the named VPN connection"
    echo
    echo "In other words, it does what vpn-slice WOULD HAVE DONE if you'd listed these"
    echo "specific hostnames in its command line as invoked AT CONNECTION TIME."
    echo
    echo "THESE CHANGES ARE TEMPORARY and won't persist past the lifetime of the VPN connection"
    exit 1;
} >&2
fi

vpn="$1"
shift 1

#####

BLOB=$(grep -oP "\bdns\d+\.$vpn\b.+\#.+" /etc/hosts|cut -d\# -f2|tail -n1)
declare -a DNS=( $(grep -oP "\bdns\d+\.$vpn" /etc/hosts|sort|uniq) )
if [[ ! "$DNS[*]" ]]; then
    echo "ERROR: can't find dnsX.${vpn} in /etc/hosts -- is ${vpn} VPN up?" >&2
    exit 1;
fi

for hostname in "$@"; do
    ip=$(dig +short ${DNS[@]/#/@} "$hostname" | tail -n1)
    if [[ ! "$?" || -z "$ip" ]]; then
        echo "ERROR: couldn't find $hostname on $vpn DNS servers" >&2
    else
        echo "Found $hostname at IP address $ip on $vpn DNS servers" >&2
     sudo ip route add "$ip" dev "tun_${vpn}" &&
            echo "$ip $hostname $BLOB" | sudo tee -a /etc/hosts >/dev/null
        if [[ ! "$?" ]]; then
            echo "ERROR: couldn't configure $hostname properly" >&2
        fi
    fi
done

Perhaps it'd be useful for me to integrate this behavior into vpn-slice? (Even if it doesn't address your exact use case.)

Do you use this after having a live connection? How are they cleaned up when the connection terminates?

@christopherdriscoll
Copy link

dnsmasq is the answer here. It's very flexible and allows all kinds of different setups for this, including directing specific domains to specific DNS upstreams. Since most corporate networks rely on a small handful of primary domains, this usually works fine, and it's simple to setup without polluting your local hosts file.

The configuration directive is something like:

server=/example.com/10.0.0.0

Then, any requests for example.com or its subdomains will be forwarded to 10.0.0.0. Setting more than one server for the same domain will use them in order, so another line with server=/example.com/8.8.4.4 will use Google DNS if the internal DNS lookup fails. Makes it fairly seamless.

Note that NXDOMAIN isn't a failure, it's an authoritative "there's nothing there". There are additional configuration parameters that can be set to make dnsmasq cascade on NXDOMAIN values. Check out the manual: http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html

Chiming in with a late reply to say that DNSMasq will not "move past" an NXDOMAIN response, even if there are additional DNS servers in the configuration file that do have an IP for the host. The strict-order option sort of reads like it should behave this way, but it only forces queries to servers in the order configured.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fancy-split-DNS Feature requests related to splitting/masquerading DNS
Projects
None yet
Development

No branches or pull requests

7 participants