I work at a company where some Web proxy servers are required to comply with externally-defined security standards. Specifically, these systems aren't allowed to initiate network connections from the DMZ towards the inside. Now, strictly speaking, this isn't entirely true. These systems do access systems on the inside, but only systems explicitly germane to the applications they support.
From a security perspective, this is a Good Thing. But for the administrators of these systems, it presents a bit of quandary. We need a mechanism to install security updates and other software on these boxes from time to time. According to the security specification, the hosts are allowed to initiate connections to the outside world, but that violates one of our own security practices. Namely, that we install software only from an internal mirror and only after the updates to that mirror have been tested on a staging system. (In Debian-speak, I'm not interested in setting up my APT sources.list to fetch directly from http:/security.debian.org/.)
We could always scp the packages needed, but this is cumbersome and time-consuming. It's also error-prone. So, we started thinking about how we might set up a VPN between the application server and our internal software mirror. The only requirement is that the VPN be initiated from the "inside-out" and that the connection is only active for as long as we need to use. In other words, it would only be active during an administration session.
SSH to the rescue...
Fortunately, SSH client and server come with support for this out of the box, requiring no additional software to be installed, and no configuration changes. On the server side, sshd, the setting "AllowTcpForwarding" defaults to "yes" unless your sshd_config file explicitly disables it. On the client side, all you have to do is request the forwarding.
We're using SSH for shell access, and the package installs are via HTTP. When we invoke ssh (from the inside -> out), we tell it to tunnel connections made on the remote server back to workstation initiating the SSH session, and then forward those to port 80 on our mirror server.
To do this, you invoke ssh with the "-R" with arguments like: workstation> ssh dmzserver -R 9999:mirrorserver:80
- dmzserver is the box we're administering, i.e. the box that needs access to the mirror
- 9999 is the port on dmzserver that we want to tunnel back towards our workstation
- mirrorserver is the IP address or hostname of the mirror server
- 80 is the port on mirrorserver that we want dmzserver to access
Note that this assumes that you can actually login to dmzserver and have permissions to execute a shell there. Note also the choice of port 9999; we choose a port above 1023 so that we don't have to ssh into dmzserver as root or some other privileged user. (Security, security...)
As long as the ssh session is active, any connection opened on dmzserver to port 9999 will be forwarded to workstation inside of the ssh session (i.e. between port 22 on the dmzserver and whatever client port ssh used when we invoked it on workstation). When those packets arrive at our workstation, it knows to send them on to the mirrorserver, port 80. (See Figure 1)
The real beauty of all this is that it requires no change to the firewall rules or our workstations, since SSH from the inside -> out complies with the spec and was already our primary method of managing the systems. It's also very convenient because it means that we don't have to contact the firewall admin every time we want to access the internal mirror, one of the proposed alternatives when we first faced this problem.
Note that for very large installs/updates, there is some penalty because you're not only having to ferry the update from the mirror server to the application server via your workstation, but you're having to encrypt and decrypt all of those packets as well. If your mirror is hosted on a box with shell access, you can ssh from their directly with a command like:
ssh -R 9999:localhost:80 dmzserver
This is the same as the workstation example, but cuts out the intermediary. (See Figure 2)
In both cases, we're really doing nothing more than allowing the temporary tunneling of HTTP traffic. What this means is that you can use it for an administrative tool requiring that protocol -- scripts that make use of "wget" like pkg-get on Solaris (http://www.bolthole.com/solaris/pkg-get.html) come to mind. Of course, you're free to forward another port if you'd like. The only thing you have to remember is that the dmzserver needs to be configured to connect to itself (or fetch from itself, depending on how you look at it). For those of you familiar with Debian's "apt-get," here's what we use for our /etc/apt/sources.list on those dmzserver systems:
deb http://localhost:9999/debian stable main contrib non-free
For us systems administrators, this is a no fuss, no muss solution.
This was first published in May 2004