mosers
/
eaas-vde-proxy
Archiviert
1
0
Fork 0
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
Dieses Repo ist archiviert. Du kannst Dateien sehen und es klonen, kannst aber nicht pushen oder Issues/Pull-Requests öffnen.

196 Zeilen
6.3 KiB
Go

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
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
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).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")
c1.Execute()
c2.Execute()
go pipeForward(c1.OutReader, c2.InWriter, cmd.In, *passthrough)
go pipeForward(c2.OutReader, c1.InWriter, cmd.Out, *passthrough)
c1.WaitH()
c2.WaitH()
}
// 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(...)"
func pipeForward(reader io.Reader, writer io.Writer, prefix string, passthrough bool) {
for {
// Read frame length
frameLength := make([]byte, 2)
if _, err := reader.Read(frameLength); err == io.EOF {
log.Fatal(prefix, "Error reading frame length")
}
// Read actual frame
frameBytes := make([]byte, int(binary.BigEndian.Uint16(frameLength)))
if _, err := reader.Read(frameBytes); err == io.EOF {
log.Fatal(prefix, "Error reading frame data")
}
// 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)
if prefix == cmd.In {
log.Debug(prefix, "Incoming MAC rewritten ", frame.DstMAC, OldMac)
frame.DstMAC = OldMac
} else if prefix == cmd.Out {
log.Debug(prefix, "Outgoing MAC rewritten ", frame.SrcMAC, NewMac)
frame.SrcMAC = NewMac
}
// Handle IPv6 packet
if ipv4layer := packet.Layer(layers.LayerTypeIPv4); ipv4layer != nil {
ipv4Packet, _ := ipv4layer.(*layers.IPv4)
if prefix == cmd.In {
log.Debug(prefix, "Incoming IP rewritten ", ipv4Packet.DstIP, OldIP)
ipv4Packet.DstIP = OldIP
} else if prefix == cmd.Out {
log.Debug(prefix, "Outgoing IP rewritten ", 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.Debugf("%s ICMP packet\nType/Code:\t%s\n", prefix, icmpPacket.TypeCode.String())
}
// Handle DHCP packet (based on IPv4) - drop for now
if dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4); dhcpLayer != nil && !passthrough {
//dhcpPacket, _ := dhcpLayer.(*layers.DHCPv4)
log.Info(prefix, "DHCP packet dropped")
continue
}
// Handle TCP packet
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcpPacket, _ := tcpLayer.(*layers.TCP)
if err := tcpPacket.SetNetworkLayerForChecksum(ipv4Packet); err != nil {
log.Error(prefix, "Error setting network layer for checksum", err)
}
}
}
// Drop IPv6 packets
if ipv6layer := packet.Layer(layers.LayerTypeIPv6); ipv6layer != nil && !passthrough {
log.Info(prefix, "IPv6 packet dropped")
continue
}
// Handle ARP packet
if frame.EthernetType == layers.EthernetTypeARP {
arpPacket := packet.Layer(layers.LayerTypeARP).(*layers.ARP)
log.Debugf(
"%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 prefix == cmd.In {
arpPacket.DstProtAddress = OldIP
log.Debugf(
"%sARP after modification\nDstProtAddress:\t%s\n",
prefix,
net.IP(arpPacket.DstProtAddress),
)
if arpPacket.Operation == layers.ARPReply {
isInteresting = true
arpPacket.DstHwAddress = OldMac
log.Debugf(
"%sDstHwAddress:\t%s\n",
prefix,
net.HardwareAddr(arpPacket.DstHwAddress),
)
}
} else if prefix == cmd.Out {
arpPacket.SourceHwAddress = NewMac
arpPacket.SourceProtAddress = NewIP
log.Debugf(
"%sARP after modification\nSrcHwAddress:\t%s\nSrcProtAddress:\t%s\n",
prefix,
net.HardwareAddr(arpPacket.SourceHwAddress),
net.IP(arpPacket.SourceProtAddress),
)
}
}
// Forward original frame to other plug
if passthrough {
writer.Write(frameLength)
writer.Write(frameBytes)
continue
}
// Serialize packet back to binary
buf := gopacket.NewSerializeBuffer()
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 {
util.WriteBinary(fmt.Sprintf("/tmp/pck_%di.dat", time.Now().Unix()), frameBytes)
util.WriteBinary(fmt.Sprintf("/tmp/pck_%do.dat", time.Now().Unix()), newFrameBytes)
//util.WritePcap("xyz.pcap", packet.Data(), packet.Metadata().CaptureInfo)
}
// Forward modified frame to other plug
writer.Write(newFrameLength)
writer.Write(newFrameBytes)
}
}