Skip to content

Instantly share code, notes, and snippets.

@craSH
Last active June 3, 2016 08:17
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save craSH/3ac797a4371054ef9fd1 to your computer and use it in GitHub Desktop.
Save craSH/3ac797a4371054ef9fd1 to your computer and use it in GitHub Desktop.
Script to setup multiple SSH tunnels in a reliable way for use with FoxyProxy or other SOCKS-aware clients
#!/usr/bin/env bash
#
# Use to setup numerous various tunnels to SSH servers, useful with ssh config blocks like those below
# for each host, with incrementing port numbers for each - then configure FoxyProxy etc to use the unique
# port for each host you want to tunnel out of.
#
# Thanks to tecknicaltom <tecknicaltom@neg9.org> for the initial idea behind tying this all together.
#
# Host host_alpha
# IdentityFile ~/.ssh/id_ecdsa-$USER-host_alpha-<remote_hostname>-<key_gen_year>-<key_gen_month>
# DynamicForward localhost:4504
#
# Host host_bravo
# IdentityFile ~/.ssh/id_ecdsa-$USER-host_bravo-<remote_hostname>-<key_gen_year>-<key_gen_month>
# DynamicForward localhost:4505
#
# Example FoxyProxy config XML block (import/export):
#
# <proxy name="host_alpha" id="12345" notes="localhost:4504/socks (SSH)" enabled="true" color="#AFBD31" mode="manual" autoconfMode="pac" lastresort="false">
# <manualconf host="localhost" port="4504" socksversion="5" isSocks="true"/>
# <autoconf url="" reloadPac="false" loadNotification="true" errorNotification="true" autoReload="false" reloadFreqMins="60" disableOnBadPAC="true"/>
# <matches>
# <match enabled="true" name="*" isRegex="false" pattern="*" reload="true" autoReload="false" isBlackList="false" isMultiLine="false" fromSubscription="false" caseSensitive="false"/>
# </matches>
# </proxy>
#
# <proxy name="host_bravo" id="54321" notes="localhost:4505/socks (SSH)" enabled="true" color="#AFBD31" mode="manual" autoconfMode="pac" lastresort="false">
# <manualconf host="localhost" port="4505" socksversion="5" isSocks="true"/>
# <autoconf url="" reloadPac="false" loadNotification="true" errorNotification="true" autoReload="false" reloadFreqMins="60" disableOnBadPAC="true"/>
# <matches>
# <match enabled="true" name="*" isRegex="false" pattern="*" reload="true" autoReload="false" isBlackList="false" isMultiLine="false" fromSubscription="false" caseSensitive="false"/>
# </matches>
# </proxy>
#
#
# SSH Options
# -N Do not execute a remote command. This is useful for just forwarding ports (protocol version 2 only).
# -f Requests ssh to go to background just before command execution. This is useful if ssh is going to ask
# for passwords or passphrases, but the user wants it in the background. This implies -n.
# -n (implied from -f, above) Redirects stdin from /dev/null (actually, prevents reading from stdin).
# This must be used when ssh is run in the background.
# -q Quiet mode. Causes most warning and diagnostic messages to be suppressed.
ssh_cli_options="-Nfq -oControlMaster=no -oControlPath=none -oControlPersist=no"
# AutoSSH options (see man page for autossh for all environment variable information)
export AUTOSSH_GATETIME=0
export AUTOSSH_POLL=30
# Hosts to connect to/setup tunnels for, one per line
hosts_list="${HOME}/.config/scripts/init-tunnels"
if [ ! -r "$hosts_list" ]; then
echo "[FATAL] Can't read $hosts_list - ensure it exists and contains one host per line." >&2
exit 1
fi
hosts=$(cat "$hosts_list")
# Connect to each host with the specified options
connection_count=0
for host in $hosts; do
# No monitor port (needed sometimes in weird environments)
#ssh_cmd="autossh -M 0"
# Choose a monitor port off of a base and 10 away from the previous one
ssh_cmd="autossh -Nf -M $((48004 + (connection_count += 10))) $ssh_cli_options"
$ssh_cmd $host
if [ 0 -eq $? ]; then
echo -n "[INFO] Tunnel established: $host"
socks_port=$(grep "^Host.*${host}" ~/.ssh/config -A 5 \
| grep "DynamicForward" \
| head -n 1 | awk -F ':' '{print $NF}')
if [ -n "$socks_port" ]; then
echo ", SOCKS listener: $socks_port"
else
echo
fi
else
echo "[ERROR] Tunnel FAILED ($?): $host" >&2
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment