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

Documentation improved

main
Simon Moser vor 3 Jahren
Ursprung 6d29070fe6
Commit eb7a31446a
Signiert von: mosers
GPG-Schlüssel-ID: 96B3365A234B500C

@ -4,6 +4,9 @@
![overview](README.assets/overview.png) ![overview](README.assets/overview.png)
## Documentation
See [[Wiki|Home]]
## Problematic protocols ## Problematic protocols
Important and implemented: Important and implemented:

@ -22,7 +22,7 @@ type Cmd struct {
func Start(args string) (*Cmd, io.Reader, io.Writer) { func Start(args string) (*Cmd, io.Reader, io.Writer) {
ir, iw := io.Pipe() ir, iw := io.Pipe()
or, ow := io.Pipe() or, ow := io.Pipe()
c := Cmd { c := Cmd{
"vde_plug " + args, "vde_plug " + args,
exec.Command("vde_plug", args), exec.Command("vde_plug", args),
ir, ir,
@ -47,8 +47,3 @@ func (c *Cmd) WaitH() {
log.Printf("%s failed with %s\n", c.fullCommand, err) log.Printf("%s failed with %s\n", c.fullCommand, err)
} }
} }
const (
Out = ">> " // Prefix for traffic from VM
In = "<< " // Prefix for traffic to VM
)

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

@ -40,13 +40,7 @@ func WritePcap(file string, data []byte) {
err = r.WritePacket(ci, data) err = r.WritePacket(ci, data)
} }
// WriteBinary writes the provided data to a given binary file // WritePIDFile writes the processes PID to a given file
func WriteBinary(file string, data []byte) {
if err := ioutil.WriteFile(file, data, 0644); err != nil {
log.Errorf("Error writing binary file %s", file)
}
}
func WritePIDFile(filename string) { func WritePIDFile(filename string) {
if filename == "" { if filename == "" {
return return
@ -56,6 +50,7 @@ func WritePIDFile(filename string) {
} }
} }
// GenerateMac generates a random MAC address
func GenerateMac(customMAC string) net.HardwareAddr { func GenerateMac(customMAC string) net.HardwareAddr {
if customMAC != "" { if customMAC != "" {
ret, _ := net.ParseMAC(customMAC) ret, _ := net.ParseMAC(customMAC)
@ -74,6 +69,7 @@ func GenerateMac(customMAC string) net.HardwareAddr {
return mac return mac
} }
// GenerateXID generates a random XID for DHCP
func GenerateXID() []byte { func GenerateXID() []byte {
buf := make([]byte, 4) buf := make([]byte, 4)
if _, err := rand.Read(buf); err != nil { if _, err := rand.Read(buf); err != nil {
@ -84,6 +80,7 @@ func GenerateXID() []byte {
return buf return buf
} }
// GenerateUId generates a random UId string as hostname
func GenerateUId(path string) string { func GenerateUId(path string) string {
adl := adler32.Checksum([]byte(path)) adl := adler32.Checksum([]byte(path))
byt := make([]byte, 4) byt := make([]byte, 4)
@ -126,8 +123,9 @@ func (c If) IP(a, b net.IP) net.IP {
return b return b
} }
// Source: https://github.com/aler9/landiscover/blob/main/utils.go // Source: https://github.com/aler9/landiscover/blob/main/utils.go, MIT LICENSE
// <size>part<size>part
// DnsQueryDecode takes encoded hostnames from Microsoft and decodes it
func DnsQueryDecode(data []byte, start int) (string, int) { func DnsQueryDecode(data []byte, start int) (string, int) {
var read []byte var read []byte
toread := uint8(0) toread := uint8(0)
@ -170,6 +168,7 @@ func DnsQueryDecode(data []byte, start int) (string, int) {
return string(read), pos + 1 - start return string(read), pos + 1 - start
} }
// DnsQueryEncode takes string hostnames and encodes it to Microsoft format
func DnsQueryEncode(in string) []byte { func DnsQueryEncode(in string) []byte {
tmp := strings.Split(in, ".") tmp := strings.Split(in, ".")
@ -196,3 +195,9 @@ func DnsQueryEncode(in string) []byte {
return ret return ret
} }
// Prefixes for traffic from (out) or to (in) VM
const (
Out = ">> "
In = "<< "
)