SSH is an excellent piece of software which can help you do a lot of things such as have encrypted shells etc. But what makes SSH incredibly flexible is having tunnels.

A typical ssh tunnel works from the client to the ssh server and it forwards a local port on the client to the server seamlessly.

client ----> ssh_conn ----> ssh_server
client --> tunneled_port --> ssh_server
ssh -L 10000:localhost:10000 username@ssh_server

This connection creates a tunneled port on client:10000 i.e., anything sent to this port appears as if it’s automatically sent to ssh_server on port 10000. The localhost here is confusing, but think of it as….”what is localhost for ssh_server?”. It would be the ssh_server itself, right?
If you do a netstat on the client, you see a listener on the port 10000/tcp.

Now comes the more interesting reverse tunnel. The reverse tunnel is different in that, you have a tunnel being initiated by the client that says to the ssh server, “Hey, I’m initiating this connection that will allow you to automatically access a port on *me* after *I* initiate the connection?” (confused!!?!)

client ---> ssh_connection ---> server  ---+
                                           |
client <-- tunneled_port  <----- server ---+
ssh -NR 10000:localhost:10000 user@ssh_server

Here the meaning of localhost is slightly different, though.  The “localhost” means what is localhost for the client (and not on the server as in the previous case)!   So what you’re saying is, “Hey SSH server, I’m initiating this connection to you but if you connect to your port 10000 you will get a tunnel to *my* port 10000.”  If you do a netstat on the server you see a listener on port 10000. Isn’t it great that you can make the server listen to a port which acts as a tunnel to you…so anyone on the server can seamlessly connect to you even though technically you were the client!