Better Living Through OpenSSH Config Files
By Red Siege | February 15, 2024
By: Justin Palk, Senior Security Consultant
SSH is an incredibly valuable tool for penetration testing. It provides us with a secure channel for administering machines, remotely executing tools, transferring files, forwarding ports and proxying traffic. But what if I told you it was possible to make it even better?
What if I told you you could have tab completion for opening connections to hosts you use regularly?
Or have it automatically forward ports or create the proxies you always use?
Or set your login user on a per-machine basis?
If you don’t know how to do all of this, let me introduce you to the OpenSSH client config file. This is going to be an overview of the features I find the most useful, rather than a deep-dive into all configuration options you can set on the client side.
A user’s OpenSSH client config file lives in ~/.ssh/config, alongside the authorized_keys file and the user’s public and private keys.

.ssh directory listing
The file consists of a series of host blocks setting the options for a given SSH server to connect to. At its most basic, a host block will consist of a mandatory hostname directive, and likely either a port and/or a user directive, as shown in the example below. Anything not specified in the config file will fall back on the SSH defaults, such as the current logged-in username and port 22/TCP.
host concentrator hostname 10.0.0.9 port 2222 user vpn-admin
With this block in a config file, typing ssh concentrator would be functionally equivalent to typing:
ssh vpn-admin@10.0.0.9 -p 2222
You can also tab-complete host entries in the config file on the command line, so typing ssh conc<tab> would expand out to ssh concentrator.
If there’s a port forward you use routinely on a host, such as forwarding a port on your local host to a local port on the remote server to access a C2 server’s admin port, you can use a LocalForward directive, specifying the <local IP>:<local port> <remote IP>:<remote port>. If you don’t specify a local IP, SSH will default to using localhost. The example below shows how to forward localhost port 40404/TCP on the client machine to localhost 40404/TCP on the server.
host teamserver hostname 10.10.0.2 port 2222 LocalForward 127.0.0.1:40404 127.0.0.1:40404
Similarly, you can set up a standard reverse port forward with a RemoteForward directive using the same syntax for hosts and ports. The example below would forward any requests coming to 10.10.0.3:8080 on the remote host to 127.0.0.1:8080 on the client.
host reverse-proxy hostname 10.10.0.3 port 2222 ReverseForward 10.10.0.3:8080 127.0.0.1:8080
To set up a SOCKS5 proxy every time you connect to a host, you can use the DynamicForward directive, which requires only the local IP and port to be specified. This block includes a DynamicForward directive which will open a SOCKS5 proxy on localhost port 9000/TCP every time you connect to the server.
host vps hostname 10.10.0.6 port 2222 DynamicForward 127.0.0.1:9000
To set common options used for multiple hosts, you can choose a naming scheme for those hosts and then use a wildcard host entry to set those common options. For example, let’s imagine we’re doing a penetration test of NoneSuch Ltd., and we have several pieces of infrastructure with port forwards we’re using for the test, including:
The team server will need a local port forward to access the C2 server’s admin port, and all three hosts will need SOCKS5 proxies on different ports. But they’ll all have some things in common, too, such as a port, a username, and a private key used for authentication. Also, we want to enable the escape command line on all connections (using host *, so we can use SSH control sequences to manage port forwards on the fly without having to end our session. That would give us a config file that looks like this:
host nonesuch-*
port 22422
user operator
IdentityFile /home/operator/.ssh/nonesuch_id_ed25519
host nonesuch-teamserver
hostname 10.0.10.2
LocalForward 127.0.0.1:40404 127.0.0.1:40404
DynamicForward 127.0.0.1:9000
host nonesuch-dropbox
hostname 10.0.20.2
DynamicForward 127.0.0.1:9001
host nonesuch-vps
hostname 10.0.30.2
DynamicForward 127.0.0.1:9002
host *
EnableEscapeCommandLine yes
You could also use an SSH config file to streamline connections through a jumpbox. For example, if you had a series of VPN client hosts in a restricted VLAN, accessible only through a SSH jumpbox, you could use the ProxyCommand directive to make that jumpbox serve as a proxy server to transparently access those VPN hosts, as shown below.
host jumpbox
hostname 10.100.0.1
port 22422
host vpn-*
# %h and %p below are the host and port, and will draw from the other host entries
ProxyCommand ssh jumpbox -W %h:%p
user vpn-operator
port 33533
IdentityFile /home/operator/.ssh/vpn-id_ed25519
host vpn-1
hostname 10.200.0.129
host vpn-2
hostname 10.200.0.130
host vpn-3
hostname 10.200.0.131
host vpn-4
hostname 10.200.0.132
host vpn-5
hostname 10.200.0.133
This is just scratching the surface of what you can do with an SSH config file, but it covers the day-to-day use cases that I’ve found to be really helpful. Taking just a few minutes to set up an SSH config file can remove little points of friction from your workflow and make everything go just that much more smoothly.
About Justin Palk, Senior Security Consultant:

Justin Palk has more than 16 years of experience in IT and information security, and has worked in the academic, federal civilian government and health research sectors. He has held a variety of roles including system administrator, developer, auditor, assessment team lead and web application penetration tester. He regularly competes in CTFs in the U.S. and Europe.
Certifications:
GCIH, GWAPT, GPEN, GMOB, GDSA
Related Stories
View MoreBy Red Siege | September 3, 2026
by Justin Palk A couple of years ago, I put together a series on standing up a simple Windows AD domain in a lab environment. This article is part of […]
Learn MoreBy Red Siege | August 13, 2026
by Justin Palk A couple of years ago, I put together a series on standing up a simple Windows AD domain in a lab environment. This article is part of […]
Learn MoreBy Red Siege | July 7, 2026
by Justin Palk A couple of years ago, I put together a series on standing up a simple Windows AD domain in a lab environment. This is the start of […]
Learn More