Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNSChef modification for Hackathon #9

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions dnschef.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
[A] # Queries for IPv4 address records
*.thesprawl.org=192.0.2.1
test.httpgrey.com=192.168.1.4,GREY
test.httpwhite.com=192.168.1.5,WHITE
test.nonhttpgrey.com=192.168.1.7,GREY
test.nonhttpwhite.com=192.168.1.8,WHITE


[AAAA] # Queries for IPv6 address records
*.thesprawl.org=2001:db8::1
Expand Down Expand Up @@ -37,4 +41,4 @@

[RRSIG]
; FORMAT: covered algorithm labels labels orig_ttl sig_exp sig_inc key_tag name base64(sig)
*.thesprawl.org=A 5 3 86400 20030322173103 20030220173103 2642 thesprawl.org. oJB1W6WNGv+ldvQ3WDG0MQkg5IEhjRip8WTrPYGv07h108dUKGMeDPKijVCHX3DDKdfb+v6oB9wfuh3DTJXUAfI/M0zmO/zz8bW0Rznl8O3tGNazPwQKkRN20XPXV6nwwfoXmJQbsLNrLfkGJ5D6fwFm8nN+6pBzeDQfsS3Ap3o=
*.thesprawl.org=A 5 3 86400 20030322173103 20030220173103 2642 thesprawl.org. oJB1W6WNGv+ldvQ3WDG0MQkg5IEhjRip8WTrPYGv07h108dUKGMeDPKijVCHX3DDKdfb+v6oB9wfuh3DTJXUAfI/M0zmO/zz8bW0Rznl8O3tGNazPwQKkRN20XPXV6nwwfoXmJQbsLNrLfkGJ5D6fwFm8nN+6pBzeDQfsS3Ap3o=
103 changes: 83 additions & 20 deletions dnschef.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import string
import base64
import time
import iptc

# DNSHandler Mixin. The class contains generic functions to parse DNS requests and
# calculate an appropriate response based on user parameters.
Expand Down Expand Up @@ -77,11 +78,11 @@ def parse(self,data):

# Find all matching fake DNS records for the query name or get False
fake_records = dict()

#print "qname", qname
for record in self.server.nametodns:

#print "nametodns[record]", nametodns[record]
fake_records[record] = self.findnametodns(qname,self.server.nametodns[record])

#print "record in loop", record
# Check if there is a fake record for the current request qtype
if qtype in fake_records and fake_records[qtype]:

Expand Down Expand Up @@ -154,10 +155,55 @@ def parse(self,data):

else:
# dnslib doesn't like trailing dots
#print "fake_record",fake_record
#print "record type info ", recType
#print "Record type [record] ", recType[record]
if fake_record[-1] == ".": fake_record = fake_record[:-1]
response.add_answer(RR(qname, getattr(QTYPE,qtype), rdata=RDMAP[qtype](fake_record)))

response = response.pack()
response.add_answer(RR(qname, QTYPE.TXT, rdata=TXT("Proxy IP = 192.168.1.1")))
# Add iptables if it is grey packet
print "rectype for this query", recType[qname]
if recType[qname] == "GREY":
print "Entered if condition"
table = iptc.Table(iptc.Table.NAT)
chain = table.create_chain('dnatrules111')
rule = iptc.Rule()
rule.protocol = 'tcp'
rule.in_interface = 'eth0'

m = rule.create_match('tcp')
m.dport = '80'

t = rule.create_target('DNAT')
t.to_destination = '192.168.1.11'

chain.insert_rule(rule)

rule1 = iptc.Rule()
rule1.protocol = 'tcp'
rule1.in_interface = 'eth0'

m = rule1.create_match('tcp')
m.dport = '443'

t = rule1.create_target('DNAT')
t.to_destination = '192.168.1.11'

chain.insert_rule(rule1)

rule2 = iptc.Rule()
rule2.protocol = 'tcp'
rule2.in_interface = 'eth0'

m = rule2.create_match('tcp')
m.dport = '!80'

t = rule2.create_target('DNAT')
t.to_destination = '192.168.1.222'

chain.insert_rule(rule2)
print "Created iptable rules"
response = response.pack()

elif qtype == "*" and not None in fake_records.values():
print "[%s] %s: cooking the response of type '%s' for %s with %s" % (time.strftime("%H:%M:%S"), self.client_address[0], "ANY", qname, "all known fake records.")
Expand Down Expand Up @@ -250,7 +296,7 @@ def findnametodns(self,qname,nametodns):

# Make qname case insensitive
qname = qname.lower()

print nametodns
# Split and reverse qname into components for matching.
qnamelist = qname.split('.')
qnamelist.reverse()
Expand Down Expand Up @@ -351,12 +397,13 @@ def handle(self):
class ThreadedUDPServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):

