#!/bin/bash socket_id=$( ls -l /proc/$$/fd/1 | sed 's/.*\[\([0-9]\+\)\]/\1/' ) source_ip=$( ss -ent | grep "ino:$socket_id" | awk '{print $5}' ) source_ip=${source_ip%:*} source_ip=${source_ip#::ffff:} CONFIG_FILE="$(dirname $0)/knockthrough.conf" [ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE" || exit 1 [ -z "$RULES_FILE" ] && exit 1 resolve_port() { local p=$( cat ./services /etc/services \ | sed 's/#.*$//;/^[[:space:]]$/d;s/[[:space:]]\+/ /g;s/^/ /;s/$/ /' \ | grep -F "/$2" \ | grep -F " $1 " \ | head -n1 \ | cut -d' ' -f3 \ ) echo ${p%/*} } is_numeric() { [[ "$1" =~ ^[0-9]+$ ]] && return 0 return 1 } err_msg() { echo "Syntax error on line $n: $@" >&2 } parse_rules() { local inkeyword=$1 local sip=$2 while read line; do line=${line%%[#;]*} [ -z "$line" ] && continue set $line local keyword=$1 local proto=$2 local port=$3 local ttl=$4 [ "$keyword" != "$inkeyword" ] && continue if ! is_numeric "$port"; then local p=$( resolve_port $port $proto ) [ -z "$p" ] && continue || port=$p fi rule="$FILTER_CHAIN -s $sip/32 -p $proto -m $proto --dport $port -j ACCEPT" iptables-save | grep -q "$rule" [ $? -ne 0 ] && iptables -A $rule if [ -n "$ttl" ]; then echo "iptables -D $rule" \ | at -M now + $ttl minutes >/dev/null 2>&1 fi done } html_fortune () { cat < Fortune
$( fortune )
END } read inkeyword httplocation dummy if [ "$inkeyword" = "GET" ]; then read httpreq while [ ${#httpreq} -gt 2 ]; do read httpreq done httplocation=${httplocation#/} httplocation=${httplocation%/}/ httplocation=${httplocation%%/*} if [ -n "$httplocation" ]; then cat $RULES_FILE | parse_rules "$httplocation" "$source_ip" fi body=$( html_fortune ) echo -en "HTTP/1.0 200 OK\nContent-Type: text/html\nContent-Length: ${#body}\n\n$body" else cat $RULES_FILE | parse_rules "$inkeyword" "$source_ip" fortune fi exit 0