DHCP Request / Reply. (Python) DHCP клиент / сервер не глотает фейковый пакет
Нужно на питоне создать скрипт который будет эмитировать некоторые DHCP пакеты. При этом когда пускаю в сеть DHCP Discovery роутер (TP_Link) на это не отвечает, просто игнорирует. Насколько я знаю поле checksum не проверяется ни сервером ни клиентом, поэтому оставляю его пустым
import socket
import binascii
import struct
import uuid
import random
class DHCPGen:
def __init__(self):
self.dataHead = []
def dhcpdiscoveer(self):
self.dataHead = [
b'\x01\x01' # Message Type
b'\x06\x00', # Request Type
struct.pack('!I', random.randrange(0, 2147483647, 1)), # Transaction ID /20
b'\x00\x00', # elasted
b'\x00\x00', # flags
b'\x00\x00\x00\x00', # You (Client) IP address
b'\x00\x00\x00\x00', # You (Client) IP address
b'\x00\x00\x00\x00', # Next server IP address
b'\x00\x00\x00\x00', # Relay agent IP address
struct.pack('!6B', *[0, 227, 197, 187, 99, 255]), # Client MAC
struct.pack('!5H', *[0 for i in range(0, 5)]), # Client HW address padding
struct.pack('!32H', *[0 for i in range(0, 32)]), # Server host name (not given 0x00(64)) /29
struct.pack('!64H', *[0 for i in range(0, 64)]), # Boot file name (not given 0x00(128))
b'\x63\x82\x53\x63', # Magic cookie DHCP
#options
b'\x35\x01\x01', # (53) DHCP Mes Type: Discover (1)
b'\x3d\x07\x01'+struct.pack('!6B', *[0, 227, 197, 187, 99, 255]), # (61) Client identifier /33
b'\x32\x04'+struct.pack('!4B', *[192, 168, 1, 128]), # (50) Requested IP address
b'\x0c',
struct.pack('!B', len(socket.gethostname())), # (12) Host Name (len)
bytes(socket.gethostname(), 'ASCII'), # (12) Host Name (text)
b'\x3c\x08\x4d\x53\x46\x54\x20\x35\x2e\x30', # (60) Vendor class ident
b'\x37\x0e\x01\x03\x06\x0f\x1f\x21\x2b\x2c\x2e\x2f\x77\x79\xf9\xfc', # Parameter Request List
b'\xff' # end
]
return self.dataHead
def __getLocMac(self):
locmac = []
for i in [("%X" % uuid.getnode())[i:i+2] for i in range(0, 12, 2)]:
if i == '':
continue
locmac.append(int(i, 16))
if len(locmac) < 6:
locmac.insert(0, int('00', 16))
return locmac
def __getLocIp(self):
ip = [int(i) for i in socket.gethostbyname(socket.gethostname()).split('.')]
return ip
if __name__ == '__main__':
dhcp = DHCPGen()
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.bind(('', 68))
sock.sendto(b''.join(dhcp.dhcpdiscoveer()), ('<broadcast>', 67))
sock.close()
Точно такая же ситуация и с ответом на DHCP Discover. DHCP клиент не отвечает request-ом на offer.
Запуская скрипт подключаюсь с ноута (Windows) к сети, Wireshark показывает, клиент отправил Discover, скрипт ловит пакет, парсит, генерирует Offer, но Offer остаётся проигнорированным. Однако ответ от реального dhcp ловится и успешно глотается.
import socket
import binascii
import struct
import uuid
import random
class DHCPGen:
def __init__(self):
self.dataHead = []
def offer(self, parsedData):
self.dataHead = [
parsedData['sourceMac'],
struct.pack('!6B', *self.__getLocMac()),
b'\x08\x00\x45\x00',
b'\x02\x40',
struct.pack('!H', random.randrange(0, 65535, 1)),
b'\x00\x00\x64\x11\x00\x00',
struct.pack('!4B', *[192, 168, 0, 108]),
struct.pack('!4B', *[192, 168, 0, 220]),
b'\x00\x43\x00\x44',
b'\x02\x2c',
b'\x0a\x80',
# DHCP
b'\x02',
b'\x01\x06\x00',
parsedData['transaction'],
b'\x00\x00\x00\x00',
b'\x00\x00\x00\x00', # Client IP addr
struct.pack('!4B', *[192, 168, 0, 220]), # You (client) ip addr
b'\x00\x00\x00\x00',
b'\x00\x00\x00\x00',
parsedData['sourceMac'],
struct.pack('!5H', *[0 for i in range(0, 5)]), # Client HW address padding
struct.pack('!32H', *[0 for i in range(0, 32)]), # Server host name (not given 0x00(64)) /29
struct.pack('!64H', *[0 for i in range(0, 64)]), # Boot file name (not given 0x00(128))
b'\x63\x82\x53\x63',
b'\x35\x01\x02', # (53) Message type 2 offer
b'\x36\x04'+struct.pack('!4B', *[192, 168, 0, 108]), # (54) DHCP Server IP
b'\x33\x04\x00\x00\x1c\x20', # (51) Lease Time
b'\x01\x04\xff\xff\xff\x00', # (1) Subnet Mask
b'\x03\x04'+struct.pack('!4B', *[192, 168, 0, 108]), # (3) Router IP
b'\x06\x04'+struct.pack('!4B', *[192, 168, 0, 108]), # (6) DNS server
b'\xff',
struct.pack('!274B', *[0 for i in range(0, 274)])
]
length = len(b''.join(self.dataHead)) - 14
self.dataHead[3] = struct.pack('!H', length)
self.dataHead[9] = struct.pack('!H', length - 20)
return self.dataHead
def parseHeader(self, data):
parsedData = {
'destMac' : data[0:6],
'sourceMac' : data[6:12],
'typeip' : data[12:15],
'protoData' : data[14:16],
'clientMac' : data[70:76],
'transaction' : data[46:50]
}
return parsedData
def __getLocMac(self):
locmac = []
for i in [("%X" % uuid.getnode())[i:i+2] for i in range(0, 12, 2)]:
if i == '':
continue
locmac.append(int(i, 16))
if len(locmac) < 6:
locmac.insert(0, int('00', 16))
return locmac
def __getLocIp(self):
ip = [int(i) for i in socket.gethostbyname(socket.gethostname()).split('.')]
return ip
if __name__ == '__main__':
dhcp = DHCPGen()
sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
sock.bind(('eth0', 0))
sock.settimeout(20)
while True:
try:
mes = sock.recvfrom(1024)
data = mes[0]
if binascii.hexlify(data[14:16]) != b'4500' or struct.unpack('!H', data[16:18])[0] < 280 or binascii.hexlify(data[23:24]) != b'11' or binascii.hexlify(data[282:285]) != b'350101':
continue
print(data)
parsed = dhcp.parseHeader(data)
print('__________________')
reply = b''.join(dhcp.offer(parsed))
sock.send(reply)
except Exception as e:
print('Error: '+str(e))
sock.close()
Что в этих заголовках не так? Почему реальные ни клиент ни сервер на них не отвечают?