Dynamic firewall rules for iptables

Here's the problem: you're allowing access to some ports of your server based on source IPs. This is common practise, even if it's not 100% secure (since source IPs can be spoofed in certain situations). However what if you've no fixed source IP address(es) (which is common practise too) that you can feed into iptables rules? You can register a domain name at a dynamic DNS provider (eg. dyndns.org) and have your client (a DSL router or a client app on your PC) automatically update the IP of that domain name, whenever your client's internet connection get's up. But still, iptables does not allow use of domain names in firewall rules (and it's good so Smiling ). Here's where my script comes into play. It allows you to specify a list of domain names and destinations (host+port) for which the script will automatically generate permitting iptables rules.

The script is self-documented: take a look at the comments at the start of the script to learn how it can be set up. Don't forget to configure cron to execute the script periodically so iptables rules are updated regularily as the clients' IPs change.

AttachmentSize
dynamic_address_rules-1.1.sh11.76 KB
dynamic_address_rules-1.2.sh12.05 KB
dynamic_address_rules-1.3.sh12.24 KB
dynamic_address_rules-1.4.sh12.36 KB

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

dynamic address rules update

I've uploaded a new version with some minor bugfixes and modifications in logging.

Would you

Would you pls provide me the txt format of this script?
Dynamic firewall rules for iptables
2009, February 22 - 17:46 — müzso

Re: Would you

The script is attached to my post and is downloadable for everybody. See the "Attachments" section towards the end of the post.

Hard Coded eth0

I noticed that you have hard coded eth0.

I recomend that you allow for non hard coded eth?

I will modify the code to allow this if you would like me to send it back?

Re: Hard Coded eth0

Thanks for the suggestion. I've uploaded v1.3 that has the network interface name as a parameter at the start of the script. If the script gains more popularity I might even add config file support (ie. the parameters would be pulled out from the script and placed in a separate config file in /etc).

Bugfix for my dynamic firewall rules script

If there was already a rule in the rule_generation_specs array and a new rule was added and the cache file already existed with the old rule's cache record, then the iptables chain's rules were regenerated, but only the new spec rule was applied ... thus IPs of all old rules were denied access.
This got fixed in v1.2.

iptables DNAT and SNAT

Hello,

Could be this script modified to manage DNAT and SNAT (POSTROUTING and PREROUTING rules), with dynamic ips?

Thanks

Re: iptables DNAT and SNAT

Yes, it could be modified.

Will this accept a port-range (rather than single port)

Wow, awesome script! Thank you for sharing this.

First, would it be easier to simply hard-code the dynamic DNS entries in a iptables script file, and re-run the file (flushing/resetting the rules) every X minutes? Or is there a reason this wouldn't work?

Second, I'm curious about how to open multiple ports...

The current example shows:
"dynamic2.address.example.com;22"

Could it open multiple ports by using a port-range, for example:
"dynamic2.address.example.com;0:1023"

Or is there any way to simply remove the second parameter for complete access by that host?
"dynamic2.address.example.com"

Re: Will this accept a port-range (rather than single port)


First, would it be easier to simply hard-code the dynamic DNS entries in a iptables script file, and re-run the file (flushing/resetting the rules) every X minutes? Or is there a reason this wouldn't work?

It'd be definitely easier. Whether it works as expected ... it depends. Under certain circumstances it might work. But that method would rely on the system-wide DNS resolver to return an up-to-date DNS response for the given domain name. Since if you specify a domain name in your iptables command, it'll use the DNS servers as given in your /etc/resolv.conf file (supposing you use the simple file based DNS resolver).
In case of DynDNS, the SOA DNS servers for the dyndns.org domain (eg. ns1.dyndns.org) return a TTL of 60 seconds. If your DNS forwarder honors that, then you should have no problem, since your iptables command will always get an up-to-date IP address for the given domain name. However if your DNS server does not honor the TTLs returned by the ns*.dyndns.org servers (or if you use another dynamic DNS provider that uses a significantly larger TTL), then it will not work well, since your iptables script will get a cached IP address that might not be up-to-date.

And there's another issue: DNS server failure. I've already experienced that dyndns.org name servers can fail sometimes. During the development of this script I've experienced multiple DNS reponse failures from the ns*.dyndns.org servers (probably due to high load). My script can query multiple DNS servers in case one fails. If you specify all dyndns.org DNS servers in your rule, then the script will query each until it gets an IP address from one of them. It is quite unlikely that all ns*.dyndns.org servers fail at the same time so that should be enough. There're five dyndns.org DNS servers (ns1.dyndns.org, ..., ns5.dyndns.org).

Could it open multiple ports by using a port-range, for example:
"dynamic2.address.example.com;0:1023"

The current version does not support port ranges (of course this enhancement might be added later). You can add multiple ports only by listing them one by one.
Eg.: "dynamic2.address.example.com;0,1,2,3,4,5,6,...,1023"
Of course in the above example the "..." should be replaced with all the ports in the range. It'd make quite a long line and I'm not even sure it'd work. I've never tested any rule strings that long. Theoretically it should, but who knows (there might be some secret buffer limitation that I cannot recall right now).

Or is there any way to simply remove the second parameter for complete access by that host?
"dynamic2.address.example.com"

No. The second parameter is compulsory. I could remove this limitation of course. I did not think that somebody would ever require all ports to be opened for a given client address. Of course there're cases (dumb protocols like Oracle's SQL*Net) when you've no choice.

Syndicate content