Tutorials

OpenSSH Port Forwarding and SOCKS Proxy

Table of Contents

Introduction

In addition to providing a secure shell on a remote server, OpenSSH allows port forwarding and can be used as a SOCKS-compliant proxy. These features can be extremely useful when working over insecure networks or around restrictive firewalls.

With both of these features, network traffic originating from a host appears to originate from the remote OpenSSH server instead. Also, the traffic between the OpenSSH client and the OpenSSH server is encrypted by the SSH protocol.

Requirements

  • OpenSSH client host
  • OpenSSH server host

SSH port forwarding is extremely convenient and flexible; however, there are a few items to keep in mind.

  • Firewalls Rules: The destination services to which the connection is established must be accessible to the OpenSSH server. Internal firewall rules and routing must allow the OpenSSH server unrestricted access to the destination service.
  • Privileged Ports: A local port of 1024 or higher must be used. Ports under 1024 are considered privileged ports and can only be created by the root user. To use these privileged ports, the OpenSSH client must be run with root privileges (using sudo, for example).
  • Network Traffic Encryption: Traffic between the OpenSSH client and the OpenSSH server will be encrypted even if the forwarded protocol (e.g. HTTP) is not encrypted. The traffic will return to its original, potentially unencrypted, state after the OpenSSH server and onto the destination. This is usually acceptable if the OpenSSH server and destination are on the same private subnet.

Local Port Forwarding Overview

Local port forwarding allows traffic to be sent to a new port established by the OpenSSH client on a local machine. This port can be bound to any IP address on the local machine, but will usually be the loopback address, 127.0.0.1. The OpenSSH client forwards the traffic onto a remote OpenSSH server over a secure connection. The OpenSSH server continues to forward the traffic onto a specified destination IP address and port provided by the OpenSSH client.

Simple Port Forwarding Example

Gwen is working remotely, but needs to access a MongoDB instance running on an internal host (10.11.50.10) at her cloud provider. There is no VPN available, but there is another host (ops.example.com) accessible over SSH on the same internal network as the MongoDB server.

In this situation, Gwen can forward traffic to the internal MongoDB instance through the OpenSSH server. She begins by establishing an SSH connection from her local workstation to the OpenSSH server:

ssh -L 27017:10.11.50.10:27017 user@ops.example.com

Now traffic to localhost (127.0.0.1) on port 27017 is forwarded through the OpenSSH server and onto the internal MongoDB server. MongoDB can now be accessed from another shell terminal on the local workstation:

mongo

The mongo command assumes the host is localhost and port is 27017 unless otherwise specified.

It is important to note that despite connecting to a insecure (non-SSL/TLS) MongoDB port locally, the traffic is encrypted over the public Internet by SSH. The encryption ends at the OpenSSH server endpoint where traffic travels on the internal subnet.

Multiple Port Forwarding Example

OpenSSH can also forward traffic over several local ports to different destinations at the same time.

For example, Gwen needs to access a Memcached server on another internal host (10.11.50.11) in addition to accessing the internal MongoDB instance (10.11.50.10). Additional -L parameters are easily specified.

ssh -L 27017:10.11.50.10:27017 -L 11211:10.11.50.12:11211 user@ops.example.com

Both services can now be accessed locally. To connect to MongoDB:

mongo

The mongo command assumes the host is localhost and port is 27017 unless otherwise specified. To establish a connection to Memcache, Gwen enters:

telnet localhost 11211

Privileged Port Forwarding Example

Harry needs to begin coding against a REST API that is not officially deployed. The test REST API server (testapi.example.com) is available, but access is restricted to a single publicly available host (ops.example.com). Luckily, SSH access is available to the host. Harry enters:

sudo ssh -L 443:testapi.example.com:443 user@ops.example.com

The REST API is now accessible from Harry's workstation:

curl https://localhost/

sudo is used to run the OpenSSH client because port 443 is lower than 1024. Any port under 1024 is a privileged port and must be created by the root user.

It is generally advisable not to run processes as the root user. Port forwarding can be accomplished by a normal user, but an unprivileged local port must be specified. Harry enters:

ssh -L 5555:testapi.example.com:443 user@ops.example.com

The REST API is now locally accessible over port 5555.

curl https://localhost:5555

Remote Port Forwarding Overview

Remote port forwarding allows the reverse behavior of local port forwarding. Essentially, a port specified on a remote host forwards traffic to the local OpenSSH client host.

Remote Port Forwarding Example

Mary Jane is designing a web application on her local workstation. The application is bound to local port 8888. Her client asks to review the application. She can provide the customer with screenshots or perform a demo via a screen share, but she prefers to provide clients with a more interactive experience.

Mary Jane has SSH access to a publicly accessible server (ops.example.com) on the Internet where port 8080 is available. She forwards the remote port to her local machine by issuing the following connection to the OpenSSH server:

ssh -R 8080:localhost:8888 user@ops.example.com

The client can now open http://ops.example.com:8080 in their browser and access the web application directly from Mary Jane's local machine.

Note: The OpenSSH server must not have an existing process bound to the specified remote port. Also, local or network firewalls need to allow incoming access to the remote port.

SOCKS Proxy Overview

Most operating systems and web browsers allow network traffic to be passed through a SOCKS-compliant proxy server. OpenSSH can act as a SOCKS v4 or v5 compliant proxy. This allows all traffic from the source machine to proxy through an OpenSSH server on a remote host. The traffic source then appears to originate from the OpenSSH server host.

SOCKS Proxy Example

Peter is working remotely. He needs to access the company Intranet, but it is not publicly accessible. Peter has access to a server (ops.example.com) on the company network that provides remote SSH access.

Peter uses OpenSSH to establish a SOCKS-compliant proxy.

 ssh -D 8080 user@ops.example.com

By default, port 8080 binds to all available addresses on the local machine. Peter configures his local network or web browser settings to utilize the OpenSSH PROXY. Using Firefox, he follows these instructions:

  1. Launch the Firefox web browser.
  2. Navigate to Preferences... from the Firefox menu.
  3. Click on Advanced within Preferences.
  4. Click on Network.
  5. Click on Connect / Settings...
  6. Select Manual proxy configuration:
  7. Specify the following settings for the SOCKS Host:
    • SOCKS Host: 127.0.0.1
    • Port: 8080
    • Select SOCKS v5
  8. Click OK.

All browser traffic is now be proxied through the OpenSSH server. If the OpenSSH server can access the company Intranet, the browser will be able to access the company Intranet as well.

Note: All source web traffic appears to originate from the OpenSSH server. This can be useful for accessing blocked sites, so long as the OpenSSH server has access to the destination site.