From 90f3524a0464590092535adfab579c220491b8ad Mon Sep 17 00:00:00 2001 From: Alexandr Kolesov Date: Sun, 3 Nov 2024 16:26:39 +0400 Subject: [PATCH 1/3] Fix injector --- integration/Makefile | 3 ++ integration/docker-compose.yml | 10 +++--- pkg/codec/injector_test.go | 28 +++------------ pkg/proxy.go | 2 +- pkg/proxy_test.go | 63 ++++++++++++++++++++++++++++++++-- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/integration/Makefile b/integration/Makefile index 5c2c11c..044cd33 100644 --- a/integration/Makefile +++ b/integration/Makefile @@ -1,3 +1,6 @@ +.PHONY: all +all: test + .PHONY: test test: # Start the containers diff --git a/integration/docker-compose.yml b/integration/docker-compose.yml index c7a7ed7..e979e2e 100644 --- a/integration/docker-compose.yml +++ b/integration/docker-compose.yml @@ -1,21 +1,21 @@ services: - obfuscating-proxy: # server + proxy-client: build: context: ./../ dockerfile: ./docker/Dockerfile - command: ["obfsproxy", "-l", "0.0.0.0:8080", "-t", "deobfuscating-proxy:8081", "-k", "test-key", "-r", "50", "-s"] + command: ["obfsproxy", "-l", "0.0.0.0:8080", "-t", "proxy-server:8081", "-k", "test-key", "-r", "50", "-c"] ports: - "8080:8080" - deobfuscating-proxy: # client + proxy-server: build: context: ./../ dockerfile: ./docker/Dockerfile - command: ["obfsproxy", "-l", "0.0.0.0:8081", "-t", "mock-server:80", "-k", "test-key", "-r", "50", "-c"] + command: ["obfsproxy", "-l", "0.0.0.0:8081", "-t", "mock-server:80", "-k", "test-key", "-r", "50", "-s"] ports: - "8081:8081" - mock-server: # target + mock-server: image: nginx:alpine volumes: - ./mock-server.conf:/etc/nginx/conf.d/default.conf diff --git a/pkg/codec/injector_test.go b/pkg/codec/injector_test.go index e0cba3f..714750f 100644 --- a/pkg/codec/injector_test.go +++ b/pkg/codec/injector_test.go @@ -20,16 +20,16 @@ func TestInjector(t *testing.T) { data: []byte("hello world"), }, { - name: "full rate", + name: "100% rate", seed: 42, rate: 100, data: []byte("test data"), }, { - name: "partial rate", + name: "500% rate", seed: 42, rate: 500, - data: []byte("partial injection test"), + data: generateRandomBytes(10000000, 42), }, { name: "empty input", @@ -54,26 +54,8 @@ func TestInjector(t *testing.T) { }) t.Run("Chunked encode/decode", func(t *testing.T) { - encodedChunks := make([]byte, 0) - for i := 0; i < len(tt.data); i += 2 { - end := i + 2 - if end > len(tt.data) { - end = len(tt.data) - } - chunk := encoder(tt.data[i:end]) - encodedChunks = append(encodedChunks, chunk...) - } - - decodedChunks := make([]byte, 0) - for i := 0; i < len(encodedChunks); i += 3 { - end := i + 3 - if end > len(encodedChunks) { - end = len(encodedChunks) - } - chunk := decoder(encodedChunks[i:end]) - decodedChunks = append(decodedChunks, chunk...) - } - + encodedChunks := transformByChunks(encoder, tt.data, 2) + decodedChunks := transformByChunks(decoder, encodedChunks, 3) require.Equal(t, tt.data, decodedChunks, "Chunked encode/decode failed") }) }) diff --git a/pkg/proxy.go b/pkg/proxy.go index 239980f..7574ac7 100644 --- a/pkg/proxy.go +++ b/pkg/proxy.go @@ -63,7 +63,7 @@ func (p *Proxy) handleConnection(clientConn net.Conn) { } } -func (p *Proxy) proxy(dst, src net.Conn, t codec.Transformer) { +func (p *Proxy) proxy(src, dst net.Conn, t codec.Transformer) { buf := make([]byte, 1024) for { n, err := src.Read(buf) diff --git a/pkg/proxy_test.go b/pkg/proxy_test.go index fe3e17f..4f65715 100644 --- a/pkg/proxy_test.go +++ b/pkg/proxy_test.go @@ -1,15 +1,74 @@ package pkg import ( + "bytes" "io" "net" + "net/http" + "net/http/httptest" "testing" "github.com/askolesov/obfsproxy/pkg/codec" "github.com/stretchr/testify/require" ) -func TestProxy(t *testing.T) { +func TestProxyChain(t *testing.T) { + // Create a mock HTTP server that mirrors input + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, _ = io.Copy(w, r.Body) + })) + defer mockServer.Close() + + mockServerAddr := mockServer.Listener.Addr().String() + + // Create codec for proxies + key := []byte("test-key") + xorer, err := codec.NewXorer(key) + require.NoError(t, err) + + injector, err := codec.NewInjector(456, 20) + require.NoError(t, err) + + chain, err := codec.NewChain([]codec.Codec{ + codec.NewInverter(), + xorer, + injector, + }) + require.NoError(t, err) + + // Start proxy 1 (server) + proxyServer := NewProxy("localhost:50502", mockServerAddr, true, chain) + go func() { + _ = proxyServer.Start() + }() + + // Start proxy 2 (client) + proxyClient := NewProxy("localhost:50503", proxyServer.ListenAddr, false, chain) + go func() { + _ = proxyClient.Start() + }() + + // Generate test data (10MB) + dataSize := 10 * 1024 * 1024 // 10MB + testData := make([]byte, dataSize) + for i := range testData { + testData[i] = byte(i * 345876 % 256) + } + + // Send data through proxy chain + resp, err := http.Post("http://"+proxyClient.ListenAddr, "application/octet-stream", bytes.NewReader(testData)) + require.NoError(t, err) + defer resp.Body.Close() + + // Read response + result, err := io.ReadAll(resp.Body) + require.NoError(t, err) + + // Compare input and output + require.Equal(t, testData, result, "Response data should match input data") +} + +func TestProxy_Proxy(t *testing.T) { // Create a proxy instance p := &Proxy{} @@ -31,7 +90,7 @@ func TestProxy(t *testing.T) { codec := codec.NewInverter() // Run proxy in a goroutine - go p.proxy(in2, out1, codec.NewEncoder()) + go p.proxy(out1, in2, codec.NewEncoder()) go func() { // Write test data to server From 83453e5d06490b095bac92adca2db148ebf81b08 Mon Sep 17 00:00:00 2001 From: Alexandr Kolesov Date: Sun, 3 Nov 2024 16:33:26 +0400 Subject: [PATCH 2/3] Add diagram --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index e2d1930..20107de 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,16 @@ obfsproxy is a simple obfuscating proxy designed to provide a layer of obfuscation for network traffic. It works by applying multiple transformations to the data passing through it, making it harder for network monitors to identify the content of the communication. +```mermaid +graph LR + client[VPN Client] -->|Original Traffic| proxy1[Proxy Client\nobfsproxy] + proxy1 -->|Obfuscated Traffic| proxy2[Proxy Server\nobfsproxy] + proxy2 -->|Original Traffic| server[VPN Server] + + style proxy1 fill:#f9f,stroke:#333 + style proxy2 fill:#f9f,stroke:#333 +``` + ## Features - Multiple obfuscation methods: From 9a6b14cb2e7d8cc4fa90d339f2fe57c5c75fd2c1 Mon Sep 17 00:00:00 2001 From: Alexandr Kolesov Date: Sun, 3 Nov 2024 16:36:05 +0400 Subject: [PATCH 3/3] Fix diagram --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 20107de..c5a2c3c 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ obfsproxy is a simple obfuscating proxy designed to provide a layer of obfuscati ```mermaid graph LR - client[VPN Client] -->|Original Traffic| proxy1[Proxy Client\nobfsproxy] - proxy1 -->|Obfuscated Traffic| proxy2[Proxy Server\nobfsproxy] + client[VPN Client] -->|Original Traffic| proxy1[obfsproxy client] + proxy1 -->|Obfuscated Traffic| proxy2[obfsproxy server] proxy2 -->|Original Traffic| server[VPN Server] - style proxy1 fill:#f9f,stroke:#333 - style proxy2 fill:#f9f,stroke:#333 + style proxy1 fill:#ddd,stroke:#333 + style proxy2 fill:#ddd,stroke:#333 ``` ## Features