Decades ago, I was walking between bars with my Microsoft executive friend and he asked me, “What’s your favorite piece of software?”.
My answer was 3 letters: “SSH“. He had no idea what I was talking about and I explained:
Secure SHell can be used for:
-
Remote logins
-
Secure file transfer
-
Proxy to secure networks
-
Accessing ports on remote machines that are blocked by a firewall
-
Configuring and monitoring fleets of machines.
-
Mounting remote filesystems
I didn’t mention it in that conversation, but it is the best way to use the best version control protocol: git.
If you work with computers, SSH is the most important tool you can know. It’s installed by default on macOS and Linux, and readily available on Windows. Once you understand it, you’ll wonder how anyone who works with 2 or more computers can do without it.
This article covers key generation, agent forwarding, multi-hop connections, SSH tunneling for browser access to private networks, and file transfers through jump boxes. Every technique here is something I’ve used daily in production environments.
Components
Details
-
The user account (on the remote machine)
-
The SSH server (on the remote machine)
-
Configuration can determine if user can use password or needs a key
-
Can determine if someone has access to sftp (Secure File Transfer Protocol)
-
Can contain a remote user in a chroot environment
-
-
The ssh_config defines per-host rules
-
An SSH key allows you to log into a remote system without having to type your password
-
Public key goes on remote machines
-
Private key stays on your local machine
-
It is convenient, efficient, and actually more secure than passwords.
-
-
The ssh-agent allows you to store the key (and the key’s passphrase) for future connections and can even forward the key through computers.
Key Generation
Details
First, create a keypair:
ssh-keygen
Always put a passphrase on your key. An unprotected private key is like leaving your house key in your unlocked car in your driveway.
Your private key should only ever exist on your personal machine. Never copy it to a server. The entire point of SSH key authentication is that your private key stays private.
Agent Forwarding
Details
Agent forwarding is what makes SSH truly powerful. It lets you hop through multiple servers without copying your private key to any of them.
Configuration
Create or edit ~/.ssh/config on your local machine:
Host *
ForwardAgent yes
ServerAliveInterval 30
User yourusername
ForwardAgent yes tells SSH to carry your authentication credentials through to the next server. ServerAliveInterval 30 prevents your session from timing out during periods of inactivity.
Managing Your Agent
Check if the agent is running:
ssh-add -l
If you see “Could not open a connection to your authentication agent,” start it:
eval $(ssh-agent)
Add your key:
ssh-add ~/.ssh/id_rsa
You’ll be prompted for your passphrase. After that, the key is loaded in memory and you won’t be asked again until the agent session ends.
I have a suspicion that computers only break when you turn them on. I rarely turn my laptop off. I often have had keys loaded in my agent for weeks not needing more than my laptop password for thousands of machines. Who says you have to choose between security and convenience?
Verify your key is loaded:
ssh-add -l
You should see your key’s fingerprint and path listed. You can have many keys loaded in your agent at the same time. The ssh_config tells the agent which key to use.
Multi-Hop Connections
Details
Two-Hop: Through a Jump Box
The most common use-case is reaching a private server through a publicly accessible jump box. You can script this into a one-liner:
#!/bin/bash ssh -t -t -i "~/.ssh/id_rsa" jump.example.com -D 12345 ssh $1
Save this as jump.sh, make it executable, and then connect to any private host by passing its IP:
./jump.sh 172.31.10.126
One command, and you’re two hops deep.
Three-Hop: Through a VPN Tunnel
Sometimes you need to reach servers connected to your cloud environment via VPN. Cloud providers typically won’t route traffic from a public subnet through a VPN tunnel, so there’s a second jump box in a private subnet.
Add the -A flag to carry your agent session through each hop:
ssh -t -t jump-public.example.com ssh -t -t -A jump-private ssh target-host
Three hops, one command, no keys on any intermediate server.
SSH Tunneling for Browser Access
Details
This is one of the most underused SSH features. An SSH tunnel lets you browse web interfaces inside a private network as if you were sitting on the local network — without a VPN client.
Set Up the Tunnel
Append -D with a port number to your SSH connection:
ssh -i ~/.ssh/id_rsa you@jump.example.com -D 12345
This creates a SOCKS proxy on your local machine at port 12345.
Configure Your Browser
Set your browser to use a SOCKS-5 proxy:
SOCKS Host: 127.0.0.1
Port: 12345
In Firefox: Preferences → General → Network Settings → Manual proxy configuration.
With the tunnel open and the proxy set, you can browse to any web resource the jump box can reach — Jenkins dashboards, monitoring tools, database admin panels, internal wikis — using their real internal addresses. No URL changes needed.
Important: Disable the proxy when you disconnect the SSH session, or your browser won’t be able to reach anything.
A Browser Profile for Every Environment
If you manage multiple environments (dev, staging, production), Firefox profiles let you have a dedicated browser window for each, with its own proxy settings, bookmarks, and saved credentials.
Create a new profile:
# macOS /Applications/Firefox.app/Contents/MacOS/firefox-bin -P -no-remote # Linux firefox -P -no-remote
Then write a script for each environment:
#!/bin/bash eval $(ssh-agent) ssh-add ~/.ssh/id_rsa firefox -P "Staging" -no-remote & ssh you@staging-jump.example.com -D 12346
Use a different proxy port for each environment. Configure each Firefox profile to use its corresponding port. Set your commonly used internal pages as startup tabs.
Now running the script opens a pre-configured browser and tunnel in one shot. Every tab, bookmark, and credential stays scoped to that environment.
If you don’t mind configuring tools, the FoxyProxy plugin can use the appropriate key/proxy/ports for every defined remote resourse.
Transferring Files Through a Jump Box
Details
Direct scp doesn’t work when the target server isn’t publicly accessible. Use SSH’s ProxyCommand to route through the jump box:
#!/bin/bash
function readme {
echo "Usage:"
echo "To PUT: $0 PUT jumpIP hostIP /remote/path local-file"
echo "To GET: $0 GET jumpIP hostIP /remote/path local-file"
}
if [ -z "$5" ]; then
readme
exit 0
fi
direction=$1
jumpIP=$2
host=$3
remotepath=$4
file=$5
if [ "$direction" == "GET" ]; then
scp -o "ProxyCommand ssh -W %h:%p $jumpIP" "$host:$remotepath" "$file"
elif [ "$direction" == "PUT" ]; then
scp -o "ProxyCommand ssh -W %h:%p $jumpIP" "$file" "$host:$remotepath"
else
readme
fi
Examples:
# Upload a file ./scp-jump.sh PUT 54.68.133.40 10.101.30.111 /tmp/ LocalFile.tgz # Download a file ./scp-jump.sh GET 54.68.133.40 10.101.30.111 /tmp/RemoteFile.tgz .
Troubleshooting
Details
When SSH connections fail, check these in order:
-
Account exists on the target server — Your user needs to be provisioned on the remote host.
-
Config file is correct — Check
~/.ssh/configfor typos, especially in the User directive. -
Agent is running — Run
ssh-add -l. If it complains, start the agent. -
Key is loaded — If
ssh-add -lshows nothing, add your key. -
Username is correct — Your UNIX username may differ from your laptop login. Specify it explicitly with
ssh user@hostif needed. This can also be configured in~/.ssh/config.
Most SSH problems come down to one of these five things. Check them before diving into anything more complex.
Recommended Tools
Details
A good SSH experience starts with a good terminal. Linux and MacOS come with servicable consoles with SSH built in by default.
Traditionally, Windows users chose PuTTY. It is comfortable for people who prefer GUIs over CLI tools; so is Notepad.exe. I still use VI, but that’s for another article. PuTTY comes with PAgent, an integrated SSH agent for PuTTY, so it can do most of what I describe in this guide, but many of these things are easier done from the command line. For example you can call PuTTY from CMD like putty.exe -ssh user@host -P port.
Windows has the option of enabling Windows Services for Linux, which is essentially a full Linux Virtual Machine running on Hyper-V. As a Linux guy, I consider this the most useful terminal on Windows.
The easiest windows ssh client to set up is the GIT for Windows. It comes with an excellent Cywin-based console that is tailored for git and SSH.
