|
|
@ -3,13 +3,16 @@ package main
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/binary"
|
|
|
|
"flag"
|
|
|
|
"flag"
|
|
|
|
|
|
|
|
"fmt"
|
|
|
|
"github.com/google/gopacket"
|
|
|
|
"github.com/google/gopacket"
|
|
|
|
"github.com/google/gopacket/layers"
|
|
|
|
"github.com/google/gopacket/layers"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
"net"
|
|
|
|
"net"
|
|
|
|
"proxy/cmd"
|
|
|
|
"proxy/cmd"
|
|
|
|
|
|
|
|
"proxy/util"
|
|
|
|
"strconv"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
var OldMac net.HardwareAddr
|
|
|
|
var OldMac net.HardwareAddr
|
|
|
@ -17,7 +20,6 @@ var NewMac net.HardwareAddr
|
|
|
|
var OldIP net.IP
|
|
|
|
var OldIP net.IP
|
|
|
|
var NewIP net.IP
|
|
|
|
var NewIP net.IP
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Start the two plugs and run two concurrent forward methods
|
|
|
|
// Start the two plugs and run two concurrent forward methods
|
|
|
|
func main() {
|
|
|
|
func main() {
|
|
|
|
// Get command line arguments
|
|
|
|
// Get command line arguments
|
|
|
@ -32,13 +34,13 @@ func main() {
|
|
|
|
log.SetLevel(log.Level(*logLvl))
|
|
|
|
log.SetLevel(log.Level(*logLvl))
|
|
|
|
OldMac, _ = net.ParseMAC(*oldmac)
|
|
|
|
OldMac, _ = net.ParseMAC(*oldmac)
|
|
|
|
NewMac, _ = net.ParseMAC(*newmac)
|
|
|
|
NewMac, _ = net.ParseMAC(*newmac)
|
|
|
|
OldIP = net.ParseIP(*oldip)
|
|
|
|
OldIP = net.ParseIP(*oldip).To4()
|
|
|
|
NewIP = net.ParseIP(*newip)
|
|
|
|
NewIP = net.ParseIP(*newip).To4()
|
|
|
|
log.SetFormatter(&log.TextFormatter{
|
|
|
|
log.SetFormatter(&log.TextFormatter{
|
|
|
|
DisableTimestamp: true,
|
|
|
|
DisableTimestamp: true,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
c1 := cmd.New("vde_plug", "/run/vde/sw_main.sock")
|
|
|
|
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()
|
|
|
|
c1.Execute()
|
|
|
|
c2.Execute()
|
|
|
|
c2.Execute()
|
|
|
|
go pipeForward(c1.OutReader, c2.InWriter, cmd.In, *passthrough)
|
|
|
|
go pipeForward(c1.OutReader, c2.InWriter, cmd.In, *passthrough)
|
|
|
@ -49,7 +51,6 @@ 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.
|
|
|
|
// For now only output the packet's information
|
|
|
|
|
|
|
|
// Is meant to be run concurrently with "go pipeForward(...)"
|
|
|
|
// Is meant to be run concurrently with "go pipeForward(...)"
|
|
|
|
func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough bool) {
|
|
|
|
func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough bool) {
|
|
|
|
for {
|
|
|
|
for {
|
|
|
@ -67,6 +68,7 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough
|
|
|
|
|
|
|
|
|
|
|
|
// Convert frame to full stack packet
|
|
|
|
// Convert frame to full stack packet
|
|
|
|
packet := gopacket.NewPacket(frameBytes, layers.LayerTypeEthernet, gopacket.Default)
|
|
|
|
packet := gopacket.NewPacket(frameBytes, layers.LayerTypeEthernet, gopacket.Default)
|
|
|
|
|
|
|
|
isInteresting := false // Debug Help
|
|
|
|
|
|
|
|
|
|
|
|
// Handle Ethernet frame
|
|
|
|
// Handle Ethernet frame
|
|
|
|
frame := packet.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
|
|
|
|
frame := packet.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
|
|
|
@ -88,14 +90,27 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough
|
|
|
|
log.Debug(prefix, "Outgoing IP rewritten ", ipv4Packet.SrcIP, NewMac)
|
|
|
|
log.Debug(prefix, "Outgoing IP rewritten ", ipv4Packet.SrcIP, NewMac)
|
|
|
|
ipv4Packet.SrcIP = NewIP
|
|
|
|
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
|
|
|
|
// Handle ARP packet
|
|
|
|
if frame.EthernetType == layers.EthernetTypeARP {
|
|
|
|
if frame.EthernetType == layers.EthernetTypeARP {
|
|
|
|
arpPacket := packet.Layer(layers.LayerTypeARP).(*layers.ARP)
|
|
|
|
arpPacket := packet.Layer(layers.LayerTypeARP).(*layers.ARP)
|
|
|
|
log.Infof(
|
|
|
|
log.Infof(
|
|
|
|
"%sARP before modification\nAddrType:\t%s\nProtocol:\t%s\nOperation:\t%s\n" +
|
|
|
|
"%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",
|
|
|
|
"SrcHwAddress:\t%s\nSrcProtAddress:\t%s\nDstHwAddress:\t%s\nDstProtAddress:\t%s\n",
|
|
|
|
prefix,
|
|
|
|
prefix,
|
|
|
|
arpPacket.AddrType,
|
|
|
|
arpPacket.AddrType,
|
|
|
|
arpPacket.Protocol,
|
|
|
|
arpPacket.Protocol,
|
|
|
@ -107,15 +122,15 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if !passthrough && prefix == cmd.In {
|
|
|
|
if !passthrough && prefix == cmd.In {
|
|
|
|
log.Debug(prefix,"Incoming MAC rewritten (ARP) ", net.HardwareAddr(arpPacket.DstHwAddress), OldMac)
|
|
|
|
log.Debug(prefix, "Incoming MAC rewritten (ARP) ", net.HardwareAddr(arpPacket.DstHwAddress), OldMac)
|
|
|
|
|
|
|
|
if arpPacket.Operation == layers.ARPReply {
|
|
|
|
|
|
|
|
arpPacket.DstHwAddress = OldMac
|
|
|
|
arpPacket.DstProtAddress = OldIP
|
|
|
|
arpPacket.DstProtAddress = OldIP
|
|
|
|
log.Infof(
|
|
|
|
log.Infof(
|
|
|
|
"%sARP after modification\nDstProtAddress:\t%s\n",
|
|
|
|
"%sARP after modification\nDstProtAddress:\t%s\n",
|
|
|
|
prefix,
|
|
|
|
prefix,
|
|
|
|
net.IP(arpPacket.DstProtAddress),
|
|
|
|
net.IP(arpPacket.DstProtAddress),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
if arpPacket.Operation == layers.ARPReply {
|
|
|
|
|
|
|
|
arpPacket.DstHwAddress = OldMac
|
|
|
|
|
|
|
|
log.Infof(
|
|
|
|
log.Infof(
|
|
|
|
"%sDstHwAddress:\t%s\n",
|
|
|
|
"%sDstHwAddress:\t%s\n",
|
|
|
|
prefix,
|
|
|
|
prefix,
|
|
|
@ -123,7 +138,7 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if !passthrough && prefix == cmd.Out {
|
|
|
|
} 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.SourceHwAddress = NewMac
|
|
|
|
arpPacket.SourceProtAddress = NewIP
|
|
|
|
arpPacket.SourceProtAddress = NewIP
|
|
|
|
log.Infof(
|
|
|
|
log.Infof(
|
|
|
@ -135,22 +150,24 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Handle DHCP packet
|
|
|
|
// Serialize packet back to binary
|
|
|
|
if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil {
|
|
|
|
|
|
|
|
//dhcpPacket, _ := dhcpLayer.(*layers.DHCPv4)
|
|
|
|
|
|
|
|
log.Info(prefix, "DHCP packet dropped")
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf := gopacket.NewSerializeBuffer()
|
|
|
|
buf := gopacket.NewSerializeBuffer()
|
|
|
|
if err := gopacket.SerializePacket(buf, gopacket.SerializeOptions{}, packet); err != nil {
|
|
|
|
opts := gopacket.SerializeOptions{ComputeChecksums: true, FixLengths: true}
|
|
|
|
log.Error(prefix, "Error serializing packet to send")
|
|
|
|
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
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
newFrameBytes := buf.Bytes()
|
|
|
|
newFrameBytes := buf.Bytes()
|
|
|
|
newFrameLength := make([]byte, 2)
|
|
|
|
newFrameLength := make([]byte, 2)
|
|
|
|
binary.BigEndian.PutUint16(newFrameLength, uint16(len(newFrameBytes)))
|
|
|
|
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
|
|
|
|
// Forward original frame to other plug
|
|
|
|
writer.Write(newFrameLength)
|
|
|
|
writer.Write(newFrameLength)
|
|
|
|
writer.Write(newFrameBytes)
|
|
|
|
writer.Write(newFrameBytes)
|
|
|
|