Creating a multi hop SSH tunnel by chaining SSH commands and using a jump host

Taken from:

When it not possible to reach a server you want to SSH to directly, you can make use of SSH’s built in capability to chain multiple commands. Suppose you have a network setup like in the image below.

Network overview

Network overview

Firewalls or ACL’s prevent direct access to the ‘web server’ in network #2. In between is a ‘jump host’ in network #1. A ‘jump host’ is a host you can SSH to, and from there reach the next hop. How to SSH to the web server?

You could do this manually:

ssh -l user jump-host

and then from that server:

ssh -l user webserver.dmz

But using the -t switch, you can chain them together like this:

ssh -A -t -l user jump-host \
ssh -A -t -l user webserver.dmz

The -A switch enables forwarding of the ssh-agent. When using key based authentication, you’ll be able to login with typing the certificate’s password only once.

Using this technique, you can also build a SSH tunnel through the jump host:

ssh -A -t -l user jump-host \
-L 8080:localhost:8080 \
ssh -A -t -l user webserver.dmz \
-L 8080:localhost:8080

When you type: http://localhost:8080 in a browser, you are connected over a secure tunnel to the web server in Network #2. Thanks to the chaining of commands, this is now possible.

You can use many chained commands, so this is very flexible.

Veröffentlicht unter Linux | Verschlagwortet mit

Using Sshuttle in Daily Work


I was first introduced to sshuttle by Sooyoung (@5ooyoung) in Favorite Medium as a workaround to The Great Firewall in China.

Since then, it has become my light-weight network tunneling tool in daily work.

Install sshuttle

The installation is easy now. You can install it through Mac OSX Homebrew, or Ubuntu apt-get.

I use sshuttle to..

1. Tunnel all traffic

This is the first command I learned. It forwards all TCP traffic and DNS requests to a remote SSH server.

Just like ssh, you can use any server specified in ~/.ssh/config. The -v flag means verbose mode.

Besides TCP and DNS, currently sshuttle does not forward other requests such as UDP, ICMP ping etc.

2. Tunnel all traffic, but exclude some

You can exclude certain TCP traffic using -x option.

3. Tunnel only certain traffic

To tunnel only certain TCP traffic, specify the IP addresses or IP ranges that need tunneling.

This command comes in handy, whenever I need to test an app feature (e.g. Netflix movie streaming) which only available in certain countries, or to bypass ISP faulty caches.

4. VPN to office network

I seldom do VPN, but all you need is the remote SSH server with -NH flags turned on.

-N flag tells sshuttle to figure out by itself the IP subnets to forward, and -H flag to scan for hostnames within remote subnets and store them temporarily in /etc/hosts.

IP addresses.. troublesome?

Well, I try not to deal with IP addresses manually. So I wrote a few sshuttle helpers (tnl, tnlbut, tnlonly, vpnto) that allow me to use domain names instead of IP addresses:

Tunnel all traffic

Tunnel all traffic, but exclude some

Tunnel only certain traffic

VPN to office network

The script is available on my GitHub repo. You can load it into your ~/.bashrc. To override the default tunneling SSH server in the script:

Preventing Brute Force SSH Attacks

Many VPS customers are surprised at the number of failed SSH login attempts to their servers. By just having a listening server on the Internet, you will get dozens or even hundreds of brute force login attempts each day. Most of these attempts come from automated scripts running on other compromised machines. If you are tired of reading through the failed attempts in the logs, there are a number of things that you can to do block the attempts, or otherwise make them unsuccessful.

1- If you will always be connecting to your server from the same IP address, you can firewall off port 22 to everything EXCEPT your own IP address.

iptables -A INPUT -p tcp -d 0/0 -s YOUR.IP.GOES.HERE –dport 22 -j ACCEPT
iptables -A INPUT -p tcp -d 0/0 –dport 22 -j DROP

Then run ‚iptables-save‘

Note: if you setup IP tables this way then it may cause you to lose ssh access to your server if your IP ever changes. And it can also make access to your server by RimuHosting staff more difficult.  It will also obviously prevent you from connecting to your server except from that one source IP.

2- Run sshd on a non-standard port. Since most automated attacks only attempt to connect on port 22, this can be an effective way to hide from automated attackers. To configure this, just change the Port line in /etc/ssh/sshd_config and restart ssh

Port 1022

3- Use the AllowUsers directive in the ssh configuration to only allow certain users or IP’s. In /etc/ssh/sshd_config, you can specify a list of allowed users like this:

