2016-10-07 4 views
2

Я пытаюсь создать DHCP-сервер, и первым шагом для меня является передача пакетов через мой Ethernet-порт. Я пытаюсь отправить пакеты на свой Ethernet-интерфейс и обнаружил ошибку.Python Raw Socket to Ethernet Interface (Windows)

Код приведен ниже.

import socket 

def sendeth(src, dst, eth_type, payload, interface = "eth0"): 
    """Send raw Ethernet packet on interface.""" 

    assert(len(src) == len(dst) == 6) # 48-bit ethernet addresses 
    assert(len(eth_type) == 2) # 16-bit ethernet type 

    #s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW) 
    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) 

    # From the docs: "For raw packet 
    # sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])" 
    s.bind((interface, 0)) 
    return s.send(src + dst + eth_type + payload) 

if __name__ == "__main__": 
    print("Sent %d-byte Ethernet packet on eth0" % 
    sendeth("\xFE\xED\xFA\xCE\xBE\xEF", 
      "\xFE\xED\xFA\xCE\xBE\xEF", 
      "\x7A\x05", 
      "hello")) 

У меня возникли проблемы с созданием сокета. AF_PACKET не распознается, поэтому я предполагаю, что работает только для Linux. Я прокомментировал это и добавил новую строку под ним. Я снова запустил его, и я начал получать ошибку, показанную ниже.

Traceback (most recent call last): 
    File "eth.py", line 27, in <module> 
    "hello")) 
    File "eth.py", line 19, in sendeth 
    s.bind((interface, 0)) 
    File "C:\Python27\lib\socket.py", line 224, in meth 
    return getattr(self._sock,name)(*args) 
socket.gaierror: [Errno 11001] getaddrinfo failed 

Кто-нибудь знает, почему это происходит?

+1

Что вы передаете для интерфейса? «eth0» не будет работать в Windows. – intrepidhero

+0

Действительно, в моем скромном опыте с сокетами Windows имена интерфейсов обычно непонятны. Есть даже сторонний модуль для обработки их – Vovanrock2002

ответ

0

Похоже, вы не получите доступа к локальным сетям с этим сокетом:

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) 

socket.IPPROTO_RAW дает вам доступ к 3-го уровня протокола (IP), в то время как Ethernet находится на уровне 1 и 2. На уровне 3 Ethernet-тракт уже проанализирован и его заголовки отброшены. Вам нужно добраться до уровня 2, а протокол ETH_P_ALL - это отличное место для начала. Я не верю, что модуль python socket реализует его на этом низком уровне, но вы можете взаимодействовать с WinAPI через модуль ctypes.

+0

Когда я пытаюсь использовать ETH_P_ALL, я получаю сообщение об ошибке: AttributeError: объект 'module' не имеет атрибута 'ETH_P_ALL' – Sam

+1

@Sam Да, ETH_P_ALL не реализован в 'socket'. Вы должны работать непосредственно с WinAPI. – Vovanrock2002

0

Этот пример из документов кажется поучительным. https://docs.python.org/2/library/socket.html

import socket 

# the public network interface 
HOST = socket.gethostbyname(socket.gethostname()) 

# create a raw socket and bind it to the public interface 
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP) 
s.bind((HOST, 0)) 

# Include IP headers 
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 

# receive all packages 
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 

# receive a package 
print s.recvfrom(65565) 

# disabled promiscuous mode 
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) 

Я думаю, что ключ socket.gethostbyname (socket.gethostname()). «eth0», используемый в вашем примере, не будет поддерживаться в Windows.

+0

Что произойдет, если у меня будет несколько интерфейсов? – Sam

+0

hmmm ... gethostbyname возвращает IP-адрес. Возможно, попробуйте связать с IP-адресом, назначенным физическому интерфейсу, который вы хотите? – intrepidhero

0

DHCP - это протокол UDP. Для реализации DHCP-сервера вам не нужен необработанный сокет.

Используйте сокет AF_INET/SOCK_DGRAM и привяжите его к адресу 255.255.255.255, чтобы реализовать свой сервер.

+0

Спасибо. Это делает мою жизнь намного легче. После получения сообщения в сокете, привязанного к 255.255.255.255, я должен обработать сообщение и отправить информацию для клиента, чтобы установить его IP. Чувствительно из сферы этой темы, знаете ли вы место, описывающее это взаимодействие? Или мне нужно погрузиться в документацию RFC2131? – Sam

0

Подходит к вопросу с другого направления: зачем вам вообще нужно работать с сетью? DHCP обычно реализуется через UDP.

  1. DHCP-сервер всегда имеет некоторый IP-адрес (и пул адресов, которые он может арендовать).
  2. Если клиент хочет и IP (на самом деле DHCP может сделать гораздо больше, чем просто назначать IP-адреса, но давайте остановимся на этом случае использования), он отправляет широковещательный DHCPREQUEST с IP-адресом источника 0.0.0.0 и IP-адресом назначения 255.255.255.255. Серверы также отвечают на него по протоколу UDP, но с собственным IP-адресом источника.

Если вы хотите создать реализацию DHCP, начиная с уровня OSI уровня 2 (ethernet), вы получите головную боль поддержания уровня 3 (IP) и 4 (UDP). Я не вижу в этом никакой пользы.

Если вы хотите, чтобы протокол DHCP, основанный на ethernet, был готов к работе по следующей проблеме: маршрутизаторы не пересылают широковещательные пакеты, если этого не попросят сделать это. Например, для маршрутизаторов Cisco это выглядит следующим образом:

router(config)# interface ethernet 0/0 
router(config-if)# ip helper-address 10.1.23.5 
router(config-if)# end 
router# 

Таким образом, мы настраиваем маршрутизатор таким образом, он знает, что есть кое-что полезно подключен к Ethernet порту 0/0 с IP 10.1.23.5, который нуждается в трансляции (source).

Смежные вопросы