OpenSSH

OpenSSH is a free, open-source suite of tools that follow the SSH protocol, provide encrypted communication, remote login, and file transfers between computers

The OpenSSH suite consists of the following:


ssh (client)

OpenSSH remote login client

ssh connects and logs into the specified destination, which may be specified as either: user@hostname or a URI (Uniform Resource Identifier) of the form ssh://user@hostname:port

Non-interactive command execution

If you add a command after:

ssh user@host ls
ssh ssh://user@host ls

Instead of opening a shell, SSH will connect and runs ls on the remote machine and prints the output and disconnect


ssh options / flags

full OpenBSD manual-page can be found here, here’s some options:

-i identity_file

Selects a file from which the identity (private key) for public key authentication is read. You can also specify a public key file to use the corresponding private key that is loaded in ssh-agent when the private key file is not present locally.

The default is ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519 and ~/.ssh/id_ed25519_sk

It is possible to have multiple -i options (and multiple identities specified in configuration files).

If no certificates have been explicitly specified by the CertificateFile directive, ssh will also try to load certificate information from the filename obtained by appending -cert.pub to identity filenames.

CertificateFile:
CertificateFile is a configuration option in SSH (used in ~/.ssh/config or /etc/ssh/ssh_config) that tells SSH to use a specific SSH certificate file when authenticating

-p port

Port to connect to on the remote host (default is 22)

This can be specified on a per-host basis in the configuration file, that mean you don’t have to type the option every time in the command, you can set it once for a specific host in the SSH configuration file, and SSH will automatically apply it whenever you connect to that host.

ssh -p 2005 user@host

-l login_name

Specifies the user to log in as on the remote machine. This also may be specified on a per-host basis in the configuration file

ssh -l user host

Less common than user@host, but still valid.


-4

Forces ssh to use IPv4 addresses only


-6

Forces ssh to use IPv6 addresses only.


-v

Verbose mode. Causes ssh to print debugging messages about its progress. Multiple -v options increase the verbosity. The maximum is 3.


-L (local forwarding)

Create a local entry point (port or Unix socket) on your machine, and forward everything through an encrypted SSH tunnel to a destination on the remote server side. In short: makes something on your laptop behave like it is connected to something on the remote server.

There’s 4 forms:

-L [bind_address:]port:host:hostport
     
-L [bind_address:]port:remote_socket
     
-L local_socket:host:hostport
     
-L local_socket:remote_socket

bind_address (optional)

By default, the local port is bound in accordance with the GatewayPorts setting. However, an explicit bind_address may be used to bind the connection to a specific address. The bind_address of localhost indicates that the listening port be bound for local use only, while an empty address or * indicates that the port should be available from all interfaces.

GatewayPorts no (default)

  • Forwarded ports are always bound to localhost
  • SSH ignores any attempt to expose them externally

GatewayPorts yes

  • Forwarded ports are allowed to bind to all interfaces

GatewayPorts clientspecified client decides:

  • 127.0.0.1 = local only
  • 0.0.0.0 or * = all interfaces (LAN-accessible if allowed)

port / local_socket

The entry point on your machine. This is what your local apps connect to

This is the fake service your machine exposes

host:hostport / remote_socket

The destination as seen from the remote server, this is resolved on the server side, not your machine

user@server

The SSH server. The tunnel goes through this host


Now each form in detail:

1. TCP to TCP forwarding

-L [bind_address:]local_port:host:hostport

means open a local TCP port and forward it to a remote TCP service. Example:

ssh -L 8080:localhost:80 user@server

It creates a local TCP listener on port 8080, and every connection to it is forwarded through an SSH tunnel to the server, where sshd opens a TCP connection to localhost:80 on the remote machine and relays data between the two sockets.


2. TCP to Unix socket forwarding

-L [bind_address:]local_port:remote_socket

means open a local TCP port, forward it to a Unix socket on the server. Example:

ssh -L 8080:/var/run/app.sock user@server

Creates a local TCP listener on localhost:8080, and each connection is forwarded through SSH to the server where sshd connects to the Unix domain socket /var/run/app.sock and relays data between the TCP stream and that socket.


3. Unix socket to TCP forwarding

-L local_socket:host:hostport

means open a Unix socket locally, forward to a remote TCP service. Example:

ssh -L /tmp/app.sock:localhost:80 user@server

Creates a local Unix domain socket at /tmp/app.sock, and each connection to it is forwarded through SSH to the server where sshd opens a TCP connection to localhost:80 and relays data between the Unix socket stream and the TCP socket.


4. Unix socket to Unix socket forwarding

-L local_socket:remote_socket

means open a Unix socket locally, forward it to a Unix socket on the server. Example:

ssh -L /tmp/app.sock:/var/run/docker.sock user@server

Creates a local Unix domain socket at /tmp/app.sock, and each connection to it is forwarded through SSH to the server where sshd connects to /var/run/docker.sock and relays data between the two Unix sockets.

docker.sock is the Unix socket used by the Docker daemon to accept API requests locally on the server, just for the example :)


-R (remote forwarding)

Creates a listening entry point (port or Unix socket) on the remote SSH server, and forwards everything through the encrypted SSH tunnel back to your local machine.

In short: makes something on the server behave like it is connected to something on your machine.