AllowUsers bob john root@ root@

This will allow users ‚bob‘ and ‚john‘ to log in from anywhere, and root is only allowed to log in from those two IP addresses.

4- Use strong passwords! Brute force attempts will try common passwords like words (or combinations of words) in a dictionary, names, and common passwords. Strong passwords generally use a combination of upper and lower-case characters, numbers, and non-alphanumeric characters.

5- Even better, don’t use passwords at all. Instead, install your public key on the server and use it to log in. If all of your users will use public keys, you can set PasswordAuthentication to ’no‘. To disable password authentication just for root, use ‚PermitRootLogin without-password‘. For Debian/Ubuntu, you’ll also need to turn off ‚UsePam‘ and ‚ChallengeResponseAuthentication‘.

6- If you need to permit logins from arbitrary addresses, consider using a program like DenyHosts or Fail2ban. They watch for failed logins and add the IP addresses of attackers to /etc/hosts.deny and/or update firewall rules to null route them. DenyHosts can also be configured to synchronize with a global database so you can proactively deny hosts that other users have blacklisted.  Keep in mind that mistyping your password when you try to log in will then probably lock you out of your VPS.

7- Use ‚hashlimit‘ in ‚iptables‘:

iptables -I INPUT -m hashlimit -m tcp -p tcp –dport 22 –hashlimit 1/min
–hashlimit-mode srcip –hashlimit-name ssh -m state –state NEW -j ACCEPT

This rule limits one connection to the SSH port from one IP address per minute.

For more information, ‚man iptables‘ and ‚iptables -m hashlimit –help‘.

8 – Use port knocking to completely hide the port your SSH server is listening too; example.  This will of course make it pretty complicated for you to log in.

If you manage to lock yourself out, you can always log in using your root password via the Console over SSH feature.


How to disable SSH host key checking


Remote login using the SSH protocol is a frequent activity in today’s internet world. With the SSH protocol, the onus is on the SSH client to verify the identity of the host to which it is connecting. The host identify is established by its SSH host key. Typically, the host key is auto-created during initial SSH installation setup.

By default, the SSH client verifies the host key against a local file containing known, trustworthy machines. This provides protection against possible Man-In-The-Middle attacks. However, there are situations in which you want to bypass this verification step. This article explains how to disable host key checking using OpenSSH, a popular Free and Open-Source implementation of SSH.

When you login to a remote host for the first time, the remote host’s host key is most likely unknown to the SSH client. The default behavior is to ask the user to confirm the fingerprint of the host key.

If your answer is yes, the SSH client continues login, and stores the host key locally in the file~/.ssh/known_hosts. You only need to validate the host key the first time around: in subsequent logins, you will not be prompted to confirm it again.

Yet, from time to time, when you try to remote login to the same host from the same origin, you may be refused with the following warning message:

There are multiple possible reasons why the remote host key changed. A Man-in-the-Middle attack is only one possible reason. Other possible reasons include:

  • OpenSSH was re-installed on the remote host but, for whatever reason, the original host key was not restored.
  • The remote host was replaced legitimately by another machine.

If you are sure that this is harmless, you can use either 1 of 2 methods below to trick openSSH to let you login. But be warned that you have become vulnerable to man-in-the-middle attacks.

The first method is to remove the remote host from the ~/.ssh/known_hosts file. Note that the warning message already tells you the line number in the known_hosts file that corresponds to the target remote host. The offending line in the above example is line 3(„Offending key in /home/peter/.ssh/known_hosts:3“)

You can use the following one liner to remove that one line (line 3) from the file.

Note that with the above method, you will be prompted to confirm the host key fingerprint when you run ssh to login.

The second method uses two openSSH parameters:

    • StrictHostKeyCheckin, and
    • UserKnownHostsFile.

This method tricks SSH by configuring it to use an empty known_hosts file, and NOT to ask you to confirm the remote host identity key.

The UserKnownHostsFile parameter specifies the database file to use for storing the user host keys (default is ~/.ssh/known_hosts).

The /dev/null file is a special system device file that discards anything and everything written to it, and when used as the input file, returns End Of File immediately.

By configuring the null device file as the host key database, SSH is fooled into thinking that the SSH client has never connected to any SSH server before, and so will never run into a mismatched host key.

