Python DNS Proxy
Here is a DNS proxy server script written in Python. The purpose is to forward DNS requests to another (real) DNS server, and then send the replies back to the client. No mangling of the UDP datagrams are performed, the packets are simply passing through.
I have only tried to run the script on Linux, and the script will also attempt to find the script host's own DNS server in /etc/resolv.conf to use as the remote DNS server. And since it will attempt to bind on port 53, you will probably have to run the script as root.
Enjoy:
#!/usr/bin/python from threading import Thread import socket import Queue import time class Forward(Thread): def __init__(self, packet, client_address, dns_ip, reply_queue): Thread.__init__(self) self.packet = packet self.client_address = client_address self.dns_ip = dns_ip self.dns_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.reply_queue = reply_queue def run(self): self.dns_sock.sendto(self.packet, (self.dns_ip, 53)) while True: new_packet, address = self.dns_sock.recvfrom(512) if address[0] == self.dns_ip: self.reply_queue.put((new_packet, self.client_address)) break class DNSProxy(object): def __init__(self, listen_port, dns_ip): self.dns_ip = dns_ip self.reply_queue = Queue.Queue() self.server_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.server_sock.bind(("", listen_port)) self.server_sock.setblocking(0) print "Using DNS server IP: %s" % (dns_ip) def check(self): # Check for incoming requests and start threads on them. try: packet, address = self.server_sock.recvfrom(512) if len(packet) > 0: print "Recevied request from:", address t = Forward(packet, address, self.dns_ip, self.reply_queue) t.start() except socket.error, e: if e[0] != 11 and e[0] != 10035: raise # Check if any threads has put a reply on the queue to send. try: packet, address = self.reply_queue.get_nowait() self.server_sock.sendto(packet, address) print "Sent reply to:", address except Queue.Empty: pass def get_dns_server(): fh = open("/etc/resolv.conf", "r") for line in fh: if len(line) > 11: if line[:11] == "nameserver ": return line[11:].strip() fh.close() if __name__ == "__main__": proxy = DNSProxy(53, get_dns_server()) while True: proxy.check() time.sleep(0.01)