network ssh scp - ghdrako/doc_snipets GitHub Wiki

Escape Sequence

# Supported escape sequences:
~.  - terminate connection (and any multiplexed sessions)
~B  - send a BREAK to the remote system
~C  - open a command line
~R  - Request rekey (SSH protocol 2 only)
~^Z - suspend ssh
~#  - list forwarded connections
~&  - background ssh (when waiting for connections to terminate)
~?  - this message
~~  - send the escape character by typing it twice

Compare a remote file with a local file

ssh user@host cat /path/to/remotefile | diff /path/to/localfile -

SSH connection through host in the middle

ssh -t reachable_host ssh unreachable_host

Run command over SSH on remote host

cat > cmd.txt << __EOF__
cat /etc/hosts
__EOF__

ssh host -l user $(<cmd.txt)

Running the Script on multiple Servers

for server in $(cat servers.txt) ; do ssh your_user@${server}
'bash -s' < ./remote_check.sh ; done
$cat remote_check.sh
#!/bin/bash
server_name=$(hostname)
function memory_check() {
echo "#######"
echo "The current memory usage on ${server_name} is: "
free -h
echo "#######"
}
function cpu_check() {
echo "#######"
echo "The current CPU load on ${server_name} is: "
echo ""
uptime
echo "#######"

}
function tcp_check() {
echo "#######"
echo "Total TCP connections on ${server_name}: "
echo ""
cat /proc/net/tcp | wc -l
echo "#######"
}
function kernel_check() {
echo "#######"
echo "The exact Kernel version on ${server_name} is: "
echo ""
uname -r
echo "#######"
}
function all_checks() {
memory_check
cpu_check
tcp_check
kernel_check
}
all_checks

Get public key from private key

ssh-keygen -y -f ~/.ssh/id_rsa

Get all fingerprints

ssh-keygen -l -f .ssh/known_hosts

SSH authentication with user password

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no user@remote_host

SSH authentication with publickey

ssh -o PreferredAuthentications=publickey -o PubkeyAuthentication=yes -i id_rsa user@remote_host

Simple recording SSH session

function _ssh_sesslog() {

  _sesdir="<path/to/session/logs>"

  mkdir -p "${_sesdir}" && \
  ssh $@ 2>&1 | tee -a "${_sesdir}/$(date +%Y%m%d).log"

}

# Alias:
alias ssh='_ssh_sesslog'

Using Keychain for SSH logins

### Delete all of ssh-agent's keys.
function _scl() {

  /usr/bin/keychain --clear

}

### Add key to keychain.
function _scg() {

  /usr/bin/keychain /path/to/private-key
  source "$HOME/.keychain/$HOSTNAME-sh"

}

SSH login without processing any login scripts

ssh -tt user@host bash

Port Forwarding

Recalcitrant user can tunnel SSH inside DNS, HTTP, or almost any other service or protocol. The only way to absolutely block SSH is to deny all TCP or UDP connections from the inside of your network to the outside world, use a Web proxy that intelligently inspects traffic, and not allow your clients access to public DNS even through a proxy.

Example Environment

SSH client is behind a firewall. This might be anything from a corporate firewall to a home router.The SSH server is on the public Internet. Anyone can connect to it, and it can freely access the rest of the Internet.

Types of Port Forwarding:

  • local port forwarding,
  • remote port forwarding, and
  • dynamic port forwarding

SSH local port forwarding

Local port forwarding redirects one port on the client to one port on the server. Essentially you're saying, "Grab such-and-such port on the SSH server and make it local to my client."

Local forwarding is used to forward a port from the client machine to the server machine. Basically, the SSH client listens for connections on a configured port, and when it receives a connection, it tunnels the connection to an SSH server. The server connects to a configurated destination port, possibly on a different machine than the SSH server.

Typical uses for local port forwarding include:

  • Tunneling sessions and file transfers through jump servers
  • Connecting to a service on an internal network from the outside
  • Connecting to a remote file share over the Internet

Quite a few organizations for all incoming SSH access through a single jump server.

ssh -L 80:intra.example.com:80 gw.example.com

This example opens a connection to the gw.example.com jump server, and forwards any connection to port 80 on the local machine to port 80 on intra.example.com.

By default, anyone (even on different machines) can connect to the specified port on the SSH client machine. However, this can be restricted to programs on the same host by supplying a bind address:

    ssh -L 127.0.0.1:80:intra.example.com:80 gw.example.com