The parameter StrictHostKeyChecking specifies if SSH will automatically add new host keys to the host key database file. By setting it to no, the host key is automatically added, without user confirmation, for all first-time connection. Because of the null key database file, all connection is viewed as the first-time for any SSH server host. Therefore, the host key is automatically added to the host key database with no user confirmation. Writing the key to the /dev/null file discards the key and reports success.

Please refer to this excellent article about host keys and key checking.

By specifying the above 2 SSH options on the command line, you can bypass host key checking for that particular SSH login. If you want to bypass host key checking on a permanent basis, you need to specify those same options in the SSH configuration file.

You can edit the global SSH configuration file (/etc/ssh/ssh_config) if you want to make the changes permanent for all users.

If you want to target a particular user, modify the user-specific SSH configuration file (~/.ssh/config). The instructions below apply to both files.

Suppose you want to bypass key checking for a particular subnet (

Add the following lines to the beginning of the SSH configuration file.

Note that the configuration file should have a line like Host * followed by one or more parameter-value pairs. Host *means that it will match any host. Essentially, the parameters following Host *are the general defaults. Because the first matched value for each SSH parameter is used, you want to add the host-specific or subnet-specific parameters to the beginning of the file.

As a final word of caution, unless you know what you are doing, it is probably best to bypass key checking on a case by case basis, rather than making blanket permanent changes to the SSH configuration files.

If you make it this far in the article, you may find the following more recent ssh articles interesting:

Allow root ssh login with public key authentication
How to auto fill in ssh client parameters
One-liner to shutdown remote host
X11 Forwarding over SSH

Howto use SSH local and remote port forwarding


Port forwarding, or tunneling, is a way to forward otherwise insecure TCP traffic through SSH Secure Shell. You can secure for example POP3, SMTP and HTTP connections that would otherwise be insecure.

There are two kinds of port forwarding: local and remote forwarding. They are also called outgoing and incoming tunnels, respectively.

Local port forwarding forwards traffic coming to a local port to a specified remote port. For example, all traffic coming to port 1234 on the client could be forwarded to port 23 on the server (host).

Note: The value of localhost is resolved after the Secure Shell connection has been established — so when defining local forwarding (outgoing tunnels), localhost refers to the server (remote host computer) you have connected to.

Remote port forwarding does the opposite: it forwards traffic coming to a remote port to a specified local port. For example, all traffic coming to port 1234 on the server (host) could be forwarded to port 23 on the client (localhost).

Local port forwarding

Accessing a service (in this example SSH port tcp/22, but it could be anything like a web server on tcp/80) on a machine at work ( from your machine at home (, simply by connecting to the server at work :

$ ssh -L 10000:

We see the service is available on the loopback interface only, listening on port tcp/10000 :

$ netstat -tunelp | grep 10000

tcp 0 0* LISTEN 1000 71679 12468/ssh

From your home machine, you should be able to connect to the machine at work :

$ ssh root@localhost -p 10000

Local port forward for anyone at home !

If you want other people on your home subnet to be able to reach the machine at work by SSH, add the option -g :

$ ssh -L 10000: -g

We now see the service is available on all interfaces on your home computer, available for anyone to connect to on the local subnet :

$ netstat -tunelp | grep 10000

tcp 0 0* LISTEN 1000 72265 12543/ssh

Anyone on your local subnet should be able to connect to the machine at work by doing this :

$ ssh root@ -p 10000

Remote port forwarding

Giving access to a service (SSH port tcp/22) on your home machine ( to people at work

$ ssh -R 10000:

We see on our server at work (on the loopback interface on port tcp/10000) that we have access to our SSH server at home :$ netstat -tunelp | grep 10000

tcp 0 0* LISTEN 0 73719534 3809/1

People logged in on the machine now should be able to SSH into your home machine by doing :$ ssh user@localhost -p 10000

Remote port forwarding for anyone at work !

If you want everybody on the subnet at work to be able to SSH into your home machine, there’s no -g option for remote forward, so you need to change the SSH configuration of, add to sshd_config :

GatewayPorts yes

Connect just as before :

home$ ssh -R 10000:

Now, it’s listening on all interfaces on the server at work :$ netstat -tunelp | grep 10000

tcp 0 0* LISTEN 0 73721060 4426/1

Anyone at work can now connect to your home machine by SSH via the server :$ ssh -p 10000


– You would need to log in as root if you want services to listen on a port < 1024.
– Don’t forget to open necessary ports on any firewall either at home or work.
– Unfortunately you can only forward services running on TCP, but there’s a way to forward UDP through SSH using netcat