Prevent SSH connections from timing out so often

The default null  packet used by an SSH client to keep the connection alive is usually sent every 5 minutes. If the SSH sessions are timing out frequently, it might help to send those packets faster.

Add these lines to your SSH client configuration and profit:

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 2

 

Customizing screen using screenrc

This is my current .screenrc  file, it includes a nice status bar (hardstatus) and easy window switching by using Alt+Left/Right Arrow Keys

hardstatus alwayslastline
hardstatus string "%{= KW}%-Lw%{+b Bw}%50>%n-%f %t%{-}%+Lw%< %=%C%a %Y-%M-%d"

bindkey ^[[1;3D prev # Alt+Left = Previous Window
bindkey ^[[1;3C next # Alt+Right = Next Window

defscrollback 2000 # Keep a lot of history

bind c screen 1 # Start numbering at 1

This can be copied to any machine and placed in the home directory of the user (~), or manually sourced inside screen by pressing Ctrl+A and then typing :source <path_to_screenrc>

 

Result:

 

Managing SSH tunnels running in the background

A common problem for me when setting up SSH tunnels is that even though the ssh client process is running, data is not going through.

Steps to reproduce:

  • Create a tunnel (ssh -D  or ssh -L  or ssh -R ) on some port
  • Data is not going through, so we need to restart it
  • The connection cannot be established because bind: Address already in use
  • We have to kill the old client, ps aux | grep ssh , to find the right  process and then kill -9  it
  • Re-create the tunnel

Instead, we could leverage sockets when creating the connection, which allow communication with the SSH process (as opposed to searching for the pid ). This is enabled by the -S option:

ssh -NMfn -S /tmp/server1.local.socket -o ExitOnForwardFailure=yes -D 8080 server1.local 

# Additional flags: 
# -N Don't open a terminal
# -M Master mode, necessary for socket commands
# -f Go to background
# -S Control socket

Once the socket is set up, we can send commands to it. For example, exit  to close the connection (regardless of the state of the connection):

ssh -S /tmp/server1.local.socket -O exit server1.local

Finally, here is a script that will create SOCKS tunnels (proxies) to a list of hostnames. When the script is run again, it will attempt to close any existing tunnels and establish brand new connections:

#!/bin/bash


# These are the servers that we will set up SOCKS tunnels to
HOSTS="server1.local server2.remote"
BASE_PORT=11000

# Some fancy output
bold=$(tput bold)
normal=$(tput sgr0)

# Send exit to all existing sockets
for HOST in $HOSTS; do
  if [ -e /tmp/$HOST.socket ]; then
    ssh -S /tmp/$HOST.socket -O exit $HOST
  fi
done

# Set up variables and nice output
PORT=$BASE_PORT
STATUS_LINE="%-35s%-15s${bold}%s${normal}"
printf "${bold}$STATUS_LINE\n${normal}" "HOST" "SOCKS PORT" "STATUS"
for HOST in $HOSTS; do
  printf "$STATUS_LINE" "$HOST" "$PORT" "CONNECTING"
  # Attempt to create tunnel
  ssh -NMfn -S /tmp/$HOST.socket -o ConnectTimeout=5 -o ExitOnForwardFailure=yes -D $PORT $HOST &> /dev/null
  # Report outcome
  if (( $? == 0 )); then
    printf "\r$STATUS_LINE\n" "$HOST" "$PORT" "DONE      "
  else
    printf "\r$STATUS_LINE\n" "$HOST" "$PORT" "FAILED    "
  fi

  # Increment port number
  PORT=$(expr $PORT + 1)                                                                                                                                                                                                                     
done