2013-09-01

Firewall Check

I'm sure there are plenty of tools out there that do better than I, but this was my hack and I'm going to put it out there...

So, on the server, I setup its own user account. Its shell was set to something I could control, and it did exactly what I was looking for in a couple of commands:

# Add a temp user to the system so we can tinker around with this...
adduser --home=/tmp/netcat --shell=/tmp/netcat/nc --ingroup=nogroup --disabled-password --system tmpnetcat

# Setup the home so I can login using SSH keys since passwords are disabled anyways...
install -d -otmpnetcat -gnogroup -m0700 /tmp/netcat/.ssh
install -otmpnetcat -gnogroup -m640 ~/.ssh/id_rsa.pub /tmp/netcat/.ssh/authorized_keys

# Enable this user for accesing /bin/nc without a password as root so they can bind to any address for testing.
echo -e '\n\ntmpnetcat ALL=NOPASSWD: /bin/nc' >> /etc/sudoers

# Insert the script we'll execute when this user logs in.
cat <<NCEXEC > /tmp/netcat/nc
#!/bin/bash

PORT=$2
if [ -z "$PORT" ]; then
echo -e "\n\n\033[31mI require a port to listen\033[0m. Use ssh $USER@$HOSTNAME [port]\n\n" >/dev/stderr
exit 1
fi

echo "Listening on port $PORT."
for i in 1 2 3; do
cat <<EOF | /usr/bin/sudo /bin/nc -l -s 192.168.0.1 -p $PORT
HTTP/1.1 200 OK
Date: $(date '+a, %m %b %Y %R:%S GMT %z')
Server: Port Testing
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 0
Content-Type: text/plain; charset=UTF-8

EOF
done
NCEXEC

The server is basically just a shell account that opens a netcat on a port for listening and echos a passing response message for 3 client connections.

The client is simple. This script should get us going:

#!/bin/bash

exec 3>status.log

export interrupted=false

# Bash for() loops have a way with Ctrl+C/SIGINT interrupts. This ensures we'll get our shell back when we INT everything.
is_interrupt () { interrupted=true; }
trap is_interrupt 2

# Grep -v out the ports we use so we don't cause a conflict.
for port in $(seq 1 65535|egrep -v '22|53|80|443|953|3306|6010'); do
if [ "$interrupted" = "true" ]; then
exec 3>&-
exit 2
fi

ssh -q tmpnetcat@kizmedia $port 2>ssh.err >ssh.out &
sshpid=$!

# Wait for the nc to be up and listening.
while [ -z ssh.out ]; do
sleep 0.1s
done

if httping -t2 -c3 -p$port markizano.net; then
echo "$port passed." | tee -a /proc/$$/fd/3
else
echo "$port failed." | tee -a /proc/$$/fd/3
fi

sleep 0.5s
if [ -d /proc/$sshpid ]; then
killz=0
while [ -d /proc/$sshpid ]; do
echo "Killing ssh pid $pid";
kill -15 $sshpid
sleep 1s
killz=$(($killz+1))
if [ $killz -ge 6 ]; then
echo -e "Murdering SSH Pid $sshpid!!!"
kill -9 $sshpid
fi
done
fi
done

exec 3>&-


When it's all said and done, you should have a file called status.log that contains a list of pass or fail messages per port that was attempted. Save this log - it takes a long time to generate. This allows for just a little bit of tolerance. I've yet to make it into anything packageable or fancy. It's a hack at best. I guess I know why I didn't find this easily on searching.