From 759efce521dfacf6d53b6a13ceb27eeafc4771d1 Mon Sep 17 00:00:00 2001 From: Leonid Bugaev Date: Wed, 11 May 2016 16:27:48 +0500 Subject: [PATCH] Add support for IPv6 --- Makefile | 3 ++- input_raw.go | 3 --- input_raw_test.go | 20 +++++++++++--- raw_socket_listener/listener.go | 45 ++++++++++++++++++++----------- raw_socket_listener/tcp_packet.go | 25 ++++++++--------- 5 files changed, 60 insertions(+), 36 deletions(-) diff --git a/Makefile b/Makefile index 559eb4f..adb6f9b 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ SOURCE_PATH = /go/src/github.com/buger/gor/ RUN = docker run -v `pwd`:$(SOURCE_PATH) -p 0.0.0.0:8000:8000 -t -i gor BENCHMARK = BenchmarkRAWInput TEST = TestRawListenerBench +VERSION = DEV-$(shell date +%s) release: release-x64 @@ -53,7 +54,7 @@ profile_test: # Used mainly for debugging, because docker container do not have access to parent machine ports run: - $(RUN) go run $(SOURCE) --input-dummy=0 --output-http="http://localhost:9000" --input-raw :9000 --input-http :9000 --verbose --debug --middleware "./examples/middleware/echo.sh" + $(RUN) go run $(SOURCE) --input-dummy=0 --output-http="http://localhost:9000" --input-raw 127.0.0.1:9000 --input-http 127.0.0.1:9000 --verbose --debug --middleware "./examples/middleware/echo.sh" run-2: $(RUN) go run $(SOURCE) --input-file ./fixtures/requests.gor --output-dummy=0 diff --git a/input_raw.go b/input_raw.go index 10090bb..50a68d8 100644 --- a/input_raw.go +++ b/input_raw.go @@ -4,7 +4,6 @@ import ( raw "github.com/buger/gor/raw_socket_listener" "log" "net" - "strings" "time" ) @@ -62,8 +61,6 @@ func (i *RAWInput) Read(data []byte) (int, error) { } func (i *RAWInput) listen(address string) { - address = strings.Replace(address, "[::]", "127.0.0.1", -1) - Debug("Listening for traffic on: " + address) host, port, err := net.SplitHostPort(address) diff --git a/input_raw_test.go b/input_raw_test.go index 2fb7bf0..d30b0de 100644 --- a/input_raw_test.go +++ b/input_raw_test.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "log" "math/rand" + "net" "net/http" "net/http/httptest" "net/http/httputil" @@ -25,9 +26,20 @@ func TestRAWInput(t *testing.T) { wg := new(sync.WaitGroup) quit := make(chan int) - origin := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) - defer origin.Close() - originAddr := strings.Replace(origin.Listener.Addr().String(), "[::]", "127.0.0.1", -1) + listener, err := net.Listen("tcp", "[::1]:0") + if err != nil { + t.Fatal(err) + } + origin := &http.Server{ + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}), + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + } + go origin.Serve(listener) + defer listener.Close() + + originAddr := listener.Addr().String() + var respCounter, reqCounter int64 @@ -51,7 +63,7 @@ func TestRAWInput(t *testing.T) { Plugins.Inputs = []io.Reader{input} Plugins.Outputs = []io.Writer{output} - client := NewHTTPClient(origin.URL, &HTTPClientConfig{}) + client := NewHTTPClient("http://" + listener.Addr().String(), &HTTPClientConfig{}) go Start(quit) diff --git a/raw_socket_listener/listener.go b/raw_socket_listener/listener.go index 910e02c..2b74026 100644 --- a/raw_socket_listener/listener.go +++ b/raw_socket_listener/listener.go @@ -131,7 +131,7 @@ func (t *Listener) listen() { } return case data := <- t.packetsChan: - packet := ParseTCPPacket(data[:4], data[4:]) + packet := ParseTCPPacket(data[:16], data[16:]) t.processTCPPacket(packet) case <- gcTicker: now := time.Now() @@ -241,7 +241,7 @@ func findPcapDevice(addr string) (*pcap.Interface, error) { for _, device := range devices { for _, address := range device.Addresses { - if address.IP.String() == addr { + if device.Name == addr || address.IP.String() == addr { return &device, nil } } @@ -272,8 +272,6 @@ func (t *Listener) readPcap() { t.readyCh <- true - // log.Println(handle.Stats()) - for { packet, err := source.NextPacket() @@ -285,16 +283,31 @@ func (t *Listener) readPcap() { // Skip ethernet layer, 14 bytes data := packet.Data()[14:] - ihl := uint8(data[0]) & 0x0F + version := uint8(data[0]) >> 4 - // Truncated IP info - if len(data) < int(ihl*4) { - continue + var srcIP []byte + + if version == 4 { + ihl := uint8(data[0]) & 0x0F + + // Truncated IP info + if len(data) < int(ihl*4) { + continue + } + + srcIP = data[12:16] + data = data[ihl*4:] + } else { + // Truncated IP info + if len(data) < 40 { + continue + } + + srcIP = data[8:24] + + data = data[40:] } - srcIP := data[12:16] - data = data[ihl*4:] - // Truncated TCP info if len(data) < 13 { continue @@ -305,9 +318,9 @@ func (t *Listener) readPcap() { // We need only packets with data inside // Check that the buffer is larger than the size of the TCP header if len(data) > int(dataOffset*4) { - newBuf := make([]byte, len(data) + 4) - copy(newBuf[:4], srcIP) - copy(newBuf[4:], data) + newBuf := make([]byte, len(data) + 16) + copy(newBuf[:16], srcIP) + copy(newBuf[16:], data) t.packetsChan <- newBuf } @@ -343,8 +356,8 @@ func (t *Listener) readRAWSocket() { if n > 0 { if t.isValidPacket(buf[:n]) { newBuf := make([]byte, n + 4) - copy(newBuf[4:], buf[:n]) - copy(newBuf[:4], []byte(addr.(*net.IPAddr).IP)) + copy(newBuf[16:], buf[:n]) + copy(newBuf[:16], []byte(addr.(*net.IPAddr).IP)) t.packetsChan <- newBuf } diff --git a/raw_socket_listener/tcp_packet.go b/raw_socket_listener/tcp_packet.go index d31ed89..bb6ef7d 100644 --- a/raw_socket_listener/tcp_packet.go +++ b/raw_socket_listener/tcp_packet.go @@ -19,7 +19,7 @@ const ( fNS ) -type tcpID [12]byte +type tcpID [24]byte // TCPPacket provides tcp packet parser // Packet structure: http://en.wikipedia.org/wiki/Transmission_Control_Protocol @@ -48,10 +48,10 @@ func ParseTCPPacket(addr []byte, data []byte) (p *TCPPacket) { } func (p *TCPPacket) GenID() { - copy(p.ID[:4], p.Addr) - copy(p.ID[4:], p.Raw[0:2]) // Src port - copy(p.ID[6:], p.Raw[2:4]) // Dest port - copy(p.ID[8:], p.Raw[8:12]) // Ack + copy(p.ID[:16], p.Addr) + copy(p.ID[16:], p.Raw[0:2]) // Src port + copy(p.ID[18:], p.Raw[2:4]) // Dest port + copy(p.ID[20:], p.Raw[8:12]) // Ack } func (p *TCPPacket) UpdateAck(ack uint32) { @@ -73,16 +73,17 @@ func (t *TCPPacket) ParseBasic() { } func (t *TCPPacket) Dump() []byte { - buf := make([]byte, len(t.Data) + 16 + 4) + buf := make([]byte, len(t.Data) + 16 + 16) + tcpBuf := buf[16:] - binary.BigEndian.PutUint16(buf[6:8], t.DestPort) - binary.BigEndian.PutUint16(buf[4:6], t.SrcPort) + binary.BigEndian.PutUint16(tcpBuf[2:4], t.DestPort) + binary.BigEndian.PutUint16(buf[0:2], t.SrcPort) - binary.BigEndian.PutUint32(buf[8:12], t.Seq) - binary.BigEndian.PutUint32(buf[12:16], t.Ack) + binary.BigEndian.PutUint32(buf[4:8], t.Seq) + binary.BigEndian.PutUint32(buf[8:12], t.Ack) - buf[16] = 64 - copy(buf[20:], t.Data) + tcpBuf[16] = 64 + copy(tcpBuf[20:], t.Data) return buf }