|
|
@ -7,7 +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"
|
|
|
|
"github.com/krolaw/dhcp4"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
"net"
|
|
|
|
"net"
|
|
|
@ -51,7 +51,7 @@ func main() {
|
|
|
|
DisableTimestamp: true,
|
|
|
|
DisableTimestamp: true,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
if *logFile != "" {
|
|
|
|
if *logFile != "" {
|
|
|
|
if f, err := os.OpenFile(*logFile, os.O_WRONLY | os.O_CREATE, 0755); err != nil {
|
|
|
|
if f, err := os.OpenFile(*logFile, os.O_WRONLY|os.O_CREATE, 0755); err != nil {
|
|
|
|
log.Error("Error opening logFile ", *logFile)
|
|
|
|
log.Error("Error opening logFile ", *logFile)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
log.SetOutput(f)
|
|
|
|
log.SetOutput(f)
|
|
|
@ -156,8 +156,12 @@ func pipeForward(prefix string) {
|
|
|
|
|
|
|
|
|
|
|
|
// Forward original frame to other plug
|
|
|
|
// Forward original frame to other plug
|
|
|
|
if Passthrough {
|
|
|
|
if Passthrough {
|
|
|
|
writer.Write(frameLength)
|
|
|
|
if _, err := writer.Write(frameLength); err != nil {
|
|
|
|
writer.Write(frameBytes)
|
|
|
|
log.Error("Error forwarding original packet length", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := writer.Write(frameBytes); err != nil {
|
|
|
|
|
|
|
|
log.Error("Error forwarding original packet data", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -180,8 +184,12 @@ func pipeForward(prefix string) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Forward modified frame to other plug
|
|
|
|
// Forward modified frame to other plug
|
|
|
|
writer.Write(newFrameLength)
|
|
|
|
if _, err := writer.Write(newFrameLength); err != nil {
|
|
|
|
writer.Write(newFrameBytes)
|
|
|
|
log.Error("Error forwarding packet length", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := writer.Write(newFrameBytes); err != nil {
|
|
|
|
|
|
|
|
log.Error("Error forwarding packet data", err)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -211,7 +219,7 @@ 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() {
|
|
|
|
if !ip.IsGlobalUnicast() {
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OldIP = *ip
|
|
|
|
OldIP = *ip
|
|
|
@ -274,19 +282,19 @@ func filterMAC(prefix string, dst interface{}, src interface{}, context gopacket
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func handleDHCP(content []byte, srcMAC net.HardwareAddr, prefix string) {
|
|
|
|
func handleDHCP(content []byte, srcMAC net.HardwareAddr, prefix string) {
|
|
|
|
req := dhcp.Packet(content)
|
|
|
|
req := dhcp4.Packet(content)
|
|
|
|
if req.HLen() > 16 { // Invalid size
|
|
|
|
if req.HLen() > 16 { // Invalid size
|
|
|
|
log.Error(prefix, "Invalid DHCP size")
|
|
|
|
log.Error(prefix, "Invalid DHCP size")
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
options := req.ParseOptions()
|
|
|
|
options := req.ParseOptions()
|
|
|
|
var reqType dhcp.MessageType
|
|
|
|
var reqType dhcp4.MessageType
|
|
|
|
if t := options[dhcp.OptionDHCPMessageType]; len(t) != 1 {
|
|
|
|
if t := options[dhcp4.OptionDHCPMessageType]; len(t) != 1 {
|
|
|
|
log.Error(prefix, "Invalid DHCP message type")
|
|
|
|
log.Error(prefix, "Invalid DHCP message type")
|
|
|
|
return
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
reqType = dhcp.MessageType(t[0])
|
|
|
|
reqType = dhcp4.MessageType(t[0])
|
|
|
|
if reqType < dhcp.Discover || reqType > dhcp.Inform {
|
|
|
|
if reqType < dhcp4.Discover || reqType > dhcp4.Inform {
|
|
|
|
log.Error(prefix, "Invalid DHCP message type: ", reqType)
|
|
|
|
log.Error(prefix, "Invalid DHCP message type: ", reqType)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -294,13 +302,13 @@ func handleDHCP(content []byte, srcMAC net.HardwareAddr, prefix string) {
|
|
|
|
log.Debug(prefix, "DHCP message registered: ", reqType)
|
|
|
|
log.Debug(prefix, "DHCP message registered: ", reqType)
|
|
|
|
if prefix == cmd.Out {
|
|
|
|
if prefix == cmd.Out {
|
|
|
|
switch reqType {
|
|
|
|
switch reqType {
|
|
|
|
case dhcp.Discover:
|
|
|
|
case dhcp4.Discover:
|
|
|
|
if OldIP == nil {
|
|
|
|
if OldIP == nil {
|
|
|
|
log.Fatal(prefix, "DHCPDISCOVER but not previous address is known")
|
|
|
|
log.Fatal(prefix, "DHCPDISCOVER but not previous address is known")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sendDHCPReply(req, dhcp.Offer, OldIP, options, srcMAC)
|
|
|
|
sendDHCPReply(req, dhcp4.Offer, OldIP, options, srcMAC)
|
|
|
|
case dhcp.Request:
|
|
|
|
case dhcp4.Request:
|
|
|
|
reqIP := net.IP(options[dhcp.OptionRequestedIPAddress])
|
|
|
|
reqIP := net.IP(options[dhcp4.OptionRequestedIPAddress])
|
|
|
|
if reqIP == nil {
|
|
|
|
if reqIP == nil {
|
|
|
|
reqIP = req.CIAddr()
|
|
|
|
reqIP = req.CIAddr()
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -308,34 +316,37 @@ func handleDHCP(content []byte, srcMAC net.HardwareAddr, prefix string) {
|
|
|
|
log.Error(prefix, "Invalid IP requested in DHCP: ", reqIP)
|
|
|
|
log.Error(prefix, "Invalid IP requested in DHCP: ", reqIP)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sendDHCPReply(req, dhcp.ACK, reqIP, options, srcMAC)
|
|
|
|
sendDHCPReply(req, dhcp4.ACK, reqIP, options, srcMAC)
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// TODO: talk to dhcp server
|
|
|
|
// TODO: talk to DHCP server
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// sendDHCPReply creates a response dhcp packet and sends it
|
|
|
|
// 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) {
|
|
|
|
func sendDHCPReply(req dhcp4.Packet, mt dhcp4.MessageType, lease net.IP, reqOpt dhcp4.Options, dstMAC net.HardwareAddr) {
|
|
|
|
log.Info("Sending DHCP response: ", mt, lease)
|
|
|
|
log.Info("Sending DHCP response: ", mt, lease)
|
|
|
|
// Getting the options
|
|
|
|
// Getting the options
|
|
|
|
serverIP := []byte{10, 0, 0, 1} // TODO: serverIP
|
|
|
|
serverIP := []byte{10, 0, 0, 1} // TODO: serverIP
|
|
|
|
serverMAC := util.GenerateMac("") // TODO: server MAC
|
|
|
|
serverMAC := util.GenerateMac("") // TODO: server MAC
|
|
|
|
opt := dhcp.Options{
|
|
|
|
opt := dhcp4.Options{
|
|
|
|
dhcp.OptionSubnetMask: []byte{255, 255, 255, 0}, // TODO: subnet mask
|
|
|
|
dhcp4.OptionSubnetMask: []byte{255, 255, 255, 0}, // TODO: subnet mask
|
|
|
|
dhcp.OptionRouter: serverIP, // TODO: Presuming Server is also your router
|
|
|
|
dhcp4.OptionRouter: serverIP, // TODO: Presuming Server is also your router
|
|
|
|
dhcp.OptionDomainNameServer: serverIP, // TODO: Presuming Server is also your DNS server
|
|
|
|
dhcp4.OptionDomainNameServer: serverIP, // TODO: Presuming Server is also your DNS server
|
|
|
|
}.SelectOrderOrAll(reqOpt[dhcp.OptionParameterRequestList])
|
|
|
|
}.SelectOrderOrAll(reqOpt[dhcp4.OptionParameterRequestList])
|
|
|
|
|
|
|
|
|
|
|
|
// Creating the full packet layer by layer
|
|
|
|
// Creating the full packet layer by layer
|
|
|
|
dhcplayer := dhcp.ReplyPacket(req, mt, serverIP, lease, 24 * time.Hour, opt)
|
|
|
|
|
|
|
|
buf := gopacket.NewSerializeBuffer()
|
|
|
|
buf := gopacket.NewSerializeBuffer()
|
|
|
|
opts := gopacket.SerializeOptions{
|
|
|
|
opts := gopacket.SerializeOptions{
|
|
|
|
ComputeChecksums: true,
|
|
|
|
ComputeChecksums: true,
|
|
|
|
FixLengths: true,
|
|
|
|
FixLengths: true,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
eth := layers.Ethernet{
|
|
|
|
|
|
|
|
SrcMAC: serverMAC,
|
|
|
|
|
|
|
|
DstMAC: dstMAC,
|
|
|
|
|
|
|
|
EthernetType: layers.EthernetTypeIPv4,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ipv4 := layers.IPv4{
|
|
|
|
ipv4 := layers.IPv4{
|
|
|
|
Version: 4,
|
|
|
|
Version: 4,
|
|
|
@ -348,18 +359,12 @@ func sendDHCPReply(req dhcp.Packet, mt dhcp.MessageType, lease net.IP, reqOpt dh
|
|
|
|
SrcPort: 67,
|
|
|
|
SrcPort: 67,
|
|
|
|
DstPort: 68,
|
|
|
|
DstPort: 68,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
udp.SetNetworkLayerForChecksum(&ipv4)
|
|
|
|
dhcp := dhcp4.ReplyPacket(req, mt, serverIP, lease, 24*time.Hour, opt)
|
|
|
|
err := gopacket.SerializeLayers(buf, opts,
|
|
|
|
if err := udp.SetNetworkLayerForChecksum(&ipv4); err != nil {
|
|
|
|
&layers.Ethernet{
|
|
|
|
log.Error("Error building DHCP response", err)
|
|
|
|
SrcMAC: serverMAC,
|
|
|
|
}
|
|
|
|
DstMAC: dstMAC,
|
|
|
|
if err := gopacket.SerializeLayers(buf, opts, ð, &ipv4, &udp, gopacket.Payload(dhcp)); err != nil {
|
|
|
|
EthernetType: layers.EthernetTypeIPv4,
|
|
|
|
log.Error("Error serializing DHCP response", err)
|
|
|
|
},
|
|
|
|
|
|
|
|
&ipv4,
|
|
|
|
|
|
|
|
&udp,
|
|
|
|
|
|
|
|
gopacket.Payload(dhcplayer))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
packetData := buf.Bytes()
|
|
|
|
packetData := buf.Bytes()
|
|
|
|
|
|
|
|
|
|
|
@ -367,11 +372,10 @@ func sendDHCPReply(req dhcp.Packet, mt dhcp.MessageType, lease net.IP, reqOpt dh
|
|
|
|
packetLength := make([]byte, 2)
|
|
|
|
packetLength := make([]byte, 2)
|
|
|
|
binary.BigEndian.PutUint16(packetLength, uint16(len(packetData)))
|
|
|
|
binary.BigEndian.PutUint16(packetLength, uint16(len(packetData)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if _, err := VmWriter.Write(packetLength); err != nil {
|
|
|
|
util.WriteBinary(fmt.Sprintf("/tmp/dhcp_%d.dat", time.Now().Unix()), packetData)
|
|
|
|
log.Error("Error writing DHCP response length", err)
|
|
|
|
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:])
|
|
|
|
if _, err := VmWriter.Write(packetData); err != nil {
|
|
|
|
|
|
|
|
log.Error("Error writing DHCP response data", err)
|
|
|
|
VmWriter.Write(packetLength)
|
|
|
|
}
|
|
|
|
VmWriter.Write(packetData)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|