|
|
|
@ -21,22 +21,33 @@ var OldMAC net.HardwareAddr
|
|
|
|
|
var NewMAC net.HardwareAddr
|
|
|
|
|
var OldIP net.IP
|
|
|
|
|
var NewIP net.IP
|
|
|
|
|
|
|
|
|
|
// In-/Output to VM and network
|
|
|
|
|
|
|
|
|
|
var VmReader io.Reader
|
|
|
|
|
var VmWriter io.Writer
|
|
|
|
|
var NetReader io.Reader
|
|
|
|
|
var NetWriter io.Writer
|
|
|
|
|
var Passthrough bool
|
|
|
|
|
var XId []byte
|
|
|
|
|
|
|
|
|
|
// DHCP variables
|
|
|
|
|
|
|
|
|
|
var DHCPXId []byte
|
|
|
|
|
var DHCPIP net.IP
|
|
|
|
|
var RouterIP net.IP
|
|
|
|
|
var DNSIP net.IP
|
|
|
|
|
var DHCPRouterIP net.IP
|
|
|
|
|
var DHCPDNSIP net.IP
|
|
|
|
|
var DHCPMAC net.HardwareAddr
|
|
|
|
|
var DHCPMask []byte
|
|
|
|
|
var DHCPState dhcp4.MessageType
|
|
|
|
|
var DHCPCandidate net.IP
|
|
|
|
|
var UId string
|
|
|
|
|
var Wireshark bool
|
|
|
|
|
|
|
|
|
|
// User-provided variables
|
|
|
|
|
|
|
|
|
|
var Hostname string
|
|
|
|
|
var Passthrough bool
|
|
|
|
|
var Wireshark bool
|
|
|
|
|
|
|
|
|
|
// UId used as host name
|
|
|
|
|
var UId string
|
|
|
|
|
|
|
|
|
|
// Start the two plugs and run two concurrent forward methods
|
|
|
|
|
func main() {
|
|
|
|
@ -82,8 +93,8 @@ func main() {
|
|
|
|
|
NetWriter = os.Stdin
|
|
|
|
|
}
|
|
|
|
|
c2, VmReader, VmWriter = cmd.Start(*sockProxy)
|
|
|
|
|
go pipeForward(cmd.In)
|
|
|
|
|
go pipeForward(cmd.Out)
|
|
|
|
|
go pipeForward(In)
|
|
|
|
|
go pipeForward(Out)
|
|
|
|
|
if NewIP == nil && !Passthrough {
|
|
|
|
|
sendDHCPRequest(dhcp4.Discover, net.IPv4zero)
|
|
|
|
|
}
|
|
|
|
@ -95,11 +106,12 @@ func main() {
|
|
|
|
|
|
|
|
|
|
// Reads from an input and writes to and output,
|
|
|
|
|
// do things to the content in between.
|
|
|
|
|
// Is meant to be run concurrently with "go pipeForward(...)"
|
|
|
|
|
// Is meant to be run concurrently with "go pipeForward(...)".
|
|
|
|
|
// This is the main loop of the proxy.
|
|
|
|
|
func pipeForward(prefix string) {
|
|
|
|
|
var reader io.Reader
|
|
|
|
|
var writer io.Writer
|
|
|
|
|
if prefix == cmd.In {
|
|
|
|
|
if prefix == In {
|
|
|
|
|
reader = NetReader
|
|
|
|
|
writer = VmWriter
|
|
|
|
|
} else {
|
|
|
|
@ -139,8 +151,8 @@ func pipeForward(prefix string) {
|
|
|
|
|
packet := gopacket.NewPacket(frameBytes, layers.LayerTypeEthernet, gopacket.Default)
|
|
|
|
|
|
|
|
|
|
// Handle Ethernet frame
|
|
|
|
|
frame := packet.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
|
|
|
|
|
log.Debug("Start packet")
|
|
|
|
|
frame := packet.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
|
|
|
|
|
filterMAC(prefix, &frame.DstMAC, &frame.SrcMAC, frame.LayerType())
|
|
|
|
|
|
|
|
|
|
// Handle IPv4 packet
|
|
|
|
@ -222,6 +234,7 @@ func pipeForward(prefix string) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// filterPayloads filters binary payloads to be able to process unsupported protocols
|
|
|
|
|
func filterPayload(prefix string, payload *[]byte) {
|
|
|
|
|
// Populate slices with values to on vm and network side
|
|
|
|
|
vmVals := [][]byte{OldMAC}
|
|
|
|
@ -238,7 +251,7 @@ func filterPayload(prefix string, payload *[]byte) {
|
|
|
|
|
// Choose for which slice to search for and which to replace it with
|
|
|
|
|
searchVals := vmVals
|
|
|
|
|
replaceVals := netVals
|
|
|
|
|
if prefix == cmd.In {
|
|
|
|
|
if prefix == In {
|
|
|
|
|
searchVals = netVals
|
|
|
|
|
replaceVals = vmVals
|
|
|
|
|
}
|
|
|
|
@ -255,12 +268,12 @@ func filterIP(prefix string, dst interface{}, src interface{}, context gopacket.
|
|
|
|
|
var condVal net.IP
|
|
|
|
|
var newVal net.IP
|
|
|
|
|
var which string
|
|
|
|
|
if prefix == cmd.In {
|
|
|
|
|
if prefix == In {
|
|
|
|
|
target = dst
|
|
|
|
|
which = "dst"
|
|
|
|
|
condVal = NewIP
|
|
|
|
|
newVal = OldIP
|
|
|
|
|
} else if prefix == cmd.Out {
|
|
|
|
|
} else if prefix == Out {
|
|
|
|
|
target = src
|
|
|
|
|
which = "src"
|
|
|
|
|
condVal = OldIP
|
|
|
|
@ -271,9 +284,9 @@ func filterIP(prefix string, dst interface{}, src interface{}, context gopacket.
|
|
|
|
|
|
|
|
|
|
// If no OldIP is set yet, get it from outgoing src field
|
|
|
|
|
if OldIP == nil {
|
|
|
|
|
if prefix == cmd.In {
|
|
|
|
|
if prefix == In {
|
|
|
|
|
return
|
|
|
|
|
} else if prefix == cmd.Out {
|
|
|
|
|
} else if prefix == Out {
|
|
|
|
|
if isIp {
|
|
|
|
|
if !ip.IsGlobalUnicast() {
|
|
|
|
|
return
|
|
|
|
@ -302,9 +315,9 @@ func filterMAC(prefix string, dst interface{}, src interface{}, context gopacket
|
|
|
|
|
// If no OldMAC is set yet, get it from outgoing src field
|
|
|
|
|
// Has to be HardwareAddr because this is used for ethernet frames which call this method first
|
|
|
|
|
if OldMAC == nil {
|
|
|
|
|
if prefix == cmd.In {
|
|
|
|
|
if prefix == In {
|
|
|
|
|
return
|
|
|
|
|
} else if prefix == cmd.Out {
|
|
|
|
|
} else if prefix == Out {
|
|
|
|
|
OldMAC = *src.(*net.HardwareAddr)
|
|
|
|
|
log.Info("OldMAC set to ", OldMAC)
|
|
|
|
|
}
|
|
|
|
@ -314,12 +327,12 @@ func filterMAC(prefix string, dst interface{}, src interface{}, context gopacket
|
|
|
|
|
var condVal net.HardwareAddr
|
|
|
|
|
var newVal net.HardwareAddr
|
|
|
|
|
var which string
|
|
|
|
|
if prefix == cmd.In {
|
|
|
|
|
if prefix == In {
|
|
|
|
|
target = dst
|
|
|
|
|
which = "dst"
|
|
|
|
|
condVal = NewMAC
|
|
|
|
|
newVal = OldMAC
|
|
|
|
|
} else if prefix == cmd.Out {
|
|
|
|
|
} else if prefix == Out {
|
|
|
|
|
target = src
|
|
|
|
|
which = "src"
|
|
|
|
|
condVal = OldMAC
|
|
|
|
@ -337,6 +350,8 @@ func filterMAC(prefix string, dst interface{}, src interface{}, context gopacket
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// handleDHCP provides the main DHCP functionality to request an IP from a server on the one hand
|
|
|
|
|
// and provide an IP to the VM on the other hand
|
|
|
|
|
func handleDHCP(content []byte, dstMAC net.HardwareAddr, srcMAC net.HardwareAddr, prefix string) {
|
|
|
|
|
req := dhcp4.Packet(content)
|
|
|
|
|
if req.HLen() > 16 { // Invalid size
|
|
|
|
@ -356,7 +371,7 @@ func handleDHCP(content []byte, dstMAC net.HardwareAddr, srcMAC net.HardwareAddr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
log.Debug(prefix, "DHCP message registered: ", reqType)
|
|
|
|
|
if prefix == cmd.Out {
|
|
|
|
|
if prefix == Out {
|
|
|
|
|
switch reqType {
|
|
|
|
|
case dhcp4.Discover:
|
|
|
|
|
if OldIP == nil {
|
|
|
|
@ -399,10 +414,10 @@ func handleDHCP(content []byte, dstMAC net.HardwareAddr, srcMAC net.HardwareAddr
|
|
|
|
|
DHCPMask = mask
|
|
|
|
|
}
|
|
|
|
|
if dns := options[dhcp4.OptionDomainNameServer]; dns != nil {
|
|
|
|
|
DNSIP = dns
|
|
|
|
|
DHCPDNSIP = dns
|
|
|
|
|
}
|
|
|
|
|
if router := options[dhcp4.OptionRouter]; router != nil {
|
|
|
|
|
RouterIP = router
|
|
|
|
|
DHCPRouterIP = router
|
|
|
|
|
}
|
|
|
|
|
DHCPCandidate = offIP
|
|
|
|
|
sendDHCPRequest(dhcp4.Request, offIP)
|
|
|
|
@ -422,7 +437,7 @@ func handleDHCP(content []byte, dstMAC net.HardwareAddr, srcMAC net.HardwareAddr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sendDHCPReply creates a response DHCP packet and sends it
|
|
|
|
|
// sendDHCPReply creates a response DHCP packet for the VM and sends it
|
|
|
|
|
func sendDHCPReply(req dhcp4.Packet, mt dhcp4.MessageType, lease net.IP, reqOpt dhcp4.Options, dstMAC net.HardwareAddr) {
|
|
|
|
|
if DHCPIP == nil || DHCPMAC == nil {
|
|
|
|
|
log.Info("DHCP server is not known, discover request from VM discarded")
|
|
|
|
@ -435,8 +450,8 @@ func sendDHCPReply(req dhcp4.Packet, mt dhcp4.MessageType, lease net.IP, reqOpt
|
|
|
|
|
// Getting the options
|
|
|
|
|
opt := dhcp4.Options{
|
|
|
|
|
dhcp4.OptionSubnetMask: DHCPMask,
|
|
|
|
|
dhcp4.OptionRouter: RouterIP,
|
|
|
|
|
dhcp4.OptionDomainNameServer: DNSIP,
|
|
|
|
|
dhcp4.OptionRouter: DHCPRouterIP,
|
|
|
|
|
dhcp4.OptionDomainNameServer: DHCPDNSIP,
|
|
|
|
|
}.SelectOrderOrAll(reqOpt[dhcp4.OptionParameterRequestList])
|
|
|
|
|
|
|
|
|
|
// Creating the full packet layer by layer
|
|
|
|
@ -482,10 +497,11 @@ func sendDHCPReply(req dhcp4.Packet, mt dhcp4.MessageType, lease net.IP, reqOpt
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sendDHCPRequest creates a request DHCP packet for the server and sends it
|
|
|
|
|
func sendDHCPRequest(mt dhcp4.MessageType, reqIP net.IP) {
|
|
|
|
|
log.Info("Sending DHCP request: ", mt)
|
|
|
|
|
if mt == dhcp4.Discover {
|
|
|
|
|
XId = GenerateXID()
|
|
|
|
|
DHCPXId = GenerateXID()
|
|
|
|
|
}
|
|
|
|
|
DHCPState = mt
|
|
|
|
|
|
|
|
|
@ -527,7 +543,7 @@ func sendDHCPRequest(mt dhcp4.MessageType, reqIP net.IP) {
|
|
|
|
|
Value: reqIP.To4(),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
dhcp := dhcp4.RequestPacket(mt, NewMAC, reqIP, XId, false, dhcpOpts)
|
|
|
|
|
dhcp := dhcp4.RequestPacket(mt, NewMAC, reqIP, DHCPXId, false, dhcpOpts)
|
|
|
|
|
if err := udp.SetNetworkLayerForChecksum(&ipv4); err != nil {
|
|
|
|
|
log.Error("Error building DHCP request: ", err)
|
|
|
|
|
}
|
|
|
|
|