SSH Connection Multiplexing, Port Forwarding, and SOCK Proxy

By Rob Giseburt

Introduction

This is the third part of a series about using SSH with bastion hosts. You may wish to read the other parts if you haven’t already:

SSH Connection Multiplexing

If you might be opening multiple connections through the bastion host, either to a single machine or to multiple machines, it’s possible to use “connection multiplexing” to share the same connection to the bastion host as a transport to many ssh connections. This saves both resources and time establishing new connections. For a more in-depth discussion of connection multiplexing, look here.

In brief, to enable basic connection multiplexing, add the ControlPath, ControlMaster, and ControlPersist keys to your ~/.ssh/config file, as shown (the first two lines are the same as before):

Host destination.com
    ProxyCommand ssh -A user@bastion.com -W %h:%p
    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlMaster auto
    ControlPersist 10m

A note of warning about ControlPersist: That tells SSH to leave a connection open from the client machine to the bastion host. This may not be desirable or considered safe, depending on your environment. You may omit it and still benefit from multiple concurrent connections (such as when using GIT or Ansible) sharing resources.

If you chose to use ControlPersist, you can close the connection manually with the command

# Close the connection nicely -- waiting for connections to close:
ssh -O stop destination.com 

# Close the connection forcefully, terminating all active connections:
ssh -O exit destination.com

BONUS #2: Port Forwarding and SOCKS Proxy

Credit to my colleague Timothy Weiand for suggesting this be added.

It is possible to have the ssh connection act as a SOCKS proxy. (See the section under “DynamicForward” at the ssh_config man page.) This can be useful to use as a light-weight temporary VPN. There are many security considerations to be taken into account, since you will be potentially creating a tunnel from your local network (which might be a coffee shop!) to the network on the other side of the bastion host, so use with caution, and don’t leave this open longer than necessary!

You may add -D port to the ssh command line, or DynamicForward port to the config file to tell ssh to listen for SOCKS4 or SOCKS5 connections on port on the local host. It will stay open as long as the connection is active, which is often as long as the shell into the other machine is open. (Combine this with connection multiplexing and ControlPersist for longer-term SOCK proxy connections. Use with caution!)

Note that you can add this to the connection to the bastion host or to the connection to the destination machine, depending on where you want the proxied connections to be coming from. To have the SOCKS proxy terminate at a machine on the other side of the bastion host, simply add the -D port to the ssh connection to that machine, like so:

ssh -D 1234 user@destination.com
destination.com# 

Now you can configure any software that supports SOCKS proxies (such as a web browser) to use localhost:1234 as the SOCKS proxy and, as long as that connection is open, those proxied connections will appear to be coming from the destination machine to other devices on the same network, including the destination machine.

In order to make the connections appear to be coming from the bastion host, you can either ssh directly to the bastion host, or add the -D port to the ssh command to the bastion host in the configuration file (bold portions are the relevant addition):

Host destination.com
    ProxyCommand ssh -A -D 1234 user@bastion.com -W %h:%p

Now, if you open a connection normally (without the -D on the command line) to the destination machine, it will also open a SOCKS proxy terminating at the bastion host that lasts as long as the connection to the bastion host. (The connection multiplexing and ControlPersist setting can make that last longer than the connection to the destination machine, however.)

You can also forward arbitrary local ports (without a SOCKS proxy) to arbitrary host/port combinations through the SSH tunnel in a similar manner. Replace the -D port in the above examples for SOCKS with -L port:host:host_port to forward port on localhost to connect to host on port host_port. It will appear to come from either the bastion host or the destination machine, the same as for SOCKS connections.

Note that you cannot open ports <=1024 to listen to unless you are root on most OSes, so you’ll need to pick an unused port higher than 1024 most of the time.

You can also forward ports of the other side of the ssh connection to come through the tunnel and come from your local machine to your local network, including the localhost. Just replace -L port:host:host_port with -R remote_port:host:host_port, and it will forward any connections to remote_port on the machine you’re connected to to host:host_port as if they came from your localhost. The same rules about opening listening ports <=1024 apply to remote_port — you will most likely have to be root, and many ssh configurations will not allow you to ssh directly in as root.

Credit to my colleague Timothy Weiand for helping research this.

Advertisements

2 thoughts on “SSH Connection Multiplexing, Port Forwarding, and SOCK Proxy

    1. Rob Giseburt Post author

      Hi Mike!

      They actually don’t interact quite like you’re thinking. DynamicForward enables a SOCKS proxy, which is an entire protocol to handle management of proxy port usage. (See http://en.wikipedia.org/wiki/SOCKS for more info.)

      Connection Multiplexing allows multiple ssh “sessions” to share the same actual connection. By itself, this allows you to call ssh to the same user@host combination and it will simply use the same IP-level connection and open a second (or third, etc) shell.

      Where the two interact is when you configure Connection Multiplexing to leave an “unused” connection open for a certain period of time. When you have DynamicForward on, then you effectively have a SOCKS proxy server sitting there waiting for connections — at least until it times out.

      Otherwise you have to keep a shell open to hold the connection (and SOCKS proxy) open. There are other ways around this limitation, but this is the easiest and most commonly used.

      -Rob

      Like

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s