Skip to content

Instantly share code, notes, and snippets.

@lilydjwg
Created April 17, 2016 13:37
Show Gist options
  • Save lilydjwg/db1615b944894b27a9538b4852207a77 to your computer and use it in GitHub Desktop.
Save lilydjwg/db1615b944894b27a9538b4852207a77 to your computer and use it in GitHub Desktop.
Answer AAAA DNS queries on behalf of a DNS server
#!/usr/bin/env python3
import socket
import struct
import traceback
import subprocess
import time
import signal
import dnslib
from dnslib import DNSRecord
from netfilterqueue import NetfilterQueue
AAAA = dnslib.QTYPE.reverse['AAAA']
udpsock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
PORT = 53
def handle_packet(pkt):
s = time.time()
try:
ip = pkt.get_payload()
# 28 = 20B IPv4 header + 8B UDP header
dns = DNSRecord.parse(ip[28:])
if dns.q.qtype == AAAA:
ret = dns.reply()
src = socket.inet_ntoa(ip[12:16])
sport = struct.unpack('!H', ip[20:22])[0]
p = ret.pack()
# print(ret, p)
checksum = 0
p = struct.pack('!HHHH', PORT, sport, len(p) + 8, checksum) + p
udpsock.sendto(p, (src, sport))
pkt.drop()
else:
pkt.accept()
except KeyboardInterrupt:
pkt.accept()
raise
except Exception:
traceback.print_exc()
pkt.accept()
e = time.time()
print('%.3fms' % ((e - s) * 1000))
def main():
nfqueue = NetfilterQueue()
nfqueue.bind(1, handle_packet)
try:
nfqueue.run()
except KeyboardInterrupt:
print()
def quit(signum, sigframe):
raise KeyboardInterrupt
if __name__ == '__main__':
signal.signal(signal.SIGTERM, quit)
signal.signal(signal.SIGQUIT, quit)
signal.signal(signal.SIGHUP, quit)
subprocess.check_call(['iptables', '-I', 'INPUT', '-p', 'udp', '-m', 'udp', '--dport', str(PORT), '-j', 'NFQUEUE', '--queue-num', '1'])
try:
main()
finally:
subprocess.check_call(['iptables', '-D', 'INPUT', '-p', 'udp', '-m', 'udp', '--dport', str(PORT), '-j', 'NFQUEUE', '--queue-num', '1'])
@lilydjwg
Copy link
Author

lilydjwg commented Apr 17, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment