OpenSSH Tunnels - Tips & Tricks

Today I spent too much time debugging an SSH tunnel problem. Thus I decided to browse through my shell history and gather my ssh tunnel know-how.

Access an intranet resource from remote

In the following simplified example we access an internally hosted git repository from outside the intranet. We use the -L option of ssh to “Specifies that the given port on the local (client) host is to be forwarded to the given host and port on the remote side”. The syntax is -L [bind_address:]port:host:hostport. With the following command you can access the git repository at localhost:54321.

$ ssh -L localhost:54321:gitblit.server:12345 devop@remote-gateway

This scenario has been described previously in Accessing a Git Repository through multiple Remotes.

Create a SOCKS proxy

If you ask wikipedia - a SOCKS server proxies TCP connections to an arbitrary IP address, and provides a means for UDP packets to be forwarded.

The following command starts a SOCKS proxy on port 8124.

$ ssh -D 8124 devop@<gateway-server> -N

Given you configure your browser (or OS) to use the SOCKS proxy created above your would have access to the wiki in your intranet…

Exposing an SSH tunnel to the public network interface of a remote server

Finally, the scenario that motivated this post… I wanted to expose a service running on my developer machine to a static public IP address backed by a server running in the wild.

Usually our services regardless of production, staging or development are running behind an Nginx. But this use-case was special. I wanted to create a tunnel that exposes a port from my developer machine to a publicly available network interface.

Starting from my shell history I created a tunnel using the -R option. This option specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side. The syntax is -R [bind_address:]port:host:hostport.

I wanted to demo a service running locally via a publicly available server:

$ ssh -R remote-gateway:10080:localhost:8080 devop@remote-gateway -N

No success. The tunnel is bound to the loopback address of the server.

Finally I found the missing piece in this post: How to make ssh tunnel open to public?

By default, sshd(8) (the SSH server) binds remote port forwardings to the loopback address. Without changing the server side configuration there is no way for the client to create a tunnel exposed to the open. A reasonable default on second thought.

This behaviour can be changed with the option GatewayPorts in /etc/ssh/sshd_config

GatewayPorts clientspecified

…and restarting the ssh service: service ssh restart.

clientspecified allows the client to select the address to which the forwarding is bound.

For more details use man sshd_config locally or check the man page online at SSHD_CONFIG(5).

Let’s check the tunnel with netstat

$ netstat -tlpn | grep 10080
tcp        0      0 <public_ip remote-gateway>:10080    0.0.0.0:*               LISTEN      -

Looks good.

A special thanks goes to Markus for helping me on this one with his netstat know-how and patience!

Some random ssh-add goodies:

Add and list a private key to the authentication agent

Just provide the private key to add to the tool ssh-add

$ ssh-add .ssh/id_rsa

and use -l as only parameter to list currently available keys:

$ ssh-add -l

Validate local keys against GitHub deploy keys

$ ssh-add -l -E MD5
4096 MD5:01:23:45:67:89:ab:cd:ef:gh:01:23:45:67:89:ab:cd /Users/devop/.ssh/my_build_rsa (RSA)

Coccinellida

Last, but not least a nice tool to manage ssh tunnels: Coccinellida - is A Simple SSH Tunnel Manager written in Cocoa for Mac OS X.

Coccinellida

It uses Mac OS X system provided ssh client to create secured tunnel connections to remote servers