# Override SocketServer.UDPServer to add extra parameters
def __init__(self, server_address, RequestHandlerClass, nametodns, nameservers, ipv6, log):
def __init__(self, server_address, RequestHandlerClass, nametodns, recType, nameservers, ipv6, log):
self.nametodns = nametodns
self.nameservers = nameservers
self.ipv6 = ipv6
self.address_family = socket.AF_INET6 if self.ipv6 else socket.AF_INET
self.log = log
self.recType = recType

SocketServer.UDPServer.__init__(self,server_address,RequestHandlerClass)

Expand All @@ -366,17 +413,18 @@ class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
allow_reuse_address = True

# Override SocketServer.TCPServer to add extra parameters
def __init__(self, server_address, RequestHandlerClass, nametodns, nameservers, ipv6, log):
def __init__(self, server_address, RequestHandlerClass, nametodns, recType, nameservers, ipv6, log):
self.nametodns = nametodns
self.nameservers = nameservers
self.ipv6 = ipv6
self.address_family = socket.AF_INET6 if self.ipv6 else socket.AF_INET
self.log = log
self.recType = recType

SocketServer.TCPServer.__init__(self,server_address,RequestHandlerClass)

# Initialize and start the DNS Server
def start_cooking(interface, nametodns, nameservers, tcp=False, ipv6=False, port="53", logfile=None):
def start_cooking(interface, nametodns, recType, nameservers, tcp=False, ipv6=False, port="53", logfile=None):
try:

if logfile:
Expand All @@ -387,9 +435,9 @@ def start_cooking(interface, nametodns, nameservers, tcp=False, ipv6=False, port

if tcp:
print "[*] DNSChef is running in TCP mode"
server = ThreadedTCPServer((interface, int(port)), TCPHandler, nametodns, nameservers, ipv6, log)
server = ThreadedTCPServer((interface, int(port)), TCPHandler, nametodns, recType, nameservers, ipv6, log)
else:
server = ThreadedUDPServer((interface, int(port)), UDPHandler, nametodns, nameservers, ipv6, log)
server = ThreadedUDPServer((interface, int(port)), UDPHandler, nametodns, recType, nameservers, ipv6, log)

# Start a thread with the server -- that thread will then start
# more threads for each request
Expand Down Expand Up @@ -462,9 +510,9 @@ def start_cooking(interface, nametodns, nameservers, tcp=False, ipv6=False, port
# Main storage of domain filters
# NOTE: RDMAP is a dictionary map of qtype strings to handling classes
nametodns = dict()
recType = {}
for qtype in RDMAP.keys():
nametodns[qtype] = dict()

# Incorrect or incomplete command line arguments
if options.fakedomains and options.truedomains:
print "[!] You can not specify both 'fakedomains' and 'truedomains' parameters."
Expand Down Expand Up @@ -501,13 +549,28 @@ def start_cooking(interface, nametodns, nameservers, tcp=False, ipv6=False, port
for section in config.sections():

if section in nametodns:
for domain,record in config.items(section):

# Make domain case insensitive
domain = domain.lower()

nametodns[section][domain] = record
print "[+] Cooking %s replies for domain %s with '%s'" % (section,domain,record)
print "section", section
if section =='A':
for domain,record in config.items(section):
domain = domain.lower()
rinfo = record.split(',')
print "rinfo", rinfo
record = rinfo[0]
print "record", record
rtype = rinfo[1]
nametodns[section][domain] = record
#nametodns[section][domain]['rtype'] = rtype
recType[domain] = rtype
print "[+] Cooking %s replies for domain %s of type %s with '%s'" % (section,domain,rtype,record)
print "Record type", recType
else:
for domain,record in config.items(section):

# Make domain case insensitive
domain = domain.lower()

nametodns[section][domain] = record
print "[+] Cooking %s replies for domain %s with '%s'" % (section,domain,record)
else:
print "[!] DNS Record '%s' is not supported. Ignoring section contents." % section

Expand Down Expand Up @@ -609,4 +672,4 @@ def start_cooking(interface, nametodns, nameservers, tcp=False, ipv6=False, port
print "[*] No parameters were specified. Running in full proxy mode"

# Launch DNSChef
start_cooking(interface=options.interface, nametodns=nametodns, nameservers=nameservers, tcp=options.tcp, ipv6=options.ipv6, port=options.port, logfile=options.logfile)
start_cooking(interface=options.interface, nametodns=nametodns, recType=recType, nameservers=nameservers, tcp=options.tcp, ipv6=options.ipv6, port=options.port, logfile=options.logfile)