How it works...

The -J and ProxyJump options are a way to connect through a specified host, to a host beyond.

The manual entry from the official manual pages (https://man.openbsd.org/ssh) for -J [user@]host[:port] is as follows:

Connect to the target host by first making a ssh connection to the jump host described by destination and then establishing a TCP forwarding to the ultimate destination from there. Multiple jump hops may be specified separated by comma characters. This is a shortcut to specify a ProxyJump configuration directive.

The manual entry from https://man.openbsd.org/ssh_config for ProxyJump is as follows:

Specifies one or more jump proxies as either [user@]host[:port] or an ssh URI. Multiple proxies may be separated by comma characters and will be visited sequentially. Setting this option will cause ssh(1) to connect to the target host by first making a ssh(1) connection to the specified ProxyJump host and then establishing a TCP forwarding to the ultimate target from there.

If we use the -v flag with SSH, we can see what happens in more detail:

[vagrant@centos1 ~]$ ssh -v CentOS3-V4
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
debug1: Reading configuration data /home/vagrant/.ssh/config
debug1: /home/vagrant/.ssh/config line 1: Applying options for *
debug1: /home/vagrant/.ssh/config line 8: Applying options for CentOS3-V4
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 58: Applying options for *
debug1: Setting implicit ProxyCommand from ProxyJump: ssh -v -W %h:%p CentOS2-V4
debug1: Executing proxy command: exec ssh -v -W 192.168.33.12:22 CentOS2-V4
<SNIP>
debug1: permanently_drop_suid: 1000
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
debug1: Reading configuration data /home/vagrant/.ssh/config
debug1: /home/vagrant/.ssh/config line 1: Applying options for *
debug1: /home/vagrant/.ssh/config line 4: Applying options for CentOS2-V4
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 58: Applying options for *
debug1: Connecting to 192.168.33.11 [192.168.33.11] port 22.
debug1: Connection established.
debug1: key_load_public: No such file or directory
<SNIP>
debug1: kex_input_ext_info: server-sig-algs=<rsa-sha2-256,rsa-sha2-512>
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Next authentication method: gssapi-keyex
debug1: No valid Key exchange context
debug1: Next authentication method: gssapi-with-mic
debug1: Unspecified GSS failure. Minor code may provide more information
No Kerberos credentials available (default cache: KEYRING:persistent:1000)

debug1: Unspecified GSS failure. Minor code may provide more information
No Kerberos credentials available (default cache: KEYRING:persistent:1000)

debug1: Next authentication method: publickey
debug1: Trying private key: /home/vagrant/.ssh/id_rsa
debug1: Trying private key: /home/vagrant/.ssh/id_dsa
debug1: Trying private key: /home/vagrant/.ssh/id_ecdsa
debug1: Trying private key: /home/vagrant/.ssh/id_ed25519
debug1: Next authentication method: password
vagrant@192.168.33.11's password:
debug1: Authentication succeeded (password).
Authenticated to 192.168.33.11 ([192.168.33.11]:22).
debug1: channel_connect_stdio_fwd 192.168.33.12:22
debug1: channel 0: new [stdio-forward]
debug1: getpeername failed: Bad file descriptor
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: network
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: Remote protocol version 2.0, remote software version OpenSSH_7.4
debug1: match: OpenSSH_7.4 pat OpenSSH* compat 0x04000000
debug1: Authenticating to 192.168.33.12:22 as 'vagrant'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256
debug1: kex: host key algorithm: ecdsa-sha2-nistp256
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: curve25519-sha256 need=64 dh_need=64
debug1: kex: curve25519-sha256 need=64 dh_need=64
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
<SNIP>
vagrant@192.168.33.12's password:
debug1: Authentication succeeded (password).
Authenticated to 192.168.33.12 (via proxy).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: proc
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: Sending environment.
debug1: Sending env LANG = en_GB.UTF-8
Last login: Thu Aug 9 14:22:08 2018 from 192.168.33.11
[vagrant@centos3 ~]$

Emboldened in the preceding output, we can see the key steps that take place during the connection sequence:

  1. SSH reads the configuration for the host we're connecting to.
  2. SSH realises it has to use a ProxyJump host to access the specifed box.
  3. SSH translates the ProxyJump option into the equivalent ProxyCommand entry.
  4. SSH reads the configuration for the ProxyJump host.
  5. SSH connects and authenticates against the ProxyJump host.
  6. SSH uses its established connection to the ProxyJump to connect to the destination host.
  7. SSH notes that it's authenticated to the destination host (via proxy).