diff --git a/proxy/main.go b/proxy/main.go index 52eb11a..1122fe9 100644 --- a/proxy/main.go +++ b/proxy/main.go @@ -3,13 +3,16 @@ package main import ( "encoding/binary" "flag" + "fmt" "github.com/google/gopacket" "github.com/google/gopacket/layers" log "github.com/sirupsen/logrus" "io" "net" "proxy/cmd" + "proxy/util" "strconv" + "time" ) var OldMac net.HardwareAddr @@ -17,7 +20,6 @@ var NewMac net.HardwareAddr var OldIP net.IP var NewIP net.IP - // Start the two plugs and run two concurrent forward methods func main() { // Get command line arguments @@ -32,13 +34,13 @@ func main() { log.SetLevel(log.Level(*logLvl)) OldMac, _ = net.ParseMAC(*oldmac) NewMac, _ = net.ParseMAC(*newmac) - OldIP = net.ParseIP(*oldip) - NewIP = net.ParseIP(*newip) + OldIP = net.ParseIP(*oldip).To4() + NewIP = net.ParseIP(*newip).To4() log.SetFormatter(&log.TextFormatter{ DisableTimestamp: true, }) c1 := cmd.New("vde_plug", "/run/vde/sw_main.sock") - c2 := cmd.New("vde_plug", "/run/vde/sw_proxy" + *proxy + ".sock") + c2 := cmd.New("vde_plug", "/run/vde/sw_proxy"+*proxy+".sock") c1.Execute() c2.Execute() go pipeForward(c1.OutReader, c2.InWriter, cmd.In, *passthrough) @@ -49,7 +51,6 @@ func main() { // Reads from an input and writes to and output, // do things to the content in between. -// For now only output the packet's information // Is meant to be run concurrently with "go pipeForward(...)" func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough bool) { for { @@ -67,6 +68,7 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough // Convert frame to full stack packet packet := gopacket.NewPacket(frameBytes, layers.LayerTypeEthernet, gopacket.Default) + isInteresting := false // Debug Help // Handle Ethernet frame frame := packet.Layer(layers.LayerTypeEthernet).(*layers.Ethernet) @@ -88,34 +90,47 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough log.Debug(prefix, "Outgoing IP rewritten ", ipv4Packet.SrcIP, NewMac) ipv4Packet.SrcIP = NewIP } + + // Handle ICMP packet (based on IPv4) + if icmpLayer := packet.Layer(layers.LayerTypeICMPv4); icmpLayer != nil { + icmpPacket, _ := icmpLayer.(*layers.ICMPv4) + log.Infof("%s ICMP packet\nType/Code:\t%s\n", prefix, icmpPacket.TypeCode.String()) + } + + // Handle DHCP packet (based on IPv4) + if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil && !passthrough { + //dhcpPacket, _ := dhcpLayer.(*layers.DHCPv4) + log.Info(prefix, "DHCP packet dropped") + continue + } } // Handle ARP packet if frame.EthernetType == layers.EthernetTypeARP { arpPacket := packet.Layer(layers.LayerTypeARP).(*layers.ARP) log.Infof( - "%sARP before modification\nAddrType:\t%s\nProtocol:\t%s\nOperation:\t%s\n" + - "SrcHwAddress:\t%s\nSrcProtAddress:\t%s\nDstHwAddress:\t%s\nDstProAddress:\t%s\n", - prefix, - arpPacket.AddrType, - arpPacket.Protocol, - strconv.Itoa(int(arpPacket.Operation)), - net.HardwareAddr(arpPacket.SourceHwAddress), - net.IP(arpPacket.SourceProtAddress), - net.HardwareAddr(arpPacket.DstHwAddress), - net.IP(arpPacket.DstProtAddress), - ) + "%sARP before modification\nAddrType:\t%s\nProtocol:\t%s\nOperation:\t%s\n"+ + "SrcHwAddress:\t%s\nSrcProtAddress:\t%s\nDstHwAddress:\t%s\nDstProtAddress:\t%s\n", + prefix, + arpPacket.AddrType, + arpPacket.Protocol, + strconv.Itoa(int(arpPacket.Operation)), + net.HardwareAddr(arpPacket.SourceHwAddress), + net.IP(arpPacket.SourceProtAddress), + net.HardwareAddr(arpPacket.DstHwAddress), + net.IP(arpPacket.DstProtAddress), + ) if !passthrough && prefix == cmd.In { - log.Debug(prefix,"Incoming MAC rewritten (ARP) ", net.HardwareAddr(arpPacket.DstHwAddress), OldMac) - arpPacket.DstProtAddress = OldIP - log.Infof( - "%sARP after modification\nDstProtAddress:\t%s\n", - prefix, - net.IP(arpPacket.DstProtAddress), - ) + log.Debug(prefix, "Incoming MAC rewritten (ARP) ", net.HardwareAddr(arpPacket.DstHwAddress), OldMac) if arpPacket.Operation == layers.ARPReply { arpPacket.DstHwAddress = OldMac + arpPacket.DstProtAddress = OldIP + log.Infof( + "%sARP after modification\nDstProtAddress:\t%s\n", + prefix, + net.IP(arpPacket.DstProtAddress), + ) log.Infof( "%sDstHwAddress:\t%s\n", prefix, @@ -123,7 +138,7 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough ) } } else if !passthrough && prefix == cmd.Out { - log.Debug(prefix,"Outgoing MAC rewritten (ARP) ", net.HardwareAddr(arpPacket.SourceHwAddress), NewMac) + log.Debug(prefix, "Outgoing MAC rewritten (ARP) ", net.HardwareAddr(arpPacket.SourceHwAddress), NewMac) arpPacket.SourceHwAddress = NewMac arpPacket.SourceProtAddress = NewIP log.Infof( @@ -135,24 +150,26 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough } } - // Handle DHCP packet - if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil { - //dhcpPacket, _ := dhcpLayer.(*layers.DHCPv4) - log.Info(prefix, "DHCP packet dropped") - continue - } - + // Serialize packet back to binary buf := gopacket.NewSerializeBuffer() - if err := gopacket.SerializePacket(buf, gopacket.SerializeOptions{}, packet); err != nil { - log.Error(prefix, "Error serializing packet to send") + opts := gopacket.SerializeOptions{ComputeChecksums: true, FixLengths: true} + if err := gopacket.SerializePacket(buf, opts, packet); err != nil { + log.Errorf("%s Error serializing packet to send\n%s\nSrc:\t%s\nDst:\t%s\n", prefix, err, frame.SrcMAC, frame.DstMAC) continue } newFrameBytes := buf.Bytes() newFrameLength := make([]byte, 2) binary.BigEndian.PutUint16(newFrameLength, uint16(len(newFrameBytes))) + // Write interesting things to debug file + if isInteresting && !passthrough { + util.WriteBinary(fmt.Sprintf("/tmp/arp_%di.dat", time.Now().Unix()), frameBytes) + util.WriteBinary(fmt.Sprintf("/tmp/arp_%do.dat", time.Now().Unix()), newFrameBytes) + //util.WritePcap("xyz.pcap", packet.Data(), packet.Metadata().CaptureInfo) + } + // Forward original frame to other plug writer.Write(newFrameLength) writer.Write(newFrameBytes) } -} \ No newline at end of file +} diff --git a/proxy/proxy b/proxy/proxy index f773201..51c0cf6 100755 Binary files a/proxy/proxy and b/proxy/proxy differ diff --git a/proxy/util/util.go b/proxy/util/util.go new file mode 100644 index 0000000..4f9a270 --- /dev/null +++ b/proxy/util/util.go @@ -0,0 +1,32 @@ +package util + +import ( + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcapgo" + log "github.com/sirupsen/logrus" + "io/ioutil" + "os" +) + +func WritePcap(file string, data []byte, ci gopacket.CaptureInfo) { + f, err := os.Create(file) + if err != nil { + log.Errorf("Error writing pcap file %s", file) + } + defer f.Close() + + r, err := pcapgo.NewNgWriter(f, layers.LinkTypeEthernet) + if err != nil { + log.Errorf("Error writing pcap file %s", file) + } + defer r.Flush() + + err = r.WritePacket(ci, data) +} + +func WriteBinary(file string, data []byte) { + if err := ioutil.WriteFile(file, data, 0644); err != nil { + log.Errorf("Error writing binary file %s", file) + } +} \ No newline at end of file