Skip to content

Instantly share code, notes, and snippets.

@debuglevel
Created December 19, 2023 09:53
Show Gist options
  • Save debuglevel/f69edb134962c92f7339dcebc1361d93 to your computer and use it in GitHub Desktop.
Save debuglevel/f69edb134962c92f7339dcebc1361d93 to your computer and use it in GitHub Desktop.
SSH JumpHost / ProxyCommand

CAUTION: Nothing tested here.

ssh -J <user>@<bastion:port> <user>@<target:port>
       ^^^^^^
       on bastion
                             ^^^^^^
                             on target
                                    ^^^^^^^^^^^^^
                                    as seen from bastion?

Using stdin/stdout:

     -W host:port
             Requests that standard input and output on the client be forwarded to host on port over the secure channel.  Implies -N, -T,
             ExitOnForwardFailure and ClearAllForwardings.
             
     ProxyCommand
             Specifies the command to use to connect to the server.  The command string extends to the end of the line, and is executed using the user's
             shell ‘exec’ directive to avoid a lingering shell process.

             In the command string, any occurrence of ‘%h’ will be substituted by the host name to connect, ‘%p’ by the port, and ‘%r’ by the remote user
             name.  The command can be basically anything, and should read from its standard input and write to its standard output.  It should eventually
             connect an sshd(8) server running on some machine, or execute sshd -i somewhere.  Host key management will be done using the HostName of the
             host being connected (defaulting to the name typed by the user).  Setting the command to “none” disables this option entirely.  Note that
             CheckHostIP is not available for connects with a proxy command.

             This directive is useful in conjunction with nc(1) and its proxy support.  For example, the following directive would connect via an HTTP proxy
             at 192.0.2.0:

                ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p

ssh -l tom -o 'ProxyCommand="ssh -l jerry -W %h:%p firewall.example.com"' realserver.example.com
    ^^^^^^                        ^^^^^^^^
    on realserver                 on firewall
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                              executed locally    

Locally the ProxyCommand is executed first (which opens a stdin/stdout pipe), and then the surrounding ssh is executed through that pipe (i.e. ssh sends its stuff into that pipe and reads from it). Therefore, both -i id_file would read from the local machine (and not one of them from the bastion).

Easiest might be to configure via ~/.ssh/config:

Host firewall
        Hostname firewall.example.com
        User debuglevel
        IdentityFile /home/debuglevel/.ssh/firewall_id
        Port 22
 
Host realserver
        Hostname realserver.example.com  # or IP as seen from firewall? (DNS probably resolved locally, but IP as available from bastion)
        User debuglevel
        IdentityFile /home/debuglevel/.ssh/realserver_id  # id on the local machine
        Port 22
        ProxyCommand ssh -W %h:%p firewall  # %h: host name to connect to, %p: port, %r: remote user name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment