Difference between revisions of "OpenSSH-VPN script"

From UCLUG
Jump to: navigation, search
m (Chruck moved page OpenSSH-VPN to OpenSSH-VPN script: Better page description)
(Prefaced with a description of the page, script block using wiki markup)
 
Line 1: Line 1:
<pre>#!/bin/bash
+
This is a script that Jared Sutton demonstrated for his March 2013 talk about VPN capabilities of OpenSSH:
  
SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )"
+
#!/bin/bash
SSH_SOCKET=$(mktemp -u -p "$SCRIPT_DIR")
+
 
+
SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )"
if [ "$USER" != "root" ]; then
+
SSH_SOCKET=$(mktemp -u -p "$SCRIPT_DIR")
  echo "ERROR: this script must be run as the root user." 1>&2
+
  exit -1
+
if [ "$USER" != "root" ]; then
fi
+
  echo "ERROR: this script must be run as the root user." 1>&2
 
+
  exit -1
function error_exit {
+
fi
  echo "ERROR: $1" >&2
+
 
+
function error_exit {
  if [ $2 -gt -1 ]; then
+
  echo "ERROR: $1" >&2
    control_c
+
 
  fi
+
  if [ $2 -gt -1 ]; then
 
+
    control_c
  exit $2
+
  fi
}
+
 
 
+
  exit $2
function server_cmd {
+
}
  ssh -S "$SSH_SOCKET" [email protected]"$SERVER" "$1"
+
}
+
function server_cmd {
 
+
  ssh -S "$SSH_SOCKET" [email protected]"$SERVER" "$1"
function ssh_client_command {
+
}
  ssh -S "$SSH_SOCKET" -O $* "$SERVER"
+
}
+
function ssh_client_command {
 
+
  ssh -S "$SSH_SOCKET" -O $* "$SERVER"
function control_c {
+
}
  echo ""
+
  server_cmd "iptables -t nat -F"
+
function control_c {
  echo "INFO: Flushed the NAT firewall table on the server"
+
  echo ""
  echo -n "INFO: Terminating the SSH connection..."
+
  server_cmd "iptables -t nat -F"
  ssh -S "$SSH_SOCKET" -O exit "$SERVER"
+
  echo "INFO: Flushed the NAT firewall table on the server"
  exit 0
+
  echo -n "INFO: Terminating the SSH connection..."
}
+
  ssh -S "$SSH_SOCKET" -O exit "$SERVER"
 
+
  exit 0
function process_args {
+
}
  options=':s:n:m:k'
+
 
+
function process_args {
  while getopts "$options" option; do
+
  options=':s:n:m:k'
    case "$option" in
+
 
      s ) SERVER="$OPTARG" && [ -n "$PRIV_KEY" ] || PRIV_KEY="$SCRIPT_DIR/$SERVER.privkey" ;;
+
  while getopts "$options" option; do
      n ) NETWORK="$OPTARG" ;;
+
    case "$option" in
      m ) NETMASK="$OPTARG" ;;
+
      s ) SERVER="$OPTARG" && [ -n "$PRIV_KEY" ] || PRIV_KEY="$SCRIPT_DIR/$SERVER.privkey" ;;
      k ) PRIV_KEY="$OPTARG" ;;
+
      n ) NETWORK="$OPTARG" ;;
      \? ) echo "Unknown option: -$OPTARG" 1>&2; exit -2 ;;
+
      m ) NETMASK="$OPTARG" ;;
      :  ) echo "Missing option argument for -$OPTARG" 1>&2; exit -3 ;;
+
      k ) PRIV_KEY="$OPTARG" ;;
      *  ) echo "Unimplimented option: -$OPTARG" 1>&2; exit -4 ;;
+
      \? ) echo "Unknown option: -$OPTARG" 1>&2; exit -2 ;;
    esac
+
      :  ) echo "Missing option argument for -$OPTARG" 1>&2; exit -3 ;;
  done
+
      *  ) echo "Unimplimented option: -$OPTARG" 1>&2; exit -4 ;;
 
+
    esac
  #shift $(($OPTIND - 1))
+
  done
 
+
 
  [ -n "$SERVER"  ] || error_exit "You must specifiy a server with the -s argument." -5
+
  #shift $(($OPTIND - 1))
  [ -n "$NETWORK" ] || error_exit "You must specifiy a network with the -n argument." -6
+
 
  [ -n "$NETMASK" ] || error_exit "You must specifiy a netmask with the -m argument." -7
+
  [ -n "$SERVER"  ] || error_exit "You must specifiy a server with the -s argument." -5
}
+
  [ -n "$NETWORK" ] || error_exit "You must specifiy a network with the -n argument." -6
 
+
  [ -n "$NETMASK" ] || error_exit "You must specifiy a netmask with the -m argument." -7
process_args $*
+
}
 
+
# trap the SIGINT signal (most often a "ctrl+c" keystroke) and cleanup before exiting
+
process_args $*
trap control_c SIGINT
+
 
+
# trap the SIGINT signal (most often a "ctrl+c" keystroke) and cleanup before exiting
ssh -NTf -M -S "$SSH_SOCKET" -w 0:0 -D 7777 -i "$PRIV_KEY" [email protected]"$SERVER"
+
trap control_c SIGINT
[ $? -eq 0 ] || error_exit "could not connect to the SSH server '$SERVER'" -1
+
echo "INFO: SSH connection established (control socket at '$SSH_SOCKET')"
+
ssh -NTf -M -S "$SSH_SOCKET" -w 0:0 -D 7777 -i "$PRIV_KEY" [email protected]"$SERVER"
 
+
[ $? -eq 0 ] || error_exit "could not connect to the SSH server '$SERVER'" -1
server_cmd "echo 1 > /proc/sys/net/ipv4/ip_forward"
+
echo "INFO: SSH connection established (control socket at '$SSH_SOCKET')"
[ $? -eq 0 ] || error_exit "could not enable IP forwarding on '$SERVER'" 1
+
echo "INFO: Turned on IP forwarding on the server"
+
server_cmd "echo 1 > /proc/sys/net/ipv4/ip_forward"
 
+
[ $? -eq 0 ] || error_exit "could not enable IP forwarding on '$SERVER'" 1
server_cmd "ifconfig tun0 10.0.0.100 pointopoint 10.0.0.200"
+
echo "INFO: Turned on IP forwarding on the server"
[ $? -eq 0 ] || error_exit "could not initialize the tunnel interface on '$SERVER'" 2
+
echo "INFO: Initialized the point-to-point tunnel interface on the server"
+
server_cmd "ifconfig tun0 10.0.0.100 pointopoint 10.0.0.200"
 
+
[ $? -eq 0 ] || error_exit "could not initialize the tunnel interface on '$SERVER'" 2
server_iface=$(server_cmd "route -n | grep $NETWORK" | awk '{ print $8 }')
+
echo "INFO: Initialized the point-to-point tunnel interface on the server"
server_cmd "iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o $server_iface -j MASQUERADE"
+
[ $? -eq 0 ] || error_exit "could not enable IP masquerading on '$SERVER'" 3
+
server_iface=$(server_cmd "route -n | grep $NETWORK" | awk '{ print $8 }')
echo "INFO: Added an IP masquerading firewall rule on the server"
+
server_cmd "iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o $server_iface -j MASQUERADE"
 
+
[ $? -eq 0 ] || error_exit "could not enable IP masquerading on '$SERVER'" 3
ifconfig tun0 10.0.0.200 pointopoint 10.0.0.100
+
echo "INFO: Added an IP masquerading firewall rule on the server"
[ $? -eq 0 ] || error_exit "could not initialize tunnel interface on local system" 4
+
echo "INFO: Initialized the point-to-point tunnel interface on the client"
+
ifconfig tun0 10.0.0.200 pointopoint 10.0.0.100
 
+
[ $? -eq 0 ] || error_exit "could not initialize tunnel interface on local system" 4
route add -net "$NETWORK" netmask "$NETMASK" gw 10.0.0.100
+
echo "INFO: Initialized the point-to-point tunnel interface on the client"
[ $? -eq 0 ] || error_exit "could not add network route on local system" 5
+
echo "INFO: Added a route for the VPN network on the client"
+
route add -net "$NETWORK" netmask "$NETMASK" gw 10.0.0.100
 
+
[ $? -eq 0 ] || error_exit "could not add network route on local system" 5
echo -n "INFO: VPN connected.  Press <CTRL> + C to disconnect..."
+
echo "INFO: Added a route for the VPN network on the client"
 
+
# wait for user input and process any keystrokes appropriately
+
echo -n "INFO: VPN connected.  Press <CTRL> + C to disconnect..."
while [ /bin/true ]; do
+
  read -n 1 char
+
# wait for user input and process any keystrokes appropriately
 
+
while [ /bin/true ]; do
  case "$char" in
+
  read -n 1 char
    c )
+
 
      char=""
+
  case "$char" in
      echo -e "\nINFO: Detected 'c' key press.  Spawning remote terminal session to '$SERVER'..."
+
    c )
      server_cmd
+
      char=""
      echo -n "INFO: VPN still connected.  Press <CTRL> + C to disconnect..."
+
      echo -e "\nINFO: Detected 'c' key press.  Spawning remote terminal session to '$SERVER'..."
      ;;
+
      server_cmd
    s )
+
      echo -n "INFO: VPN still connected.  Press <CTRL> + C to disconnect..."
      echo ""
