SSH Tunneling across multiple hosts in Linux

Sometimes you need to communicate with a server (or other device) that is not directly accessible from your own computer. If you can reach this server via another server this is not an issue and can be solved by setting up a SSH Tunnel across your network.

An example

Let’s start with a example:

  • Computer A is where you are working.
  • Server A is accessible by computer A.
  • Server B has a administration web interface but its IP Address is completely shielded by a firewall; except for Server A.

Thus the only way to reach the web interface on Server B from Computer A would be through Server A.

The solution

You can solve this by setting up an SSH Tunnel which spans several server; the command for this is:

ssh -t -t -L[LOCAL_PORT]:localhost:[PORT_ON_A] [USER]@[SERVER_A] 'ssh -L[PORT_ON_A]:localhost:[PORT_ON_B] [USER]@[SERVER_B]'

Basically you are chaining a specific IP port to guide traffic from and to your PC.

The variables shown here represent:

  • LOCAL_PORT, the port on you local PC where you want to connect to in order to communicate with SERVER_B
  • PORT_ON_A, the port on SERVER_A which is used to transfer your data across to SERVER_B (may be any port number but make sure it does not collide with other tunnels / uses)
  • USER, your account name / login name on SERVER_A and/or SERVER_B
  • SERVER_A, the hostname or IP address of your first jump point
  • PORT_ON_B, the destination port to which you want to connect; in our example we wanted to connect to a web interface (port 80) thus we use the value 80 here
  • SERVER_B, the hostname or IP address of your intended destination

You might notice the use of a double -t argument in our command; this is not an error but is actually required in order to create the connection (without it your system might complain that it is unable to acquire a TTY; explaining the details of this would go beyond this blog posting)

Our example command

To complete this exercise I will show you the full command with which we could satisfy the requirement in our opening example:

ssh -t -t -L8081:localhost:10000 [email protected] 'ssh -L10000:localhost:80 [email protected]'

See that we used port 8081 as local port? We did that to prevent collisions with services on our local machine. Were you to use (for example) port 80 it might produce unwanted results such as your local apache (if you have one) being unreachable.

Now all we need to do to visit the website on Server B would be to enter the following URL in your browser:

http://localhost:8081

That’s all there is to it. If anything is not clear, just leave a comment.

4 thoughts on “SSH Tunneling across multiple hosts in Linux

  1. Accidentily, I learned about this while getting worked in a couple days ago. But I learned a few other tricks as well:

    add -f, which means that ssh goes into the background after connecting, so you don’t have to leave your terminal window open

    In your example, you tunnel twice for a single host, to get back to port 80. Instead, you can use -D and no tunnel, which will create a SOCKS proxy. Execute the command, configure the proxy in your browser, and you can reach any host that is reachable by Server A. If you need to SSH forward to server B, or anything else that can’t use a SOCKS proxy, then you can suffice with a single tunnel (since you don’t need to go back to the specific port).

    ~RW

  2. The is a disadvantage in this approach. You are setting up two tunnels. One from local to A and one from A to B. That means that you would need an (Open)SSH deamon on your server B.

    However in your situation you say that server B is accessible from Server A meaning that you actually don’t need the second tunnel right? Wouldn’t it be easier to just tunnel a non-localhost connection through server A? Something like this would probably work.

    ssh -t -t -L8081:b.server.example.com:80 [email protected]

  3. This helped. Thanks a lot for the clear post on SSH Tunneling

  4. hey,thanks for your post,i have a problem,when i try to tunnel,i after connecting to second server.i try to reach a website,and in terminal i get “channel 3: open failed: connect failed: Connection refused”

    i am trying to tunnel through main server of our department(university) to tunnel through a linux pc.
    it’s obvious that i don’t have root privilages on any of these systems.:D
    can you help me please?:)

Comments are closed.