Paranoid Penguin - Linux VPNs with OpenVPN, Part V

In talking about the value of using VPN software when using untrusted networks
like WLAN hot spots, I've described the benefits of using your home network's
Web proxy rather than surfing the Web directly through the untrusted network.
From a policy-enforcement standpoint, this allows you to enforce whatever URL
or content filtering with which your home network's proxy is configured; from an
endpoint-security standpoint, it makes phishing and man-in-the-middle attacks
harder.

On the downside, it also results in a somewhat slower Web browsing experience,
because each user's Web traffic must traverse a longer, slower path than without
the VPN tunnel in place. Also, making remote users use your corporate Web proxy
without also configuring them to use your corporate DNS servers may fail to
prevent man-in-the-middle attacks (in which DNS redirection is a common
technique), giving a false sense of security.

I return to the DNS problem shortly, but how do you use Web proxies with
OpenVPN? It's quite simple. On the Web proxy itself, you simply need to make
sure there's an Access Control List (ACL) allowing client connections from
tunnel IPs. This is a moot question if your Squid server is running on a
different box from the OpenVPN server, and the OpenVPN server is using
Network Address Translation (NAT) to “hide” all tunnel-originated packets
behind its own IP address (I discuss NAT shortly).

If, however, you are running the Web proxy on the OpenVPN server itself, you
need an ACL. For Squid, you need to add something like this to
/etc/squid/squid.conf:

The acl line defines an object named
openvpn_tunnels, representing
transactions whose source IP addresses fall between 10.31.33.1 and
10.31.33.254. The http_access line allows transactions initiating from this
IP range. As with any other change you make to this file, you need to
restart Squid for this ACL to take effect (sudo /etc/init.d/squid
restart).

Your clients will, of course, need to be configured to use your Web proxy, but
they target the same IP address regardless of whether they're connecting from
afar via OpenVPN or connecting directly to your LAN. That is, if you're already
having your users proxy all their Web traffic, no change to their Web browser
settings should be necessary for them to use the same proxy through OpenVPN.

Enforcing DNS

If you're requiring all remote users to route all their Internet traffic
through the VPN tunnel, it isn't enough to force them to use the remote
network's default gateway. You also need to force them to use the remote
network's DNS servers. Otherwise, a man-in-the-middle attack that involves DNS
spoofing on the client side of the tunnel will succeed. Once a remote user's
browser has been handed a phishing site's IP address for a given URL, it
doesn't matter whether it connects to that IP directly or through the VPN
tunnel (unless, perhaps, the phishing site's IP address is on a blacklist
enforced by your corporate Web proxy or firewall).

If your remote clients all run Windows, it's easy to enforce server-side DNS
settings. Simply add the following line to your OpenVPN server's OpenVPN
configuration file:

push "dhcp-option DNS 10.0.0.100"
push "dhcp-option DNS 10.0.0.120"

Of course, you should replace 10.0.0.100 and 10.0.0.120 with the addresses
of the DNS servers you want your clients to use.

Unfortunately, this won't work for non-Windows clients. For Linux and other
UNIX clients, you'll need to edit those client systems' /etc/resolv.conf files
either manually or dynamically. The server-side configuration parameter
foreign_option_<I>n<I> lets you pass data to tunnel-initiation scripts
(--up scripts); for example, the line foreign_option_1='dhcp-option DNS
10.0.0.100' sends the line dhcp-option DNS
10.0.0.100 to any defined “up”
scripts, which can then act on that data.

The details of how all this works are out of the scope of this article. Suffice it
to say that the OpenVPN man page describes how “up” scripts work, and the link
to the update-resolv-conf script in the Resources for this article provides a script
you can alter to rewrite /etc/resolv.conf to give precedence to your
“home”
network's DNS servers.

NAT and iptables on the OpenVPN Server

There's one more critical step necessary to allow remote users to route packets
to the Internet through their VPN tunnels. You need to set up Network Address
Translation (NAT) so that traffic entering your “home” network from VPN tunnels
appears to originate from the OpenVPN server.

This is because the networks from which remote clients connect will have
either different network IP addresses than your “home” network, in which case the odds
are your “home” network infrastructure won't have a route to the remote
clients, or they'll have the same network IP addresses, in which case it's
quite possible that different hosts on opposite ends of the VPN tunnels will
have the same host IP addresses!

Note that this problem plays out differently on “bridging” (Layer 2) VPN
tunnels than on “routing” (Layer 3) VPN tunnels. Because all my examples so far
have involved a routing VPN scenario, what I'm about to say regarding NAT applies
to routed VPN tunnels.

So, the way to sidestep the problem of foreign IP addresses on
remote clients' packets completely is simply to rewrite all packets entering the OpenVPN
server's local network with the OpenVPN server's local IP address. To do so,
add just one firewall rule, like this:

Note that as with any other time you execute the command
iptables, this is
not a persistent change. To make this rule persistent across reboots, you
need to add an equivalent line to whatever configuration file or script
controls firewalling on your OpenVPN server.

The OpenVPN man page has an entire section on firewalls (called
“FIREWALLS”)
that contains lots of good information about managing iptables firewall rules
on your OpenVPN server. Remember, any VPN server is a security device. It's a
good idea to run not just a single NAT rule, but a detailed set of filtering
rules that restrict how people can connect to the server and to what systems
your VPN clients may connect.

(Speaking of iptables, it's been a long time since I covered Linux's powerful
firewall capabilities in this column. Look for an in-depth article on writing
your own Linux firewall rules in a future column.)