Last active
October 27, 2019 05:02
-
-
Save Mister-Meeseeks/8a52e3eb253e5f78f5d841530f4b95eb to your computer and use it in GitHub Desktop.
Use SSH socks tunnels to bypass firewall that blocks outbound Internet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -eu | |
# Script is designed to build an SSH proxy for external Internet access on a | |
# host, which sits behind a NAT/firewall that doesn't allow outbound traffic. | |
# (Common in exchange data centers). | |
# | |
# Call this from a bridge with access to the Intrent and inbound access to the | |
# host. On success it will make available on host both a Socks5 proxy deamon | |
# (at localhost:8080) and a tunnel to the bridge machine's http proxy (at | |
# Elocalhost:8118). | |
# | |
# Requires local/bridge machine to have ssh, bash, and whoami. For HTTP | |
# proxy functionality the bridge machine must have an HTTP proxy (e.g. privoxy) | |
# running at the HTTP proxy port. If not, Socks5 proxy will still work. | |
# | |
# Requires remote/destination machine to have ssh, nc, and socks5 capable | |
# client. (proxychains suggested) | |
destAuthArg="" | |
localAuthArg="" | |
while getopts i:j:P opt ; do | |
case "$opt" in | |
i) destAuthArg="-i $OPTARG";; # Must exist on local machine, if used | |
j) localAuthArg="-i $OPTARG";; # Must exst on destination machine | |
esac | |
done | |
shift $(($OPTIND - 1)) | |
destAddr=$1 # Use user@host if different user on destination machine | |
reverseTunnelPort=19999 | |
reverseTunnelDest=localhost:22 | |
socksProxyPort=8080 | |
httpProxyPort=8118 | |
# Before each tunnel step, check if the port is already built, in which case | |
# we don't need to run the command again. This avoids spurious errors when | |
# the script is re-run. | |
function testRemotePort() { | |
local portNum=$1 | |
! isRemotePortOpen $portNum | |
} | |
function isRemotePortOpen() { | |
local portNum=$1 | |
local portTestCmd="nc -z localhost $portNum" | |
ssh $destAuthArg $destAddr "$portTestCmd" | |
} | |
# First build a reverse tunnel to allow an outbound path on the remote. | |
if testRemotePort $reverseTunnelPort ; then | |
ssh $destAuthArg -f -C -N -R $reverseTunnelPort:$reverseTunnelDest $destAddr | |
fi | |
# These commands get called on the remote destination... | |
socksProxyCmd="ssh $localAuthArg -f -D $socksProxyPort -C -N \ | |
-p $reverseTunnelPort $(whoami)@localhost" | |
# ...with these remote calls | |
if testRemotePort $socksProxyPort ; then | |
ssh $destAuthArg -f $destAddr "$socksProxyCmd" | |
fi | |
# Now do the same with the HTTP proxy | |
httpTunnel=$httpProxyPort:localhost:$httpProxyPort | |
httpProxyCmd="ssh $localAuthArg -f -L $httpTunnel -C -N \ | |
-p $reverseTunnelPort $(whoami)@localhost" | |
if testRemotePort $httpProxyPort ; then | |
ssh $destAuthArg -f $destAddr "$httpProxyCmd" | |
fi | |
# This spawns two SSH daemons on the localmachine and one on the remote host, | |
# all of which survive after the script finishes running. If you want to kill | |
# the daemons, use ps/pkill. | |
# To acccess outbound internet on destination configure proxychains config with | |
# proxy_dns | |
# socks5 127.0.0.1 8080 | |
# | |
# Then run any outbound-accessing internet command as | |
# $ proxychains [command] | |
# e.g. | |
# $ proxychains curl google.com | |
# | |
# HTTP proxy access will be available on the remote machine at 8081. However | |
# for any requests to work, it requires the bridge machine to have an actual | |
# HTTP proxy (like privoxy) listening at localhost on 8081 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment