If you don’t know where you are going, any road will take you there.
– Lewis Carroll

My production servers reside behind a perimeter firewall in a data center. A minimal set of ports are open to the world, notably port 22 for sshd and port 80 for the Apache webservers which proxy requests to one of several Tomcat instances. The Tomcat ports are blocked at the data center’s perimeter firewall which means no direct access to Tomcat’s manager interfaces. But that’s OK, there are several options for reaching the Tomcat manager from outside the data center. I’ll glance over three options and then delve into a fourth option that is the gooey center of this posting.

The following are some options for accessing Tomcat Manager interfaces that are behind a firewall. This posting focuses on reaching Tomcat but the techniques have general application in many situations where you need to reach a blocked network service.

1. I can ssh to a server with X11 forwarding

ssh -Y loquat.datacenter.org

and launch Firefox off the server. Since Firefox is running behind the perimeter firewall I have access to Tomcat’s ports on the data center’s servers (the relevant ports are open on the individual servers). This is quick and easy but exporting a heavy X11 app like Firefox over a slow network is not practical. Using a terminal web client like lynx or links is of course a lightweight option.

2. I can use an ssh SOCKS proxy to tunnel my local web browser traffic to the server:

ssh -D 1080 loquat.datacenter.org

Since my tunneled traffic effectively originates from inside the data center I have unfettered access to Tomcat. The downside is the effort it takes to configure the browser to use the proxy. Fortunately there are shortcuts for that. For Safari, I have a separate Network Location configured for proxying and I switch to it with some snappy Quicksilver keystrokes. I have not tried QuickProxy for Firefox, but there it is.

Lifehacker has a nice howto for dynamic port forwarding with ssh/socks. Their focus is on securing your browsing session, very much worth the effort just for that, but the technique is the same.

3. Most of the Tomcat manager functions can be triggered through a simple GET request from a commandline client such as wget or lwp-request. I like to use curl with the -n option which will fish the password for the manager out of my ~/.netrc file.

curl -n "http://127.0.0.1:9280/manager/reload?path=/crashingWebapp"

Tomcat’s Manager help page describes the various commands you can issue this way. This is my most commonly used method for manipulating the Manager. It’s quick, scriptable and requires no advanced preparation. Remembering the syntax can be a downside but since I use these commands frequently they’re readily retrievable from my shell’s command history.

4. Back to SSH port forwarding. Another option is to forward a local port to the server.

ssh -L 9280:localhost:9280 loquat.datacenter.org

Once the forwarding is established I can point my local browser to

http://localhost:9280/

and my browser’s traffic will be routed through an ssh tunnel to the Manager listening on port 9280.

This is a reasonably quick technique and I use port forwards for many other purposes so the syntax is pretty well ingrained in my typing fingers. Now, here’s my problem with using this strategy to manage Tomcat. I have three servers running Tomcat in the data center but I can only forward a given local port to one server. So to cover all my servers I would need to do something like:

ssh -L 9000:localhost:9280 loquat.datacenter.org
ssh -L 9001:localhost:9280 olive.datacenter.org
ssh -L 9002:localhost:9280 apricot.datacenter.org

That would allow me to access each via the urls:

However, I would have to remember which local port (9000, 9001 or 9002) is connected to which server.

There is a workaround to the limitation of using a port number more than once. If I have more than one network interface then I can use the same port number on each. A beneficial side effect for the following technique is that I can have named forwards to help me know what is connected where. The following instructions work for my Linux distribution and OpenSSH_4.3p2 (or other version with a forwarding specification of

[bind_address:]port:host:hostport]

— note the [bind_address:] attribute that is not available in some older versions of OpenSSH). root-equivalent access is required to establish new network interfaces. The technique can work on OS X with some tweaks to the syntax.

Step one is to configure additional IP addresses for multiple logical network interfaces (a.k.a IP aliasing). eth0 is my primary interface to the internet. I set up new interface aliases eth0:1, eth0:2 and eth0:3 with private IP addresses.

sudo ifconfig eth0:1 10.1.2.10 netmask 255.255.255.0

sudo ifconfig eth0:2 10.1.2.11 netmask 255.255.255.0

sudo ifconfig eth0:3 10.1.2.12 netmask 255.255.255.0

I now have one physical network card with four interfaces (counting the original eth0 primary interface).

For the mnemonic convenience, I next assign host names to the addresses in /etc/hosts

127.0.0.1 localhost
10.1.2.10 loquat.local
10.1.2.11 olive.local
10.1.2.12 apricot.local

Then I establish port forwards to each server in the data center. Note that the same local port number is used in each case but they are bound to different virtual interfaces.

ssh -N -f -L loquat.local:9280:localhost:9280 loquat.rcc.uga.edu

ssh -N -f -L olive.local:9280:localhost:9280 olive.rcc.uga.edu

ssh -N -f -L apricot.local:9280:localhost:9280 apricot.rcc.uga.edu

Now I can address the Managers on various servers by name, using the same port number.

Each of my servers runs multiple Tomcat instances; each instance has its own manager; each instance listens on a different port. I can similarly create additional port forwards to the ports for those instances as well.

With a little scripting and configuration the IP aliases and forwards can be automatically setup at boot time.

Wasn’t that fun?

Related:

SSH Port Forwarding
Host multiple SSL sites on a single network card with IP aliasing

Advertisements