Firewall Netcat

by GI Jack

All right, boys and girls, dropping something fresh.

So you've been testing connections or trying to open a connect of sorts and bam, it doesn't work.  After you get over that dumb look on your face and some head scratching, you realize that overly complex set of firewall rules you installed on another project is just blocking your wonderful adventures exploring security in packet land with Netcat.

Of course, instead of angrily mashing iptables -F, or fat-fingering an iptables -j ACCEPT rule for Every, Last, Port that you then have to get rid of (or just are too lazy to), there is now an answer for you:

Firewall Netcat: with the magical powers of iptables, Netcat, and wrapped in a gooey Bash shell that melts boxen, not your fingers!

How does this work?  You simply install the script to $PATH, and then instead of using nc you use fw_nc.sh, and the same syntax as your nc binary.  The script will get port, protocol, and direction from the syntax, automatically add an iptables firewall rule, and the run Netcat with your statement.  When Netcat completes, or the script get a signal, it deletes the rule before exiting.  The ALLOW rule is only active when Netcat is.

You can now Netcat through firewalls with the same Netcat syntax you've been using for years!  No additional tooling needed.

Fully supported, supports incoming and outgoing, TCP and UDP.

#!/usr/bin/env bash
# Exit Codes: 0 - success 
#             1 - script error
#             2 - user error 
#             4 - help

help_and_exit() {
	cat 1>&2 << EOF
${BRIGHT}fw_nc.sh${NOCOLOR}: Firewall Netcat by GI Jack

Open port(s) in the firewall, runs netcat, and then remove the firewall rule.

Script gets port and proto from netcat statement. No special options. 
Just use netcat syntax.

	${BRIGHT}Usage${NOCOLOR}:
	fw_nc.sh <netcat statement>
EOF
	exit 4
}

BRIGHT=$(tput bold)
NOCOLOR=$(tput sgr0) # reset to default colors
BRIGHT_RED=$(tput setaf 1;tput bold)
BRIGHT_YELLOW=$(tput setaf 3;tput bold)
BRIGHT_CYAN=$(tput setaf 6;tput bold)

exit_with_error() {
echo 1>&2 "${BRIGHT}fw_nc.sh: ${BRIGHT_RED}ERROR${NOCOLOR}: ${2}"
exit ${1}
}

message() {
	echo "fw_nc.sh: ${@}"
}

check_sudo() {
	# Check if this script can run sudo correctly. 
	# Uses as_root, see below
	if [ ${UID} -eq 0 ];then
		ROOT_METHOD="uid"
		# TODO: FIX Polkit support
		#elif [[ ! -z $DISPLAY && $(tty) = /dev/pts/* ]];then
		# ROOT_METHOD="pkexec"
	elif [ $(sudo whoami) == "root" ];then
		ROOT_METHOD="sudo"
	else
		exit_with_error 4 "Cannot gain root! This program needs root to work. Exiting..."
	fi
	# One last check
	[ $(as_root whoami) != "root" ] && exit_with_error 4 "Cannot gain root! This program needs root to work. Exiting..."
}


as_root() {
	# Execute a command as root
	case $ROOT_METHOD in
		sudo)
			sudo ${@}
			;;
		polkit)
			pkexec ${@}
			;;
		uid)
			${@}
			;;
	esac
}

check_nc_opts() {
	CHAIN="OUTPUT"
	PROTO="tcp"
	PORT=""
	local parms=""
	while [ ! -z "$1" ];do
		item="${1}"
		case ${item} in
			-l)
			PORT=${2}
			CHAIN="INPUT"
			;;
		-u)
			PROTO="udp"
			;;
		-*)
			shift
			continue
			;;
		*)
			parms+=${item}
			;;
			esac
			shift
		done
		[ -z "${parms}" ] && return
		set ${parms}
		[ -z ${PORT} ] && PORT=${2}
}

remove_rule_and_exit() {
	as_root iptables -D ${CHAIN} -m ${PROTO} -p ${PROTO} --dport ${PORT} -j ACCEPT
	exit
}

main() {
	# Sanity Check
	[ -z $1 ] && help_and_exit
	[ $1 == "--help" ] && help_and_exit
	[ -z $PORT ] && exit_with_error 2 "No such port"
	check_sudo
	as_root iptables -I ${CHAIN} -m ${PROTO} -p ${PROTO} --dport ${PORT} -j ACCEPT
	trap remove_rule_and_exit 1 2 3 9 15
	nc ${@}
	remove_rule_and_exit
}

check_nc_opts "${@}"
main "${@}"

Code: fw_nc.sh

Return to $2600 Index