I have a telnet enabled service, which doesn't have any form of authentication. Naturally I don't want to expose this to the public internet - so it's firewall. Now I want to allow my host to access it, but my host have a dynamic ip address. Iptables only support static ips and ip ranges - but for my use case I only wanted a single ip.
My solution is to update rules in iptables using cron, such that only the ip found at my dynamic dns is allowed through the firewall.
Example usage:
My solution is to update rules in iptables using cron, such that only the ip found at my dynamic dns is allowed through the firewall.
HOSTNAME=$1 IP=$(host $HOSTNAME | grep -iE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" |cut -f4 -d' '|head -n 1) # If chain for remote doesn't exist, create it if ! /sbin/iptables -L $HOSTNAME -n >/dev/null 2>&1 ; then /sbin/iptables -N $HOSTNAME >/dev/null 2>&1 fi # Flush old rules, and add new /sbin/iptables -F $HOSTNAME /sbin/iptables -I $HOSTNAME -s $IP -j ACCEPT # Add chain to INPUT filter if it doesn't exist if ! /sbin/iptables -C INPUT -t filter -j $HOSTNAME >/dev/null 2>&1 ; then /sbin/iptables -t filter -I INPUT -j $HOSTNAME fi
Example usage:
./dnsallow.sh my.dynamic.dns.com
hey i had a couple questions:
ReplyDelete1 - does using "$HOSTNAME" in the script mess anything up since that's a system variable too?
2 - assuming the answer to #1 is "no", i think you can simplify the second line a bit by making it:
IP=$(dig +short $HOSTNAME)
Thanks for posting this. I have added some of my own tweaks to this script and am sharing in case anyone can find it beneficial. I added a couple of sanity checks to make sure we don't try to update iptables with an invalid IP. I also added a check that prevents iptables from being updated if there hasn't been a change to the dynamic IP address. This way we can run the script in a cron job and it automatically updates iptables as needed. Also, I'm no expert scripter, so any improvements are welcome.
ReplyDeleteScript:
#!/bin/bash
DYNHOST=$1
DYNIP=$(host $DYNHOST | grep -iE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" |cut -f4 -d' '|head -n 1)
# Exit if invalid IP address is returned
case $DYNIP in
0.0.0.0 )
exit 1 ;;
255.255.255.255 )
exit 1 ;;
esac
# Exit if IP address not in proper format
if ! [[ $DYNIP =~ (([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ]]; then
exit 1
fi
# If chain for remote doesn't exist, create it
if ! /sbin/iptables -L $DYNHOST -n >/dev/null 2>&1 ; then
/sbin/iptables -N $DYNHOST >/dev/null 2>&1
fi
# Check IP address to see if the chain matches first; skip rest of script if update is not needed
if ! /sbin/iptables -n -L $DYNHOST | grep -iE " $DYNIP " >/dev/null 2>&1 ; then
# Flush old rules, and add new
/sbin/iptables -F $DYNHOST >/dev/null 2>&1
/sbin/iptables -I $DYNHOST -s $DYNIP -j ACCEPT
# Add chain to INPUT filter if it doesn't exist
if ! /sbin/iptables -C INPUT -t filter -j $DYNHOST >/dev/null 2>&1 ; then
/sbin/iptables -t filter -I INPUT -j $DYNHOST
fi
fi
Also it appears that iptables will not accept chains with names longer than 28 characters. So I also used this to truncate the chain name:
ReplyDelete# Truncate $DYNHOST to 28 characters
DYNHOST=${DYNHOST:0:28}
Where exactly do you add this part> At the end?
ReplyDeleteCould I run the script twice with different hostnamrs?
ReplyDelete