To tell the SSH client to activate local forwarding, use the -L flag.

# ssh -L localIP:localport:remoteIP:remoteport hostname

If you don't specify an IP address on the SSH client, SSH attaches to 127.0.0.1. You can skip the first colon in this case, making the command:

# ssh -L localport:remoteIP:remoteport hostname 

Example 0: I use local port forwarding to connect to a remote server pride, that doesn't encrypt its HTTP services, adding encryption to the otherwise insecure channel. In this case, I want to connect port 80 on my local machine to port 80 on pride's localhost address.

# sudo ssh -L 80:127.0.0.1:80 mwlucas@pride

Example 1:

# Forwarding our local 2250 port to nmap.org:443 from localhost through localhost
host1> ssh -L 2250:nmap.org:443 localhost

# Connect to the service:
host1> curl -Iks --location -X GET https://localhost:2250

Example 2:

# Forwarding our local 9051 port to db.d.x:5432 from localhost through node.d.y
host1> ssh -nNT -L 9051:db.d.x:5432 node.d.y

# Connect to the service:
host1> psql -U db_user -d db_dev -p 9051 -h localhost

    -n - redirects stdin from /dev/null
    -N - do not execute a remote command
    -T - disable pseudo-terminal allocation

SSH remote port forwarding

Remote port forwarding works in reverse. A port on the SSH server is forwarded to a port on your SSH client. You're saying, "Take such-and-such port on my client and attach it to the remote server."

# ssh -R remoteIP:remoteport:localIP:localport hostname

If you don't specify an IP address to attach to on the SSH server, SSH attaches to 127.0.0.1.

# ssh -R remoteport:localIP:localport hostname

I want to connect port 2222 on SSH server pride to port 22 on the SSH client, using the localhost address on both sides, so I run:

$ ssh -R 2222:localhost:22 pride

My client connects to the SSH server and gives me a command prompt. As long as that SSH session remains open, another user on pride could SSH to my workstation by running:

$ ssh -p 2222 localhost
ssh -R 8080:localhost:80 public.example.com

This allows anyone on the remote server to connect to TCP port 8080 on the remote server. The connection will then be tunneled back to the client host, and the client then makes a TCP connection to port 80 on localhost. Any other host name or IP address could be used instead of localhost to specify the host to connect to.

This particular example would be useful for giving someone on the outside access to an internal web server. Or exposing an internal web application to the public Internet. This could be done by an employee working from home, or by an attacker.

By default, OpenSSH only allows connecting to remote forwarded ports from the server host. However, the GatewayPorts option in the server configuration file sshd_config can be used to control this. The following alternatives are possible:

    GatewayPorts no

This prevents connecting to forwarded ports from outside the server computer.

    GatewayPorts yes

This allows anyone to connect to the forwarded ports. If the server is on the public Internet, anyone on the Internet can connect to the port.

    GatewayPorts clientspecified

This means that the client can specify an IP address from which connections to the port are allowed. The syntax for this is:

    ssh -R 52.194.1.73:8080:localhost:80 host147.aws.example.com

In this example, only connections from the IP address 52.194.1.73 to port 8080 are allowed.

# Forwarding our local 9051 port to db.d.x:5432 from host2 through node.d.y
host1> ssh -nNT -R 9051:db.d.x:5432 node.d.y

# Connect to the service:
host2> psql -U postgres -d postgres -p 8000 -h localhost
$ ssh 10.0.0.50 df -h  #  execute a single command on the remote host using ssh

Dynamic Port Forwarding

Dynamic port forwarding transforms your SSH client into a SOCKS proxy. Any traffic sent to the proxy will be sent to the SSH server, which will forward that traffic as its own routing and firewall rules permit. For this example, I have a client behind a firewall and a server on the public Internet. I'll configure port 9999 on my client as the SOCKS server, and dynamically forward all traffic to the server for processing. I'll then point my Web browser at that port. All of my Web traffic should go over the tunnel and then onto the Internet, bypassing the local firewall and proxy server.

$ ssh -D localaddress:localport hostname

Here, I create a proxy on port 9999 on the local host. All traffic sent to the proxy is forwarded to the SSH server pride, who in turns sends it to its destination.

$ ssh -D 9999 pride

As usual with port forwarding, you'll log on to the server and get a command prompt. The dynamic forwarding runs in the background. Configure the Web browser on the client machine to use a SOCKS proxy on port 127.0.0.1:9999. It should send all traffic over the SSH session to your server.

