with SSH. As a de facto standard of remote access, it can be used as
a replacement to telnet, ftp, rcp, and rlogin. Additionally, it can
be used to provide a secure channel for other needs such encrypting
arbitrary IP services between two hosts or tunnelling IP services
through an intermediary host. The following details how to use local
port forwarding to access web services on a remote network that are
otherwise unavailable from the outside world. Our setup details:
PROMPT: troy@server [0] LOCALBOX: homebox (home workstation) INTERMEDIARY: jumphost (internet accessible) REMOTE HOSTS: mgmtserv (10.18.3.138, corporate accessible only) monserv (10.5.76.28, corporate accessible only) NOTES: OpenSSH is used in the examples on both the localbox and intermediary, though SUNWssh would also work (presumably SSH from SSH.com would work as well, but I haven't tested it)So I'm working from home and I need to access a management web host
and a monitoring web host at work. The problem is that both of these
hosts serve up pages only accessible to internal networks at work.
Thankfully, I can use SSH to tunnel connections I make to local ports on
my workstation (homebox) to the ports that the remote internal servers
are listening on (see note 1). Knowing in advance that I need to connect
to two remote hosts, I can use:
troy@homebox [0] ssh -l troy jumphost -L8080:10.18.3.138:80 -L8081:10.5.76.28:80 troy@jumphost's password: Last login: Tue Dec 28 01:04:01 2010 from homebox troy@jumphost [0]At this point, I can simply open a web browser to access either of the
internal web sites by connecting to ports bound to localhost on homebox:
http://localhost:8080 |-> mgmtserv http://localhost:8081 |-> monservLet's say instead that I tunnelled connectivity to 'mgmtserv' through
'jumphost' and after the session was open, I remembered that I needed
to connect to 'monserv' as well. Instead of opening a new SSH session
through the intermediary host (jumphost), I can add a new port forwarded
session to the existing active SSH session (note 2):
troy@homebox [0] ssh -l troy jumphost -L8080:mgmtserv:80 troy@jumphost's password: Last login: Thu Dec 9 13:22:57 2010 from homebox troy@jumphost [0] ~C ssh> -L8081:monserv:80 Forwarding port. troy@jumphost [0]After logging in to 'jumphost' above, the first command shows '~C', which
opens a command line session to be interpreted by SSH and not the shell
(note 3). Following the 'ssh>' prompt, we can add both local and remote
port forwardings. For our needs, we are adding a locally forwarded port.
After this is done, if you would like to see a listing of your forwarded
connections, use '~#':
troy@jumphost [0] ~# The following connections are open: #4 client-session (t4 r0 i0/0 o0/0 fd 8/9 cfd -1)The above shows the current ssh, though before connecting to any locally
forwarded ports on 'homebox'. The example below shows the same, though
also the connection to 'mgmtserv' after connecting to localhost:8080 on
'homebox':
troy@jumphost [0] ~# The following connections are open: #4 client-session (t4 r0 i0/0 o0/0 fd 8/9 cfd -1) #7 direct-tcpip: listening port 8080 for 10.18.3.138 port 80, connect from 127.0.0.1 port 52500 (t4 r3 i0/0 o3/0 fd 13/13 cfd -1)While I suggested earlier using a web browser to connect to either of
the remote hosts, SSH can tunnel arbitrary services, not just HTTP.
This means that you are not required to use a web browser to access
those services. In the following, I simply use telnet to connect to
to the locally forwarded ports on 'homebox' which connect to the
remote services (note 4):
mgmtserv: troy@homebox [0] telnet 0 8080 Trying 0.0.0.0... Connected to 0. Escape character is '^]'. GET / HTTP/1.1 HOST: mgmtserv HTTP/1.1 200 OK Date: Tue, 28 Dec 2010 07:34:51 GMT Server: Apache/2.2.6 (FreeBSD) mod_ssl/2.2.6 OpenSSL/0.9.7e-p1 DAV/2 PHP/5.2.4 with Suhosin-Patch X-Powered-By: PHP/5.2.4 Set-Cookie: PHPSESSID=c2b347fbc78ea76b8d989231fc8ba49c; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 3090 Content-Type: text/html <snip...> monserv: troy@homebox [0] telnet 0 8081 Trying 0.0.0.0... Connected to 0. Escape character is '^]'. GET / HTTP/1.1 HOST: monserv HTTP/1.1 200 OK Date: Tue, 28 Dec 2010 07:35:49 GMT Server: Apache/2.2.3 (Red Hat) X-Powered-By: PHP/5.1.6 Expires: Thu, 19 Nov 1981 08:52:00 GMT Last-Modified: Tue, 28 Dec 2010 07:35:54 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache P3P: CP="CAO PSA OUR" Set-Cookie: Cacti=m24387bvvna78238g4l5ar8md2; path=/ Content-Length: 1189 Connection: close Content-Type: text/html; charset=UTF-8 <snip...>In the above, I've asked the remote web servers for the root page and
told it which host I want the page for (in case the server uses name
based hosting):
GET / HTTP/1.1 HOST: mgmtservOther commands to the web server could have been used but this will
suffice for example purposes. After I've finished working, closed out
the connections to the local ports on 'homebox' and ended the ssh session
through 'jumphost', again using telnet, I get back the following showing
the local ports are now closed:
troy@homebox [0] telnet 0 8080 Trying 0.0.0.0... telnet: connect to address 0.0.0.0: Connection refused troy@homebox [1] telnet 0 8081 Trying 0.0.0.0... telnet: connect to address 0.0.0.0: Connection refused troy@homebox [1]
NOTES
Note 1: To use port forwarding via SSH, 'AllowTcpForwarding' on the
intermediary host must be enabled (set to "yes"; see sshd_config).
Also, make sure to use local ports that either aren't blocked by a
local firewall or modify your local firewall to allow connectivity
to the local ports. The local ports will listen on localhost
(127.0.0.1), which is also where you will be connecting from.
Note 2: In the second port forwarding example, host names are used
instead of IP addresses. This is perfectly acceptable as long as
the intermediary host can resolve those host names to an IP address.
If it cannot, IP addresses must be used.
Note 3: You will likely not see '~C' appear on screen since it is caught
by SSH as an escape sequence to allow you to add the additional port
forwardings. It is displayed here simply for reference. The example
showing open sessions with '~#' will behave in the same manner.
Also, SSH escape sequences must always be followed by a newline to
be interpreted by SSH.
Note 4: Somewhat unrelated, using telnet as listed can be a useful means
of troubleshooting HTTP services. You could use telnet to
troubleshoot other services in this manner as well.