+
      ;;
      ;;
+
    s )
  esac
+
      echo ""
 
+
      ;;
  sleep 1s
+
  esac
done
+
 
</pre>
+
  sleep 1s
 +
done

Latest revision as of 19:31, 27 March 2013

This is a script that Jared Sutton demonstrated for his March 2013 talk about VPN capabilities of OpenSSH:

#!/bin/bash

SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )"
SSH_SOCKET=$(mktemp -u -p "$SCRIPT_DIR")

if [ "$USER" != "root" ]; then
  echo "ERROR: this script must be run as the root user." 1>&2
  exit -1
fi

function error_exit {
  echo "ERROR: $1" >&2
  
  if [ $2 -gt -1 ]; then
    control_c
  fi
  
  exit $2
}

function server_cmd {
  ssh -S "$SSH_SOCKET" [email protected]"$SERVER" "$1"
}

function ssh_client_command {
  ssh -S "$SSH_SOCKET" -O $* "$SERVER"
}

function control_c {
  echo ""
  server_cmd "iptables -t nat -F"
  echo "INFO: Flushed the NAT firewall table on the server"
  echo -n "INFO: Terminating the SSH connection..."
  ssh -S "$SSH_SOCKET" -O exit "$SERVER"
  exit 0
}

function process_args {
  options=':s:n:m:k'
  
  while getopts "$options" option; do
    case "$option" in
      s ) SERVER="$OPTARG" && [ -n "$PRIV_KEY" ] || PRIV_KEY="$SCRIPT_DIR/$SERVER.privkey" ;;
      n ) NETWORK="$OPTARG" ;;
      m ) NETMASK="$OPTARG" ;;
      k ) PRIV_KEY="$OPTARG" ;;
      \? ) echo "Unknown option: -$OPTARG" 1>&2; exit -2 ;;
      :  ) echo "Missing option argument for -$OPTARG" 1>&2; exit -3 ;;
      *  ) echo "Unimplimented option: -$OPTARG" 1>&2; exit -4 ;;
    esac
  done
  
  #shift $(($OPTIND - 1))
  
  [ -n "$SERVER"  ] || error_exit "You must specifiy a server with the -s argument." -5
  [ -n "$NETWORK" ] || error_exit "You must specifiy a network with the -n argument." -6
  [ -n "$NETMASK" ] || error_exit "You must specifiy a netmask with the -m argument." -7
}

process_args $*

# trap the SIGINT signal (most often a "ctrl+c" keystroke) and cleanup before exiting
trap control_c SIGINT

ssh -NTf -M -S "$SSH_SOCKET" -w 0:0 -D 7777 -i "$PRIV_KEY" [email protected]"$SERVER"
[ $? -eq 0 ] || error_exit "could not connect to the SSH server '$SERVER'" -1
echo "INFO: SSH connection established (control socket at '$SSH_SOCKET')"

server_cmd "echo 1 > /proc/sys/net/ipv4/ip_forward"
[ $? -eq 0 ] || error_exit "could not enable IP forwarding on '$SERVER'" 1
echo "INFO: Turned on IP forwarding on the server"

server_cmd "ifconfig tun0 10.0.0.100 pointopoint 10.0.0.200"
[ $? -eq 0 ] || error_exit "could not initialize the tunnel interface on '$SERVER'" 2
echo "INFO: Initialized the point-to-point tunnel interface on the server"

server_iface=$(server_cmd "route -n | grep $NETWORK" | awk '{ print $8 }')
server_cmd "iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o $server_iface -j MASQUERADE"
[ $? -eq 0 ] || error_exit "could not enable IP masquerading on '$SERVER'" 3
echo "INFO: Added an IP masquerading firewall rule on the server"

ifconfig tun0 10.0.0.200 pointopoint 10.0.0.100
[ $? -eq 0 ] || error_exit "could not initialize tunnel interface on local system" 4
echo "INFO: Initialized the point-to-point tunnel interface on the client"

route add -net "$NETWORK" netmask "$NETMASK" gw 10.0.0.100
[ $? -eq 0 ] || error_exit "could not add network route on local system" 5
echo "INFO: Added a route for the VPN network on the client"

echo -n "INFO: VPN connected.  Press <CTRL> + C to disconnect..."

# wait for user input and process any keystrokes appropriately
while [ /bin/true ]; do
  read -n 1 char
  
  case "$char" in
    c )
      char=""
      echo -e "\nINFO: Detected 'c' key press.  Spawning remote terminal session to '$SERVER'..."
      server_cmd
      echo -n "INFO: VPN still connected.  Press <CTRL> + C to disconnect..."
      ;;
    s )
      echo ""
      ;;
  esac
  
  sleep 1s
done