IPtables whitelist dynamic IP by hostname
Solution 1:
iptables
works on IP addresses, not on hostnames. You can use hostnames as arguments, but they will be resolved at the time the command is entered. Doing a DNS lookup for each passing packet would be much too slow.
Your idea to adjust the rules is therefore the only approach. This can be either at a regular schedule, controlled by a program like systemd or cron, or better if you can manage to receive a notification whenever the IP address changes.
You don't have to store the old address, just make an iptables chain for your rule and replace the rule. See the -R
option to iptables
. To have a rule to replace on the first check, just add a dummy rule so that there will be a rule to replace when the first check runs.
You can also avoid the extra chain and replace a rule at a specific position in INPUT
or FORWARD
, but that is much more work to maintain, as the position number changes whenever you add or delete rules.
Solution 2:
The way I do this is:
- Run a script every x minutes from crontab to update an "ipset"
- Have IPtables use the ipset
Assuming you have only 1 IP address in this ipset, the following script would do:
#!/bin/bash
# Update ipset to let my dynamic IP in
set=whitelist
host=myhost.dynamic.example.com
me=$(basename "$0")
ip=$(dig +short $host)
if [ -z "$ip" ]; then
logger -t "$me" "IP for '$host' not found"
exit 1
fi
# make sure the set exists
ipset -exist create $set hash:ip
if ipset -q test $set $host; then
logger -t "$me" "IP '$ip' already in set '$set'."
else
logger -t "$me" "Adding IP '$ip' to set '$set'."
ipset flush $set
ipset add $set $host
fi
In crontab
I call this script every 5 minutes :
*/5 * * * * root /usr/local/bin/ipset-update-dyn
In iptables, the rule using the ipset looks like this :
-A INPUT -p tcp -m set --match-set whitelist src -m state --state NEW -j ACCEPT