-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain2.py
257 lines (184 loc) · 6.74 KB
/
main2.py
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
'''
Licencia GPL v3
Autores: Alejandro Sacristan Leal & Camilo Jose Narvaez Montenegro & Loui Gerald Quintero & Juan Pablo Urrego
Materia: Comunicación y Redes
Universidad: Pontificia Universidad Javeriana de Bogotá Colombia
Semestre: 2021-10
Desarrollo: Servidor DNS con MasterFile solo tipo A y Foreing Resolver
Fecha de Entrega: 2/5/2021
'''
import socket, glob, json
# Estandar DNS
LocalHost = '127.0.0.1' #Local Host 127.0.0.1
OpenDNS = '208.67.220.220' # IP de OpenDNS
DNSPort = 53 # Puerto DNS estandar
SIZE = 512 # Mensajes UDP de 512 octetos or lees
serverDNSAddressPort = (OpenDNS, DNSPort) # Datos de Servidor DNS Amigo
# Creando y Configurando Servidor UDP
udpServerSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udpServerSocket.bind((LocalHost, DNSPort))
# Cargar Zonas para respuesta Autoritativa del MasterFile
def getMasterFile():
jsonZona = {}
zonaFile = glob.glob('MasterFile/*.zona')
for zona in zonaFile:
with open(zona) as MaterFileData:
data = json.load(MaterFileData)
zonaName = data["$origin"]
jsonZona[zonaName] = data
return jsonZona
MaterFileData = getMasterFile()
def searchDomineMasterFiles(domainName):
try:
global MaterFileData
zonaName = '.'.join(domainName)
return MaterFileData[zonaName]
except KeyError:
return False
# Edit Flags
def hackFlags(flags):
# Byte Uno
byteUNO = bytes(flags[:1])
QR = '1'
Opcode = ''
AA = '1' # Respuesta Autoritativa
TC = '0'
RD = '0'
for bit in range(1,5):
Opcode += str(ord(byteUNO)&(1<<bit))
# Byte Dos
byteDOS = bytes(flags[1:2])
RA = '0'
Z = '000'
RCODE = '0000'
# Uniendo las Partes que componen el flag y conviertiendolas a bytes
newFlags = (int(QR+Opcode+AA+TC+RD, 2).to_bytes(1, 'big')) + (int(RA+Z+RCODE, 2).to_bytes(1, 'big'))
return newFlags
def dsnQuestionToBytes(domainName, tipo):
dsnQuestionInBytes = b''
for part in domainName:
lenght = len (part)
dsnQuestionInBytes += bytes([lenght])
for char in part:
dsnQuestionInBytes += ord(char).to_bytes(1, 'big')
if tipo == 'a':
dsnQuestionInBytes += (1).to_bytes(2,'big')
dsnQuestionInBytes += (1).to_bytes(2,'big')
return dsnQuestionInBytes
# Query section
def queryQuestionDomain(dataGram):
aux = 0
auxTwo = 0
flag = 0
dataLeng = 0
domainNameChar = ''
domainName = []
for byte in dataGram:
if flag == 1:
if byte != 0:
domainNameChar += chr(byte)
aux +=1
if aux == dataLeng:
domainName.append(domainNameChar)
domainNameChar = ''
flag = 0
aux = 0
if byte == 0:
domainName.append(domainNameChar)
break
else:
flag = 1
dataLeng = byte
auxTwo += 1
questionType = dataGram[auxTwo:auxTwo+2]
return (domainName, questionType)
def searchTypeADominesMasterFiles(dataGram):
domainName, questionType = queryQuestionDomain(dataGram)
questionTypeChar = ''
if questionType == b'\x00\x01':
questionTypeChar = 'a'
zona = searchDomineMasterFiles(domainName)
return (zona[questionTypeChar], questionTypeChar, domainName)
def booleanFindZone(dataGram):
domainName, questionType = queryQuestionDomain(dataGram[12:])
questionTypeChar = ''
if questionType == b'\x00\x01':
questionTypeChar = 'a'
zona = searchDomineMasterFiles(domainName)
if zona == False:
return True
else:
return False
def convertDNSbodyTObytes(domainname, questionTypeChar, ttl, value):
DNSbody = b'\xc0\x0c'
if questionTypeChar == 'a':
DNSbody = DNSbody + bytes([0]) + bytes([1])
DNSbody = DNSbody + bytes([0]) + bytes([1])
DNSbody += int(ttl).to_bytes(4, byteorder='big')
if questionTypeChar == 'a':
DNSbody = DNSbody + bytes([0]) + bytes([4])
for part in value.split('.'):
DNSbody += bytes([int(part)])
return DNSbody
# Domain Name System Query
def makeQueryRespondDNS(dataGram):
errorNotFindZone = booleanFindZone(dataGram)
if errorNotFindZone == False:
TansactionID = dataGram[:2]
TransactionIDHex = ''
for byte in TansactionID:
TransactionIDHex += hex(byte)[:2]
Flags = hackFlags(dataGram[2:4])
QDCOUNT = b'\x00\x01'
ANCOUNT = len(searchTypeADominesMasterFiles(dataGram[12:])[0]).to_bytes(2,'big')
NSCOUNT = (0).to_bytes(2, 'big')
ARCOUNT = (0).to_bytes(2, 'big')
DNSheader = TansactionID + Flags + QDCOUNT + ANCOUNT + NSCOUNT + ARCOUNT
DNSbody = b''
zonaMasterfile, questionTypeChar, domainName = searchTypeADominesMasterFiles(dataGram[12:])
dsnQuestion = dsnQuestionToBytes(domainName, questionTypeChar)
for zona in zonaMasterfile:
DNSbody += convertDNSbodyTObytes(domainName, questionTypeChar, zona["ttl"], zona["value"])
QueryRespond = DNSheader + dsnQuestion + DNSbody
else:
QueryRespond = False
return QueryRespond
# Cliente UDP send queryAsk from original cliente to OpenDNS and return the queryResponds of OpenDNS
def foreingResolver(dataGramFromFriendDNS, serverDNSAddressPort):
# Creando Nuevo UDP Socket
UDPSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Enviando datagrama del cliente a OpenDNS
UDPSocket.sendto(dataGramFromFriendDNS, serverDNSAddressPort)
queryRespondDNSFriend, addrDNSfriend = UDPSocket.recvfrom(512)
#Retornando Datagrama de OpenDNS
return queryRespondDNSFriend
# Servidor DNS
try:
while True:
print("Dancing...")
# 1 Configurando Servidor UDP para la recepcion de datagramas UDP no mas de 512 octetos
dataGram1, addrCliente = udpServerSocket.recvfrom(SIZE)
# 2 Enviando Datagrama a OpenDns y Resiviendo la respuesta
queryRespond = foreingResolver(dataGram1, serverDNSAddressPort)
print("Query Recibido Cliente ")
print(addrCliente)
print(dataGram1)
print(" ")
# 3 Enviando el query Responds al mismo cliente
udpServerSocket.sendto(queryRespond, addrCliente)
print("Query Enviado Cliente ")
print(addrCliente)
print(queryRespond)
print(" ")
print("---------------------------")
print("Esperando mas Datagramas...")
print("---------------------------")
print(":)")
print(" ")
except KeyboardInterrupt:
udpServerSocket.close()
print(" ")
print(" ")
print(' Adios Amigo Que la Fuerza te Acompañe...')
print(" :)")
print(" ")