UFW rules for specific host / dynamic dns

1

1

How can I setup UFW (Uncomplicated Firewall) to add rules for specific hosts? Eg. I want to allow SSH only from yourpc.no-ip.org?

Force

Posted 2013-09-18T11:28:07.720

Reputation: 642

Answers

4

I found a very useful script that creates rules dynamically for specific hosts in this blog. The script needs to be run with cron, so it can lookup a hostname and add/delete rules in case the IP changed.

#!/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 content of /etc/ufw-dynamic-hosts.allow could look like this:

tcp:22:yourpc.no-ip.org

and a crontab entry for executing the script every five minutes could look like this:

*/5 * * * * /usr/local/sbin/ufw-dynamic-host-update > /dev/null

Force

Posted 2013-09-18T11:28:07.720

Reputation: 642

+1 -- In my case, i use 'ufw status' instead 'ufw status numbered' in line 12 because of some "bad variable name" error in some cases. Also on root crontab i forced to use 'sudo sh /usr/local/sbin/ufw-dynamic-host-update > /dev/null'. For debugging you should make it to point in a file like 'sudo sh /usr/local/sbin/ufw-dynamic-host-update >> /etc/ufw-custom-log'. – giannis.epp – 2015-10-08T12:18:15.970