# Networking

## SSH connection gateways

### Background

When connecting to well-secured networks whose internal hosts are not directly reachable from the Internet, a common pattern is “bouncing”, “gatewaying” or “proxying” SSH connections via an intermediate host (often called a “bastion”, “gateway” or “jump box”).

Gatewaying requires making an initial/outer SSH connection to the gateway system, then using that connection as a transport for the “real” connection to the final/internal host.

At a basic level, one could `ssh gatewayhost`, then `ssh internalhost` from the resulting shell. This works for individual long-running sessions, but becomes a burden when it must be done frequently.

There are two gateway solutions available in Fabric, mirroring the functionality of OpenSSH’s client: `ProxyJump` style (easier, less overhead, can be nested) or `ProxyCommand` style (more overhead, can’t be nested, sometimes more flexible). Both support the usual range of configuration sources: Fabric’s own config framework, SSH config files, or runtime parameters.

### `ProxyJump`

This style of gateway uses the SSH protocol’s `direct-tcpip` channel type - a lightweight method of requesting that the gateway’s `sshd` open a connection on our behalf to another system. (This has been possible in OpenSSH server for a long time; support in OpenSSH’s client is new as of 7.3.)

Channel objects (instances of `paramiko.channel.Channel`) implement Python’s socket API and are thus usable in place of real operating system sockets for nearly any Python code.

`ProxyJump` style gatewaying is simple to use: create a new `Connection` object parameterized for the gateway, and supply it as the `gateway` parameter when creating your inner/real `Connection`:

    from fabric import Connection

    c = Connection('internalhost', gateway=Connection('gatewayhost'))

As with any other `Connection`, the gateway connection may be configured with its own username, port number, and so forth. (This includes `gateway` itself - they can be chained indefinitely!)

### `ProxyCommand`

The traditional OpenSSH command-line client has long offered a `ProxyCommand` directive (see man ssh_config), which pipes the inner connection’s input and output through an arbitrary local subprocess.

Compared to `ProxyJump` style gateways, this adds overhead (the extra subprocess) and can’t easily be nested. In trade, it allows for advanced tricks like use of SOCKS proxies, or custom filtering/gatekeeping applications.

`ProxyCommand` subprocesses are typically another `ssh` command, such as `ssh -W %h:%p gatewayhost`; or (on SSH versions lacking `-W`) the widely available `netcat`, via `ssh gatewayhost nc %h %p`.

Fabric supports `ProxyCommand` by accepting command string objects in the `gateway` kwarg of `Connection`; this is used to populate a `paramiko.proxy.ProxyCommand` object at connection time.

### Additional concerns

If you’re unsure which of the two approaches to use: use `ProxyJump` style. It performs better, uses fewer resources on your local system, and has an easier-to-use API.

Warning

Requesting both types of gateways simultaneously to the same host (i.e. supplying a `Connection` as the `gateway` via kwarg or config, and loading a config file containing `ProxyCommand`) is considered an error and will result in an exception.