Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Reverse SSH tunnel NGINX config script

To be used with /etc/ssh/sshd_config ForceCommand.

Requirements:

Example usage:

#!/bin/bash
clear
declare -A parsed=()
function rand () {
head /dev/urandom | tr -dc a-z | head -c 3 ; echo ''
}
function get_port () {
tail /var/log/auth.log --lines 200 \
| grep 'Local forwarding listening on 127.0.0.1 port' \
| tail -n1 \
| ([[ $(cat) =~ .*[[:space:]]([[:digit:]]*).* ]]; echo ${BASH_REMATCH[1]})
}
function get_name () {
tail /var/log/auth.log --lines 200 \
| grep 'server_input_global_request: tcpip-forward listen' \
| tail -n1 \
| ([[ $(cat) =~ .*[[:space:]]listen[[:space:]](.*)[[:space:]]port.* ]]; echo ${BASH_REMATCH[1]}) \
| tr -s '/'
}
function parse () {
IFS='#' read -ra servers <<< "${config//\}\}/#}"
parsed[.length]=${#servers[@]}
for i in "${!servers[@]}"
do
IFS='#' read -ra locations <<< "${servers[i]//location /#}"
local server_name=${locations:20:-12}
unset "locations[0]"
locations=("${locations[@]}")
parsed[$server_name]=$i
parsed[$i]=$server_name
parsed[$i.length]=${#locations[@]}
for j in "${!locations[@]}"
do
[[ ${locations[$j]} =~ (.*)[[:space:]]\{proxy_pass[[:space:]].*:(.*)\; ]]
local location=${BASH_REMATCH[1]}
local proxy_pass=${BASH_REMATCH[2]}
if [ ${#location} -gt 2 ]
then
location=${location:1:-6}
proxy_pass=${proxy_pass:0:-2}
fi
parsed[$i.$location]=${j}
parsed[$i.$j.location]=$location
parsed[$i.$j.port]=$proxy_pass
done
done
}
function sort_locations () {\
for ((i=0; i <= $((${#locations[@]} - 2)); ++i))
do
for ((j=((i + 1)); j <= ((${#locations[@]} - 1)); ++j))
do
a=${locations[i]}
if [ ${#a} -eq 1 ]
then
a=''
fi
a=${a//[^\/]}
b=${locations[j]}
if [ ${#b} -eq 1 ]
then
b=''
fi
b=${b//[^\/]}
if [ ${#b} -gt ${#a} ]
then
tmp=${locations[i]}
locations[i]=${locations[j]}
locations[j]=$tmp
fi
done
done
}
function stringify () {
config=''
for i in $(seq 0 $((${parsed[.length]} - 1)))
do
if [ -n "${parsed[$i]}" ]
then
config+="server {server_name ${parsed[$i]};listen 443;"
locations=()
declare -A ports=()
for j in $(seq 0 $((${parsed[$i.length]} - 1)))
do
if [ -n "${parsed[$i.$j.location]}" ]
then
locations[$j]=${parsed[$i.$j.location]}
ports[${parsed[$i.$j.location]}]=${parsed[$i.$j.port]}
fi
done
sort_locations
local location
for location in "${locations[@]}"
do
if [ -n "$location" ]
then
local proxy_pass="http://127.0.0.1:${ports[$location]}"
if [ ${#location} -gt 1 ]
then
location="~$location(/.*)\$"
proxy_pass+="\$1\$is_args\$args"
fi
config+="location $location {proxy_pass $proxy_pass;}"
fi
done
config+="}"
fi
done
}
function add () {
local i=${parsed[$server_name]}
if [ -z "$i" ]
then
i=${parsed[.length]}
parsed[.length]=$(($i + 1))
parsed[$server_name]=$i
parsed[$i]=$server_name
fi
if [ -n "${parsed[$i.$location]}" ]
then
echo "The web address $url is already in use."
exit 1
fi
local j=${parsed[$i.length]}
if [ -z "$j" ]
then
j=0
fi
parsed[$i.length]=$(($j + 1))
parsed[$i.$location]=$j
parsed[$i.$j.location]=$location
parsed[$i.$j.port]=$port
}
function remove () {
local i=${parsed[$server_name]}
local j=${parsed[$i.$location]}
unset "parsed[$i.$j.location]"
if [ ${parsed[$i.length]} -eq 1 ]
then
unset "parsed[$i]"
fi
}
function load () {
config=$(cat $file \
| tr -d '\n\r' \
| tr -s ' ')
}
function store () {
echo -e "$config" > $file
}
file='/etc/nginx/sites-available/tunnel.seapip.com'
name=$(get_name)
[[ "$name" =~ \/?([^\/]*)\/?(.*)\/? ]]
server_name=${BASH_REMATCH[1]}
location="/${BASH_REMATCH[2]}"
if [ "$server_name" == 'localhost' ]
then
server_name=$(rand)
fi
server_name+=".seapip.com"
port=$(get_port)
url="https://$server_name"
if [ ${#location} -gt 1 ]
then
url+="$location/"
fi
load && parse && add && stringify && store
trap "load && parse && remove && stringify && store" EXIT
echo "$url"
read -r -d '' _ </dev/tty
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment