|
|
@ -2,22 +2,47 @@ package main
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
|
|
|
"flag"
|
|
|
|
"github.com/google/gopacket"
|
|
|
|
"github.com/google/gopacket"
|
|
|
|
"github.com/google/gopacket/layers"
|
|
|
|
"github.com/google/gopacket/layers"
|
|
|
|
_ "github.com/google/gopacket/layers"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
|
|
|
|
"net"
|
|
|
|
"proxy/cmd"
|
|
|
|
"proxy/cmd"
|
|
|
|
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var OldMac net.HardwareAddr
|
|
|
|
|
|
|
|
var NewMac net.HardwareAddr
|
|
|
|
|
|
|
|
var OldIP 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
|
|
|
|
|
|
|
|
logLvl := flag.Int("log", 4, "allowed: 5 (debug), 4 (info), 3 (warning), 2 (error), 1 (fatal)")
|
|
|
|
|
|
|
|
oldip := flag.String("oldip", "10.0.0.11", "IP before change")
|
|
|
|
|
|
|
|
newip := flag.String("newip", "10.0.0.15", "IP after change")
|
|
|
|
|
|
|
|
oldmac := flag.String("oldmac", "52:54:00:12:34:56", "MAC before change")
|
|
|
|
|
|
|
|
newmac := flag.String("newmac", "52:54:00:12:34:aa", "MAC after change")
|
|
|
|
|
|
|
|
passthrough := flag.Bool("passthrough", false, "Whether to pass every traffic through")
|
|
|
|
|
|
|
|
proxy := flag.String("proxy", "1", "Number of the proxy switch")
|
|
|
|
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
log.SetLevel(log.Level(*logLvl))
|
|
|
|
|
|
|
|
OldMac, _ = net.ParseMAC(*oldmac)
|
|
|
|
|
|
|
|
NewMac, _ = net.ParseMAC(*newmac)
|
|
|
|
|
|
|
|
OldIP = net.ParseIP(*oldip)
|
|
|
|
|
|
|
|
NewIP = net.ParseIP(*newip)
|
|
|
|
|
|
|
|
log.SetFormatter(&log.TextFormatter{
|
|
|
|
|
|
|
|
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.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)
|
|
|
|
go pipeForward(c1.OutReader, c2.InWriter, cmd.In, *passthrough)
|
|
|
|
go pipeForward(c2.OutReader, c1.InWriter, cmd.Out)
|
|
|
|
go pipeForward(c2.OutReader, c1.InWriter, cmd.Out, *passthrough)
|
|
|
|
c1.WaitH()
|
|
|
|
c1.WaitH()
|
|
|
|
c2.WaitH()
|
|
|
|
c2.WaitH()
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -26,22 +51,18 @@ func main() {
|
|
|
|
// do things to the content in between.
|
|
|
|
// do things to the content in between.
|
|
|
|
// For now only output the packet's information
|
|
|
|
// 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) {
|
|
|
|
func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough bool) {
|
|
|
|
for {
|
|
|
|
for {
|
|
|
|
// Read frame length and print it
|
|
|
|
// Read frame length
|
|
|
|
frameLength := make([]byte, 2)
|
|
|
|
frameLength := make([]byte, 2)
|
|
|
|
_, err := reader.Read(frameLength)
|
|
|
|
if _, err := reader.Read(frameLength); err == io.EOF {
|
|
|
|
if err == io.EOF {
|
|
|
|
log.Fatal(prefix, "Error reading frame length")
|
|
|
|
break
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
frameLengthInt := int(binary.BigEndian.Uint16(frameLength))
|
|
|
|
|
|
|
|
fmt.Printf("%s Frame length: %d\n", prefix, frameLengthInt)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Read actual frame
|
|
|
|
// Read actual frame
|
|
|
|
frameBytes := make([]byte, frameLengthInt)
|
|
|
|
frameBytes := make([]byte, int(binary.BigEndian.Uint16(frameLength)))
|
|
|
|
_, err = reader.Read(frameBytes)
|
|
|
|
if _, err := reader.Read(frameBytes); err == io.EOF {
|
|
|
|
if err == io.EOF {
|
|
|
|
log.Fatal(prefix, "Error reading frame data")
|
|
|
|
break
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Convert frame to full stack packet
|
|
|
|
// Convert frame to full stack packet
|
|
|
@ -49,22 +70,89 @@ func pipeForward(reader io.Reader, writer io.Writer, prefix string) {
|
|
|
|
|
|
|
|
|
|
|
|
// Handle Ethernet frame
|
|
|
|
// Handle Ethernet frame
|
|
|
|
frame := packet.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
|
|
|
|
frame := packet.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
|
|
|
|
fmt.Printf("src: %s\ndst: %s\ntyp: %s\n", frame.SrcMAC, frame.DstMAC, frame.EthernetType)
|
|
|
|
if !passthrough && prefix == cmd.In {
|
|
|
|
|
|
|
|
log.Debug(prefix, "Incoming MAC rewritten ", frame.DstMAC, OldMac)
|
|
|
|
|
|
|
|
frame.DstMAC = OldMac
|
|
|
|
|
|
|
|
} else if !passthrough && prefix == cmd.Out {
|
|
|
|
|
|
|
|
log.Debug(prefix, "Outgoing MAC rewritten ", frame.SrcMAC, NewMac)
|
|
|
|
|
|
|
|
frame.SrcMAC = NewMac
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Handle IP packet
|
|
|
|
|
|
|
|
if ipv4layer := packet.Layer(layers.LayerTypeIPv4); ipv4layer != nil {
|
|
|
|
|
|
|
|
ipv4Packet, _ := ipv4layer.(*layers.IPv4)
|
|
|
|
|
|
|
|
if !passthrough && prefix == cmd.In {
|
|
|
|
|
|
|
|
log.Debug(prefix, "Incoming IP rewritten ", ipv4Packet.DstIP, OldIP)
|
|
|
|
|
|
|
|
ipv4Packet.DstIP = OldIP
|
|
|
|
|
|
|
|
} else if !passthrough && prefix == cmd.Out {
|
|
|
|
|
|
|
|
log.Debug(prefix, "Outgoing IP rewritten ", ipv4Packet.SrcIP, NewMac)
|
|
|
|
|
|
|
|
ipv4Packet.SrcIP = NewIP
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
fmt.Printf("%sARP Packet:\n%#v\n", prefix, arpPacket)
|
|
|
|
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),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
if arpPacket.Operation == layers.ARPReply {
|
|
|
|
|
|
|
|
arpPacket.DstHwAddress = OldMac
|
|
|
|
|
|
|
|
log.Infof(
|
|
|
|
|
|
|
|
"%sDstHwAddress:\t%s\n",
|
|
|
|
|
|
|
|
prefix,
|
|
|
|
|
|
|
|
net.HardwareAddr(arpPacket.DstHwAddress),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if !passthrough && prefix == cmd.Out {
|
|
|
|
|
|
|
|
log.Debug(prefix,"Outgoing MAC rewritten (ARP) ", net.HardwareAddr(arpPacket.SourceHwAddress), NewMac)
|
|
|
|
|
|
|
|
arpPacket.SourceHwAddress = NewMac
|
|
|
|
|
|
|
|
arpPacket.SourceProtAddress = NewIP
|
|
|
|
|
|
|
|
log.Infof(
|
|
|
|
|
|
|
|
"%sARP after modification\nSrcHwAddress:\t%s\nSrcProtAddress:\t%s\n",
|
|
|
|
|
|
|
|
prefix,
|
|
|
|
|
|
|
|
net.HardwareAddr(arpPacket.SourceHwAddress),
|
|
|
|
|
|
|
|
net.IP(arpPacket.SourceProtAddress),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Handle DHCP packet
|
|
|
|
// Handle DHCP packet
|
|
|
|
if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil {
|
|
|
|
if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil {
|
|
|
|
dhcpPacket, _ := dhcpLayer.(*layers.DHCPv4)
|
|
|
|
//dhcpPacket, _ := dhcpLayer.(*layers.DHCPv4)
|
|
|
|
fmt.Printf("%sDHCP Packet:\n%#v\n", prefix, dhcpPacket)
|
|
|
|
log.Info(prefix, "DHCP packet dropped")
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf := gopacket.NewSerializeBuffer()
|
|
|
|
|
|
|
|
if err := gopacket.SerializePacket(buf, gopacket.SerializeOptions{}, packet); err != nil {
|
|
|
|
|
|
|
|
log.Error(prefix, "Error serializing packet to send")
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
newFrameBytes := buf.Bytes()
|
|
|
|
|
|
|
|
newFrameLength := make([]byte, 2)
|
|
|
|
|
|
|
|
binary.BigEndian.PutUint16(newFrameLength, uint16(len(newFrameBytes)))
|
|
|
|
|
|
|
|
|
|
|
|
// Forward original frame to other plug
|
|
|
|
// Forward original frame to other plug
|
|
|
|
writer.Write(frameLength)
|
|
|
|
writer.Write(newFrameLength)
|
|
|
|
writer.Write(frameBytes)
|
|
|
|
writer.Write(newFrameBytes)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|