In 2011, I wrote this post on Dynamic DNS: https://www.geeklab.info/2011/02/iptables-and-dynamic-dns. While this is still useful, I found a newer, cooler way to do Dynamic DNS in combination with iptables. It's called libnetfilter_queue.
iptables is used to change the inner netfilter tables of the kernel. And because the kernel has no internal resolver, it is impossible for the kernel to do on-the-fly dns lookups. But by offloading this decision to userspace, it is possible. The libnetfilter_queue lib offers that functionality.
libnetfilter_queue is a userspace library providing an API to packets that have been queued by the kernel packet filter. It has bindings for Python and several other languages.
Requirements for my setup
python-NetfilterQueue - https://github.com/kti/python-netfilterqueue
libnfnetlink
libnetfilter_queue
libmnl
You may need to build the first dependency yourself. The other 3 are available in Fedora 20 by default. If you're running RHEL/CentOS, the Fedora packages can be recompiled for your setup.
iptables rule
First, you need to get iptables to enqueue specific packets to your queue.
iptables -I INPUT -p tcp --dport 631 -m state --state NEW -j NFQUEUE --queue-num 6789 -m comment --comment "Remote CUPS printer" |
Queue handler
Then we write a script that handles the queue. A quick-and-dirty implementation:
#!/usr/bin/python import socket from netfilterqueue import NetfilterQueue def getIP(d): """ This method returns the first IP address string that responds as the given domain name """ try: data = socket.gethostbyname(d) #ip = repr(data) return data except Exception: # fail gracefully! return False def dnsfilter(pkt): if pkt.get_payload_len() < 0x10: "Don't know how to handle this too small packet" pkt.drop() return False payload=pkt.get_payload() srcip=".".join("{:d}".format(ord(c)) for c in payload[0x0c:0x10]) allowedip=getIP('localhost') print "Debug: SRC="+srcip+" ALLOWED="+allowedip+" RESULT=", if srcip==allowedip: print "Accept" pkt.accept() else: print "Drop" pkt.drop() nfqueue = NetfilterQueue() nfqueue.bind(6789, dnsfilter) try: nfqueue.run() except KeyboardInterrupt: print |
This is a quick-and-dirty implementation that misses basic features such as caching the result of gethostbyname. This may introduce terrible delays if used wrong.
Ubuntu/Debian
I'm running RedHat-based software on all of my machines. Above information may be useful for Ubuntu/Debian users, but it's not tested and I'm not supporting it.Servers: RedHat Enterprise Linux/CentOS is more suitable for servers, as there's a lot of professional level support available. I think that's important, because if I say, get a car accident, I want the servers to be managable by another professional.
Desktops/Laptops: RPM packages are pretty exchangable between RedHat-based platforms. That's a good reason to run Fedora on the desktop.