Skip to content

[New] Advanced SSH Tunneling and Port-Forwarding Uses and Configurations #5191

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions docs/guides/networking/ssh/advanced-ssh-tunneling/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
---
slug: advanced-ssh-tunneling
author:
name: Linode
email: [email protected]
description: 'This guide goes beyond basic SSH uses and teaches the reader how to build configurations for their specific needs. This guide explains the configuration and usage for creating dynamic tunnels, remote and local forwarding, multi-hop proxies, pivoting, tunneling other protocols through SSH, and working with a few common open-source tools. .'
keywords: ["ssh", "tunneling", "port forwarding", "remote forwarding", "local forwarding", "multi-hop", "pivoting"]
tags: ["ssh", "networking"]
license: '[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0)'
published: 2022-02-16
title: 'Advanced SSH Tunneling and Port-Forwarding Uses and Configurations'
contributor:
name: Jan Slezak
link: https://github.com/scumdestroy
external_resources:
- '[Official SSH Documentation1](https://www.ssh.com/academy/ssh/tunneling)'
- '[Link Title 2](http://www.example.net)'
---

[SSH](https://www.ssh.com/) (Secure Shell Protocol) is the standard tool and protocol for logging in to servers remotely, however, when wielded by a knowledgable user, its deep configuration options can increase its potential capabilities tremendously. This guide will teach you to create secure and encrypted connections in new ways. These concepts can provide solutions for challenges you may be facing and may inspire changes that simplify your workflow or open new possibilities.

### Example Use Cases

- Accessing files, services and servers on remote, internal networks over the internet.

- Bypassing firewall rules (egress filters) to access a remote FTP server, even though the firewall only allows outgoing traffic on port 80

- Encrypting traffic that uses unencrypted protocols, such as IRC, IMAP or VNC.

- Encrypting all of your HTTP traffic, even though you are on a public network.

- Accessing a MySQL server on an internal network, that only accepts logins from `localhost`

### Before You Begin

{{< note >}}
Many forwarding and tunneling configurations require sudo or root permissions on either or both ends of the connection. Therefore, some steps in this guide require root privileges. Be sure to run the steps below as `root` or with the `sudo` prefix. For more information on privileges, see our [Users and Groups](/docs/tools-reference/linux-users-and-groups/) guide.
{{< /note >}}

1. Familiarize yourself with our [Getting Started](/docs/getting-started/) guide and complete the steps for setting your Linode's hostname and timezone.

2. This guide will use `sudo` wherever possible. Complete the sections of our [Securing Your Server](/docs/security/securing-your-server/) to create a standard user account, harden SSH access and remove unnecessary network services.

3. When choosing ports for SSH tunneling, you should choose ports higher than 1024. Ports below 1024 are reserved for specific protocols or root processes and may cause conflicts with your SSH process.

This guide will use various IPs and ports that will change depending on the example, your configuration, and your needs. To best prevent confusion, the IP addresses will remain the same and are described below.

- Your local machine, the ssh client: `127.0.0.1` or `localhost` 

- The ssh server, which will serve as the pivot point: `10.10.10.2`

- Destination machine, which is not publicly facing, but is accessible from the SSH server: `10.10.10.100` 

- As many configurations require `sudo` permissions, I will be using the `root` user.

{{< caution >}}
Effective use of tunneling can allow you to bypass security measures such as firewall rules and gain access to internal services and machines. This ability is also a double-edged sword, so it is important to disable access to these options in your SSH server configuration when you are not using them, to prevent malicious actors from accessing sensitive data.
{{< /caution >}}

## Preparing SSH for Tunneling

1. Set your SSH configuration file to allow Port-Forwarding. By default, it is located at `/etc/ssh/ssh_config`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this step to be done on the local machine, or the ssh server? Or both?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


    AllowTcpForwarding yes
    AllowStreamLocalForwarding yes
    GatewayPorts yes

{{< note >}}
Possible values for `AllowTcpForwarding` are `yes`, `no`, `remote` (to allow remote forwarding) and `local` (to allow local forwarding)

Possible values for GatewayPorts are `yes` (anyone can connect to remote forwarded ports), `no` (only local connections from server are allowed, this is the Default value) and `clientspecified` (which you would follow with a specific IP address, though if left blank, anyone can connect)

{{< /note >}}

2. Make sure the machines involved have at least three network interfaces (for example, `loopback`, `eth0` and `tun0`).

        ifconfig
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proper amount of indenting for a line like this is 8 spaces. 4 to keep it inline with the numbered list, and 4 to create a code block.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


3. If you have local access to the SSH server, make sure `sshd` is running.

```bash
sudo systemctl start sshd
```



# Local Port Forwarding

Local port forwarding allows a user to expose local, internal resources to a server. The remote server can then access that resource quite transparently as if it was within its local network. For example, a user may want to forward a port (and its attached service) to a corporate web server, an internal mail server's IMAP port, an SMB share, or almost any other service running on an internal network.
Local port forwarding is denoted by the `-L` option.

```bash
 ssh -L local_port:destination:destination_portbash
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "bash" at the end of this line meant to be there? Is it meant to signify the [email protected] part?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In markdown, you can set syntax highlighting by putting the code language in this format into the code block. but since y'all use 8 spaces for code blocks instead, I'll go ahead and pull these out

```

```bash
 ssh -L 8888:10.10.10.100:3306 [email protected]
```

In the example above, you can send traffic to `127.0.0.1:8888` and it will go through the tunnel to `10.10.10.100:3306`

## Dynamic Port Forwarding

This option will use your desired port as a SOCKS proxy, allowing you to run traffic through a tool like `proxychains` or a browser extension like `FoxyProxy`[[[FoxyProxy · GitHub](https://github.com/foxyproxy)].
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of tool is proxychains?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


Install Proxychains

```bash
sudo apt install proxychains4
```

Set up dynamic port forwarding with SSH

```bash
ssh -D 9050 [email protected]
```

{{< note >}}
For simplicity, I recommend using port 9050, the default port used by proxychains. However, if you wish to change that, you can find the configuration at `/etc/proxychains.conf`.
{{< /note >}}

Now you can run applications through proxychains as if you are on the local network you connected through SSH. For example, here is how to use Nmap (a common port scanning tool) to perform a basic scan on the previously inaccessible network.

```bash
 proxychains nmap 10.10.10.100       
```

To run a browser through proxychains, I recommend [FoxyProxy](https://addons.mozilla.org/en-US/firefox/addon/foxyproxy-standard/), which is available for Firefox and Chromium. Simply install the add-on by visiting the Add-On page and enable it in your settings.

```http
Chrome and Chromium-based Browsers: https://chrome.google.com/webstore/detail/foxyproxy-standard/gcknhkkoolaabfmlnjonogaaifnjlfnp?hl=en
Firefox: https://addons.mozilla.org/en-US/firefox/addon/foxyproxy-standard/
```

Once enabled, click on the FoxyProxy icon in your toolbar and go to "**Options**".

- To add your proxychains set-up to FoxyProxy, click on "**Add**".

- On the next screen, set "**Proxy Type**" to `SOCKS5`.

- Set "**Proxy IP address**" to `127.0.0.1`, "**localhost**" or your local machine's IP address.

- Set "**Port**" to `9050`.

- You are free to set your proxy's name and color to whatever you prefer.

- Close the FoxyProxy tab in your browser.

- Click on the FoxyProxy icon in your toolbar. You should now see your recently added proxy. Click on your added proxy to run your browser through proxychains.

- You should be able to browse to previously inaccessible web servers on the network you connected to.

{{< note >}}

The above options assume you are using the default proxychains settings, though if you changed your proxychains configuration file to use a different protocol or port, reflect your custom options when adding your proxy to FoxyProxy.

{{< /note >}}



## Remote Port Forwarding

Remote port forwarding is a similar concept to local port forwarding, however, instead of forwarding a local port and local service to a remote network (ssh server's network), we are instead pulling a remote network's resource into our local machine. In other words, the SSH server will listen for any connection to a port we specify and then tunnel any traffic to our local SSH client and forwards it to our destination port.

```bash
ssh -R [REMOTE:]REMOTE_PORT:DESTINATION:DESTINATION_PORT [USER@]SSH_SERVER
```

Using our example IPs, we would run the following in our terminal.

```bash
ssh -R 8080:127.0.0.1:3000 user@10,10,10,2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the commas here intentional?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

```

Remote port forwarding is often used to provide access to an internal service to a client outside of that network. The example above would allow you to access a web server running on `10.10.10.100:8080` by sending your browser to `http://127.0.0.1:3000`.



## Keeping Sessions Alive

It is quite likely that a situation may occur where your connection is momentarily dropped or your IP address changes due to external factors. Unfortunately, you will need to manually re-establish your connection as there is no native solution in your SSH client, though a simple bash script does alleviate this problem. If your connection happens to drop, it will automatically and continuously attempt to reconnect. Remember to change the values for the `IP` (127.0.0.1), `user`, SSH server (`host`), and `ports` (8080) before you run the following in your terminal.

```bash
while true; do
ssh -N -oExitOnForwardFailure=yes -L 8080:127.0.0.1:8080 user@host
sleep 1
done
```

## Multi-Hop

Chain multiple SSH tunnels together using one command with the `-t` flag.

```bash
ssh -p 8888 [email protected] -t ssh -p 8889 [email protected]
```

## Additional SSH Flags

- On slow networks, you can add `-C` to enable compression mode. This will compress all data sent through the connection, resulting in a lesser strain on your network. SSH will perform identically to a normal session, while the feature works in the background.

- If you will not be using the terminal after your connection, but rather your browser or another tool, you can use the flag `-N` to tell SSH not to open an active shell. This is commonly used with `-n` to put SSH in the background and prevents reading from your stdin.

- To enable X11 forwarding, add the `-X` flag.

## Additional Information

- [Official SSH Documentation on using the config file](https://www.ssh.com/academy/ssh/config)

- [Linux man page for ssh](https://linux.die.net/man/1/ssh)

- [sshuttle](https://github.com/sshuttle/sshuttle), an alternative open-source tool that works as a transparent proxy server and supports DNS tunneling.

- [proxychains](https://github.com/haad/proxychains), an open-source tool that forces programs through a proxy. It supports SOCKS4, SOCKS5, HTTP(S), and Tor.