There’s 5 forms:

-R [bind_address:]port:host:hostport
     
-R [bind_address:]port:local_socket
     
-R remote_socket:host:hostport
     
-R remote_socket:local_socket
     
-R [bind_address:]port

Each form in detail:

1. TCP to TCP forwarding

-R [bind_address:]port:host:hostport

Example:

ssh -R 8080:localhost:3000 user@server

It creates a TCP listener on the remote server at port 8080, and every connection to it is forwarded through SSH to your local machine, where sshd connects to localhost:3000 and relays data between the two TCP sockets.


2. TCP to Unix socket forwarding

-R [bind_address:]port:local_socket

Example:

ssh -R 8080:/tmp/app.sock user@server

Creates a TCP listener on the remote server at port 8080, and each connection is forwarded through SSH to your local machine where sshd connects to the Unix socket /tmp/app.sock and relays data between TCP and Unix socket streams.


3. Unix socket to TCP forwarding

-R remote_socket:host:hostport

Example:

ssh -R /tmp/app.sock:localhost:3000 user@server

Creates a Unix domain socket on the remote server at /tmp/app.sock, and each connection to it is forwarded through SSH to your local machine where sshd opens a TCP connection to localhost:3000 and relays data between the Unix socket and TCP socket.


4. Unix socket to Unix socket forwarding

-R remote_socket:local_socket

Example:

ssh -R /tmp/remote.sock:/tmp/local.sock user@server

Creates a Unix domain socket on the remote server, and each connection is forwarded through SSH to your local machine where sshd connects to the local Unix socket and relays data between the two socket endpoints.


5. Port Only (dynamic SOCKS proxy)

-R [bind_address:]port

Example:

ssh -R 1080 user@server

Creates a SOCKS proxy listener on the remote server at port 1080, and SSH acts as a dynamic proxy, forwarding connections requested by SOCKS clients on the server back through the tunnel to destinations resolved on your local side.

A SOCKS proxy is a generic network proxy protocol that lets a client ask a proxy server to open a connection to any destination IP/port on its behalf, and then relay the traffic.

Note:
If the port argument is 0, the listen port will be dynamically allocated on the server and reported to the client at run time. When used together with -O forward, the allocated port will be printed to the standard output.

-D

Specifies a local dynamic application-level port forwarding. This works by allocating a socket to listen to port on the local side, optionally bound to the specified bind_address. Whenever a connection is made to this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine.

Currently the SOCKS4 and SOCKS5 protocols are supported, and ssh will act as a SOCKS server. Only root can forward privileged ports. Dynamic port forwardings can also be specified in the configuration file.

-D [bind_address:]port

By default, the local port is bound in accordance with the GatewayPorts setting. However, an explicit bind_address may be used to bind the connection to a specific address. The bind_address of localhost indicates that the listening port be bound for local use only, while an empty address or * indicates that the port should be available from all interfaces.


-J

Connect to the target host by first making an SSH connection to an intermediate jump host, and then forwarding the SSH traffic through that host to reach the final destination.

Each jump host is used in sequence, where SSH creates a tunnel through the first host, then uses it to connect to the next, until it reaches the final target.

ssh -J user@host user@host

Multiple jump hops may be specified separated by comma characters:

ssh -J jump1,jump2,jump3, ... ,jumpN user@host

IPv6 addresses must be enclosed in square brackets.

This is a shortcut for the ProxyJump configuration directive, meaning it can also be defined permanently in ~/.ssh/config instead of typing it every time.


-N

Do not execute a remote command. This is useful for just forwarding ports.

So instead of logging you into the server, SSH just stays running in the background and maintains the tunnel.


-T

Disable pseudo-terminal allocation.

SSH will not request a terminal on the remote machine, meaning no interactive shell environment is created. This is used when running non-interactive commands or when the remote side does not need a terminal


-F configfile

Specifies an alternative per-user configuration file. If a configuration file is given on the command line, the system-wide configuration file /etc/ssh/ssh_config will be ignored. The default for the per-user configuration file is ~/.ssh/config

If set to none, no configuration files will be read.

ssh -F myconfig user@host

-o option

Can be used to give options in the format used in the configuration file. This is useful for specifying options for which there is no separate command-line flag. For full details of all options, and their possible values, see ssh_config.


-V

Display the version number and exit


-q

Quiet mode. Causes most warning and diagnostic messages to be suppressed.


sshd (server daemon)

sshd listens for connections from clients. It is normally started at boot from /etc/rc. It forks a new daemon for each incoming connection. The forked daemons handle key exchange, encryption, authentication, command execution, and data exchange.


ssh-keygen


ssh-agent


ssh-add


ssh-copy-id


ssh-keyscan


File transfer tools

scp (Secure Copy)


sftp (SSH File Transfer Protocol)


OpenSSH Files

Client-side

~/.ssh/
  • id_rsa, id_ed25519 → private keys
  • id_rsa.pub → public key
  • known_hosts → trusted servers
  • config → client configuration

Server-side

/etc/ssh/
  • sshd_config → server configuration
  • ssh_host_* → server host keys

Host keys vs user keys (critical distinction)

Host keys

  • Identify the server
  • Stored on server
  • Verified by client

User keys

  • Identify the user
  • Stored on client
  • Verified by server