SSH Remote Network Access

In a 2020 technical meeting, someone asked about some SSH ProxyJump documentation I’d posted. I promised to follow up with a full configuration for using ProxyJump with a remote network, so here goes nothing.

Network View

Let’s assume a simple setup:

I 0 n . t 0 e . r 0 n . e 0 t / 0 B 1 a 2 s . t 1 i 2 o . n 1 2 . 1 2 l o g 1 i 0 n . . 1 m 0 y . . 1 c 0 o . m 1 P r i 1 v 0 a . t 1 e 0 . / 1 0 . . m 0 y / . 2 c 4 o m

Here are three views of it.

  • Logical: Internet <-> Bastion Host <-> Private Network
  • DNS: Internet <-> login.my.com <-> *.my.com
  • IPv4: 0.0.0.0/0 <-> 12.12.12.12 + 10.10.10.1 <-> 10.10.10.0/24

The bastion host can also be called a “jump host.” It has two interfaces: public (12.12.12.12) and private (10.10.10.1).

When Simple Isn’t Enough

The simple way to access a *.my.com host (e.g., dev.my.com) is with a shell one-liner:

# plain ssh
ssh -J login.my.com dev.my.com
# scp
scp -o 'ProxyJump login.my.com' myfile.txt dev.my.com:/my/dir

It’s often the case, however, that you login to several my.com hosts and that you further have some internal-only web applications you want to access there. (What follows will work more easily if you have SSH keys working with ssh-agent, but it’s not necessary.)

SSH Client Configuration

First, we need to setup your ~/.ssh/config file. The Host stanza for your bastion host will also enable three optional SSH features: compression, agent forwarding, and SOCKS5 proxying (via the DynamicForward setting). The SOCKS5 proxy will allow you to reach your internal-only web apps.

# part of ~/.ssh/config
Host login.my.com
  Compression yes
  ControlPath ~/.ssh/cm-%r@%h:%p
  ControlMaster auto
  ControlPersist 9H
  ForwardAgent yes
  DynamicForward 127.0.0.1:1080

The various Control directives allow you to run multiple SSH sessions over a single network connection. The ssh_config(5) man page has more information.

The next customization for your ssh config file ensures any SSH session destined for *.my.com uses your control session. This stanza must specifically exclude your bastion host:

# part of ~/.ssh/config
Host *.my.com !login.my.com
  CheckHostIP no
  ProxyCommand ssh mybastion -W %h:%p

The important thing to note here is that you’ll need to use fully qualified domain names (e.g., dev.my.com) rather than short versions (dev) if you want to use the multiplex connection.

SSH Session Setup

Now setup the session:

ssh -f -N login.my.com 2>/dev/null

The “-f -N” options will invoke ssh without a remote command and put it into the background. Even though it’s backgrounded, ssh will allow you to check its status:

ssh -O check login.my.com

It will return something like “Master running” if successful.

Now you can do ssh dev.my.com in a terminal window and you will be able to directly into your dev machine. (I say “directly,” but if you run “who” while logged in, your session will show up as coming from the bastion host.) As a side benefit, you will also be able to use scp directly to my.com hosts. Remember, you need to use the FQDN. If that’s a hassle for you, try a shell alias to simplify things.

SOCKS5 Web Proxy

Finally, if you want to be able to access your internal-only web apps using the SOCKS5 proxy, you’ll need to configure your web browsers accordingly.

In both setups below, I reference 1080 as the proxy port. That number is arbitrary, but it must match the port you specified in your DynamicForward directive (above).

curl

The easiest http client to configure for this is the curl command-line utility. You just need to set the proxy option:

# all on one line
curl --proxy socks5h://127.0.0.1:1080 https://webapp.my.com

# or set an environment variable for multiple invocations
export HTTPS_PROXY="socks5h://127.0.0.1:1080"
curl https://webapp.my.com
curl https://dashboard.my.com

The “socks5h” protocol designation ensures that DNS name resolution is done at the SSH bastion host, not on your local workstation. The ENVIRONMENT section of the curl(1) man page lists the range of environment variables you can use to indicate the presence of a proxy.

Firefox

If you want a full-featured web browser for accessing your internal network web sites, you can use Firefox for that:

  1. Launch Firefox
  2. Enter “about:config” into the URL box.
  3. Ignore the “this might void your warranty” warning.
  4. Change some settings:
network.proxy.socks: localhost
network.proxy.socks_port: 1080
network.proxy.socks_remote_dns: true
network.proxy.type: 1

I’ve found it necessary to start my proxied browser within a couple minutes of setting up the control/multiplex session. Something times out otherwise, but I haven’t really sought to understand that. At that point, Firefox ought to be able to browser your internal web sites.

It’s worth noting that, with those configuration changes in place, Firefox will fail to work properly if your ssh session isn’t running. Personally, I only use Firefox for proxied communications, but if you want more flexibility you can setup a Firefox profile just for proxied sessions.

FoxyProxy

Another option for proxying browser traffic is the extension available from FoxyProxy. The company offers various commerical proxy and VPN services, but its proxy extension for various web browsers — Chrome, Edge, Firefox, Safari, and others — is open source and free to download.

SSH Session Close

Finally, when you’re ready to close your multiplex session, just ask ssh nicely:

ssh -O exit login.my.com

Howto  Networking