Steel /stēl/ Verb: Mentally prepare (oneself) to do or face something difficult.

4Oct/120

On OpenConnect, Unbound, DNSSEC, and DNS Forwards

OpenConnect is a VPN client that is compatible with the Cisco AnyConnect VPN services.

Unbound is a "validating, recursive, and caching DNS resolver".

dnssec-trigger is a program that tries to be smart about the resolvers offered up by DHCP, to allow you a DNSSEC secured browsing experience while still being able to work in environments like hotspots where DNS is commonly hijacked.

Put them all together and you create my current problem.

The crux of the issue comes about after connecting to a VPN. In a normal configuration the VPN client will generally update the resolv.conf with the DNS server addresses given from DHCP on the VPN. This is generally a good thing, because there is often a name space that is exposed internally and not externally, and the only way to access that name space is via the companies DNS servers over the VPN.

Or to put it another way, my company has supersecretpayrollserver.company.com that is only accessible internally and via the VPN. A security conscious DNS admin (or a paranoid one, depends on your perspective) will often create DNS views, one for external traffic and one for internal traffic. When working from the internal network the above will resolve to say 10.0.0.204, but when working externally you get nothing. Why expose names you don't have to?

After OpenConenct connects to the VPN server, it executes a script called vpnc-script in order to configure all the appropriate routes and such. As well, during this process it configures DNS for you appropriately. However, if you are running dnssec-trigger, any modifications to resolv.conf will be promptly destroyed and you will probably be reverted back to "nameserver 127.0.0.1". This is problematic, you now don't have any ability to access your super secret payroll server by name.

In order to alleviate this issue, some modifications to vpnc-script are necessary. Essentially what we want is for the vpnc-script to detect that unbound is running, and based off of that instruct unbound to forward requests for your companies domain to the DNS servers supplied via the VPN.

Unfortunately, there are a lot of vpnc-scripts floating around, so to do this modification you kind of have to eyeball it. I have submitted patches to David Woodhouse at Intel for his version of the vpnc-script and for the Fedora version as well. Hopefully those will come through.

The first section you will need to modify is near the top of the vpnc-script, there are a bunch of if elif's instantiating MODIFYRESOLVCONF and RESTORERESOLVCONF with different functions, you will need to add the following before the final else:
[sourcecode language="bash"]
elif command -v unbound-control > /dev/null && unbound-control status &> /dev/null; then
MODIFYRESOLVCONF=modify_resolvconf_unbound
RESTORERESOLVCONF=restore_resolvconf_unbound
[/sourcecode]
What this does, for those who don't read BASH, is it is testing for the existence of the unbound -control program in PATH, using command. command is a bit old school, I chose it for maximum portability. If unbound-control exists, it then tests to ensure unbound is running. If both of those conditions are true (return 0) we then set the global functions to our unbound functions.

Finally, we need to define those functions, so further down in the script you will see a lot of definitions of functions modifying resolv.conf. Anywhere in there, that is not in the middle of a function definition, add the following:
[sourcecode language="bash"]
# === resolv.conf handling via unbound =========

modify_resolvconf_unbound() {
if [ -n "$CISCO_DEF_DOMAIN" ]; then
unbound-control forward_add +i ${CISCO_DEF_DOMAIN} ${INTERNAL_IP4_DNS[@]}
unbound-control flush_requestlist
unbound-control flush_zone ${CISCO_DEF_DOMAIN}
fi
}

restore_resolvconf_unbound() {
if [ -n "$CISCO_DEF_DOMAIN" ]; then
unbound-control forward_remove +i ${CISCO_DEF_DOMAIN}
unbound-control flush_requestlist
unbound-control flush_zone ${CISCO_DEF_DOMAIN}
fi
}
[/sourcecode]
Again for the non code people out there, when the modify_resolconf_unbound function is called, it ensures that "CISCO_DEF_DOMAIN" is defined, if so it then configures unbound to forward requests for anything in the domain to the the INTERNAL_IP4_DNS, or internal IPv4 DNS addresses supplied when the connection to the VPN was initiated. We then flush the cache for that domain so that any IP/NAME conflicts won't exist.

In the restore_resolvconf_unbound function we do exactly the opposite, we remove the forwards and flush the cache for that domain so the name space will be consistent and work.

Obviously these functions are called when the interface is either brought up or down.

That is about it, hopefully after some more iterations of the code (which I will try to keep this page up to date with) we can get this into the "official" script and it will just work for folks.

Now to get it all working with NetworkManager....

   
This work by Erinn Looney-Triggs is licensed under a Creative Commons Attribution-ShareAlike 3.0 United States.