#!/bin/bash
# @author : Prashant Borole (prashantb :can be reached at: cse iitb ac in)
# A simple proxy-proxy that authenticates on users' behalf.
# Known limitations :
# Works for Basic proxy authentication at the moment (though it is not that hard to add digest support)
# Can process single request at a time. Any parallel requests will not be satisfied. This may lead to referred elements not being loaded, eg. images. Download accelerators are rendered useless.
# Due to the logging format, there can be storage issues when downloading huge files.
# Significantly slower than squid or some custom asyncio implementation as each request spawns bunch of new processes
# No cache. Each request is strictly sent to upstream proxy
# no https or ftp support
# TODO put this in some standard location
CONFIG_FILE="$HOME/.proxy.conf"
export LISTEN_PORT=
export PROXY=
export PROXY_PORT=
export LOG_FILE=
init()
{
exec 2>&- 2>&1
exec 5>&1
exec >>"$LOG_FILE"
}
readConfig()
{
# really cheap config parsing.
# FIXME improve
# echo "Loading Configuration from $CONFIG_FILE"
export LISTEN_PORT=$(grep "LISTEN_PORT=" "$CONFIG_FILE" | cut -d '=' -f2)
export PROXY=$(grep "PROXY=" "$CONFIG_FILE" | cut -d '=' -f2)
export PROXY_PORT=$(grep "PROXY_PORT=" "$CONFIG_FILE" | cut -d '=' -f2)
export LOG_FILE=$(grep "LOG_FILE=" "$CONFIG_FILE" | cut -d '=' -f2)
}
if [ "$1" != "--" ]; then
# read the config initially
readConfig
# accept credentials
echo -n "$PROXY:$PROXY_PORT user name : "
read USER_NAME
echo -n "$USER_NAME@$PROXY:$PROXY_PORT Password : "
read -s PASSWORD
echo
export B64CRED=`echo -ne "$USER_NAME:$PASSWORD" | base64`
unset USER_NAME PASSWORD
echo "Credentials accepted."
# launch in background
$0 -- &
exit 0
else
trap 'echo "cleaning up $TMP_DIR" ; rm -fr "$TMP_DIR"; killall -9 nc tee >/dev/null 2>&1' EXIT
trap 'echo "Shutting down proxy server on port $LISTEN_PORT" ; exit 0' SIGUSR1
trap 'echo "Reloading config..." ; readConfig' SIGUSR2
trap 'echo "[UNCLEAN] Shutting down proxy server on port $LISTEN_PORT" ; exit 1' SIGINT SIGKILL SIGSEGV SIGPIPE SIGHUP SIGTERM SIGABRT
readConfig
init
echo "`date` Server $0[$$] started"
fi
TMP_DIR=`mktemp -d /tmp/proxy.XXXXXXXX`
BACK_FIFO="$TMP_DIR"/back_fifo
# create a pipe
mknod "$BACK_FIFO" p
echo "Accepting connections on port $LISTEN_PORT"
while true ; do
nc -l "$LISTEN_PORT" 0<$BACK_FIFO | tee request | (while read line ; do if [ "$line" = "^M" ] ; then echo "Proxy-Authorization: Basic $B64CRED" ; echo ; else echo "$line" ; fi; done) | nc -w 5 "$PROXY" "$PROXY_PORT" | tee response 1>$BACK_FIFO
head -n+1 request
head -n+1 response
done
echo "THIS SHOULD NEVER HAPPEN. SOMETHING IS WRONG !!!"
exit 1
# @author : Prashant Borole (prashantb :can be reached at: cse iitb ac in)
# A simple proxy-proxy that authenticates on users' behalf.
# Known limitations :
# Works for Basic proxy authentication at the moment (though it is not that hard to add digest support)
# Can process single request at a time. Any parallel requests will not be satisfied. This may lead to referred elements not being loaded, eg. images. Download accelerators are rendered useless.
# Due to the logging format, there can be storage issues when downloading huge files.
# Significantly slower than squid or some custom asyncio implementation as each request spawns bunch of new processes
# No cache. Each request is strictly sent to upstream proxy
# no https or ftp support
# TODO put this in some standard location
CONFIG_FILE="$HOME/.proxy.conf"
export LISTEN_PORT=
export PROXY=
export PROXY_PORT=
export LOG_FILE=
init()
{
exec 2>&- 2>&1
exec 5>&1
exec >>"$LOG_FILE"
}
readConfig()
{
# really cheap config parsing.
# FIXME improve
# echo "Loading Configuration from $CONFIG_FILE"
export LISTEN_PORT=$(grep "LISTEN_PORT=" "$CONFIG_FILE" | cut -d '=' -f2)
export PROXY=$(grep "PROXY=" "$CONFIG_FILE" | cut -d '=' -f2)
export PROXY_PORT=$(grep "PROXY_PORT=" "$CONFIG_FILE" | cut -d '=' -f2)
export LOG_FILE=$(grep "LOG_FILE=" "$CONFIG_FILE" | cut -d '=' -f2)
}
if [ "$1" != "--" ]; then
# read the config initially
readConfig
# accept credentials
echo -n "$PROXY:$PROXY_PORT user name : "
read USER_NAME
echo -n "$USER_NAME@$PROXY:$PROXY_PORT Password : "
read -s PASSWORD
echo
export B64CRED=`echo -ne "$USER_NAME:$PASSWORD" | base64`
unset USER_NAME PASSWORD
echo "Credentials accepted."
# launch in background
$0 -- &
exit 0
else
trap 'echo "cleaning up $TMP_DIR" ; rm -fr "$TMP_DIR"; killall -9 nc tee >/dev/null 2>&1' EXIT
trap 'echo "Shutting down proxy server on port $LISTEN_PORT" ; exit 0' SIGUSR1
trap 'echo "Reloading config..." ; readConfig' SIGUSR2
trap 'echo "[UNCLEAN] Shutting down proxy server on port $LISTEN_PORT" ; exit 1' SIGINT SIGKILL SIGSEGV SIGPIPE SIGHUP SIGTERM SIGABRT
readConfig
init
echo "`date` Server $0[$$] started"
fi
TMP_DIR=`mktemp -d /tmp/proxy.XXXXXXXX`
BACK_FIFO="$TMP_DIR"/back_fifo
# create a pipe
mknod "$BACK_FIFO" p
echo "Accepting connections on port $LISTEN_PORT"
while true ; do
nc -l "$LISTEN_PORT" 0<$BACK_FIFO | tee request | (while read line ; do if [ "$line" = "^M" ] ; then echo "Proxy-Authorization: Basic $B64CRED" ; echo ; else echo "$line" ; fi; done) | nc -w 5 "$PROXY" "$PROXY_PORT" | tee response 1>$BACK_FIFO
head -n+1 request
head -n+1 response
done
echo "THIS SHOULD NEVER HAPPEN. SOMETHING IS WRONG !!!"
exit 1
Note that you can NOT use something like sed or awk, because they simply give up when there is no text to read. This breaks the pipe. A "while read" loop just cuts it :)
:-o will need at least 5 more scans through the post to digest it! will definitely do that! :D
ReplyDelete