Backgrounding OpenSSH Forwarding

Sometimes you want to use OpenSSH to forward a connection, but you don't really want a terminal session on the SSH server. Use the -N flag to tell ssh to not run anything, including a terminal, on the remote server, and the -f flag to tell ssh to go into the background on the client. Here, I background a local forwarding connection to the server pride.

$ ssh -fNL 2222:localhost:22 pride &

By backgrounding this command, you get your original terminal back. This is useful when you are not allowed to have shell access on the SSH server, but you are allowed to authenticate yourself to the server and create a tunnel. (This is one way to create an SSH-based VPN.)

pubkey auth

ssh-keygen
chmod 700 ~/.ssh
chmod 600 ~/.ssh/*
# copy pub key to server
ssh-copy-id [email protected]

# copy pubkey to cliboard (linux)
cat ~/.ssh/id_rsa.pub | pbcopy

naive approach to copy files from internal nodes through a jump server

$ ssh -A bob@jump-server
$ ssh bob@internal-server '/usr/local/bin/myscript.sh > output.csv'
$ scp bob@internal-server:output.csv . && exit
$ scp bob@jump-server:output.csv .

To forward ports locally, an SSH tunneling could be created to access services in a local machine.

$ ssh -N bob@jump-server -L 8080:internal-web-server:3000

SCP

SCP, or the secure copy protocol, was designed as a replacement for RCP. SFTP, or Secure FTP, is a protocol to replace FTP. It's an interactive protocol, allowing you to browse remote file systems. OpenSSH includes the client programs sftp and scp.

$ scp source-hostname:filename destination-hostname:filename
$ scp data.txt sloth:stuff.txt
scp -rp /home/mwlucas sloth.blackhelicopters.org:    # recursively copy a directory to another machine, use the arguments -rp

SFTP

The SSH File Transfer Protocol (SFTP) is more flexible than SCP. Where SCP only copies files, SFTP permits many different file operations such as renaming and removing files, listing directories, and so on. SFTP commands are almost identical to FTP commands to simplify transition.

Keeping SSH Connections Open

The problem with keepalives is that temporary disconnections will terminate the session. If your service provider has a problem in the middle of the night and the keepalive packets cannot cross the network for a few seconds, either your client or your server will terminate the connection.

You can set two different SSH keepalives:

  • TCP keepalives and
  • SSH keepalives

A TCP keepalive is part of the TCP protocol, is sent at the transport layer, and is not part of SSH itself. When a TCP connection remains idle for a length of time, it times out and disconnects.

OpenSSH includes a keepalive feature that sends keepalives in the encrypted channel, making those keepalives much more difficult to forge.

PuTTY supports only TCP keepalives.

On the left side of the PuTTY Configuration screen, go to the Connection button. The first option is Seconds between keepalives. This defaults to 0, disabling keepalives. In most cases, sending a TCP keepalive every 90 seconds suffices to hold a connection open.

The OpenSSH server supports TCP keepalives by default. If you want to disable this feature for some reason, set the option TCPKeepAlive to no in sshd_config

OpenSSH supports keepalives within the actual SSH channel. The keepalive packets tell intermediary network devices that this TCP session is still in use. Receiving a keepalive tells the host that the remote end is still there, and that the SSH session is still valid. An SSH keepalive is also more likely to continue holding a session open through lower-end NAT devices.

To enable SSH keepalives, decide how often you want to send a keepalive packet, and how many of those packets can be missed before the host disconnects the SSH session. The server uses the options ClientAliveInterval and ClientAliveCountMax. The client supports the options ServerAliveInterval and ServerAliveCountMax. The AliveInterval options specify how many seconds the connection needs to be idle before the host sends a keepalive request. To make a client transmit a keepalive after 90 seconds of inactivity, set ServerAliveInterval to 90. The default is 0, disabling keepalives. The AliveCountMax options tell the host how many keepalives it needs to send without receiving a response before terminating the connection. The default is 3.

Example

  • in the server's sshd_config:
ClientAliveInterval 90
ClientAliveCountMax 5

On the client side, we've put the following in ssh_config.

ServerAliveInterval 90
ServerAliveCountMax 4

if you cannot maintain a TCP connection you cannot maintain an SSH session. If you want to keep your connection alive no matter what, cranking AliveCountMax to high values helps.