- The shell script to check the ip address for the host and update the ufw rules:
#!/bin/bash HOSTS_ALLOW=/etc/ufw-dynamic-hosts.allow IPS_ALLOW=/var/tmp/ufw-dynamic-ips.allow add_rule() { local proto=$1 local port=$2 local ip=$3 local regex="${port}\/${proto}.*ALLOW.*IN.*${ip}" local rule=$(ufw status numbered | grep $regex) if [ -z "$rule" ]; then ufw allow proto ${proto} from ${ip} to any port ${port} else echo "rule already exists. nothing to do." fi } delete_rule() { local proto=$1 local port=$2 local ip=$3 local regex="${port}\/${proto}.*ALLOW.*IN.*${ip}" local rule=$(ufw status numbered | grep $regex) if [ -n "$rule" ]; then ufw delete allow proto ${proto} from ${ip} to any port ${port} else echo "rule does not exist. nothing to do." fi } sed '/^[[:space:]]*$/d' ${HOSTS_ALLOW} | sed '/^[[:space:]]*#/d' | while read line do proto=$(echo ${line} | cut -d: -f1) port=$(echo ${line} | cut -d: -f2) host=$(echo ${line} | cut -d: -f3) if [ -f ${IPS_ALLOW} ]; then old_ip=$(cat ${IPS_ALLOW} | grep ${host} | cut -d: -f2) fi ip=$(dig +short $host | tail -n 1) if [ -z ${ip} ]; then if [ -n "${old_ip}" ]; then delete_rule $proto $port $old_ip fi echo "Failed to resolve the ip address of ${host}." 1>&2 exit 1 fi if [ -n "${old_ip}" ]; then if [ ${ip} != ${old_ip} ]; then delete_rule $proto $port $old_ip fi fi add_rule $proto $port $ip if [ -f ${IPS_ALLOW} ]; then sed -i.bak /^${host}*/d ${IPS_ALLOW} fi echo "${host}:${ip}" >> ${IPS_ALLOW} done
- The sample hosts file: /etc/ufw-dynamic-hosts.allow:
tcp:22:yourpc.no-ip.org
- The crontab which execute the script every 5 minutes to update the rules:
# m h dom mon dow command */5 * * * * /usr/local/sbin/ufw-dynamic-host-update 2>&1 > /dev/null
Search This Blog
shell script: update ufw rules for the hosts with dynamic ip addresses
Subscribe to:
Post Comments (Atom)
Brilliant, Thank you.
ReplyDeleteYep, brilliant. Thanks for sharing, keep up the good work.
ReplyDeleteThe regex used to select rules has an edge case for similar-ending ports such as 8080 and 80 where when looking for port 80 it will fnd the rule for 8080 and fail. The version below uses a more resilient regex and adds some debugging statements
ReplyDelete#!/bin/bash
# From: http://notepad2.blogspot.de/2012/06/shell-script-update-ufw-rules-for-hosts.html
HOSTS_ALLOW=/etc/ufw-dynamic-hosts.allow
IPS_ALLOW=/var/tmp/ufw-dynamic-ips.allow
#MROY: output timestamp
echo "Runtime:" `date`
echo "Running with: $SHELL"
add_rule() {
local proto=$1
local port=$2
local ip=$3
local regex="\][ \t]*${port}\/${proto}[ \t]*ALLOW[ \t]*IN[ \t]*${ip}"
local rule=$(/usr/sbin/ufw status numbered | grep "$regex")
#echo "DEBUG regex: ${regex}"
#echo "DEBUG rule: ${rule}"
if [ -z "$rule" ]; then
/usr/sbin/ufw allow proto ${proto} from ${ip} to any port ${port}
#MROY:
echo "...rule added."
else
echo "rule already exists. nothing to do. (proto ${proto} from ${ip} to any port ${port})"
fi
}
delete_rule() {
local proto=$1
local port=$2
local ip=$3
local regex="${port}\/${proto}.*ALLOW.*IN.*${ip}"
local rule=$(/usr/sbin/ufw status numbered | grep $regex)
if [ -n "$rule" ]; then
/usr/sbin/ufw delete allow proto ${proto} from ${ip} to any port ${port}
#MROY:
echo "rule deleted. (proto ${proto} from ${ip} to any port ${port})"
else
echo "rule does not exist. nothing to do."
fi
}
sed '/^[[:space:]]*$/d' ${HOSTS_ALLOW} | sed '/^[[:space:]]*#/d' | while read line
do
proto=$(echo ${line} | cut -d: -f1)
port=$(echo ${line} | cut -d: -f2)
host=$(echo ${line} | cut -d: -f3)
if [ -f ${IPS_ALLOW} ]; then
old_ip=$(cat ${IPS_ALLOW} | grep ${host} | cut -d: -f2)
fi
ip=$(dig +short $host | tail -n 1)
if [ -z ${ip} ]; then
if [ -n "${old_ip}" ]; then
delete_rule $proto $port $old_ip
fi
echo "Failed to resolve the ip address of ${host}." 1>&2
exit 1
fi
if [ -n "${old_ip}" ]; then
if [ ${ip} != ${old_ip} ]; then
delete_rule $proto $port $old_ip
fi
fi
add_rule $proto $port $ip
if [ -f ${IPS_ALLOW} ]; then
sed -i.bak /^${host}*/d ${IPS_ALLOW}
fi
echo "${host}:${ip}" >> ${IPS_ALLOW}
done
#MROY:
echo "Reached end of script at" `date`
Oh you awesome person, this is just what I was looking for!
ReplyDeleteAnyone know the right syntax if I want to allow all traffic from my Dynamic ip?
ReplyDeleteSeams that Cron is running the script, but UFW did not get new rules. If I run the script manually, it works.
ReplyDelete