Using ssh_config(5) and FoxyProxy for fun and profit
by Bjørn Ove Grødal Wærås
The other day, as I just had updated my workstation to Fedora 27, I realized maybe the Include statement in ssh_config(5) had been implemented. And indeed it had.
So it’s time to reorganize my ssh-config-generate script, FoxyProxy browser plugin for tunneling web traffic through ssh, and maybe even setting up systemd so I don’t have to manually initiate the ssh sessions!
Now why would I need this? Consider the following problem: I need to connect to the web interface of a switch at a customers location.
- The customer has set up firewall, and only allows ssh from one specific host on the Internet -
- On the other hand, I can only connect to one server in the customers DMZ -
- Only a server deep in the customers backend network can connect to the web interface on the switch -
- Finally, the switch has an alternative DNS name in the customer’s internal DNS -
In order to solve this, we have to make some assumptions for the above scenario:
- ssh-server on all machines are set up, and you can manually ssh from one to the other.
- authentication using ssh keys, ssh agent, sshpass or any other mechanism is just working.
First lets look at the main ssh client configuration file:
Include config.d/*.conf Include ~/Customers/*/.ssh/config Host * ControlMaster auto ControlPath ~/.ssh/session-%r@%h:%p ControlPersist 120 ForwardAgent no VisualHostKey no
Include includes configuration files from
/home/me/.ssh/config.d with file names ending with .conf. The file
name ending with .conf is just so that I can rename a file to disable
it, which is handy. Also notice the relative path, so ssh defaults to
Include reads the ssh_config files from where I keep my
customer specific config files. An example customer would have its
config file in
/home/me/Customers/customer-a/.ssh/config. This allows
me to move the complete customers directory to
/home/me/Customers/00_inactive to disable the config.
Then comes the default host configuration. This sets parameters for
all hosts, unless overridden per host. Here i set up
ControlMaster. This allows for reuse of connections through the
ControlPersist specifies how long the connection
will be kept around after going idle.
Next i disallow forwarding of the ssh-agent, as i want my open
ssh-keys to stay om my computer. I also disable the
as I generally don’t want lots of output in my terminal.
Now lets move on to the host configuration for my own jumphost, the server I need to connect through in order to be allowed through the customer firewall.
This is our own server, so I let the config live in the file
Host jumpy HostName my_jumphost.me.example.com
Put simply, this allows med to type “ssh jumpy”, and ssh will connect using the full hostname.
Customer specific configuration
Now lets focus on customer-a.
Here the config resides in
Host cust-a-edgy HostName ssh.customer-a.example.com Port 2222 User my_user ProxyCommand ssh -W %h:%p jumpy # ProxyCommand ssh -T jumpy nc -w 420 -q 42 %h %p Host cust-a-server123 HostName server_123.secure.customer-a.example.com User some_admin_user DynamicForward 31001 LocalForward 31080 220.127.116.11:80 ProxyJump cust-a-edgy
This defines the two customer servers, and I give them my own names so tab-completion is more logical for me.
As the host cust-a-edgy is listening on a public IP address on the
Internet, the customer has changed the port.
ProxyCommand defines a
command to use instead of the regular ssh, which lets me control the
previous server in the jump-chain that should be connected to first.
Also included in a comment is the older way of doing the same in “netcat mode”.
The second host definition is the last server in the ssh jump-chain, so the forwarding configuration resides here.
DynamicForward will listen with a SOCKS PROXY on port 31001 on a
local interface on my workstation, and all traffic to this port will
be forwarded through the ssh jump-chain all the way to server_123.
I also added the line with
LocalForward just to show that I also can
listen on any given local port, forward every packet through the
jump-chain to server_123, and from this host, the packets will be sent
to the 18.104.22.168, port 80.
This host configuration block also uses the brand new
statement. This statement accepts a comma separated list of jump hosts to go through
to get to this host. SWEET!
With these few lines in the correct config files I can now type “ssh cust-a-server123” and have a shell on server_123!
Before I leave the ssh config, just let me say that all of this is documented in the ssh_config(5) man page. Also if you have not configured ssh-keys, you will be prompted for password for every host.
Now that we have a SOCKS PROXY on localhost port 31001, we can tell my
web browser to use this for connecting to the desired web interface on
switch_123.internal.example.com .I could set this as the default proxy server in my browser’s
configuration, but since I am using Firefox, and there is a add-on for
managing multiple proxys, FoxyProxy, I would rather use that.
First install the add-on.
Then set up a proxy in FoxyProxy:
- Click the small Foxy icon somewhere in your browser.
- Make sure to select “Use Enabled Proxies By Patterns and Priority”
- Click the same icon again, and select “Options”, and then “Add”
- Select “SOCKS5” as “Proxy Type”
- Insert “127.0.0.1” or “localhost” as “IP address, DNS name, server name”
- Put “31001” as “Port”. This is the DynamicForward from the ssh config above.
- Also make sure the “Send DNS through SOCKS5 proxy?” is toggled to “On”. This will ask for hostnames through the SOCKS connection, and resolve the hostname inside the customers internal network.
- Click “Save & Edit Patterns” to adjust what traffic will use this proxy.
- Remove the default wildcard for “all URLs” by clicking the garbage can below “Delete”
- Click “New” to add a new pattern
- Type some name, and insert “switch_123.internal.example.com” in the pattern field.
You are now ready to point your browser to http://switch_123.internal.example.com !
Wouldn’t it be nice if…
SystemD was configured to listen on the DynamicForward proxy port, and start the ssh session as it would be needed? Or if you could start new ssh sessions through a SOCKS proxy? Oh wait; you can use Corkscrew for that ;)
Do you want to work with Bjørn Ove Grødal Wærås? We're always on the lookout for people with experience in Linux and open source software. Let us know if you are interested in joining our team!
Looking for more content? Check out our techblog or read our whitepapers and how-to guides.
Subscribe via RSS