SSH Port Forwarding 简介 (SSH Port Forwarding is All You Need)

SSH Port forwarding is a technique used to tunnel your network traffic from the local (remote) network to the remote (local) network. Although it has several limitations, SSH port forwarding is powerful, flexible and sufficient to facilitate your server/client workflow. In this blog I briefly introduce this technique and several scenarios I have used.

Why and Why Not Port Forwarding

Overall, port forwarding is powerful, flexible and sufficient:

  • It is easy to manage. You can list all your established ports by linux command netstat -plnt. This tool also exists on Windows.
  • It does not require sudo privileges.
  • It can be applied to all users on the same node (or same network, to be accurate).
  • It provides a chain-based model for connection. Another proxy can be applied onto an existing tunnel.
  • The transmitted data is end-to-end encrypted (E2EE) by default.

There are also some inherent limitations:

  • It resides on the L3 network. It only takes effect on TCP packets. E.g., ping uses ICMP that is unaffected and ssh itself should be proxied by another way. Note that it is possible to use ssh for L2 tunneling, but it requires sudo privileges thus beyond the scope of this post.
  • It cannot automatically direct all TCP traffic. I.e., if a specific application does not support proxy itself, there is nothing else we can do. However, this should rarely happen because almost all modern apps have a dedicated proxy setting.

Local Port Forwarding

Suppose on the server you can access an address (IP with port) rAddr:rPort. And on the client you can only access the server via SSH sAddr:sPort (sPort is usually 22). With local port forwarding, it is possible to bind the remote address to your local network (e.g., localhost), and forward network traffic. The basic ssh argument is ssh -L (lAddr:)lPort:rAddr:rPort sAddr -p sPort, where lAddr and lPort are the addresses on the local network. Generally we bind at our own host, i.e., localhost, so lAddr is omitted. Once the local address is set, all nodes within the local network, including our own host, can access the remote address by accessing lAddr:lPort. SSH does the rest of the tunneling work for us.

Use Case #1: Use jupyter notebook remotely on the client

Jupyter notebook is designed to follow the client/server model, which means we can access it from our laptop, but offload any computation to the server. Also our intermediate result keeps on the server as long as the server is on. To enable this, we can start a jupyter notebook on the server, and access it on a local browser if the server has a public IP.

However, when the server is behind a NAT or within a VPN, tunneling is in need. Assume the server has a internal IP 192.168.1.181, and there is a jump host with a public IP 101.6.123.123. Make sure you can access notebook from the jump host (say with the address 192.168.1.181:12116). Now forward the connection by first executing ssh -L 12116:192.168.1.181:12116 101.6.123.123 -N -f. And on your local web browser access http://localhost:12116.

Use Case #2: Forward remote desktop on the client

If the client and the server are in the same network, both CLI (Command Line Interface) and GUI (Graphical User Interface) access is convenient, e.g., via ssh and rdp, if the target server has installed ssh and xrdp server respectively. However, if the client is not in the network. How can we access the server?

One approach is with the help of a jump host with a public IP address (The same with Use Case #1). In my working environment, the campus networking is extremely confusing. For example, our subgroup resides within a controllable router starting with 192.168.50.x. This network connects to the entire company network, starting with 10.88.xx.xx, which is then managed and connected to the big campus network. When I am at the dorm, to access ssh at the subgroup, I “jump” multiple times: first to our controllable router, then the target server. The router does not get a static IP, but luckily DDNS technique allows us to access it via a fixed domain (and only secure since it maps to an internal IP). This shows the strength of the chain-based model.

To use the GUI on that server, I add a port forwarding entry on our router (from 0.0.0.0:13389 to 192.168.50.x:3389). Then connect via 10.88.xx.xx:13389. Here comes the ssh forwarding part: even if we are not on campus, we can connect that server with a jump host, by a similar method in Case #1 to forward 13389 port to our localhost.

Another way is to “create a mapping” from a public IP address to the internal server address. Introspectable tunneling (for example, ngrok) is what you find.

Remote Port Forwarding

Remote port forwarding takes the reverse path: it allows the server to access your local network. Suppose on the client you can access lAddr:lPort, and the server address is still sAddr:sPort. With the remote port forwarding, the server can access the local address with a dedicated address rAddr:rPort, where rAddr is usually the server itself, i.e., localhost.

Use Case #3: Use local ssr to access github on the server

On my laptop I have my way to accelerate access to github via a http proxy, for example: localhost:1080. But when we need to directly push repos on our server, it is not that quick. It is easy to solve by remote forwarding, which allows the server to access the target address (lAddr:lPort) via your own laptop’s port. The new port is created to rAddr:rPort.

Assume the local ssr port is 1080. Start a remote port forwarding with this line:

ssh -R 10800:127.0.0.1:1080 myserver -N -f

Now set the github proxy by

git config --global http.proxy http://localhost:10800

git config --global https.proxy http://localhost:10800

Now you are able to access Github on the server via your local proxy client.

Dynamic Port Forwarding

Dynamic port forwarding allows us to tunnel all web traffic from one port, which acts like a SOCKS protocol. It is more powerful than local port forwarding since regardless what random port our web browser opens, the traffic is tunneled. This also keeps all DNS name resolution and connectivity to be the same as the proxy server.

Use Case #4: Access extranet without authentication on the client (Yet An Another Approach)

On campus all our network traffic to extranet is charged. However all intranet traffic does not. We can exploit this to first tunnel our web traffic to the server at the outer company. Since the traffic on that server accesses the internet for free, we can bypass the charging system.

One of the many approaches are set a proxy (for example, squid) at the proxy server and starts a local remote forwarding (e.g., from sAddr:3389 to localhost:1080) and we get a local http proxy port. A more flexible approach is to use dynamic port forwarding by executing ssh -D 1080 sAddr. Now we have a SOCKS port at localhost:1080. Any modern web browser can support socks proxying.

Advanced Features: Auto Reconnect, Check Connectivity

To keep our port always on, we can restart the ssh commands periodically. A simpler way is to use software, e.g., Mobaxterm and Bitvise SSH Client. They can continually monitor the states and the forwarding entries for you.

A Dream: Overlay Local Area Internet

When I was a child, it always frustrates me that most popular multi-player computer games can only be played on LAN. Hereafter, several centralized gaming platforms have grown big (and later faded away), by hooking the sockets in the binary and starting a small VPN. This works well if all the players are near the central server. However, it would be definitely better to build a decentralized platform where people start their own relay servers (e.g., on the edge), and support a virtual LAN. It can be even better if such relay servers help with each other to find the shortest route path, even if the networks are not related, which forms an overlay internet of local areas (Overlay LAI). In that dreamland people do not locate each other by complicated (and dynamic) IP addresses but by memorizable passphrases. Note that this has already kind of been a trend in file transmission, where traditional scp/rsync are replaced by the emerging wormhole. I hope cloud and edge computing are making us more closed than ever.

---以上---