mirror of
https://github.com/ivanilves/xiringuito.git
synced 2025-05-28 04:50:23 -07:00
222 lines
5.7 KiB
Bash
Executable File
222 lines
5.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Obscene SSH-based VPN for poors ;)
|
|
#
|
|
set -e
|
|
|
|
function print_help() {
|
|
echo "Usage: ${0} [OPTIONS] [SSH_USER@]SSH_SERVER [NETWORK1, NETWORK2, ... NETWORKx]"
|
|
echo
|
|
echo "OPTIONS"
|
|
echo "-k PRIVATE_KEY_PATH use specific SSH private key"
|
|
echo "-f MAX_FAILED_PINGS fail connection after X ping failures"
|
|
echo
|
|
echo "-C do not check if we run outdated app version"
|
|
echo "-R do not reconnect after connection failure"
|
|
echo "-D do not fetch DNS config from server"
|
|
echo "-X do not run route discovery"
|
|
echo "-h show this extremely helpful message"
|
|
echo
|
|
}
|
|
|
|
declare -r KERNEL=$(uname -s | tr [A-Z] [a-z])
|
|
if [[ ${KERNEL} != linux && ${KERNEL} != darwin ]]; then
|
|
echo "Unsupported system: ${KERNEL}"
|
|
exit 2
|
|
fi
|
|
|
|
if [[ ${KERNEL} == darwin ]]; then
|
|
if [[ ! $(ls -1 /dev/tun[0-9]) ]]; then
|
|
echo "MacOSX Virtual Network Interface not installed!"
|
|
echo "Get it here: http://tuntaposx.sourceforge.net/"
|
|
exit 3
|
|
fi
|
|
fi
|
|
|
|
if [[ ${#} -lt 1 ]]; then
|
|
print_help
|
|
exit 1
|
|
fi
|
|
|
|
# We need to save executable path and arguments for reconnection functionality
|
|
export PATH="${PATH}:."
|
|
declare -r ORIGINAL_EXEC=${0}
|
|
declare -r ORIGINAL_ARGS=${@}
|
|
|
|
while getopts "k:f:CRDXrh" o; do
|
|
case ${o} in
|
|
k)
|
|
PRIVATE_KEY_PATH=${OPTARG}
|
|
if [[ ! -f "${PRIVATE_KEY_PATH}" ]]; then
|
|
echo "Key file does not exist: ${PRIVATE_KEY_PATH}"
|
|
exit 1
|
|
fi
|
|
unset SSH_AUTH_SOCK
|
|
SSH_PRIVATE_KEY_OPTS="-i ${PRIVATE_KEY_PATH}"
|
|
;;
|
|
f)
|
|
MAX_FAILED_PINGS=${OPTARG}
|
|
if [[ ! ${MAX_FAILED_PINGS} =~ ^[0-9]{1,}$ ]]; then
|
|
echo "'-f' option accepts only positive integer values"
|
|
exit 1
|
|
fi
|
|
if [[ ${MAX_FAILED_PINGS} -eq 0 ]]; then
|
|
echo "'-f' option value should be greater then zero"
|
|
exit 1
|
|
fi
|
|
;;
|
|
C)
|
|
DONT_CHECK_IF_OUTDATED=true
|
|
;;
|
|
R)
|
|
NO_RECONNECT=true
|
|
;;
|
|
D)
|
|
NO_DNS=true
|
|
;;
|
|
X)
|
|
NO_ROUTE_DISCOVERY=true
|
|
;;
|
|
r)
|
|
RECONNECTING=true
|
|
;;
|
|
h)
|
|
print_help
|
|
exit 0
|
|
;;
|
|
*)
|
|
print_help
|
|
exit 1
|
|
esac
|
|
done
|
|
|
|
if [[ ! ${DONT_CHECK_IF_OUTDATED} ]]; then
|
|
./scripts/client-check-if-outdated.sh 2>/dev/null &
|
|
fi
|
|
|
|
declare -r MAX_FAILED_PINGS=${MAX_FAILED_PINGS-10}
|
|
|
|
shift $((OPTIND-1))
|
|
|
|
cd $(dirname ${0})
|
|
|
|
./scripts/client-preexec.sh
|
|
|
|
echo -n "[ sudo check ] "; sudo true; echo
|
|
|
|
declare -r SSH_SERVER=${1}; shift
|
|
|
|
if [[ ${#} -gt 0 ]]; then
|
|
declare -r NETWORKS=${@}
|
|
elif [[ -x ./discover-routes && ! ${NO_ROUTE_DISCOVERY} ]]; then
|
|
declare -r NETWORKS=$(./discover-routes ${SSH_SERVER} | grep "^ROUTE:" | sed 's/.*://')
|
|
fi
|
|
|
|
declare -r IP_BASE=192.168.245
|
|
declare -r TUNNEL_ID_PATH=~/.xiringuito/tunnel_id
|
|
declare -r TUNNEL_ID_FILE=${TUNNEL_ID_PATH}/${SSH_SERVER}
|
|
|
|
if [[ ! -f ${TUNNEL_ID_FILE} ]]; then
|
|
mkdir -p ${TUNNEL_ID_PATH}
|
|
let GENERATED_ID=${RANDOM}%50+1
|
|
echo ${GENERATED_ID} >${TUNNEL_ID_FILE}
|
|
fi
|
|
|
|
declare -r TUNNEL_ID=$(cat ${TUNNEL_ID_FILE})
|
|
declare -r REMOTE_PATH="/tmp/xiringuito.${TUNNEL_ID}"
|
|
|
|
declare -r SSH_OPTS="-oLogLevel=${SSH_LOG_LEVEL:-ERROR} -oConnectionAttempts=3 -oConnectTimeout=10 ${SSH_PRIVATE_KEY_OPTS} ${SSH_EXTRA_OPTS}"
|
|
|
|
if [[ ${KERNEL} == linux ]]; then
|
|
declare -r LOCAL_TUNNEL_ID=${TUNNEL_ID}
|
|
else
|
|
declare -r LOCAL_TUNNEL_ID=$(./scripts/${KERNEL}/get-local-tunnel-id.sh)
|
|
fi
|
|
|
|
trap 'exit 130' INT
|
|
trap teardown EXIT
|
|
|
|
function teardown() {
|
|
if [[ ! ${SSH_PID} ]]; then
|
|
sudo ./scripts/${KERNEL}/client-teardown.sh ${$} 0 ${LOCAL_TUNNEL_ID}
|
|
fi
|
|
}
|
|
|
|
echo "TUNNEL ID: ${TUNNEL_ID} (local: ${LOCAL_TUNNEL_ID})"
|
|
|
|
if [[ ${KERNEL} == linux ]]; then
|
|
./scripts/${KERNEL}/client-setup.sh ${TUNNEL_ID} ${IP_BASE}
|
|
fi
|
|
|
|
ssh ${SSH_OPTS} ${SSH_SERVER} mkdir -p ${REMOTE_PATH}
|
|
scp ${SSH_OPTS} ./scripts/server-*.sh ${SSH_SERVER}:${REMOTE_PATH} >/dev/null
|
|
|
|
ssh ${SSH_OPTS} ${SSH_SERVER} ${REMOTE_PATH}/server-setup.sh ${TUNNEL_ID} ${IP_BASE}
|
|
|
|
sleep 1; echo -n "SERVER: ${SSH_SERVER} ... "
|
|
set +e
|
|
ssh ${SSH_OPTS} ${SSH_SERVER} pkill -f ${REMOTE_PATH}/server-execute.sh &>/dev/null
|
|
set -e
|
|
if [[ ${KERNEL} == linux ]]; then
|
|
SSH_TUNNEL_CMD="ssh"
|
|
else
|
|
SSH_TUNNEL_CMD="sudo -E ssh"
|
|
fi
|
|
${SSH_TUNNEL_CMD} ${SSH_OPTS} -oStrictHostKeyChecking=no -w ${LOCAL_TUNNEL_ID}:${TUNNEL_ID} ${SSH_SERVER} ${REMOTE_PATH}/server-execute.sh ${TUNNEL_ID} ${IP_BASE} ${MAX_FAILED_PINGS} &
|
|
SSH_PID=${!}
|
|
sudo -E ./scripts/${KERNEL}/client-teardown.sh ${$} ${SSH_PID} ${LOCAL_TUNNEL_ID} &
|
|
|
|
sleep 5
|
|
|
|
if [[ ${KERNEL} == darwin ]]; then
|
|
./scripts/${KERNEL}/client-setup.sh ${TUNNEL_ID} ${LOCAL_TUNNEL_ID} ${IP_BASE}
|
|
fi
|
|
|
|
set +e
|
|
for NETWORK in ${NETWORKS}; do
|
|
echo "> ROUTE: ${NETWORK}"
|
|
[[ -z "${RECONNECTING}" ]] && ./scripts/${KERNEL}/client-route.sh ${LOCAL_TUNNEL_ID} ${NETWORK}
|
|
done
|
|
set -e
|
|
|
|
if [[ ! ${NO_DNS} && ! -z "${NETWORKS}" ]]; then
|
|
echo
|
|
echo "* Will now replace your DNS config with one fetched from the SSH server."
|
|
echo "* Set enviromental variable 'NO_DNS', if you do not want this to happen."
|
|
REMOTE_RESOLV_CONF=$(ssh ${SSH_OPTS} ${SSH_SERVER} cat /etc/resolv.conf | grep -v "[#;]" )
|
|
|
|
if [[ "${REMOTE_RESOLV_CONF}" =~ nameserver ]]; then
|
|
echo "${REMOTE_RESOLV_CONF}" | ./scripts/client-update-resolv-conf.sh
|
|
|
|
if [[ ${KERNEL} == darwin ]]; then
|
|
./scripts/${KERNEL}/client-update-macosx-dns.sh
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
set +e
|
|
FAILED_PINGS=0
|
|
while [[ ${FAILED_PINGS} -lt ${MAX_FAILED_PINGS} ]]; do
|
|
[[ $(ps -p ${SSH_PID} | wc -l) -eq 2 ]] || break
|
|
|
|
if [[ ${EXIT_AFTER_CONNECT} ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
./scripts/client-ping-server.sh ${TUNNEL_ID} ${IP_BASE}
|
|
if [[ ${?} -ne 0 ]]; then
|
|
let FAILED_PINGS+=1
|
|
echo "* Failed to ping server-side tunnel endpoint... (${FAILED_PINGS}/${MAX_FAILED_PINGS})"
|
|
else
|
|
FAILED_PINGS=0
|
|
fi
|
|
|
|
sleep 1
|
|
done
|
|
|
|
teardown
|
|
|
|
if [[ -z "${NO_RECONNECT}" ]]; then
|
|
exec ${ORIGINAL_EXEC} -r ${ORIGINAL_ARGS}
|
|
fi
|