SSH and port forwarding are two different
concepts. But SSH as a 'side effect' can implement port forwarding
in such a way so that if you are able to open SSH connection to remote
machine the you have an ability to do port forwarding also. The term 'side
effect' is important here, which means port forwarding done by SSH will remain
active only till SSH connection remain active. This is valid for SSH1 and
openSSH. SSH2 behaves differently though.
[bramha] ------ ssh connection ------->[vishnu]
Let's start with example:
Example 1:
----------------------------------------
brahma% ssh -L 3456:hostname:80
[vishnu]
----------------------------------------
Which says a user on machine [brahma] is opening SSH connection, thus getting shell on host [vishnu]. As a side effect user is also setting up a port forwarding from local port 3456 on machine [brahma] , passing through SSH channel between [brahma] and [vishnu] and forwarding to port 80 on another machine <hostname>(w.r.t vishnu) .
Now we see various options for <hostname> and their significance. Let us define effective TCP connection by tuple (client,client_port,server,server_port). Assuming SSH channel between client and server additionally.
However option 3. may be pretty useful if we use it little differently
and consider another example.
[rahu] [ketu]
| |
| |
| |
| |
[brahma]--------------- ssh connection --------------[vishnu]
Example 2:
---------------------------------
brahma% ssh -L 3456:ketu:80 vishnu
---------------------------------
This is interesting. Now a user on [brahma] can effectively connect on ketu at port 80. (brahma,3456,ketu,80). In openSSH by default SSH port forwarding won't allow listening on port forwarded port(3456) other than from localhost(127.0.0.1). i.e after above ssh connection only user on brahma can connect to ketu using port forward connection. Openssh has an option -g, which will allow other interface to listen for port forwarding request also. So if we open ssh channel using -g option :
Example 3:
----------------------------------
brahma% ssh -g -L 3456:ketu:80 vishnu
----------------------------------
that will allow machine [rahu] to use port forwarding between [brahma]
and [vishnu]. Which means when [rahu] opens up real connection as (rahu,6789,brahma,3456),
the effective connection would be (rahu,6789,ketu,80).
Let's see some other interesting examples:
Example 4:
---------------------------------------------------
localuser@brahma% ssh -L 3456:localhost:80
remoteuser@vishnu
--------------------------------------------------
In case you are using different user account on remote machine vishnu.Example 5:
This will use compression (-C) good for slow links such as dial-up, ssh connection will go in background (-f) and ssh won't open Shell (-N) on remote machine [vishnu]. This is useful when you need only port forwarding. But this is good only for one connection over port forwarding. Because after one connection through port forward base ssh connection will die and so the port forwarding. You can verify this by using command ' netstat -an | grep 3456' and 'ps -ef | grep ssh' output. SSH2 behaves different than openSSH in this case.
Example 6:
-------------------------------------------------------
brahma% ssh -C -f -L 3456:localhost:80 remoteuser@vishnu
sleep 300
-------------------------------------------------------
This will remedy above situation. Since base ssh connection will remain active for 300 seconds (wait till sleep command finish), thus port forward will also remain up during this period. Note: we are not using -N option as we need remote shell here to execute command 'sleep 300'. One such use of this option is to check your mails from your POP server using SSH tunnel. Since POP is sort of stateless (i.e every POP query disconnects, just like HTTP request after it completes it job. Example when you click on "Get Mail" in your POP client it opens TCP connection to POP server, download all new mails and close TCP connection. Next time you click on "Get Mail" it opens new TCP connection. So obviously we need port forwarding to be up for more than 1 connection.Let's see some more tricks:
Example 7:
----------------------------------------------------------
brahma% ssh -L 3456:localhost:7777 vishnu
(After you login on vishnu)
vishnu% ssh -L 7777:localhost:80
ketu
-----------------------------------------------------------
This is effectively same as Example 3. But using two different commands. May be useful when you have some port forwarding restrictions applied.
Example 8:
---------------------------------------------------------
brahma% ssh -R 7777:localhost:80 vishnu
---------------------------------------------------------
This is using -R (remote port forwarding). i.e it will allow to listen on port 7777 on remote host [vishnu] and forward in reverse direction at port 80 on brahma. i.e in this case any user on machine vishnu can open effective connection as (vishnu,7777,brahma,80).Example 9:
This is pretty interesting. This will open SSH connection between [brahma] and [vishnu] with compression. But it is setting up port forwarding with effective connection as (vishnu,7777,ketu,80). So there is no port forwarding set on brahma at all here.In all above examples we are saying effective connection such as (brahma,3456,vishnu,80). However if you analyze, real connection will flow like this.
brahma% telnet localhost 3456
Trying 127.0.0.1...
Connected to brahma.
Escape character is '^]'.
tcpdump output for this connection: (Only few packets are shown)
1. On loopback interface of [brahma]:
----------------------------------------------------------------------------
23:33:46.483207 lo > brahma.33458 > brahma.3456
: S 2295119957:2295119957(0) win 32767 <mss 16396,sackOK,timestamp 4050242
0,nop,wscale 0> (DF)
23:33:46.483260 lo > brahma.3456 > brahma.33458: S 2298189676:2298189676(0) ack 2295119958 win 32767 <mss 16396,sackOK,timestamp 4050242 4050242,nop,wscale 0> (DF)
23:33:46.483291 lo > brahma.33458 > brahma.3456:
. 1:1(0) ack 1 win 32767 <nop,nop,timestamp 4050242 4050242> (DF)
------------------------------------------------------------------------------
2A . On eth0 interface of [brahma]. This is real SSH
connection (tunnel for port forward)
----------------------------------------------------------------------------
23:32:08.615695 > brahma.33450 > vishnu.ssh: P 1891177335:1891177431(96)
ack 1925674155 win 10880 <nop,nop,timestamp 4040455 47624214> (DF)
[tos 0x10]
23:32:08.779753 < vishnu.ssh > brahma.33450: . 1:1(0)
ack 96 win 9480 <nop,nop,timestamp 47627035 4040455> (DF) [tos 0x10]
-----------------------------------------------------------------------------
2B. On eth0 interface of [vishnu]
-----------------------------------------------------------------------------
23:43:44.892766 eth0 < brahma.33450 > vishnu.ssh: P
1891183623:1891183719(96) ack 1925698715 win 18368 <nop,nop,timestamp
4109898 47687268> (DF) [tos 0x10]
23:43:44.892851 eth0 > vishnu.ssh > brahma.33450: .
1:1(0) ack 96 win 9480 <nop,nop,timestamp 47696480 4109898> (DF) [tos
0x10]
-----------------------------------------------------------------------------
3. on loopback interface of [vishnu]
---------------------------------------------------------------------------
23:42:12.546486 lo > localhost.33513 > localhost.
http: S 2836683535:2836683535(0) win 32767 <mss 16396,sackOK,timestamp
23:42:12.546513 lo > localhost.http > localhost.33513:
R 0:0(0) ack 2836683536 win 0 (DF)
---------------------------------------------------------------------------
So in above connection actually there were 3 real TCP connections participating.
If you have read so far, then you understood that port forwarding is a very
nice feature on SSH. This will allow users to manage their secure/encrypted
tunnel themselves. There are other ways of port forwarding also such as
using iptables, xinetd, stunnel etc. One limitation here is you need to have
SSHD running on remote machine and user must have login/shell access to SSHD
server. But this is better for security reasons also. You can control ACL
and authentication based on SSH service.
Port forwarding where gives convenience to users. A bad internal user can misuse this feature and may deceive your Firewall rules by setting up port forwarding on his home machine using ssh (or other port forwarding technique) in such a way that third outsider user can access your corporate resources through port forward channel.
[1] Openssh : http://www.openssh.com
[2] SSH: The Secure Shell, O'Reilly Book by Danie J. Barret & Richard
E. Silverman.
[3] man page of ssh.