Open Source DHCP proxy

There are several open-source projects: DHCP-replay in github https://github.com/topics/dhcp-relay

Seems https://github.com/Mirantis/dhcp-relay looks good.  And it is  Apache-2.0 license

start a DHCP proxy on a host

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

send DHCP request on another host

sudo nmap --script broadcast-dhcp-discover

Check result on DHCP proxy host

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")
                        }

  

posted @ 2023-11-01 13:45  lvmxh  阅读(13)  评论(0编辑  收藏  举报