sniffer_ip_header_decode.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import ipaddress
  2. import os
  3. import socket
  4. import struct
  5. import sys
  6. class IP:
  7. def __init__(self, buff):
  8. header = struct.unpack('<BBHHHBBH4s4s', buff)
  9. self.ver = header[0] >> 4
  10. self.ihl = header[0] & 0xF
  11. self.tos = header[1]
  12. self.len = header[2]
  13. self.id = header[3]
  14. self.offset = header[4]
  15. self.ttl = header[5]
  16. self.protocol_num = header[6]
  17. self.sum = header[7]
  18. self.src = header[8]
  19. self.dst = header[9]
  20. # IP-адруса, понятные человек
  21. self.src_address = ipaddress.ip_address(self.src)
  22. self.dst_address = ipaddress.ip_address(self.dst)
  23. # сопоставляем константы протоколов с их назначением
  24. self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}
  25. try:
  26. self.protocol = self.protocol_map[self.protocol_num]
  27. except Exception as e:
  28. print('%s No protocol for %s' % (e, self.protocol_num))
  29. self.protocol = str(self.protocol_num)
  30. def sniff(host):
  31. # создаем сырой сокет и привязываем к общедоступному интерфейсу
  32. if os.name == 'nt':
  33. socket_protocol = socket.IPPROTO_IP
  34. else:
  35. socket_protokol = socket.IPPROTO_ICMP
  36. sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
  37. sniffer.bind((host, 0))
  38. # делаем так, чтобы захватывался IP-заголовок
  39. sniffer.setsockopt(socket.IPPROTO_IP, socket.RCVALL_ON, 1)
  40. if os.name == 'nt':
  41. sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
  42. try:
  43. while True:
  44. # читаем пакет
  45. raw_buffer = sniffer.recvfrom(65535)[0]
  46. # создаем IP-заголовок из первый 20 байтов
  47. ip_header = IP(raw_buffer[0:20])
  48. # выводим обнаруженный протокол и адреса
  49. print("Protocol: %s %s -> %s" % (ip_header.protocol,
  50. ip_header.src_address,
  51. ip_header.dst_address))
  52. except KeyboardInterrupt:
  53. # если мы в Windows, выключаем неизбирательный режим
  54. if os.name == 'nt':
  55. sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
  56. sys.exit()
  57. if __name__ == '__main__':
  58. if len(sys.argv) == 2:
  59. host = sys.argv[1]
  60. sniff(host)