Open Source DHCP proxy
Seems https://github.com/Mirantis/dhcp-relay looks good. And it is Apache-2.0 license
git clone https: //github .com /Mirantis/dhcp-relay cd dhcp-relay make all env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOPROXY=proxy.golang.org go build --tags "netgo osusergo static_build" -ldflags= '-s -w -extldflags "-static"' -a -o '/home/user/dhcp-relay/BUILD/dhcp-relay' sudo . /BUILD/dhcp-relay -debug -dhcp-server-address 192.168.122.1 -debug-server localhost:8082 |
sudo nmap --script broadcast-dhcp-discover |
Then we can check the logs on the host run DHCP proxy as follow
2023 /10/31 02:46:37 DBG | Received bytes of data from socket 2023 /10/31 02:46:37 DBG | Received 358 bytes of data from socket 2023 /10/31 02:46:37 INF | --> 0x64080343: DHCP-DISCOVER [316], IfIndex=2, Src=192.168.122.54:68(52:54:00:2f:19:ff), Dst=255.255.255.255:67(ff:ff:ff:ff:ff:ff) 2023 /10/31 02:46:37 DBG | Option 82 -> Sub-option: Type=1, Len=1, Data=[32], ASCII= "2" 2023 /10/31 02:46:37 DBG | Sent 321 bytes of data to socket 2023 /10/31 02:46:37 INF | <-- 0x64080343: DHCP-DISCOVER [321], Src=0.0.0.0:67, Dst=192.168.122.1:67 2023 /10/31 02:46:40 DBG | Received bytes of data from socket 2023 /10/31 02:46:40 DBG | Received 342 bytes of data from socket 2023 /10/31 02:46:40 INF | --> 0x64080343: DHCP-OFFER [297], IfIndex=2, Src=192.168.122.1:67(52:54:00:7e:c2:89), Dst=192.168.122.171:67(52:54:00:2b:ad:08) 2023 /10/31 02:46:40 DBG | Boot File Name: 2023 /10/31 02:46:40 DBG | Option 82 -> Sub-option: Type=1, Len=1, Data=[32], ASCII= "2" 2023 /10/31 02:46:40 DBG | Sent 334 bytes of data to socket 2023 /10/31 02:46:40 INF | <-- 0x64080343: DHCP-OFFER [292], IfIndex=2, Src=0.0.0.0:67, Dst=255.255.255.255:68 |
or dump pacakge
sudo tcpdump -i any -s 0 -U -w ~ /proxy-dhcp .cap not port 22 |
patch
diff --git a/main.go b/main.go index 25f4ed4..a0479f5 100644 --- a/main.go +++ b/main.go @@ -16,12 +16,32 @@ import ( "code.local/dhcp-relay/bytecode" "code.local/dhcp-relay/gpckt" + "code.local/dhcp-relay/gpckt/dhcp" "code.local/dhcp-relay/logger" "code.local/dhcp-relay/sockets" "code.local/dhcp-relay/specs" "code.local/dhcp-relay/version" ) +const ( + UserClassInformation layers.DHCPOpt = 77 +) + +func GetUserClassInformationOption(layerDHCPv4 *layers.DHCPv4) layers.DHCPOption { + opt77 := dhcp.GetOption(layerDHCPv4, UserClassInformation) + if !dhcp.IsOption(opt77) { + return layers.DHCPOption{} + } + + if len(opt77.Data) == 0 || opt77.Length < 1 { + return layers.DHCPOption{} + } + + return opt77 +} + + + // Note: This code requires CAP_NET_RAW capability. func main() { @@ -148,6 +168,31 @@ func main() { continue } + opt77 := GetUserClassInformationOption(layerDHCPv4) + if !dhcp.IsOption(opt77) { + cl.Debugf("No Option 77: \n") + // continue + } else { + cl.Debugf("Get Option 77: %v\n", opt77) + userclass := string(opt77.Data[0 : int(opt77.Length)]) + cl.Debugf("Packet 77: %s\n", userclass) + } + opt60 := dhcp.GetOption(layerDHCPv4, layers.DHCPOptClassID) + if opt60.Length > 0 { + cl.Debugf("Get Option 60: %v\n", opt60) + classid := string(opt60.Data[0 : int(opt60.Length)]) + cl.Debugf("Packet 60: %s\n", classid) + } else { + cl.Debugf("No Option 60: \n") + } + opt53 := dhcp.GetOption(layerDHCPv4, layers.DHCPOptMessageType) + if opt53.Length > 0 { + cl.Debugf("Get Option 53: %v\n", opt53) + mst := opt53.Data[0 : int(opt53.Length)] + cl.Debugf("Packet 53: %v\n", mst) + } else { + cl.Debugf("No Option 53: \n") + } go HandleDHCPv4(cfg, sall, layerEthernet, layerIPv4, layerUDP, layerDHCPv4) } }
find the DHCP client
# class := strings.Split(classid, ":") # compare := class[0] == "HTTPClient" if strings.Split(classid, ":")[0] == "HTTPClient" { cl.Debugf("Expect DHCP client. \n") }