From eb7a31446a48918e6c700784828824431fe41712 Mon Sep 17 00:00:00 2001 From: Simon Moser Date: Mon, 27 Dec 2021 14:50:11 +0100 Subject: [PATCH] Documentation improved --- README.md | 3 ++ proxy/cmd/cmd.go | 17 ++++------- proxy/main.go | 72 ++++++++++++++++++++++++++++------------------ proxy/util/util.go | 23 +++++++++------ 4 files changed, 67 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 5e77bae..e327ddb 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ ![overview](README.assets/overview.png) +## Documentation +See [[Wiki|Home]] + ## Problematic protocols Important and implemented: diff --git a/proxy/cmd/cmd.go b/proxy/cmd/cmd.go index 3460c0c..055f8f8 100644 --- a/proxy/cmd/cmd.go +++ b/proxy/cmd/cmd.go @@ -10,19 +10,19 @@ import ( // Cmd Overloads the exec.Cmd class to save the full command // and adds custom input/output pipes type Cmd struct { - fullCommand string + fullCommand string *exec.Cmd - inReader io.Reader - InWriter io.Writer - OutReader io.Reader - outWriter io.Writer + inReader io.Reader + InWriter io.Writer + OutReader io.Reader + outWriter io.Writer } // Start creates a new cmd object with given arguments, runs and then returns it func Start(args string) (*Cmd, io.Reader, io.Writer) { ir, iw := io.Pipe() or, ow := io.Pipe() - c := Cmd { + c := Cmd{ "vde_plug " + args, exec.Command("vde_plug", args), ir, @@ -47,8 +47,3 @@ func (c *Cmd) WaitH() { log.Printf("%s failed with %s\n", c.fullCommand, err) } } - -const ( - Out = ">> " // Prefix for traffic from VM - In = "<< " // Prefix for traffic to VM -) \ No newline at end of file diff --git a/proxy/main.go b/proxy/main.go index 5db5836..824a9d0 100644 --- a/proxy/main.go +++ b/proxy/main.go @@ -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) } diff --git a/proxy/util/util.go b/proxy/util/util.go index bfd63f0..a71a383 100644 --- a/proxy/util/util.go +++ b/proxy/util/util.go @@ -40,13 +40,7 @@ func WritePcap(file string, data []byte) { err = r.WritePacket(ci, data) } -// WriteBinary writes the provided data to a given binary file -func WriteBinary(file string, data []byte) { - if err := ioutil.WriteFile(file, data, 0644); err != nil { - log.Errorf("Error writing binary file %s", file) - } -} - +// WritePIDFile writes the processes PID to a given file func WritePIDFile(filename string) { if filename == "" { return @@ -56,6 +50,7 @@ func WritePIDFile(filename string) { } } +// GenerateMac generates a random MAC address func GenerateMac(customMAC string) net.HardwareAddr { if customMAC != "" { ret, _ := net.ParseMAC(customMAC) @@ -74,6 +69,7 @@ func GenerateMac(customMAC string) net.HardwareAddr { return mac } +// GenerateXID generates a random XID for DHCP func GenerateXID() []byte { buf := make([]byte, 4) if _, err := rand.Read(buf); err != nil { @@ -84,6 +80,7 @@ func GenerateXID() []byte { return buf } +// GenerateUId generates a random UId string as hostname func GenerateUId(path string) string { adl := adler32.Checksum([]byte(path)) byt := make([]byte, 4) @@ -126,8 +123,9 @@ func (c If) IP(a, b net.IP) net.IP { return b } -// Source: https://github.com/aler9/landiscover/blob/main/utils.go -// partpart +// Source: https://github.com/aler9/landiscover/blob/main/utils.go, MIT LICENSE + +// DnsQueryDecode takes encoded hostnames from Microsoft and decodes it func DnsQueryDecode(data []byte, start int) (string, int) { var read []byte toread := uint8(0) @@ -170,6 +168,7 @@ func DnsQueryDecode(data []byte, start int) (string, int) { return string(read), pos + 1 - start } +// DnsQueryEncode takes string hostnames and encodes it to Microsoft format func DnsQueryEncode(in string) []byte { tmp := strings.Split(in, ".") @@ -196,3 +195,9 @@ func DnsQueryEncode(in string) []byte { return ret } + +// Prefixes for traffic from (out) or to (in) VM +const ( + Out = ">> " + In = "<< " +)