diff --git a/.github/workflows/build-performance.yml b/.github/workflows/build-performance.yml index 95a58dd1..c8170092 100644 --- a/.github/workflows/build-performance.yml +++ b/.github/workflows/build-performance.yml @@ -111,6 +111,9 @@ jobs: steps: - name: Pre-Cleanup run: | + # stop docker randomly disrupting container network + sudo systemctl restart docker || true + # cleanup previous results if any sudo rm -rf docker/server-data-env/output/* || true - name: Install the github cli diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index bb90d998..798213b1 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -24,7 +24,7 @@ on: default: false required: true push: - branches: [ "main", "testing-*", "issue*" ] + branches: [ "main", "dev-*" ] run-name: Code Integration [${{ github.event_name }}][${{ github.head_ref || github.ref_name }}] rev.${{ github.sha }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ca3cefbc..6a66e222 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,6 @@ on: run-name: Release (version ${{ inputs.version_tag }}, draft ${{ inputs.test_release }}) [${{ github.event_name }}][${{ github.head_ref || github.ref_name }}] - jobs: check-release: runs-on: ubuntu-latest @@ -83,7 +82,7 @@ jobs: - uses: actions/upload-artifact@v4 with: - name: qpep_user_manual + name: qpep_user_manual_b${{ github.run_id }} path: "docs/*.pdf" build-mac-os: @@ -471,13 +470,15 @@ jobs: - name: Download UserManual Artifact uses: actions/download-artifact@v4 with: - name: qpep_user_manual + name: qpep_user_manual_b${{ github.run_id }} - name: Prepare archives run: | cd ${{ github.workspace }} 7z a -tzip qpep_windows_b${{ github.run_id }}.zip ${{ github.workspace }}/installer.msi 7z a -tzip qpep_linux_b${{ github.run_id }}.zip ${{ github.workspace }}/qpep + 7z a -tzip qpep_macos_b${{ github.run_id }}.zip ${{ github.workspace }}/*.pkg + 7z a -tzip qpep_user_manual_b${{ github.run_id }}.zip ${{ github.workspace }}/user_manual.pdf - name: Create Release id: create_release @@ -526,12 +527,12 @@ jobs: asset_content_type: application/zip - name: Attach UserManual Release Asset - id: upload-release-asset + id: upload-usermanual-asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: qpep_user_manual.zip + asset_path: qpep_user_manual_b${{ github.run_id }}.zip asset_name: qpep_user_manual_v${{ github.event.inputs.version_tag }}_b${{ github.run_id }}.zip asset_content_type: application/zip diff --git a/.github/workflows/run-performance.yml b/.github/workflows/run-performance.yml index edd54ba4..d359d2d9 100644 --- a/.github/workflows/run-performance.yml +++ b/.github/workflows/run-performance.yml @@ -166,6 +166,7 @@ jobs: shell: cmd run: | cd docker/speedtests/ + set CGO_ENABLED=0 go test speed_test.go -v -c -o speedtests.test .\speedtests.test -target_url http://${{ inputs.server_public_address }}:8080/target_${{ matrix.download_size }}M.dat ^ @@ -215,7 +216,9 @@ jobs: - name: Reset Proxy if: always() + shell: cmd run: | + set CGO_ENABLED=0 go run docker/speedtests/utils/reset_proxy_util.go - name: Generate results diff --git a/docker/client-env/qpep.yml.tpl b/docker/client-env/qpep.yml.tpl index c21a2a06..e1ebc528 100644 --- a/docker/client-env/qpep.yml.tpl +++ b/docker/client-env/qpep.yml.tpl @@ -1,29 +1,24 @@ -# client -gateway: -port: -apiport: 444 -listenaddress: -listenport: 9443 +client: + local_address: + local_port: 9443 + gateway_address: + gateway_port: -# backend -backend: -ccalgorithm: -ccslowstart: -buffersize: 512 # in Kb +protocol: + backend: + buffersize: 512 + idletimeout: 30s + ccalgorithm: + ccslowstart: -# certificate -certificate: server_cert.pem +security: + certificate: server_cert.pem -# default -acks: 10 -ackdelay: 25 -congestion: 4 -decimate: 4 -decimatetime: 100 -maxretries: 50 -multistream: true -verbose: false -preferproxy: true -varackdelay: 0 -threads: 4 +general: + api_port: 444 + max_retries: 20 + diverter_threads: 4 + use_multistream: true + prefer_proxy: true + verbose: false diff --git a/docker/server-data-env/logstash/Dockerfile b/docker/server-data-env/logstash/Dockerfile index 7bbe44e9..5b0e0609 100644 --- a/docker/server-data-env/logstash/Dockerfile +++ b/docker/server-data-env/logstash/Dockerfile @@ -1,5 +1,5 @@ -FROM opensearchproject/logstash-oss-with-opensearch-output-plugin:8.6.1 +FROM opensearchproject/logstash-oss-with-opensearch-output-plugin:8.9.0 USER "root" WORKDIR /usr/share/logstash/bin diff --git a/docker/server-env/server/config/qpep.yml.tpl b/docker/server-env/server/config/qpep.yml.tpl index 55c36308..bfd59dcc 100644 --- a/docker/server-env/server/config/qpep.yml.tpl +++ b/docker/server-env/server/config/qpep.yml.tpl @@ -1,22 +1,19 @@ -# server -gateway: ${QPEP_GATEWAY} -port: 443 -apiport: 444 -listenaddress: ${QPEP_ADDRESS} -listenport: ${QPEP_PORT} +server: + local_address: ${QPEP_ADDRESS} + local_port: ${QPEP_PORT} -# backend -backend: ${QPEP_BACKEND} -ccalgorithm: ${QPEP_CCA} -ccslowstart: ${QPEP_SLOWSTART} -buffersize: 512 # in Kb +protocol: + backend: ${QPEP_BACKEND} + buffersize: 512 + idletimeout: 30s + ccalgorithm: ${QPEP_CCA} + ccslowstart: ${QPEP_SLOWSTART} -# certificate -certificate: server_cert.pem -certificate_key: server_key.pem +security: + certificate: server_cert.pem + private_key: server_key.pem -# broker settings analytics: enabled: true topic: /qpep @@ -24,15 +21,10 @@ analytics: port: 1883 protocol: tcp -# default -acks: 10 -ackdelay: 25 -congestion: 4 -decimate: 4 -decimatetime: 100 -maxretries: 100 -multistream: true -verbose: false -preferproxy: true -varackdelay: 0 -threads: 4 +general: + api_port: 444 + max_retries: 20 + diverter_threads: 4 + use_multistream: true + prefer_proxy: true + verbose: false diff --git a/docker/speedtests/speed_test.go b/docker/speedtests/speed_test.go index 2e69a580..b61c1e61 100644 --- a/docker/speedtests/speed_test.go +++ b/docker/speedtests/speed_test.go @@ -22,6 +22,7 @@ var targetURL = flag.String("target_url", "", "url to download") var connections = flag.Int("connections_num", 1, "simultaneous tcp connections to make to the server") var expectedSize = flag.Int("expect_mb", 10, "size in MBs of the target file") var debugProxy = flag.String("debug_proxy", "", "url to download") +var debugVerbose = flag.Bool("debug_verbose", false, "print verbose output") var testlog log.Logger @@ -185,7 +186,9 @@ func (s *SpeedTestsConfigSuite) TestRun() { toRead -= int64(read) flagActivity = time.Now().Unix() - test.Logf("#%d read: %d, total: %d, toRead: %d", id, read, resp.ContentLength, toRead) + if *debugVerbose { + test.Logf("#%d read: %d, total: %d, toRead: %d", id, read, resp.ContentLength, toRead) + } if time.Since(start) > 100*time.Millisecond { start = time.Now() //test.Logf("#%d bytes to read: %d", id, toRead) diff --git a/docs/user-manual.md b/docs/user-manual.md index 2c6e17ba..b1aee0e8 100644 --- a/docs/user-manual.md +++ b/docs/user-manual.md @@ -36,15 +36,17 @@ goals are to: \bigskip -The acceleration of the TCP connections is accomplished on the client side by redirecting, in one of two ways, those connections that would have normally be sent over the high latency network: +The acceleration of the TCP connections is accomplished on the client side by redirecting, with following methods, those connections that would have normally be sent over the high latency network: 1. WinDivert Driver (*Windows Only*) -2. Local Proxy +2. IPtables redirect (*Linux Only*) + +3. Local Proxy \bigskip -Both methods do seamlessly bridge, in the form of QUIC streams, the TCP connections originated on the local machine through to a QUIC tunnel which is received on the server machine. +The methods do seamlessly bridge, in the form of QUIC streams, the TCP connections originated on the local machine through to a QUIC tunnel which is received on the server machine. \bigskip @@ -79,7 +81,7 @@ The benefits of using the QUIC protocol over UDP are too numerous to list here, \newpage -QPep supports different backend implementations of the QUIC protocol at the moment: +QPep supports different backend implementations of the QUIC protocol currently: * _[Quicly](https://github.com/h2o/quicly)_ : Through the [Quicly-Go](https://github.com/Project-Faster/quicly-go) wrapper, which supports the new SEARCH CCA slowstart implementation @@ -112,8 +114,6 @@ Refer to https://github.com/Project-Faster/qpep/releases to download the latest ### Windows > Before proceding be sure to have Administrator rights for your local machine -> -> QPep currently only supports client mode on windows currently Once obtained the install.msi file, open it and you'll be greeted by the intro screen: @@ -187,10 +187,7 @@ are created in the installation directory. #### Notes on redirection -On Linux platform, setting the `prefer_proxy: true` value will not work as on the other platforms, proxy settings on Linux cannot -be set dynamically. - -This implies that only `prefer_proxy: false` is actually useful and should be set as such. +On Linux platform, setting the `prefer_proxy: true` parameter has no effect as only the iptables diverter is usable dynamically. \newpage @@ -245,6 +242,8 @@ analytics: topic: data-topic limits: + ignored_ports: + - 3389 # example exclude RDP in TCP mode incoming: - 192.168.1.100: 100K outgoing: @@ -343,7 +342,9 @@ Parameters used to configure the support for sending performance statistics to m #### Limits -Allows to set speed limits for incoming and outgoing connections. +Allows to set limits for incoming and outgoing connections. + +* **ignored_ports** : List of ports to ignore in redirection (implicitly contains port 53 for DNS) * **incoming** : Map composed by key / value pairs where the key is the address of the incoming connection and the value is the bytes per second specification (eg. 100K) @@ -439,7 +440,7 @@ From left to right: Based on these parameters we can draft the two configurations for the client and the server. -Client configuraiton +Client configuration ------ A possible configuration file `qpep.yml` for the client would be: diff --git a/go.mod b/go.mod index 5e9f68ec..1f6580c5 100644 --- a/go.mod +++ b/go.mod @@ -28,13 +28,13 @@ require ( github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d github.com/nyaosorg/go-windows-dbg v0.0.0-20210914123807-2acba179a4e5 github.com/project-faster/dialog v1.1.0 + github.com/project-faster/systray v1.4.0 github.com/segmentio/fasthash v1.0.3 github.com/stretchr/testify v1.8.2 gonum.org/v1/plot v0.12.0 ) require ( - bou.ke/monkey v1.0.2 // indirect git.sr.ht/~sbinet/gg v0.3.1 // indirect github.com/TheTitanrain/w32 v0.0.0-20180517000239-4f5cfb03fabf // indirect github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect @@ -54,7 +54,6 @@ require ( github.com/golang/mock v1.6.0 // indirect github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/gorilla/websocket v1.4.2 // indirect - github.com/kardianos/service v1.2.2 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect diff --git a/service/service.go b/service/service.go index 1545635e..d07d025f 100644 --- a/service/service.go +++ b/service/service.go @@ -280,7 +280,7 @@ func (p *QPepService) Main() error { } // be sure to clear proxy and diverter settings on exit gateway.SetSystemProxy(false) - gateway.SetConnectionDiverter(false, "", "", 0, 0, 0, 0) + gateway.SetConnectionDiverter(false, "", "", 0, 0, 0, 0, []int{}) }() logger.Info("Main") @@ -348,7 +348,7 @@ func (p *QPepService) Logger(errs chan<- error) (kservice.Logger, error) { // runAsClient method wraps the logic to setup the system as client mode func runAsClient(execContext context.Context, cancel context.CancelFunc) { logger.Info("Running Client") - windivert.EnableDiverterLogging(configuration.QPepConfig.General.Verbose) + windivert.EnableDiverterLogging(flags.Globals.Verbose) go client.RunClient(execContext, cancel) } diff --git a/shared/configuration/defaults.go b/shared/configuration/defaults.go index 25fb2c50..01c65bc8 100644 --- a/shared/configuration/defaults.go +++ b/shared/configuration/defaults.go @@ -33,8 +33,9 @@ var DefaultConfig = QPepConfigType{ Verbose: false, }, Limits: &LimitsDefinition{ - Incoming: nil, - Outgoing: nil, + Incoming: nil, + Outgoing: nil, + IgnoredPorts: []int{}, }, Analytics: &AnalyticsDefinition{ Enabled: false, diff --git a/shared/configuration/definitions.go b/shared/configuration/definitions.go index bab0e730..383b8999 100644 --- a/shared/configuration/definitions.go +++ b/shared/configuration/definitions.go @@ -72,6 +72,8 @@ type LimitsDefinition struct { Incoming map[string]string `yaml:"incoming"` // Outgoing (yaml:destinations) key defines the speed limits for outgoing connections Outgoing map[string]string `yaml:"outgoing"` + // IgnoredPorts list of network ports to be excluded from redirection + IgnoredPorts []int `yaml:"ignored_ports"` } // AnalyticsDefinition struct models the configuration values for the analytics client, by default it @@ -143,6 +145,7 @@ func (q *LimitsDefinition) merge(r *LimitsDefinition) { if r != nil { q.Incoming = r.Incoming q.Outgoing = r.Outgoing + q.IgnoredPorts = r.IgnoredPorts } } diff --git a/windivert/WinDivertEngine.cpp b/windivert/WinDivertEngine.cpp index 1c88ff02..d20209e5 100644 --- a/windivert/WinDivertEngine.cpp +++ b/windivert/WinDivertEngine.cpp @@ -34,7 +34,7 @@ UINT32 allowedGatewayInterface = 0; //!< Allowed interface id to be redirected * @param numThreads Number of worker threads to use (1-8) * @return DIVERT_OK if everything ok, an error otherwise */ -int InitializeWinDivertEngine(char* gatewayHost, char* listenHost, int gatewayPort, int listenPort, int numThreads) +int InitializeWinDivertEngine(char* gatewayHost, char* listenHost, int gatewayPort, int listenPort, int numThreads, int* ranges, int len_ranges) { if( gatewayPort < 1 || gatewayPort > 65536 || numThreads < 1 || numThreads > MAX_THREADS ) { logNativeMessageToGo(0, "Cannot initialize windiver engine with provided data, gateway port:%d, threads:%d", gatewayPort, numThreads); @@ -50,8 +50,11 @@ int InitializeWinDivertEngine(char* gatewayHost, char* listenHost, int gatewayPo InitializeSRWLock(&sharedRWLock); // The filter for windivert, captures outbound tcp packets which are not directed at the client listening port - char filterOut[256] = ""; - snprintf(filterOut, 256, FILTER_OUTBOUND, listenPort); + char filterOut[FILTER_MAX] = ""; + int wr = snprintf(filterOut, FILTER_MAX_SIZE, FILTER_OUTBOUND, listenPort ); + for( int i=0; i<1024 && i < len_ranges; i++ ) { + wr += snprintf( filterOut+wr, FILTER_MAX_SIZE-wr, FILTER_IGNORE, ranges[i], ranges[i] ); + } logNativeMessageToGo(0, "Filtering outbound with %s", filterOut); // Open Windivert engine diff --git a/windivert/include/engine.h b/windivert/include/engine.h index 9f929578..a91f7d03 100644 --- a/windivert/include/engine.h +++ b/windivert/include/engine.h @@ -1,6 +1,9 @@ #pragma once -#define FILTER_OUTBOUND "!impostor and ip.SrcAddr!=127.0.0.1 and ip.DstAddr!=127.0.0.1 and tcp and tcp.DstPort!=%d and tcp.DstPort!=53" +#define FILTER_MAX_SIZE (65 * 1024) +#define FILTER_MAX (1024) +#define FILTER_OUTBOUND "!impostor && ip.SrcAddr!=127.0.0.1 && ip.DstAddr!=127.0.0.1 && tcp && tcp.DstPort!=%d" +#define FILTER_IGNORE " && tcp.DstPort!=%d && tcp.SrcPort!=%d" #define MAXBUF WINDIVERT_MTU_MAX #define INET6_ADDRSTRLEN 45 diff --git a/windivert/include/windivert_wrapper.h b/windivert/include/windivert_wrapper.h index 301a6a23..405d823b 100644 --- a/windivert/include/windivert_wrapper.h +++ b/windivert/include/windivert_wrapper.h @@ -21,7 +21,7 @@ enum { DIVERT_ERROR_NOT_OPEN = 4, //!< Connection is not open so no state available }; -extern int InitializeWinDivertEngine(char* gatewayHost, char* listenHost, int gatewayPort, int listenPort, int numThreads); +extern int InitializeWinDivertEngine(char* gatewayHost, char* listenHost, int gatewayPort, int listenPort, int numThreads, int* ranges, int len_ranges); extern int CloseWinDivertEngine(); extern void logMessageToGo( char* message ); extern void EnableMessageOutputToGo( int enabled ); diff --git a/windivert/windivert.go b/windivert/windivert.go index 4bb30458..ed73c178 100644 --- a/windivert/windivert.go +++ b/windivert/windivert.go @@ -14,7 +14,8 @@ import ( // * _listenPort_ Packets must have source from this port // * _numThreads_ Number of threads to use for the packet capturing routines // * _gatewayInterfaces_ Only accept divert of packets of this interface id -func InitializeWinDivertEngine(gatewayAddr, listenAddr string, gatewayPort, listenPort, numThreads int, gatewayInterfaces int64) int { +func InitializeWinDivertEngine(gatewayAddr, listenAddr string, gatewayPort, listenPort, numThreads int, gatewayInterfaces int64, + ignoredPorts []int) int { log.Println("WARNING: windivert package compiled without CGO") // message to check for failing CGO return DIVERT_OK } diff --git a/windivert/windivert_darwin.go b/windivert/windivert_darwin.go index 85c760e3..488e0250 100644 --- a/windivert/windivert_darwin.go +++ b/windivert/windivert_darwin.go @@ -11,7 +11,11 @@ import "C" // * _listenPort_ Packets must have source from this port // * _numThreads_ Number of threads to use for the packet capturing routines // * _gatewayInterfaces_ Only accept divert of packets of this interface id -func InitializeWinDivertEngine(gatewayAddr, listenAddr string, gatewayPort, listenPort, numThreads int, gatewayInterfaces int64) int { +func InitializeWinDivertEngine(gatewayAddr, listenAddr string, + gatewayPort, listenPort, numThreads int, + gatewayInterface int64, + ignoredPorts []int) int { + return DIVERT_OK } diff --git a/windivert/windivert_linux.go b/windivert/windivert_linux.go index af2f4eff..2cf68cc6 100644 --- a/windivert/windivert_linux.go +++ b/windivert/windivert_linux.go @@ -12,7 +12,11 @@ import "C" // * _listenPort_ Packets must have source from this port // * _numThreads_ Number of threads to use for the packet capturing routines // * _gatewayInterfaces_ Only accept divert of packets of this interface id -func InitializeWinDivertEngine(gatewayAddr, listenAddr string, gatewayPort, listenPort, numThreads int, gatewayInterfaces int64) int { +func InitializeWinDivertEngine(gatewayAddr, listenAddr string, + gatewayPort, listenPort, numThreads int, + gatewayInterface int64, + ignoredPorts []int) int { + return DIVERT_OK } diff --git a/windivert/windivert_other_test.go b/windivert/windivert_other_test.go index a725823b..907546ea 100644 --- a/windivert/windivert_other_test.go +++ b/windivert/windivert_other_test.go @@ -46,7 +46,7 @@ func (s *WinDivertSuite) TestInitializeWinDivertEngine() { code := InitializeWinDivertEngine( addr, addr, configuration.QPepConfig.General.APIPort, 445, - 4, 0) + 4, 0, []int{}) assert.Equal(t, DIVERT_OK, code) } @@ -59,7 +59,7 @@ func (s *WinDivertSuite) TestInitializeWinDivertEngine_Fail() { code := InitializeWinDivertEngine( addr, addr, 0, 0, - 4, 0) + 4, 0, []int{80}) assert.Equal(t, DIVERT_OK, code) // ok because it's not implemented on linux } @@ -72,7 +72,7 @@ func (s *WinDivertSuite) TestCloseWinDivertEngine() { code := InitializeWinDivertEngine( addr, addr, configuration.QPepConfig.General.APIPort, 445, - 4, 0) + 4, 0, []int{80}) assert.Equal(t, DIVERT_OK, code) diff --git a/windivert/windivert_windows.go b/windivert/windivert_windows.go index 71830d15..867c76af 100644 --- a/windivert/windivert_windows.go +++ b/windivert/windivert_windows.go @@ -21,10 +21,25 @@ import ( // * _listenPort_ Packets must have source from this port // * _numThreads_ Number of threads to use for the packet capturing routines // * _gatewayInterfaces_ Only accept divert of packets of this interface id -func InitializeWinDivertEngine(gatewayAddr, listenAddr string, gatewayPort, listenPort, numThreads int, gatewayInterface int64) int { +// * _portRanges_ List of ports to ignore +func InitializeWinDivertEngine(gatewayAddr, listenAddr string, + gatewayPort, listenPort, numThreads int, + gatewayInterface int64, + ignoredPorts []int) int { + + ports := make([]C.int, 0, len(ignoredPorts)) + ports = append(ports, C.int(53)) // DNS + + for i := 0; i < len(ignoredPorts); i++ { + if ignoredPorts[i] < 0 || ignoredPorts[i] >= 65536 { + return DIVERT_ERROR_FAILED + } + ports = append(ports, C.int(ignoredPorts[i])) + } + gatewayStr := C.CString(gatewayAddr) listenStr := C.CString(listenAddr) - response := int(C.InitializeWinDivertEngine(gatewayStr, listenStr, C.int(gatewayPort), C.int(listenPort), C.int(numThreads))) + response := int(C.InitializeWinDivertEngine(gatewayStr, listenStr, C.int(gatewayPort), C.int(listenPort), C.int(numThreads), (*C.int)(&ports[0]), C.int(len(ports)))) if response != DIVERT_OK { return response } diff --git a/windivert/windivert_windows_test.go b/windivert/windivert_windows_test.go index 65cc3abe..912671ee 100644 --- a/windivert/windivert_windows_test.go +++ b/windivert/windivert_windows_test.go @@ -64,7 +64,7 @@ func (s *WinDivertSuite) TestInitializeWinDivertEngine() { code := InitializeWinDivertEngine( "127.0.0.1", "127.0.0.2", configuration.QPepConfig.General.APIPort, 445, - 4, itFaces[0]) + 4, itFaces[0], []int{80}) assert.Equal(t, DIVERT_OK, code) } @@ -77,7 +77,7 @@ func (s *WinDivertSuite) TestInitializeWinDivertEngine_Fail() { code := InitializeWinDivertEngine( "127.0.0.1", "127.0.0.2", 0, 0, - 4, itFaces[0]) + 4, itFaces[0], []int{80}) assert.NotEqual(t, DIVERT_OK, code) } @@ -90,7 +90,7 @@ func (s *WinDivertSuite) TestCloseWinDivertEngine() { code := InitializeWinDivertEngine( "127.0.0.1", "127.0.0.2", configuration.QPepConfig.General.APIPort, 445, - 4, itFaces[0]) + 4, itFaces[0], []int{80}) assert.Equal(t, DIVERT_OK, code) diff --git a/workers/client/client.go b/workers/client/client.go index 9308b2c5..513465a2 100644 --- a/workers/client/client.go +++ b/workers/client/client.go @@ -277,6 +277,13 @@ func validateConfiguration() { configuration.AssertParamNumeric("auto-redirected interfaces", len(clientAdditional.RedirectedInterfaces), 0, 256) + switch runtime.GOOS { + case "linux": + logger.Info("Platform forced prefer_proxy to false\n") + configGeneral.PreferProxy = false + break + } + // validation ok logger.Info("Client configuration validation OK\n") } diff --git a/workers/client/client_impl_linux.go b/workers/client/client_impl_linux.go index 0b77d9a2..32bc6377 100644 --- a/workers/client/client_impl_linux.go +++ b/workers/client/client_impl_linux.go @@ -8,10 +8,16 @@ import ( // initDiverter method wraps the logic for initializing the windiverter engine, returns true if the diverter // succeeded initialization and false otherwise func initDiverter() bool { + clientConfig := configuration.QPepConfig.Client + filteredPorts := configuration.QPepConfig.Limits.IgnoredPorts + + listenPort := clientConfig.LocalListenPort + listenHost := clientConfig.LocalListeningAddress + redirected = gateway.SetConnectionDiverter(true, "", - configuration.QPepConfig.Client.LocalListeningAddress, 0, - configuration.QPepConfig.Client.LocalListenPort, 0, - 0) + listenHost, 0, + listenPort, 0, + 0, filteredPorts) return redirected } @@ -19,7 +25,7 @@ func initDiverter() bool { // stopDiverter method wraps the calls for stopping the diverter func stopDiverter() { redirected = false - gateway.SetConnectionDiverter(false, "", "", 0, 0, 0, 0) + gateway.SetConnectionDiverter(false, "", "", 0, 0, 0, 0, []int{}) } // initProxy method wraps the calls for initializing the proxy diff --git a/workers/client/client_impl_windows.go b/workers/client/client_impl_windows.go index 89204265..bb68fcc9 100644 --- a/workers/client/client_impl_windows.go +++ b/workers/client/client_impl_windows.go @@ -12,6 +12,7 @@ import ( func initDiverter() bool { generalConfig := configuration.QPepConfig.General clientConfig := configuration.QPepConfig.Client + filteredPorts := configuration.QPepConfig.Limits.IgnoredPorts gatewayHost := clientConfig.GatewayHost gatewayPort := clientConfig.GatewayPort @@ -34,13 +35,13 @@ func initDiverter() bool { } } - redirected = gateway.SetConnectionDiverter(true, gatewayHost, listenHost, gatewayPort, listenPort, threads, redirectedInetID) + redirected = gateway.SetConnectionDiverter(true, gatewayHost, listenHost, gatewayPort, listenPort, threads, redirectedInetID, filteredPorts) return redirected } // stopDiverter method wraps the calls for stopping the diverter func stopDiverter() { - gateway.SetConnectionDiverter(false, "", "", 0, 0, 0, 0) + gateway.SetConnectionDiverter(false, "", "", 0, 0, 0, 0, []int{}) redirected = false } diff --git a/workers/client/client_network.go b/workers/client/client_network.go index b421e69f..22abbc2d 100644 --- a/workers/client/client_network.go +++ b/workers/client/client_network.go @@ -33,6 +33,8 @@ var ( newSessionLock sync.RWMutex // quicSession listening quic connection to the server quicSession backend.QuicBackendConnection + + filteredPorts map[int]struct{} = nil ) func setLinger(c net.Conn) { @@ -87,12 +89,30 @@ func handleTCPConn(tcpConn net.Conn) { var proxyRequest *http.Request var errProxy error if !diverted { + if filteredPorts == nil { + filteredPorts = make(map[int]struct{}) + for _, p := range configuration.QPepConfig.Limits.IgnoredPorts { + filteredPorts[p] = struct{}{} + } + } + // proxy open connection proxyRequest, errProxy = handleProxyOpenConnection(tcpConn) if errProxy == errors.ErrProxyCheckRequest { logger.Info("Checked for proxy usage, closing.") return } + + // check direct connection + if proxyRequest != nil { + _, port, _ := getAddressPortFromHost(proxyRequest.Host) + if _, ok := filteredPorts[port]; ok { + logger.Info("opening proxy direct connection") + handleProxyedRequest(proxyRequest, nil, tcpConn, nil) + return + } + } + logger.OnError(errProxy, "opening proxy connection") } @@ -351,6 +371,12 @@ func handleProxyedRequest(req *http.Request, header *protocol.QPepHeader, tcpCon logger.Info("HOST: %s", req.Host) + // direct + if header == nil { + handleDirectConnection(tcpConn, req, fmt.Sprintf("%s:%d", address, port)) + break + } + header.DestAddr = &net.TCPAddr{ IP: address, Port: port, @@ -384,16 +410,6 @@ func handleProxyedRequest(req *http.Request, header *protocol.QPepHeader, tcpCon logger.Info("HOST: %s", req.Host) - header.DestAddr = &net.TCPAddr{ - IP: address, - Port: port, - } - - if header.DestAddr.IP.String() == clientConfig.GatewayHost { - header.Flags |= protocol.QPEP_LOCALSERVER_DESTINATION - } - logger.Info("Proxied connection flags : %d %d", header.Flags, header.Flags&protocol.QPEP_LOCALSERVER_DESTINATION) - t := http.Response{ Status: "200 Connection established", StatusCode: http.StatusOK, @@ -408,6 +424,21 @@ func handleProxyedRequest(req *http.Request, header *protocol.QPepHeader, tcpCon t.Write(tcpConn) + if header == nil { + handleDirectConnection(tcpConn, nil, fmt.Sprintf("%s:%d", address, port)) + break + } + + header.DestAddr = &net.TCPAddr{ + IP: address, + Port: port, + } + + if header.DestAddr.IP.String() == clientConfig.GatewayHost { + header.Flags |= protocol.QPEP_LOCALSERVER_DESTINATION + } + logger.Info("Proxied connection flags : %d %d", header.Flags, header.Flags&protocol.QPEP_LOCALSERVER_DESTINATION) + logger.Info("(Proxied) Sending QPEP header to server, SourceAddr: %v / DestAddr: %v / ID: %v", header.SourceAddr, header.DestAddr, stream.ID()) _, err := stream.Write(header.ToBytes()) @@ -548,6 +579,55 @@ func handleQuicToTcp(ctx context.Context, streamWait *sync.WaitGroup, dst net.Co } } +func handleDirectConnection(conn net.Conn, req *http.Request, dest string) { + defer conn.Close() + + logger.Info("Start direct connection: %v -> %v -> %v", conn.RemoteAddr(), conn.LocalAddr(), dest) + defer logger.Info("End direct connection: %v -> %v -> %v", conn.RemoteAddr(), conn.LocalAddr(), dest) + + // + dialer := &net.Dialer{ + Timeout: 5 * time.Second, + KeepAlive: 3 * time.Second, + DualStack: true, + } + + c, err := dialer.Dial("tcp", dest) + if err != nil { + logger.Error("ERROR: %v", err) + return + } + defer c.Close() + + if req != nil { + req.Write(c) + } + + wg := &sync.WaitGroup{} + wg.Add(2) + + go func() { + defer func() { + _ = recover() + wg.Done() + }() + conn.SetDeadline(time.Now().Add(10 * time.Second)) + c.SetDeadline(time.Now().Add(10 * time.Second)) + _, _ = io.Copy(conn, c) + }() + go func() { + defer func() { + _ = recover() + wg.Done() + }() + conn.SetDeadline(time.Now().Add(10 * time.Second)) + c.SetDeadline(time.Now().Add(10 * time.Second)) + _, _ = io.Copy(c, conn) + }() + + wg.Wait() +} + func checkProxyTestConnection(host string) bool { return strings.Contains(host, "qpep-client-proxy-check") } diff --git a/workers/client/client_network_linux_test.go b/workers/client/client_network_linux_test.go index 29219785..40962e02 100644 --- a/workers/client/client_network_linux_test.go +++ b/workers/client/client_network_linux_test.go @@ -100,7 +100,7 @@ func (s *ClientNetworkSuite) TestGetAddressPortFromHost_Invalid() { } func (s *ClientNetworkSuite) TestInitialCheckConnection_PreferProxy() { - s.T().Skipf("Proxy set on linux not implemented yet") + s.T().Skipf("Proxy set not supported on linux") return validateConfiguration() @@ -122,11 +122,11 @@ func (s *ClientNetworkSuite) TestInitialCheckConnection_PreferProxy() { } func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferDiverterKeepRedirect() { - s.T().Skipf("Proxy set on linux not implemented yet") + s.T().Skipf("Proxy set not supported on linux") return var calledInit = false - monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64) int { + monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64, []int) int { calledInit = true return windivert.DIVERT_OK }) @@ -148,7 +148,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferDiverterKeepRedirec } func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferDiverterSwitchToProxy() { - s.T().Skipf("Proxy set on linux not implemented yet") + s.T().Skipf("Proxy set not supported on linux") return var calledInit = false @@ -181,7 +181,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferDiverterSwitchToPro } func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferDiverterExhausted() { - s.T().Skipf("Proxy set on linux not implemented yet") + s.T().Skipf("Proxy set not supported on linux") return monkey.Patch(gateway.SetSystemProxy, func(active bool) { @@ -206,7 +206,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferDiverterExhausted() } func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxyKeepRedirect() { - s.T().Skipf("Proxy set on linux not implemented yet") + s.T().Skipf("Proxy set not supported on linux") return validateConfiguration() @@ -233,7 +233,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxyKeepRedirect() } func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxySwitchToProxy_OK() { - s.T().Skipf("Proxy set on linux not implemented yet") + s.T().Skipf("Proxy set not supported on linux") return validateConfiguration() @@ -249,7 +249,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxySwitchToProxy_ } }) var calledInit = false - monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64) int { + monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64, []int) int { calledInit = true return windivert.DIVERT_OK }) @@ -263,7 +263,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxySwitchToProxy_ } func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxySwitchToProxy_Fail() { - s.T().Skipf("Proxy set on linux not implemented yet") + s.T().Skipf("Proxy set not supported on linux") return validateConfiguration() @@ -279,7 +279,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxySwitchToProxy_ } }) var calledInit = false - monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64) int { + monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64, []int) int { calledInit = true return windivert.DIVERT_ERROR_FAILED }) @@ -293,7 +293,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxySwitchToProxy_ } func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxyExhausted() { - s.T().Skipf("Proxy set on linux not implemented yet") + s.T().Skipf("Proxy set not supported on linux") return validateConfiguration() diff --git a/workers/client/client_network_windows_test.go b/workers/client/client_network_windows_test.go index 0399d86f..a8ad4f85 100644 --- a/workers/client/client_network_windows_test.go +++ b/workers/client/client_network_windows_test.go @@ -120,7 +120,7 @@ func (s *ClientNetworkSuite) TestInitialCheckConnection_PreferProxy() { func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferDiverterKeepRedirect() { var calledInit = false - monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64) int { + monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64, []int) int { calledInit = true return windivert.DIVERT_OK }) @@ -231,7 +231,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxySwitchToProxy_ } }) var calledInit = false - monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64) int { + monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64, []int) int { calledInit = true return windivert.DIVERT_OK }) @@ -258,7 +258,7 @@ func (s *ClientNetworkSuite) TestFailedCheckConnection_PreferProxySwitchToProxy_ } }) var calledInit = false - monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64) int { + monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64, []int) int { calledInit = true return windivert.DIVERT_ERROR_FAILED }) diff --git a/workers/client/client_patch_test.go b/workers/client/client_patch_test.go index 9d033c14..f9868cd2 100644 --- a/workers/client/client_patch_test.go +++ b/workers/client/client_patch_test.go @@ -55,7 +55,7 @@ func (s *ClientSuite) TestHandleServices() { }() wg2 := &sync.WaitGroup{} - wg2.Add(3) + wg2.Add(2) var calledInitialCheck = false monkey.Patch(initialCheckConnection, func() { @@ -76,15 +76,6 @@ func (s *ClientSuite) TestHandleServices() { ServerVersion: "0.1.0", } }) - var calledStatsUpdate = false - monkey.Patch(clientStatisticsUpdate, func(_ string, _ string, _ int, pubAddress string) bool { - assert.Equal(s.T(), "172.20.50.150", pubAddress) - if !calledStatsUpdate { - calledStatsUpdate = true - wg2.Done() - } - return true - }) wg := &sync.WaitGroup{} wg.Add(1) @@ -102,7 +93,7 @@ func (s *ClientSuite) TestHandleServices() { }() select { - case <-time.After(10 * time.Second): + case <-time.After((GATEWAY_CHECK_WAIT * 3) + (1 * time.Second)): s.T().Logf("Test Timed out waiting for routines to finish") s.T().FailNow() return @@ -112,7 +103,6 @@ func (s *ClientSuite) TestHandleServices() { assert.True(s.T(), calledInitialCheck) assert.True(s.T(), calledGatewayCheck) - assert.True(s.T(), calledStatsUpdate) } func (s *ClientSuite) TestHandleServices_PanicCheck() { @@ -181,7 +171,7 @@ func (s *ClientSuite) TestHandleServices_FailGateway() { }() select { - case <-time.After(10 * time.Second): + case <-time.After((GATEWAY_CHECK_WAIT * 3) + (1 * time.Second)): s.T().Logf("Test Timed out waiting for routines to finish") s.T().FailNow() return @@ -197,7 +187,7 @@ func (s *ClientSuite) TestHandleServices_FailGateway() { func (s *ClientSuite) TestHandleServices_FailStatistics() { wg2 := &sync.WaitGroup{} - wg2.Add(4) + wg2.Add(3) var calledInitialCheck = false monkey.Patch(initialCheckConnection, func() { if !calledInitialCheck { @@ -217,15 +207,6 @@ func (s *ClientSuite) TestHandleServices_FailStatistics() { ServerVersion: "0.1.0", } }) - var calledStatsUpdate = false - monkey.Patch(clientStatisticsUpdate, func(_ string, _ string, _ int, pubAddress string) bool { - assert.Equal(s.T(), "172.20.50.150", pubAddress) - if !calledStatsUpdate { - calledStatsUpdate = true - wg2.Done() - } - return false - }) var calledFailedConnectionFirst = false var calledFailedConnectionSecond = false monkey.Patch(failedCheckConnection, func() bool { @@ -266,7 +247,6 @@ func (s *ClientSuite) TestHandleServices_FailStatistics() { assert.True(s.T(), calledInitialCheck) assert.True(s.T(), calledGatewayCheck) - assert.True(s.T(), calledStatsUpdate) assert.True(s.T(), calledFailedConnectionFirst) assert.True(s.T(), calledFailedConnectionSecond) } @@ -304,41 +284,45 @@ func (s *ClientSuite) TestStopProxy() { } func (s *ClientSuite) TestInitDiverter() { - if runtime.GOOS != "windows" { - assert.False(s.T(), initDiverter()) - return - } - monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64) int { - return windivert.DIVERT_OK + redirected = false + monkey.Patch(gateway.SetConnectionDiverter, func(active bool, _ string, _ string, _ int, _ int, _ int, _ int64, _ []int) bool { + assert.True(s.T(), active) + redirected = true + return true }) assert.True(s.T(), initDiverter()) + assert.True(s.T(), redirected) } func (s *ClientSuite) TestInitDiverter_Fail() { - if runtime.GOOS != "windows" { - assert.False(s.T(), initDiverter()) - return - } - monkey.Patch(windivert.InitializeWinDivertEngine, func(string, string, int, int, int, int64) int { - return windivert.DIVERT_ERROR_ALREADY_INIT + redirected = true + monkey.Patch(gateway.SetConnectionDiverter, func(active bool, _ string, _ string, _ int, _ int, _ int, _ int64, _ []int) bool { + assert.True(s.T(), active) + redirected = false + return false }) assert.False(s.T(), initDiverter()) + assert.False(s.T(), redirected) } func (s *ClientSuite) TestStopDiverter() { - if runtime.GOOS != "windows" { - assert.False(s.T(), initDiverter()) - return - } - monkey.Patch(windivert.CloseWinDivertEngine, func() int { - return windivert.DIVERT_OK + redirected = true + monkey.Patch(gateway.SetConnectionDiverter, func(active bool, _ string, _ string, _ int, _ int, _ int, _ int64, _ []int) bool { + assert.False(s.T(), active) + redirected = false + return false }) stopDiverter() assert.False(s.T(), redirected) } -func (s *ClientSuite) TestInitialCheckConnection() { - configuration.QPepConfig.General.PreferProxy = false +func (s *ClientSuite) TestInitialCheckConnection_Proxy() { + if runtime.GOOS == "linux" { + s.T().Skipf("Proxy set not supported on linux") + return + } + + configuration.QPepConfig.General.PreferProxy = true validateConfiguration() monkey.Patch(gateway.SetSystemProxy, func(active bool) { @@ -347,14 +331,34 @@ func (s *ClientSuite) TestInitialCheckConnection() { gateway.ProxyAddress, _ = url.Parse("http://127.0.0.1:8080") }) + redirected = false assert.False(s.T(), gateway.UsingProxy) initialCheckConnection() - assert.False(s.T(), gateway.UsingProxy) - assert.Nil(s.T(), gateway.ProxyAddress) + assert.True(s.T(), gateway.UsingProxy) + assert.NotNil(s.T(), gateway.ProxyAddress) + + assert.False(s.T(), redirected) +} + +func (s *ClientSuite) TestInitialCheckConnection_Diverter() { + configuration.QPepConfig.General.PreferProxy = false + validateConfiguration() + if runtime.GOOS == "linux" { + assert.False(s.T(), configuration.QPepConfig.General.PreferProxy) + } + redirected = false + monkey.Patch(initDiverter, func() bool { + redirected = true + return true + }) + + assert.False(s.T(), gateway.UsingProxy) initialCheckConnection() assert.False(s.T(), gateway.UsingProxy) assert.Nil(s.T(), gateway.ProxyAddress) + + assert.True(s.T(), redirected) } func (s *ClientSuite) TestGatewayStatusCheck() { diff --git a/workers/client/client_test.go b/workers/client/client_test.go index 82740219..de15240b 100644 --- a/workers/client/client_test.go +++ b/workers/client/client_test.go @@ -20,6 +20,8 @@ import ( "github.com/stretchr/testify/suite" "math/big" "net" + "net/url" + "runtime" "sync" "testing" "time" @@ -44,6 +46,8 @@ func (s *ClientSuite) BeforeTest(_, testName string) { gateway.UsingProxy = false gateway.ProxyAddress = nil + GATEWAY_CHECK_WAIT = 1 * time.Second + configuration.QPepConfig = configuration.QPepConfigType{} configuration.QPepConfig.Merge(&configuration.DefaultConfig) @@ -57,7 +61,7 @@ func (s *ClientSuite) BeforeTest(_, testName string) { configuration.QPepConfig.General.MultiStream = true configuration.QPepConfig.General.WinDivertThreads = 4 configuration.QPepConfig.General.PreferProxy = true - configuration.QPepConfig.General.Verbose = true + configuration.QPepConfig.General.Verbose = false } func (s *ClientSuite) AfterTest(_, testName string) { diff --git a/workers/gateway/gateway_interface_linux.go b/workers/gateway/gateway_interface_linux.go index c69fcf62..ab068c8c 100644 --- a/workers/gateway/gateway_interface_linux.go +++ b/workers/gateway/gateway_interface_linux.go @@ -7,32 +7,14 @@ import ( "github.com/jackpal/gateway" "net" "net/url" + "strconv" ) -const ( - // 25 smtp - // 21 ftp - // 22 ssh - // 23 telnet - // 53 dns - // 67, 68. dhcp - // 80, 443 http/https - // 143 imap - // 161, 162 snmp - // 636 ldap - // 989, 990 sftp - // 1025:65535 other tcp - PROTOCOLS_PORTS_LIST = `21:25,53,67,68,80,443,143,636,161:162,989:990,1025:65535` -) - -var redirectOn = false +var ( + redirectOn = false -func getRouteListeningAddresses() []string { - if defaultListeningAddress == "" { - defaultListeningAddress = "127.0.0.1" - } - return []string{defaultListeningAddress} -} + defaultPortsIgnored = []int{53} +) func getRouteGatewayInterfaces() ([]int64, []string, error) { defaultIP, err := gateway.DiscoverInterface() @@ -50,11 +32,13 @@ func GetSystemProxyEnabled() (bool, *url.URL) { return false, nil } -func SetConnectionDiverter(active bool, gatewayAddr, listenAddr string, gatewayPort, listenPort, numThreads int, gatewayInterface int64) bool { +func SetConnectionDiverter(active bool, gatewayAddr, listenAddr string, gatewayPort, listenPort, numThreads int, + gatewayInterface int64, ignoredPorts []int) bool { redirectOn = active if active { - logger.Info("Setting system iptables\n") + logger.Info("Initializing iptables: %v %v %v %v %v %v %v\n", + gatewayAddr, listenAddr, gatewayPort, listenPort, numThreads, gatewayInterface) _, err, _ := shared.RunCommand("bash", "-c", "iptables -P FORWARD ACCEPT") if err != nil { @@ -62,15 +46,30 @@ func SetConnectionDiverter(active bool, gatewayAddr, listenAddr string, gatewayP return false } + var allIgnoredPorts = append([]int{}, defaultPortsIgnored...) + allIgnoredPorts = append(allIgnoredPorts, gatewayPort) + allIgnoredPorts = append(allIgnoredPorts, listenPort) + allIgnoredPorts = append(allIgnoredPorts, ignoredPorts...) + + var allIgnoredStr = "" + for i := 0; i < len(allIgnoredPorts); i++ { + if i == 0 { + allIgnoredStr = strconv.FormatInt(int64(allIgnoredPorts[i]), 10) + continue + } + + allIgnoredStr += "," + strconv.FormatInt(int64(allIgnoredPorts[i]), 10) + } + _, err, _ = shared.RunCommand("bash", "-c", - fmt.Sprintf("iptables -t nat -A OUTPUT -j DNAT -p tcp --to-destination %s:%d -m multiport --destination-ports %s", listenAddr, listenPort, PROTOCOLS_PORTS_LIST)) + fmt.Sprintf("iptables -t nat -A OUTPUT -j DNAT -p tcp --to-destination %s:%d -m multiport ! --dports %s", listenAddr, listenPort, allIgnoredStr)) if err != nil { logger.Error("%v\n", err) return false } _, err, _ = shared.RunCommand("bash", "-c", - fmt.Sprintf("iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp -m multiport --destination-ports %s", PROTOCOLS_PORTS_LIST)) + fmt.Sprintf("iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp -m multiport ! --dports %s", allIgnoredStr)) if err != nil { logger.Error("%v\n", err) return false diff --git a/workers/gateway/gateway_interface_windows.go b/workers/gateway/gateway_interface_windows.go index ced10189..a67bfa3f 100644 --- a/workers/gateway/gateway_interface_windows.go +++ b/workers/gateway/gateway_interface_windows.go @@ -284,10 +284,16 @@ func preloadRegistryKeysForUsers() { } } -func SetConnectionDiverter(active bool, gatewayAddr, listenAddr string, gatewayPort, listenPort, numThreads int, gatewayInterface int64) bool { +func SetConnectionDiverter(active bool, gatewayAddr, listenAddr string, + gatewayPort, listenPort, numThreads int, + gatewayInterface int64, ignoredPorts []int) bool { + if active { - logger.Info("Initializing WinDivert: %v %v %v %v %v %v\n", gatewayAddr, listenAddr, gatewayPort, listenPort, numThreads, gatewayInterface) - code := windivert.InitializeWinDivertEngine(gatewayAddr, listenAddr, gatewayPort, listenPort, numThreads, gatewayInterface) + logger.Info("Initializing WinDivert: %v %v %v %v %v %v %v\n", + gatewayAddr, listenAddr, gatewayPort, listenPort, numThreads, gatewayInterface, ignoredPorts) + + code := windivert.InitializeWinDivertEngine(gatewayAddr, listenAddr, gatewayPort, + listenPort, numThreads, gatewayInterface, ignoredPorts) logger.Info("WinDivert code: %v\n", code) if code != windivert.DIVERT_OK { logger.Error("Could not initialize WinDivert engine, code %d\n", code) diff --git a/workers/gateway/network_config_test.go b/workers/gateway/network_config_test.go index 05fb29f7..0d7a1d10 100644 --- a/workers/gateway/network_config_test.go +++ b/workers/gateway/network_config_test.go @@ -38,7 +38,7 @@ func (s *NetworkConfigSuite) TestGetLanListeningAddresses_Default() { detectedGatewayInterfaces = []int64{1} addrs, interfaces := GetLanListeningAddresses() - assert.Len(t, addrs, 1) + assertArrayEqualsString(t, []string{"127.0.0.1"}, addrs) assertArrayEqualsInt64(t, []int64{1}, interfaces) }