Open clarkmcc opened 1 year ago
You may need to set the broadcast option of the socket.
@QQ2017 is that possible to do on a Windows socket from Go? Or do you need some syscall wizardry?
@QQ2017 is that possible to do on a Windows socket from Go? Or do you need some syscall wizardry?
On windows, You can use this lib: https://github.com/krolaw/dhcp4
@QQ2017 doesn't seem to work. I'm able to receive DHCP DISCOVER
requests using both libs, but on Windows, it seems like the OFFER
responses are never making it back to the client. When I run the same code using either lib on macOS, the DISCOVER
is immediately followed by a REQUEST
from the client indicating that the OFFER
was received.
I tried to figure out how to make it fail on macOS, and disabling the interface binding seemed to cause macOS to exhibit the same behavior as Windows.
I tried to enable broadcasting on the socket using the following code, but no change. I'm suspicious now that the issue may be related to the routing table. Meaning that my OFFER
response is not actually being sent over the same socket that I received the DISCOVER
. Sadly, I'm very outside of my comfort zone here. Any ideas?
func enableBroadcasting(conn net.PacketConn) error {
c := conn.(*net.UDPConn)
r, err := c.SyscallConn()
if err != nil {
return fmt.Errorf("getting syscall conn: %v", err)
}
cErr := r.Control(func(fd uintptr) {
err = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_BROADCAST, 1)
if err != nil {
err = fmt.Errorf("setting SO_BROADCAST: %v", err)
return
}
err = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
if err != nil {
err = fmt.Errorf("setting SO_REUSEADDR: %v", err)
return
}
})
if err != nil {
return err
}
if cErr != nil {
return fmt.Errorf("control: %v", cErr)
}
return nil
}
Use TCPDUMP to grab the data of port 67 on the server and submit it to me.
tcpdump -i ens1 port 67 -w 67.pcap
@QQ2017 Any ideas on a good way to do that on Windows? I couldn't seem to find any good tools for that for Windows. I'm running parallels Windows 11 on M1.
I ran the test on macOS without the interface binding which replicates the behavior that Windows has and here's what I've got.
13:56:25.497602 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300
13:56:25.498374 IP 192.168.0.34.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274
13:56:29.763459 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300
13:56:29.764065 IP 192.168.0.34.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274
13:56:38.195574 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300
13:56:38.197123 IP 192.168.0.34.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274
13:56:54.859759 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300
13:56:54.860249 IP 192.168.0.34.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274
If I enable interface binding again
# sudo tcpdump port 67 -n -i en4
14:00:28.010758 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300
14:00:28.014130 IP 169.254.225.108.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274
14:00:28.014791 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300
14:00:28.014997 IP 169.254.225.108.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274
# My application logs
time="2023-05-11T14:00:28-06:00" level=info msg="Got a Discover from 00:68:eb:4b:4b:bc"
time="2023-05-11T14:00:28-06:00" level=info msg="offer 10.0.0.14"
time="2023-05-11T14:00:28-06:00" level=info msg="Got a Request from 00:68:eb:4b:4b:bc"
time="2023-05-11T14:00:28-06:00" level=info msg="ack for 10.0.0.14"
Not sure if any of that is helpful, I can work on getting some kind of tcpdump solution working on Windows in the mean time.
@QQ2017 Any ideas on a good way to do that on Windows? I couldn't seem to find any good tools for that for Windows. I'm running parallels Windows 11 on M1.
I ran the test on macOS without the interface binding which replicates the behavior that Windows has and here's what I've got.
13:56:25.497602 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300 13:56:25.498374 IP 192.168.0.34.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274 13:56:29.763459 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300 13:56:29.764065 IP 192.168.0.34.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274 13:56:38.195574 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300 13:56:38.197123 IP 192.168.0.34.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274 13:56:54.859759 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300 13:56:54.860249 IP 192.168.0.34.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274
If I enable interface binding again
# sudo tcpdump port 67 -n -i en4 14:00:28.010758 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300 14:00:28.014130 IP 169.254.225.108.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274 14:00:28.014791 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:68:eb:4b:4b:bc, length 300 14:00:28.014997 IP 169.254.225.108.67 > 255.255.255.255.68: BOOTP/DHCP, Reply, length 274 # My application logs time="2023-05-11T14:00:28-06:00" level=info msg="Got a Discover from 00:68:eb:4b:4b:bc" time="2023-05-11T14:00:28-06:00" level=info msg="offer 10.0.0.14" time="2023-05-11T14:00:28-06:00" level=info msg="Got a Request from 00:68:eb:4b:4b:bc" time="2023-05-11T14:00:28-06:00" level=info msg="ack for 10.0.0.14"
Not sure if any of that is helpful, I can work on getting some kind of tcpdump solution working on Windows in the mean time.
You can use wireshark on Windows, Post the pcap file to me. capture filter: port 67
I'm working on writing a DHCP server. I recognize that on Windows this library won't bind to a specific network interface, so I tried this approach. I am able to successfully bind the UDP listener to the specific IP address which is assigned to a specific network interface, but I'm not seeing any logs indicating that packets are received.
When I run this on macOS instead, it works just fine. Has anyone got this working on Windows before?