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)