diff --git a/Makefile b/Makefile index 693a80f..b79497d 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ dbuild: docker build -t gor . dtest: - docker run -v `pwd`:/gopath/src/gor -t -i --env GORACE="halt_on_error=1" gor go test $(ARGS) -race -v + docker run -v `pwd`:/gopath/src/gor -t -i --env GORACE="halt_on_error=1" gor go test $(ARGS) -race -v --verbose dfmt: docker run -v `pwd`:/gopath/src/gor -t -i gor go fmt diff --git a/input_raw.go b/input_raw.go index 3a6a960..9653559 100644 --- a/input_raw.go +++ b/input_raw.go @@ -32,6 +32,8 @@ 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) if err != nil { diff --git a/output_http.go b/output_http.go index 46a342a..ba1afa2 100644 --- a/output_http.go +++ b/output_http.go @@ -73,6 +73,7 @@ type HTTPOutput struct { address string limit int queue chan []byte + responses chan []byte redirectLimit int @@ -91,7 +92,7 @@ type HTTPOutput struct { queueStats *GorStat } -func NewHTTPOutput(address string, headers HTTPHeaders, methods HTTPMethods, urlRegexp HTTPUrlRegexp, headerFilters HTTPHeaderFilters, headerHashFilters HTTPHeaderHashFilters, elasticSearchAddr string, outputHTTPUrlRewrite UrlRewriteMap, outputHTTPRedirects int) io.Writer { +func NewHTTPOutput(address string, headers HTTPHeaders, methods HTTPMethods, urlRegexp HTTPUrlRegexp, headerFilters HTTPHeaderFilters, headerHashFilters HTTPHeaderHashFilters, elasticSearchAddr string, outputHTTPUrlRewrite UrlRewriteMap, outputHTTPRedirects int) io.ReadWriter { o := new(HTTPOutput) diff --git a/traffic_modifier_test.go b/traffic_modifier_test.go index 547876e..82e786e 100644 --- a/traffic_modifier_test.go +++ b/traffic_modifier_test.go @@ -4,13 +4,14 @@ import ( _ "bufio" "bytes" "crypto/rand" - _ "io" + "io" "io/ioutil" _ "log" _ "net" "net/http" "sync" "testing" + "strings" ) // Simple service that generate token on request, and require this token for accesing to secure area @@ -18,32 +19,40 @@ func NewFakeSecureService(wg *sync.WaitGroup) string { active_tokens := make([][]byte, 0) listener := startHTTP(func(w http.ResponseWriter, req *http.Request) { + Debug("Received request: " + req.URL.String()) + switch req.URL.Path { case "/token": // Generate random token token_length := 10 token := make([]byte, token_length) rand.Read(token) - - w.Write(token) - active_tokens = append(active_tokens, token) + + w.Write(token) case "/secure": token := []byte(req.URL.Query().Get("token")) + token_found := false for _, t := range active_tokens { if bytes.Equal(t, token) { - w.WriteHeader(http.StatusAccepted) - } else { - w.WriteHeader(http.StatusForbidden) + token_found = true + break } } + + if token_found { + w.WriteHeader(http.StatusAccepted) + } else { + w.WriteHeader(http.StatusForbidden) + } } wg.Done() }) - return "http://" + listener.Addr().String() + address := strings.Replace(listener.Addr().String(), "[::]", "127.0.0.1", -1) + return address } func TestFakeSecureService(t *testing.T) { @@ -55,20 +64,60 @@ func TestFakeSecureService(t *testing.T) { wg.Add(3) - resp, _ = http.Get(addr + "/token") + resp, _ = http.Get("http://" + addr + "/token") token, _ := ioutil.ReadAll(resp.Body) // Right token - resp, _ = http.Get(addr + "/secure?token=" + string(token)) + resp, _ = http.Get("http://" + addr + "/secure?token=" + string(token)) if resp.StatusCode != http.StatusAccepted { t.Error("Valid token should returns wrong status:", resp.StatusCode) } // Wrong tokens forbidden - resp, _ = http.Get(addr + "/secure?token=wrong") + resp, _ = http.Get("http://" + addr + "/secure?token=wrong") if resp.StatusCode != http.StatusForbidden { t.Error("Wrong tokens should be forbidden, instead:", resp.StatusCode) } wg.Wait() } + +func TestTrafficModifier(t *testing.T) { + var resp *http.Response + + wg := new(sync.WaitGroup) + + from := NewFakeSecureService(wg) + to := NewFakeSecureService(wg) + + quit := make(chan int) + + // Catch traffic from one service + input := NewRAWInput(from) + + // And redirect to another + headers := HTTPHeaders{HTTPHeader{"User-Agent", "Gor"}} + methods := HTTPMethods{"GET", "PUT", "POST"} + output := NewHTTPOutput(to, headers, methods, HTTPUrlRegexp{}, HTTPHeaderFilters{}, HTTPHeaderHashFilters{}, "", UrlRewriteMap{}, 0) + + Plugins.Inputs = []io.Reader{input} + Plugins.Outputs = []io.Writer{output} + + // Start Gor + go Start(quit) + + // Should receive 2 requests from original + 2 from replayed + wg.Add(4) + + // Sending traffic to original service + resp, _ = http.Get("http://" + from + "/token") + token, _ := ioutil.ReadAll(resp.Body) + + resp, _ = http.Get("http://" + from + "/secure?token=" + string(token)) + if resp.StatusCode != http.StatusAccepted { + t.Error("Valid token should returns wrong status:", resp.StatusCode) + } + + wg.Wait() + close(quit) +}