1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
from __future__ import print_function
import os
import sys
import signal
import socket
import select
from datetime import datetime, timedelta
import time
import functools
import dns, dns.message, dns.query, dns.flags
from dns.rdatatype import *
from dns.rdataclass import *
from dns.rcode import *
from dns.name import *
# Log query to file
def logquery(type, qname):
with open("qlog", "a") as f:
f.write("%s %s\n", type, qname)
############################################################################
# Respond to a DNS query.
############################################################################
def create_response(msg):
m = dns.message.from_wire(msg)
qname = m.question[0].name.to_text()
rrtype = m.question[0].rdtype
typename = dns.rdatatype.to_text(rrtype)
with open("query.log", "a") as f:
f.write("%s %s\n" % (typename, qname))
print("%s %s" % (typename, qname), end=" ")
r = dns.message.make_response(m)
r.set_rcode(NOERROR)
if rrtype == A:
tld = qname.split(".")[-2] + "."
ns = "local." + tld
r.answer.append(dns.rrset.from_text(qname, 300, IN, A, "10.53.0.11"))
r.answer.append(dns.rrset.from_text(tld, 300, IN, NS, "local." + tld))
r.additional.append(dns.rrset.from_text(ns, 300, IN, A, "10.53.0.11"))
elif rrtype == NS:
r.answer.append(dns.rrset.from_text(qname, 300, IN, NS, "."))
elif rrtype == SOA:
r.answer.append(dns.rrset.from_text(qname, 300, IN, SOA, ". . 0 0 0 0 0"))
else:
r.authority.append(dns.rrset.from_text(qname, 300, IN, SOA, ". . 0 0 0 0 0"))
r.flags |= dns.flags.AA
return r
def sigterm(signum, frame):
print("Shutting down now...")
os.remove("ans.pid")
running = False
sys.exit(0)
############################################################################
# Main
#
# Set up responder and control channel, open the pid file, and start
# the main loop, listening for queries on the query channel or commands
# on the control channel and acting on them.
############################################################################
ip4 = "10.53.0.11"
ip6 = "fd92:7065:b8e:ffff::11"
try:
port = int(os.environ["PORT"])
except:
port = 5300
query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
query4_socket.bind((ip4, port))
havev6 = True
try:
query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
try:
query6_socket.bind((ip6, port))
except:
query6_socket.close()
havev6 = False
except:
havev6 = False
signal.signal(signal.SIGTERM, sigterm)
f = open("ans.pid", "w")
pid = os.getpid()
print(pid, file=f)
f.close()
running = True
print("Listening on %s port %d" % (ip4, port))
if havev6:
print("Listening on %s port %d" % (ip6, port))
print("Ctrl-c to quit")
if havev6:
input = [query4_socket, query6_socket]
else:
input = [query4_socket]
while running:
try:
inputready, outputready, exceptready = select.select(input, [], [])
except select.error as e:
break
except socket.error as e:
break
except KeyboardInterrupt:
break
for s in inputready:
if s == query4_socket or s == query6_socket:
print(
"Query received on %s" % (ip4 if s == query4_socket else ip6), end=" "
)
# Handle incoming queries
msg = s.recvfrom(65535)
rsp = create_response(msg[0])
if rsp:
print(dns.rcode.to_text(rsp.rcode()))
s.sendto(rsp.to_wire(), msg[1])
else:
print("NO RESPONSE")
if not running:
break
|