SSH Tricks You Wish You Knew Sooner
SSH, or Secure Shell, is the cornerstone of remote system administration and development. It’s the secure tunnel through which we interact with servers, cloud instances, and even our Raspberry Pis. While most of us are familiar with the basic ssh user@host
command, the true power of SSH lies in its often-overlooked features and configuration options.
Many seasoned professionals rely on a handful of these tricks daily to streamline their workflow, enhance security, and troubleshoot complex network issues. If you’re ready to move beyond the basics and unlock a new level of efficiency, read on.
Let’s dive into some SSH tricks that, once learned, you’ll wonder how you ever lived without.
1. Master Your SSH Config File (~/.ssh/config
)
This is arguably the most impactful trick you can learn. The SSH client configuration file allows you to define aliases and specific settings for hosts, eliminating the need to type long commands with multiple flags. It’s an absolute game-changer for managing numerous connections.
Why it’s useful:
- Shorter Commands: Replace
ssh -i ~/.ssh/my_aws_key.pem -p 2202 user@192.168.1.100
withssh my_server
. - Centralized Settings: Define specific
User
,Port
,IdentityFile
,ProxyJump
,LocalForward
, etc., for each host or group of hosts. - Security: Helps prevent typos when specifying key paths or ports.
How to use it:
Create or open ~/.ssh/config
with your favorite text editor. Remember to set the correct permissions: chmod 600 ~/.ssh/config
.
touch ~/.ssh/config
chmod 600 ~/.ssh/config
# Then open with vim, nano, or your editor of choice
Here’s an example ~/.ssh/config
file with common scenarios:
# Default settings for all connections (optional)
Host *
ForwardAgent yes
ServerAliveInterval 60
ServerAliveCountMax 3
# My personal development server
Host devserver
HostName 192.168.1.100
User myuser
Port 2222
IdentityFile ~/.ssh/id_rsa_devserver
# Optional: Connect via a jump host
# ProxyJump jumphost
# An AWS EC2 instance
Host aws-web
HostName ec2-X-Y-Z-W.compute-1.amazonaws.com
User ubuntu
IdentityFile ~/.ssh/aws_web_key.pem
# Optional: Automatically add host key to known_hosts
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
# A jump host (bastion) definition
Host jumphost
HostName 10.0.0.5
User admin
IdentityFile ~/.ssh/id_rsa_jumphost
# A private server accessed via the jump host
Host private-db
HostName 172.16.0.10
User dbadmin
IdentityFile ~/.ssh/id_rsa_private_db
ProxyJump jumphost
LocalForward 5432 localhost:5432 # Forward local port 5432 to remote DB port 5432
# A dynamic SOCKS proxy for browsing through a remote server
Host socks-proxy
HostName your_remote_server.com
User youruser
DynamicForward 8080
NoHostAuthenticationForLocalhost yes # Important for proxying
# Keep the connection open for proxying
ExitOnForwardFailure no
ServerAliveInterval 30
ServerAliveCountMax 5
RequestTTY no
PermitLocalCommand yes
LocalCommand echo "SOCKS proxy on localhost:8080 is ready."
Key ~/.ssh/config
Directives:
Host
: Defines an alias. Wildcards like*
are allowed.HostName
: The actual hostname or IP address.User
: The username to log in as.Port
: The remote port to connect to.IdentityFile
: The path to your private key.ProxyJump
: Extremely useful for connecting to internal networks via a bastion host. This implicitly usesProxyCommand
to tunnel the connection. (Seeman ssh_config
for more details).LocalForward
: Creates a local port listening for connections and forwards them to a remote destination (e.g.,LocalForward 8080 remote.host:80
).RemoteForward
: The opposite ofLocalForward
. The remote host listens on a port and forwards connections to a local destination.DynamicForward
: Turns your SSH client into a SOCKS proxy, forwarding all traffic from a specified local port through the SSH server.ControlMaster
&ControlPath
: For connection multiplexing (covered next).ForwardAgent
: Forward your authentication agent connection (useful withssh-agent
).ServerAliveInterval
/ServerAliveCountMax
: Prevents SSH connections from timing out due to inactivity by sending “keep-alive” messages.
2. Multiplex SSH Connections with ControlMaster
Tired of waiting for SSH connections to re-authenticate or re-establish a TCP connection every time you open a new terminal or SFTP session to the same host? ControlMaster
is your solution. It allows multiple SSH sessions to share a single connection.
Why it’s useful:
- Speed: Subsequent connections to the same host are instantaneous.
- Efficiency: Reduces server load by reusing the same TCP connection.
- Convenience: No re-authentication (password or passphrase) for new sessions.
How to use it:
Add the following lines to your ~/.ssh/config
file, typically within a Host
block or globally:
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h:%p
ControlPersist 10m # Keep the master connection open for 10 minutes after all clients exit
ControlMaster auto
: Tells SSH to try to use an existing master connection or create one if none exists.ControlPath
: Specifies the path to the control socket file.%r
,%h
,%p
are escape sequences for remote username, hostname, and port, ensuring unique socket names.ControlPersist
: (OpenSSH 5.6+) Keeps the master connection open in the background even after the initial client disconnects. This is extremely useful! You can specify a duration (e.g.,10m
,1h
,no
for indefinite).
Now, when you ssh devserver
for the first time, it will establish the master connection. Subsequent ssh devserver
commands (even scp
or sftp
to devserver
) will reuse that connection.
To close the master connection explicitly (if ControlPersist
is active), you can use:
ssh -O exit devserver
Note: Ensure the ~/.ssh/sockets
directory exists and has appropriate permissions (mkdir -p ~/.ssh/sockets
).
3. SSH Agent for Key Management
If you use SSH keys with passphrases, ssh-agent
is your best friend. It’s a program that runs in the background and holds your decrypted private keys in memory. This means you only have to enter your passphrase once per session (or until the agent restarts), and then any SSH-related command can use the keys without re-prompting.
Why it’s useful:
- Convenience: No repetitive passphrase entry.
- Security: Your private key file remains encrypted on disk. The decrypted key is only in memory, making it harder for attackers to steal if your disk is compromised.
How to use it:
-
Start the agent:
eval "$(ssh-agent -s)" # Or, if you're using a specific shell: # ssh-agent bash # ssh-agent zsh
This command starts the agent and sets the
SSH_AUTH_SOCK
environment variable in your current shell, telling other SSH programs where to find the agent. -
Add your keys:
ssh-add ~/.ssh/id_rsa ssh-add ~/.ssh/my_aws_key.pem # You will be prompted for your passphrase for each key, if they have one.
You can also add keys permanently to the agent on macOS using
UseKeychain yes
in~/.ssh/config
andssh-add -K
. Linux users can usessh-add
in their shell startup scripts (e.g.,.bashrc
,.zshrc
). -
List loaded keys:
ssh-add -l
Now, any ssh
, scp
, or sftp
command will automatically use the keys loaded into the agent without prompting for passphrases again.
Important: If you reboot your machine, the ssh-agent
process will terminate, and you’ll need to restart it and add your keys again.
4. SSH Tunneling (Port Forwarding)
SSH can do more than just provide a shell; it’s a powerful tool for creating secure tunnels between machines. This is incredibly useful for accessing services on private networks, bypassing firewalls, or securely browsing the web.
There are three main types of port forwarding:
a. Local Port Forwarding (-L
)
Forwards a local port on your machine to a port on a remote host through the SSH server. Useful for accessing a service on the remote server’s network that isn’t directly exposed to you.
Scenario: You want to access a database running on 172.16.0.10:5432
from your local machine, but only your SSH server (your_remote_server.com
) can reach it.
ssh -L 5432:172.16.0.10:5432 user@your_remote_server.com -N
-L <local_port>:<target_host>:<target_port>
: The core of the local forward.-N
: Do not execute a remote command. This is useful when you only want to forward ports.user@your_remote_server.com
: Your SSH connection to the remote server.
Now, you can connect to localhost:5432
on your local machine, and your traffic will be securely tunneled through your_remote_server.com
to 172.16.0.10:5432
.
b. Remote Port Forwarding (-R
)
Forwards a port on the remote SSH server to a port on your local machine. Useful if you want to expose a local service to the remote server or other machines that can reach the remote server.
Scenario: You’re developing a web application locally on port 3000
and want to show it to a colleague who can only access your_remote_server.com
.
ssh -R 8080:localhost:3000 user@your_remote_server.com -N
-R <remote_port>:<local_host>:<local_port>
: The core of the remote forward.user@your_remote_server.com
: Your SSH connection to the remote server.
Now, your colleague can navigate to your_remote_server.com:8080
, and their traffic will be securely tunneled back to localhost:3000
on your machine.
Note: By default, GatewayPorts no
is set on the server, meaning the remote port 8080 will only be accessible from localhost
on the remote server itself. To allow others to connect, the server’s sshd_config
needs GatewayPorts yes
.
c. Dynamic Port Forwarding (-D
) (SOCKS Proxy)
This turns your SSH client into a SOCKS proxy. It’s incredibly powerful for routing all your network traffic (e.g., web browsing) through the remote server.
Scenario: You’re on an untrusted network and want to securely browse the internet as if you were on your remote server’s network.
ssh -D 8080 user@your_remote_server.com -N
-D <local_port>
: Sets up a SOCKS proxy on your local machine on the specified port.user@your_remote_server.com
: Your SSH connection to the remote server.
Once the command is running, configure your browser or applications to use localhost:8080
as a SOCKS5 proxy. All traffic from that application will then be tunneled through your remote server. This is a quick way to bypass certain network restrictions or mask your IP address.
5. Escaping the SSH Session (~
commands)
What if your remote session hangs, or you need to suspend it, or you forgot to set up a port forward? You don’t have to kill your terminal! SSH has built-in escape sequences.
To issue an escape command, press Enter
, then ~
(tilde), then the command character. If you’re pressing ~
at the start of a line and it doesn’t work, try pressing Enter
first, then ~
.
Common escape sequences:
~.
: Terminate the connection. (Equivalent toCtrl+D
for EOF, but works even if the remote shell is unresponsive.)~^Z
: Background the SSH session. (Press~
thenCtrl+Z
.) You can then usefg
to bring it back to the foreground.~#
: List forwarded connections. Useful for debugging your tunnels.~C
: Open a command line. This lets you add, remove, or list port forwards during an active session!ssh> help ssh> -L 8080:localhost:80
~?
: Display a list of all supported escape sequences.
Note: The tilde character ~
must be the first character typed on a line, after a newline.
6. Running Commands Directly & Piped Input/Output
You don’t always need an interactive shell. SSH allows you to execute commands directly on the remote server and work with piped input/output, which is fantastic for scripting and automation.
a. Run a single command:
ssh user@host "ls -l /var/log | grep auth.log"
The output of the command on the remote server is sent back to your local terminal.
b. Execute a local script on a remote server:
cat local_script.sh | ssh user@host "bash -"
This pipes the content of local_script.sh
to the bash
interpreter on the remote machine. The bash -
tells bash to read its commands from standard input.
c. Redirect remote output to a local file:
ssh user@host "cat /var/log/nginx/access.log" > local_access.log
This is often more convenient than scp
for a single file or for dynamically generated content.
7. SSH Agent Forwarding (-A
or ForwardAgent yes
)
We talked about ssh-agent
, but what if you need to connect from HostA
to HostB
, and then from HostB
to HostC
, without copying your private key to HostB
? That’s where agent forwarding comes in.
Why it’s useful:
- Security: Your private key never leaves your local machine.
- Convenience: Authenticate to multiple nested servers without typing passphrases or managing keys on intermediate hosts.
How to use it:
When connecting to the intermediate host (HostB
), use the -A
flag:
ssh -A user@hostB
Or, enable it in your ~/.ssh/config
for specific hosts:
Host hostB
ForwardAgent yes
Once connected to hostB
with agent forwarding, you can then ssh user@hostC
from hostB
, and hostB
will communicate with your local ssh-agent
to perform the authentication.
Caution: Only use agent forwarding to trusted intermediate hosts. A malicious root user on hostB
could potentially hijack your agent socket and use your keys.
8. Verbose Output for Debugging (-v
, -vv
, -vvv
)
When an SSH connection fails, or you’re having trouble with keys or configurations, the -v
(verbose) flag is your best friend. Adding more v
s increases the verbosity level.
ssh -v user@problematic_host # level 1 (basic debugging)
ssh -vv user@problematic_host # level 2 (more detail)
ssh -vvv user@problematic_host # level 3 (most detailed, including key exchanges)
The output will show you exactly what SSH is trying to do: which configuration files it’s reading, which keys it’s trying, what authentication methods it’s attempting, and often, precisely where the connection is failing. This is invaluable for troubleshooting.
9. X11 Forwarding (-X
or -Y
)
Need to run a graphical application on a remote server and display its window on your local desktop? SSH’s X11 forwarding makes this possible.
How to use it:
ssh -X user@your_remote_server
# or for trusted forwarding (fewer security checks, potentially faster)
ssh -Y user@your_remote_server
Once connected, simply run your graphical application:
xeyes
firefox
# etc.
The application’s window will appear on your local desktop. This requires an X server running on your local machine (e.g., XQuartz on macOS, most Linux desktops have it by default, PuTTY/MobaXterm can handle it on Windows).
Note: X11 forwarding can be slow over high-latency connections due to the amount of data transferred.
Conclusion
SSH is far more than just a remote terminal. By leveraging its powerful configuration options, tunneling capabilities, agent management, and debugging tools, you can transform your command-line workflow. These tricks empower you to work more securely, efficiently, and with greater flexibility across your infrastructure.
Start small: pick one or two of these tricks and integrate them into your daily routine. The ~/.ssh/config
file is an excellent starting point for most users, offering immediate productivity gains. As you become more comfortable, explore the depths of port forwarding and connection multiplexing.
What are your favorite SSH tricks? Share them in the comments below!
Further Reading & Resources:
- OpenSSH Project
man ssh
man ssh_config
man sshd_config
- Using an SSH config file
- SSH Tunneling Explained