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" |
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 |
#!/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.© GeekLabInfo iptables and dynamic DNS - part 2 is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to http://www.geeklab.info (No Ratings Yet)
Loading...