mosers
/
eaas-vde-proxy
Archiviert
1
0
Fork 0

Handle DHCP requests from VM [Close #17]

main
Simon Moser vor 3 Jahren
Ursprung 3e30f80e70
Commit 240e4fd34e
Signiert von: mosers
GPG-Schlüssel-ID: 96B3365A234B500C

@ -4,5 +4,6 @@ go 1.13
require ( require (
github.com/google/gopacket v1.1.19 github.com/google/gopacket v1.1.19
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771
github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus v1.8.1
) )

@ -1,41 +1,26 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc h1:m7rJJJeXrYCFpsxXYapkDW53wJCDmf9bsIXUg0HoeQY= github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771 h1:t2c2B9g1ZVhMYduqmANSEGVD3/1WlsrEYNPtVoFlENk=
github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc/go.mod h1:eOj1DDj3NAZ6yv+WafaKzY37MFZ58TdfIhQ+8nQbiis= github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771/go.mod h1:0AqAH3ZogsCrvrtUpvc6EtVKbc3w6xwZhkvGLuqyi3o=
github.com/mdlayher/ethernet v0.0.0-20190313224307-5b5fc417d966 h1:O3p5UmisBhl3V6lgs4Vdfg8HpjzbWJPyOfGLdwVJSmI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/mdlayher/ethernet v0.0.0-20190313224307-5b5fc417d966/go.mod h1:5s5p/sMJ6sNsFl6uCh85lkFGV8kLuIYJCRJLavVJwvg=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE=
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
github.com/mdlayher/raw v0.0.0-20190313224157-43dbcdd7739d h1:rjAS0af7FIYCScTtEU5KjIldC6qVaEScUJhABHC+ccM=
github.com/mdlayher/raw v0.0.0-20190313224157-43dbcdd7739d/go.mod h1:r1fbeITl2xL/zLbVnNHFyOzQJTgr/3fpf1lJX/cjzR8=
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18 h1:zwOa3e/13D6veNIz6zzuqrd3eZEMF0dzD0AQWKcYSs4=
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4 h1:3i7qG/aA9NUAzdnJHfhgxSKSmxbAebomYR5IZgFbC5Y=
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"github.com/google/gopacket" "github.com/google/gopacket"
"github.com/google/gopacket/layers" "github.com/google/gopacket/layers"
dhcp "github.com/krolaw/dhcp4"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"io" "io"
"net" "net"
@ -109,10 +110,17 @@ func pipeForward(prefix string) {
log.Debug("Start packet") log.Debug("Start packet")
filterMAC(prefix, &frame.DstMAC, &frame.SrcMAC, frame.LayerType()) filterMAC(prefix, &frame.DstMAC, &frame.SrcMAC, frame.LayerType())
// Handle IPv6 packet // Handle IPv4 packet
if ipv4layer := packet.Layer(layers.LayerTypeIPv4); ipv4layer != nil { if ipv4layer := packet.Layer(layers.LayerTypeIPv4); ipv4layer != nil {
ipv4Packet, _ := ipv4layer.(*layers.IPv4) ipv4Packet, _ := ipv4layer.(*layers.IPv4)
log.Debug("IP Protocol ", ipv4Packet.Protocol) log.Debug("IP Protocol ", ipv4Packet.Protocol)
// Handle DHCPv4 packet (based on IPv4)
if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil && !Passthrough {
handleDHCP(dhcpLayer.LayerContents(), frame.DstMAC, prefix)
continue
}
filterIP(prefix, &ipv4Packet.DstIP, &ipv4Packet.SrcIP, ipv4Packet.LayerType()) filterIP(prefix, &ipv4Packet.DstIP, &ipv4Packet.SrcIP, ipv4Packet.LayerType())
// Handle ICMP packet (based on IPv4) // Handle ICMP packet (based on IPv4)
@ -121,13 +129,6 @@ func pipeForward(prefix string) {
log.Debug(prefix, "ICMP Type ", icmpPacket.TypeCode) log.Debug(prefix, "ICMP Type ", icmpPacket.TypeCode)
} }
// Handle DHCP packet (based on IPv4) - drop for now
if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil && !Passthrough {
//dhcpPacket, _ := dhcpLayer.(*layers.DHCPv4)
log.Info(prefix, "DHCP packet dropped")
continue
}
// Handle TCP packet // Handle TCP packet
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil { if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcpPacket, _ := tcpLayer.(*layers.TCP) tcpPacket, _ := tcpLayer.(*layers.TCP)
@ -175,7 +176,7 @@ func pipeForward(prefix string) {
if isInteresting { if isInteresting {
util.WriteBinary(fmt.Sprintf("/tmp/pck_%di.dat", time.Now().Unix()), frameBytes) util.WriteBinary(fmt.Sprintf("/tmp/pck_%di.dat", time.Now().Unix()), frameBytes)
util.WriteBinary(fmt.Sprintf("/tmp/pck_%do.dat", time.Now().Unix()), newFrameBytes) util.WriteBinary(fmt.Sprintf("/tmp/pck_%do.dat", time.Now().Unix()), newFrameBytes)
//util.WritePcap("xyz.pcap", packet.Data(), packet.Metadata().CaptureInfo) //util.WritePcapNg("xyz.pcap", packet.Data(), packet.Metadata().CaptureInfo)
} }
// Forward modified frame to other plug // Forward modified frame to other plug
@ -210,6 +211,9 @@ func filterIP(prefix string, dst interface{}, src interface{}, context gopacket.
return return
} else if prefix == cmd.Out { } else if prefix == cmd.Out {
if isIp { if isIp {
if!ip.IsGlobalUnicast() {
return
}
OldIP = *ip OldIP = *ip
} else if isBs { } else if isBs {
OldIP = *bs OldIP = *bs
@ -267,4 +271,107 @@ func filterMAC(prefix string, dst interface{}, src interface{}, context gopacket
*bs = newVal *bs = newVal
log.Debugf("%s%s %s MAC %s changed to %s", prefix, context, which, condVal, newVal) log.Debugf("%s%s %s MAC %s changed to %s", prefix, context, which, condVal, newVal)
} }
}
func handleDHCP(content []byte, srcMAC net.HardwareAddr, prefix string) {
req := dhcp.Packet(content)
if req.HLen() > 16 { // Invalid size
log.Error(prefix, "Invalid DHCP size")
return
}
options := req.ParseOptions()
var reqType dhcp.MessageType
if t := options[dhcp.OptionDHCPMessageType]; len(t) != 1 {
log.Error(prefix, "Invalid DHCP message type")
return
} else {
reqType = dhcp.MessageType(t[0])
if reqType < dhcp.Discover || reqType > dhcp.Inform {
log.Error(prefix, "Invalid DHCP message type: ", reqType)
return
}
}
log.Debug(prefix, "DHCP message registered: ", reqType)
if prefix == cmd.Out {
switch reqType {
case dhcp.Discover:
if OldIP == nil {
log.Fatal(prefix, "DHCPDISCOVER but not previous address is known")
}
sendDHCPReply(req, dhcp.Offer, OldIP, options, srcMAC)
case dhcp.Request:
reqIP := net.IP(options[dhcp.OptionRequestedIPAddress])
if reqIP == nil {
reqIP = req.CIAddr()
}
if len(reqIP) != 4 || reqIP.Equal(net.IPv4zero) {
log.Error(prefix, "Invalid IP requested in DHCP: ", reqIP)
return
}
sendDHCPReply(req, dhcp.ACK, reqIP, options, srcMAC)
default:
return
}
} else {
// TODO: talk to dhcp server
}
}
// sendDHCPReply creates a response dhcp packet and sends it
func sendDHCPReply(req dhcp.Packet, mt dhcp.MessageType, lease net.IP, reqOpt dhcp.Options, dstMAC net.HardwareAddr) {
log.Info("Sending DHCP response: ", mt, lease)
// Getting the options
serverIP := []byte{10, 0, 0, 1} // TODO: serverIP
serverMAC := util.GenerateMac("") // TODO: server MAC
opt := dhcp.Options{
dhcp.OptionSubnetMask: []byte{255, 255, 255, 0}, // TODO: subnet mask
dhcp.OptionRouter: serverIP, // TODO: Presuming Server is also your router
dhcp.OptionDomainNameServer: serverIP, // TODO: Presuming Server is also your DNS server
}.SelectOrderOrAll(reqOpt[dhcp.OptionParameterRequestList])
// Creating the full packet layer by layer
dhcplayer := dhcp.ReplyPacket(req, mt, serverIP, lease, 24 * time.Hour, opt)
buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{
ComputeChecksums: true,
FixLengths: true,
}
ipv4 := layers.IPv4{
Version: 4,
TTL: 64,
Protocol: layers.IPProtocolUDP,
SrcIP: serverIP,
DstIP: lease,
}
udp := layers.UDP{
SrcPort: 67,
DstPort: 68,
}
udp.SetNetworkLayerForChecksum(&ipv4)
err := gopacket.SerializeLayers(buf, opts,
&layers.Ethernet{
SrcMAC: serverMAC,
DstMAC: dstMAC,
EthernetType: layers.EthernetTypeIPv4,
},
&ipv4,
&udp,
gopacket.Payload(dhcplayer))
if err != nil {
return
}
packetData := buf.Bytes()
// Sending layer through VM's pipe
packetLength := make([]byte, 2)
binary.BigEndian.PutUint16(packetLength, uint16(len(packetData)))
util.WriteBinary(fmt.Sprintf("/tmp/dhcp_%d.dat", time.Now().Unix()), packetData)
util.WritePcap(fmt.Sprintf("/tmp/dhcp_%d.pcap", time.Now().Unix()), packetData)
util.WritePcap(fmt.Sprintf("/tmp/dhcp_%d2.pcap", time.Now().Unix()), packetData[36:])
VmWriter.Write(packetLength)
VmWriter.Write(packetData)
} }

Binäre Datei nicht angezeigt.

@ -10,10 +10,11 @@ import (
"net" "net"
"os" "os"
"strconv" "strconv"
"time"
) )
// WritePcap writes the provided data to a given pcap file // WritePcapNg writes the provided data to a given pcap file
func WritePcap(file string, data []byte, ci gopacket.CaptureInfo) { func WritePcapNg(file string, data []byte) {
f, err := os.Create(file) f, err := os.Create(file)
if err != nil { if err != nil {
log.Errorf("Error writing pcap file %s", file) log.Errorf("Error writing pcap file %s", file)
@ -26,9 +27,28 @@ func WritePcap(file string, data []byte, ci gopacket.CaptureInfo) {
} }
defer r.Flush() defer r.Flush()
ci := gopacket.CaptureInfo{
Timestamp: time.Now(),
CaptureLength: len(data),
Length: len(data),
}
err = r.WritePacket(ci, data) err = r.WritePacket(ci, data)
} }
func WritePcap(file string, data []byte) {
f, _ := os.Create(file)
w := pcapgo.NewWriter(f)
w.WriteFileHeader(65536, layers.LinkTypeEthernet) // new file, must do this.
ci := gopacket.CaptureInfo{
Timestamp: time.Now(),
CaptureLength: len(data),
Length: len(data),
}
w.WritePacket(ci, data)
f.Close()
}
// WriteBinary writes the provided data to a given binary file // WriteBinary writes the provided data to a given binary file
func WriteBinary(file string, data []byte) { func WriteBinary(file string, data []byte) {
if err := ioutil.WriteFile(file, data, 0644); err != nil { if err := ioutil.WriteFile(file, data, 0644); err != nil {
@ -47,7 +67,7 @@ func WritePIDFile(filename string) {
func GenerateMac(customMAC string) net.HardwareAddr { func GenerateMac(customMAC string) net.HardwareAddr {
if customMAC != "" { if customMAC != "" {
ret, _ := net.ParseMAC("52:54:00:12:34:aa") ret, _ := net.ParseMAC(customMAC)
return ret return ret
} }
buf := make([]byte, 6) buf := make([]byte, 6)