Establish a secure multi-hop SSH tunnel from your local machine to S2 via S1 by configuring the
ProxyJump directive in your SSH client. This method routes all traffic through both servers, ensuring privacy and bypassing network restrictions without requiring complex port forwarding rules on the intermediate host.
Prerequisites and Network Topology
Before configuring the tunnel, ensure you have valid credentials for both VPS instances. You need SSH access to Server 1 (S1) and Server 2 (S2). The goal is to make your local machine appear as if it is directly connected to S2, while the connection path physically traverses S1. This setup is particularly useful when S2 is behind a firewall that only allows incoming connections from S1. Verify that both servers are running standard SSH daemons and that your local machine can reach S1 over the public internet. If you encounter issues with file transfers later, refer to our guide on resolving
rsync file transfer errors on Ubuntu VPS to troubleshoot connectivity or permission issues independently.
Configuring the SSH Client
The most efficient way to handle multi-hop connections is using the built-in
ProxyJump feature available in OpenSSH 7.3 and later. This eliminates the need for manual local port forwarding chains or third-party tools like
autossh. You will edit the
~/.ssh/config file on your local machine. This file allows you to define aliases and connection parameters for specific hosts.
Create an entry for S1 first. Define the hostname, username, and optionally a private key if you do not use the default identity. Then, create an entry for S2. Crucially, set the
ProxyJump option to the alias of S1. This tells SSH to automatically establish a connection to S1 first, and then tunnel through it to reach S2.
Host s1
HostName 192.0.2.1
User admin
IdentityFile ~/.ssh/id_rsa_s1
Host s2
HostName 198.51.100.2
User deploy
ProxyJump s1
IdentityFile ~/.ssh/id_rsa_s2
In this configuration, connecting to
s2 will automatically log you into
s1 and then forward your session to
s2. If you experience authentication failures during this process, check our article on
permission denied errors with SSH scripts to ensure your key permissions are correctly set.
Verifying the Tunnel Connection
Once the configuration is saved, test the connection from your terminal. Run the command
ssh s2. Your SSH client will first prompt you for the password or passphrase for S1, and then for S2. If successful, you will be dropped into a shell on S2. To verify that the traffic is indeed routing through S1, you can run
whoami on S2 to confirm your identity, and then check the source IP from S2's perspective if needed.
For a more robust testing method, use the verbose mode:
ssh -v s2. Look for lines indicating the establishment of the proxy connection. You should see messages about connecting to S1, authenticating, and then opening a direct stream to S2. If you receive warnings about IP changes, consult our troubleshooting guide for
SSH suspected IP change warnings to distinguish between normal behavior and security alerts.
Using the Tunnel for Other Services
Beyond simple shell access, you can route other services through this multi-hop tunnel. For example, to access a web service running on port 8080 on S2, you can use dynamic port forwarding. Add the following line to your
~/.ssh/config under the
s2 host block:
LocalForward 9999 localhost:8080
This forwards your local port 9999 to S2's port 8080 via S1. You can now open your browser and navigate to
http://localhost:9999. Any traffic sent here will be encrypted, passed to S1, tunneled to S2, and delivered to the application. This technique works for databases, APIs, and any TCP-based service. Ensure that the remote server (S2) has the service listening on
localhost or
127.0.0.1 to prevent accidental exposure to the wider internet.
Security Considerations and Best Practices
Multi-hop tunnels add complexity to your security posture. Always use strong, unique passwords or, preferably, SSH keys with passphrases for both servers. Disable password authentication on both VPS instances if possible, relying solely on key-based auth. Regularly update the SSH software on both S1 and S2 to patch known vulnerabilities. Additionally, consider implementing fail2ban or similar intrusion prevention systems to protect against brute-force attacks. If you are concerned about kernel-level security implications, review our insights on
Ubuntu 22.04 VPS security with kernel modules disabled to harden your base system.
Understanding how reverse tunnels work can also help if you need to expose a local service back through these servers. See our explanation of
SSH reverse tunnels for scenarios where the direction of the connection needs to be inverted.
Frequently Asked Questions
Can I use PuTTY for multi-hop SSH?
Yes, PuTTY supports chained connections through its "Proxy" settings. You configure the first hop (S1) as a local port forward to a temporary port, then configure the second hop (S2) to connect to that local port. While functional, the native
ProxyJump in Linux/macOS clients is generally simpler to manage than GUI-based chaining.
What happens if S1 goes offline?
If S1 becomes unreachable, your connection to S2 will fail immediately because S2 is not directly accessible from your local machine. You must restore connectivity to S1 before re-establishing the tunnel. Monitoring S1's uptime is critical for maintaining access to S2 in this topology.
Is there a performance penalty for multi-hop tunnels?
There is a slight increase in latency due to the additional round-trip time to S1. Encryption overhead remains similar since the entire channel is encrypted end-to-end. However, bandwidth throughput is rarely affected significantly unless S1 has very limited network resources or high CPU load.
How do I disconnect cleanly from S2?
Simply type
exit in the S2 shell. This closes the session on S2 and automatically terminates the underlying connection to S1. The SSH client will return you to your local terminal. No special cleanup commands are required on either server.
Can I use this tunnel for git operations?
Absolutely. By setting up the SSH config as described, any git command using the
s2 alias will automatically route through S1. This is ideal for accessing private repositories hosted on S2 without exposing them publicly. Ensure your git remote URL uses the correct SSH syntax pointing to the S2 user and repository path.