December 10, 2009

Day 10 - Solving Public Network Exposure with VPNs

This article was written by Nick Anderson.

Editor's note: I was going to make pretty diagrams as alternates to the ascii art below, but time ran out, so I wrapped them in cowsay instead. Please enjoy.

Most people are not lucky enough to deal with only private networks. Information needs to be accessible to a wide range of consumers. Whether it's working from home or accessing a website, how do you minimize exposure?

Most websites these days are backed by databases. Websites of any significant size typically have the database on a different host. Most commonly, the Application Server and Database Servers are in the same data-center (Note: I am ignoring geo-redundant scale here). How often do remote applications access a database directly? How often is remote shell access needed for management of a server? Now, how often are nefarious parties trying to shell into a publicly available servers? How can you minimize public exposure to services that do not need to be public facing but need to be accessible remotely?

A common solution is the notion of a Management Network and or Application Network. For our purposes we will combine the Management Network and Application Network into one Private Network. For this illustration we will assume a single public facing web server serving omg-estore.com that interfaces with two databases.

I've run into (and even setup in my earlier days ... shhh don't tell anyone) topologies that look like this.

 _____________________________
/                             \
|   (INTERNET)                |
|   -----------               |
|             |----(www1)     |
|             |---------(db1) |
|             |---------(db2) |
\                             /
 -----------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

www1 is the host that serves omg-estore.com, and db1 and db2 are master and slave databases. (Yes, I have ignored redundant application servers here; stop being so picky). All three machines are directly on the public network and talk to each other over the public network.

For security reasons, you probably don't want your databases accessible to the world, so how do we fix that? We can enable firewall policies: restrict remote shell access to specific ips and only allow database connections from www1. This isn't the best solution, though, as your servers are still on the public network. A firewall misconfiguration can expose your databases, so you should make security choices that are hard to accidentally break in a way that exposes you.

The first thing you should do is push the databases to a private network. This can be done with the simple addition of a dedicated nic or just bringing up a virtual interface (eth0:1) with the private subnet information. I prefer to use a dedicated nic as they can then connect to a fully private switch, and have access to a nics worth of bandwidth for database communications.

The first step:
 ___________________________________________
/                                           \
| (INTERNET)                                |
| -----------            (private net)      |
|           |----(www1)-----|               |
|                           |---------(db1) |
|                           |---------(db2) |
\                                           /
 -------------------------------------------
                               ,__,    /      
                           ____(oo)  /        
                         /(    (..)           
                        * ||--||              

This is much better: the database servers are no longer directly accessible on the internet. This change has decreased our exposed surface area by 2/3. Of course, to manage the db servers or the application server you will have to log in through the public facing application server. This makes the application server the a risk. To decrease exposure further, remote access to the public interface can be disabled.

Before disabling public remote shell access, you'll need to create a new access method. Enter the VPN. If it's not obvious at this point, your database servers should no longer have a public interface. If they do, they should be configured to only listen on the private network, or you should drop all connections on the left over public interface. The goal here is to only expose the services that need to serve public traffic.

The second step:
 ___________________________________________
/                                           \
| (INTERNET)                                |
| -----------            (private net)      |
|           |----(www1)-----|               |
|           |               |---------(db1) |
|           |               |---------(db2) |
|           |----(vpn1)-----|               |
\                                           /
 -------------------------------------------
  \
   \
       __     
      UooU\.'@@@@@@`.
      \__/(@@@@@@@@@@)
           (@@@@@@@@)
           `YY~~~~YY'
            ||    ||

This setup decreases exposure the most. Remote login is disabled on the public interfaces of www1 and vpn1. In order to log into any machines a vpn account is required on vpn1. Once on the vpn, access to the private interfaces of all machines can be gained.

This does not replace the need for continuing to follow best practices inside the private network. Database connections to the db servers should be limited to hosts that really need to connect to them. Host based firewalls can also be configured to limit source addresses of remote shell sessions.

Great! Now that all the theory is in place what software options are available to help us implement this?

First, ensure you choose a private subnet that is not in use anywhere else. Common subnets to avoid include 192.168.0.0/24, 192.168.1.0/24, 192.168.2.0/24, 172.16.0.0/16, 10.0.0.0/8. The first three being commonly used in SOHO equipment (think consumer-grade linksys/netgear home routers). Perhaps something like 192.168.30.0/24. Now that a subnet has been chosen, the VPN needs to be configured.

Luckily, some great open source tools make it pretty simple. OpenVPN is one such example. OpenVPN is an SSL-based VPN, so blocked access from a hotel or corporate firewall is unlikely (this is good for us admins that are on-call 24/7/365). Additionally, the clients are cross platform (Windows, Mac, Linux) and the setup is not difficult. In fact check out OpenVPN Access Server. OpenVPN Access Server is a package that adds a nice web interface and portal for VPN users in addition to giving you simple administration of giving you the VPN. It is free for 2 concurrent connections, if more than 2 concurrent connections are required the cost is five bucks per concurrent connection. Licenses must be purchased in packs of 10 at minimum, so a total cost to allow up to 12 concurrent connections is 50 bucks.

Putting your backend servers on a private, hidden network is an important step in reducing your public network attack surface. Since your private network is, well, private, you'll need to implement an access mechanism to permit you and others to manage the servers in the private network. Using a VPN to this access helps you secure external access to the private network.

Further reading:

7 comments :

Jeff L said...

Great article, thank you! Well written, excellent advice.

But I'm wondering why you say:

First, ensure you choose a private subnet that is not in use anywhere else. Common subnets to avoid include 192.168.0.0/24, 192.168.1.0/24, 192.168.2.0/24, 172.16.0.0/16, 10.0.0.0/8

What's the danger in using them? If they are on the private side, why does the IP range matter?

Anonymous said...

Jeff, the reason you want to avoid commonly used subnets is that if you're connecting over the vpn, then you might have the same network on both the local and remote side of the vpn, and you would be unable to connect to the servers on the remote side.

Nick Anderson said...

Jeff Mark is correct. Those are the most commonly used subnets. So if you were at home on a linksys device (defaulting to 192.168.1.x/24) and your private network has the same subnet you wont be able to connect.

Jeff L said...

Ah, makes perfect sense. Thanks.

Daniel Howard said...

You don't need the VPN if you confine access to your Operations team. I have built networks like your diagram, except the "VPN" was a bastion host that required ssh keys for login.

This approach only breaks if the users interfacing your production systems need to run elaborate GUI software or something else that can't be reasonably accommodated via SSH.

Nick Anderson said...

Daniel that is correct, there is not much you can't do with ssh. IMHO the VPN just gives your remote users a bit more flexibility. Ive used the bastion host a lot in the past as well. I did make one modification to it though. Instead of logging in to the bastion and then manually logging into servers I used netcat and proxy in ssh to provide a "seamless" login to hosts behind the bastion.

Smartass said...

You know, the reason we have assigned IP ranges is to avoid two sites using the same range. Use assigned addresses when you can.