pypxe / PyPXE

Pure Python PXE (DHCP-(Proxy)/TFTP/HTTP/NBD) Server
MIT License
547 stars 125 forks source link

DHCP Issues w/Multiple Interfaces #25

Closed icb- closed 10 years ago

icb- commented 10 years ago

When serving DHCP on CentOS 6, DHCP replies are only sent out the first interface.

I've tested two options, both of which work for me in testing with iPXE.

  1. Using SO_BINDTODEVICE to bind to the interface DHCP should use. The downside is this appears to only be available on Linux.
  2. Sending replies to the subnet broadcast (e.g. 192.168.2.255) instead of 255.255.255.255. The downside is this is goes against RFC2131 §4.1

If 'giaddr' is zero and 'ciaddr' is zero, and the broadcast bit is set, then the server broadcasts DHCPOFFER and DHCPACK messages to 0xffffffff.

icb- commented 10 years ago

I can code up either of these options. I'm looking for input on which is preferred. The later could be implemented by adding a broadcast argument that can be set to either the current '<broadcast>', 255.255.255.255, or the subnet broadcast as needed.

psychomario commented 10 years ago

-s should let you choose a source ip, thereby the interface. Does this not work as I think it should?

If not, I would prefer to stick to the RFC

psychomario commented 10 years ago

ah, it doesn't. I'm unable to change the code at the moment. I think if the bind inside the init for dhcpd is told to use self.ip rather than '', -s will let you use an interface

icb- commented 10 years ago

Binding to the interface address, rather than to the wildcard, doesn't work. The packets aren't received.

psychomario commented 10 years ago

That isn't ideal. Probably the most portable method would be your second suggestion, having an argument that allows you to specify the broadcast for dhcp. It would need to be noted that this is against the rfc.

Does the rfc mention how to handle this problem?

icb- commented 10 years ago

I've not seen it in the RFC. I've looked through the ISC DHCP server documentation, and they have a number of OS-specific workarounds. SO_BINDTODEVICE is one of them. Others include the Linux Packet Filter, and using raw sockets. Another option appears to be adding a route to 255.255.255.255 in the OS out the correct interface.

psychomario commented 10 years ago

Adding a route could break other programs.

Raw sockets means we have to do our own ip and udp as well. And we have to do our own receive filter.

I think os workarounds, or completely swapping out all network code for something like scapy, but then we have external dependencies.

mmattioli commented 10 years ago

I would avoid external dependencies like the plague, if we can do it without them then all the better. One of my favorite things about this project is that it requires no external dependencies and, because of that, is very portable.