From f1d8026691f6fbefbe0fd79eb63c9be8684ccca8 Mon Sep 17 00:00:00 2001 From: Eli Yukelzon Date: Mon, 11 Nov 2024 17:32:37 +0100 Subject: [PATCH] initial stab at v2ray --- go.mod | 41 +++---- go.sum | 52 +++++---- tlslistener/clienthelloconn.go | 3 +- v2ray/fixtures/socks_client.json | 25 +++++ v2ray/fixtures/socks_server.json | 20 ++++ v2ray/fixtures/vmess_client.json | 29 +++++ v2ray/fixtures/vmess_server.json | 29 +++++ v2ray/listener.go | 187 +++++++++---------------------- v2ray/listener_test.go | 103 +++++++++++++++++ 9 files changed, 306 insertions(+), 183 deletions(-) create mode 100644 v2ray/fixtures/socks_client.json create mode 100644 v2ray/fixtures/socks_server.json create mode 100644 v2ray/fixtures/vmess_client.json create mode 100644 v2ray/fixtures/vmess_server.json create mode 100644 v2ray/listener_test.go diff --git a/go.mod b/go.mod index 5badcb39..ebd77a77 100644 --- a/go.mod +++ b/go.mod @@ -51,10 +51,11 @@ require ( github.com/mitchellh/panicwrap v1.0.0 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/refraction-networking/utls v1.6.7 + github.com/refraction-networking/water v0.7.0-alpha github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 github.com/spaolacci/murmur3 v1.1.0 github.com/stretchr/testify v1.9.0 - github.com/v2fly/v2ray-core/v5 v5.21.0 + github.com/v2fly/v2ray-core/v5 v5.22.0 github.com/vharitonsky/iniflags v0.0.0-20180513140207-a33cd0b5f3de github.com/xtaci/smux v1.5.24 gitlab.com/yawning/obfs4.git v0.0.0-20220204003609-77af0cba934d @@ -66,9 +67,8 @@ require ( go.opentelemetry.io/otel/sdk v1.19.0 go.opentelemetry.io/otel/sdk/metric v1.19.0 go.opentelemetry.io/otel/trace v1.19.0 - go.uber.org/mock v0.3.0 - golang.org/x/net v0.23.0 - golang.org/x/net v0.30.0 + go.uber.org/mock v0.4.0 + golang.org/x/net v0.31.0 google.golang.org/api v0.148.0 ) @@ -79,14 +79,14 @@ require ( github.com/OperatorFoundation/go-bloom v1.0.1 // indirect github.com/OperatorFoundation/go-shadowsocks2 v1.2.1 // indirect github.com/Yawning/chacha20 v0.0.0-20170904085104-e3b1f968fc63 // indirect - github.com/adrg/xdg v0.5.0 // indirect + github.com/adrg/xdg v0.5.1 // indirect github.com/aead/cmac v0.0.0-20160719120800-7af84192f0b1 // indirect github.com/aead/ecdh v0.2.0 // indirect github.com/andybalholm/brotli v1.0.6 // indirect github.com/apernet/hysteria/core/v2 v2.4.5 // indirect github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e // indirect - github.com/andybalholm/brotli v1.0.6 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/blang/vfs v1.0.0 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect github.com/bufbuild/protocompile v0.14.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect @@ -100,7 +100,6 @@ require ( github.com/dvyukov/go-fuzz v0.0.0-20210429054444-fca39067bc72 // indirect github.com/ebfe/bcrypt_pbkdf v0.0.0-20140212075826-3c8d2dcb253a // indirect github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/gaukas/godicttls v0.0.3 // indirect github.com/gaukas/wazerofs v0.1.0 // indirect github.com/getlantern/algeneva v0.0.0-20240222191137-2b4e88234f59 // indirect github.com/getlantern/bufconn v0.0.0-20190625204133-a08544339f8d // indirect @@ -135,8 +134,6 @@ require ( github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect - github.com/klauspost/compress v1.17.4 // indirect - github.com/klauspost/cpuid v1.3.1 // indirect github.com/jhump/protoreflect v1.17.0 // indirect github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect @@ -181,7 +178,7 @@ require ( github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/quic-go/qpack v0.5.1 // indirect - github.com/quic-go/quic-go v0.47.0 // indirect + github.com/quic-go/quic-go v0.48.1 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/secure-io/siv-go v0.0.0-20180922214919-5ff40651e2c4 // indirect github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect @@ -191,6 +188,7 @@ require ( github.com/stretchr/objx v0.5.2 // indirect github.com/templexxx/cpu v0.0.8 // indirect github.com/templexxx/xorsimd v0.4.1 // indirect + github.com/tetratelabs/wazero v1.7.1 // indirect github.com/ti-mo/conntrack v0.3.0 // indirect github.com/ti-mo/netfilter v0.3.1 // indirect github.com/tjfoc/gmsm v1.3.2 // indirect @@ -211,26 +209,16 @@ require ( go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.starlark.net v0.0.0-20230612165344-9532f5667272 // indirect go.uber.org/atomic v1.9.0 // indirect - go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/oauth2 v0.16.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.17.0 // indirect - google.golang.org/appengine v1.6.7 // indirect go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 // indirect - golang.org/x/crypto v0.28.0 // indirect + golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/mod v0.18.0 // indirect golang.org/x/oauth2 v0.22.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect golang.org/x/tools v0.22.0 // indirect google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect @@ -248,3 +236,8 @@ replace github.com/mitchellh/panicwrap v1.0.0 => github.com/getlantern/panicwrap replace github.com/tetratelabs/wazero => github.com/refraction-networking/wazero v1.7.1-w replace github.com/apernet/hysteria/core/v2 v2.4.5 => github.com/JimmyHuang454/hysteria/core/v2 v2.0.0-20240724161647-b3347cf6334d + +replace github.com/refraction-networking/utls => github.com/reflog/utls v0.0.0-20241111121514-4d2deb0c42ff + +//replace github.com/v2fly/v2ray-core/v5 => ../v2ray-core // github.co v5.0.0-20241027222649-a72c4d264453 +replace github.com/v2fly/v2ray-core/v5 => github.com/reflog/v2ray-core/v5 v5.0.0-20241111162857-b3716b861060 diff --git a/go.sum b/go.sum index a6cd03c3..cc50ddc5 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ github.com/OperatorFoundation/go-shadowsocks2 v1.2.1 h1:hyf+kZq2rb/Kjw440hZUuedV github.com/OperatorFoundation/go-shadowsocks2 v1.2.1/go.mod h1:lH6+PiEc2/aDpMqZrLzMz+o2dlE1rPME6GYZN1j4Bsg= github.com/Yawning/chacha20 v0.0.0-20170904085104-e3b1f968fc63 h1:I6/SJSN9wJMJ+ZyQaCHUlzoTA4ypU5Bb44YWR1wTY/0= github.com/Yawning/chacha20 v0.0.0-20170904085104-e3b1f968fc63/go.mod h1:nf+Komq6fVP4SwmKEaVGxHTyQGKREVlwjQKpvOV39yE= -github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY= -github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4= +github.com/adrg/xdg v0.5.1 h1:Im8iDbEFARltY09yOJlSGu4Asjk2vF85+3Dyru8uJ0U= +github.com/adrg/xdg v0.5.1/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= github.com/aead/cmac v0.0.0-20160719120800-7af84192f0b1 h1:+JkXLHME8vLJafGhOH4aoV2Iu8bR55nU6iKMVfYVLjY= github.com/aead/cmac v0.0.0-20160719120800-7af84192f0b1/go.mod h1:nuudZmJhzWtx2212z+pkuy7B6nkBqa+xwNXZHL1j8cg= github.com/aead/ecdh v0.2.0 h1:pYop54xVaq/CEREFEcukHRZfTdjiWvYIsZDXXrBapQQ= @@ -54,8 +54,10 @@ github.com/aead/ecdh v0.2.0/go.mod h1:a9HHtXuSo8J1Js1MwLQx2mBhkXMT6YwUmVVEY4tTB8 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= -github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= +github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e h1:KBs8aBfKl5AKPKGpfn3bl0joDJXDq5fnH+AjFODiU+A= +github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e/go.mod h1:MjGWpXA31DZZWESdX3/PjIpSWIT1fOm8FNCqyXXFZFU= github.com/aristanetworks/goarista v0.0.0-20190628000427-15fc8b0bfcde/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -68,6 +70,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/vfs v1.0.0 h1:AUZUgulCDzbaNjTRWEP45X7m/J10brAptZpSRKRZBZc= +github.com/blang/vfs v1.0.0/go.mod h1:jjuNUc/IKcRNNWC9NUCvz4fR9PZLPIKxEygtPs/4tSI= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvPTF58Vq+qgmZEYZttJK+CWtSZhKenI= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d/go.mod h1:f1iKL6ZhUWvbk7PdWVmOaak10o86cqMUYEmn1CZNGEI= github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= @@ -125,8 +129,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= -github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= github.com/gaukas/wazerofs v0.1.0 h1:wIkW1bAxSnpaaVkQ5LOb1tm1BXdVap3eKjJpVWIqt2E= github.com/gaukas/wazerofs v0.1.0/go.mod h1:+JECB9Fwt0taPqSgHckG9lmT3tcoVK+9VJozTsq9UlI= github.com/getlantern/algeneva v0.0.0-20240222191137-2b4e88234f59 h1:uWNy0b1Wtpsd4n64Kat+fRjvPCBwM2Nykwt71LupJAQ= @@ -595,10 +597,16 @@ github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3c github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.47.0 h1:yXs3v7r2bm1wmPTYNLKAAJTHMYkPEsfYJmTazXrCZ7Y= -github.com/quic-go/quic-go v0.47.0/go.mod h1:3bCapYsJvXGZcipOHuu7plYtaV6tnF+z7wIFsU0WK9E= -github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= -github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= +github.com/quic-go/quic-go v0.48.1 h1:y/8xmfWI9qmGTc+lBr4jKRUWLGSlSigv847ULJ4hYXA= +github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= +github.com/reflog/utls v0.0.0-20241111121514-4d2deb0c42ff h1:IFLECF8Rma2XdluD4EZUe8a06FqWhm58f3G24ODrLKw= +github.com/reflog/utls v0.0.0-20241111121514-4d2deb0c42ff/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= +github.com/reflog/v2ray-core/v5 v5.0.0-20241111162857-b3716b861060 h1:eGoqbl/FWoGUzwfKXlRGUmbPe7g67J+vGW5FsiySm1Q= +github.com/reflog/v2ray-core/v5 v5.0.0-20241111162857-b3716b861060/go.mod h1:SacdfJBbt53z6Fv78mL8j/C8kurqWdo7NO4BiLh9aKg= +github.com/refraction-networking/water v0.7.0-alpha h1:yLMAvIi0lHHD2mvwx63GLnptpjvnmBCWFvTHTWLykLk= +github.com/refraction-networking/water v0.7.0-alpha/go.mod h1:VPQENA6E5+2V5RlX/yaBlTCKeFQ25j49DUc/pmmwkXE= +github.com/refraction-networking/wazero v1.7.1-w h1:z7Ty5PsMkJEDBCsn3ELUjceQGBT0FMVGldOSpDK3giQ= +github.com/refraction-networking/wazero v1.7.1-w/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -689,8 +697,6 @@ github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848 h1:p1UzXK6VAutXFFQMnre github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848/go.mod h1:p80Bv154ZtrGpXMN15slDCqc9UGmfBuUzheDFBYaW/M= github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI= github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU= -github.com/v2fly/v2ray-core/v5 v5.21.0 h1:MM9T/mXGiJx7j2t7gfxgVDeH9ltzHwREJfLd03b0kjw= -github.com/v2fly/v2ray-core/v5 v5.21.0/go.mod h1:1X4ntTX5jG1vncqCxAIwP9fGkbKgnlXYdjSGNvf/XzY= github.com/vharitonsky/iniflags v0.0.0-20180513140207-a33cd0b5f3de h1:fkw+7JkxF3U1GzQoX9h69Wvtvxajo5Rbzy6+YMMzPIg= github.com/vharitonsky/iniflags v0.0.0-20180513140207-a33cd0b5f3de/go.mod h1:irMhzlTz8+fVFj6CH2AN2i+WI5S6wWFtK3MBCIxIpyI= github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= @@ -791,8 +797,10 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -853,8 +861,10 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -869,8 +879,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -920,8 +930,10 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -947,8 +959,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= diff --git a/tlslistener/clienthelloconn.go b/tlslistener/clienthelloconn.go index 60869cd6..da178600 100644 --- a/tlslistener/clienthelloconn.go +++ b/tlslistener/clienthelloconn.go @@ -211,8 +211,7 @@ func (rrc *clientHelloRecordingConn) processHello(info *tls.ClientHelloInfo) (*t if len(helloMsg.SessionTicket) == 0 { return rrc.helloError("ClientHello has no session ticket", true) } - - plainText, _ := utls.DecryptTicketWith(helloMsg.SessionTicket, rrc.ticketKeys) + plainText := utls.DecryptTicketWith(helloMsg.SessionTicket, rrc.ticketKeys) if len(plainText) == 0 { return rrc.helloError("ClientHello has invalid session ticket", true) } diff --git a/v2ray/fixtures/socks_client.json b/v2ray/fixtures/socks_client.json new file mode 100644 index 00000000..1a78871a --- /dev/null +++ b/v2ray/fixtures/socks_client.json @@ -0,0 +1,25 @@ +{ + "log": { + "loglevel": "debug" + }, + "outbounds": [ + { + "protocol": "socks", + "settings": { + "servers": [ + { + "address": "127.0.0.1", + "port": 11082 + } + ] + } + } + ], + "inbounds": [ + { + "listen": "127.0.0.1", + "port": 11083, + "protocol": "socks" + } + ] +} \ No newline at end of file diff --git a/v2ray/fixtures/socks_server.json b/v2ray/fixtures/socks_server.json new file mode 100644 index 00000000..3a0766a4 --- /dev/null +++ b/v2ray/fixtures/socks_server.json @@ -0,0 +1,20 @@ +{ + "log": { + "loglevel": "debug" + }, + "outbounds": [ + { + "protocol": "freedom", + "settings": {} + } + ], + + "inbounds": [ + { + "listen": "LISTEN_ADDRESS", + "port": LISTEN_PORT, + "protocol": "socks", + "tag": "ingress" + } + ] +} \ No newline at end of file diff --git a/v2ray/fixtures/vmess_client.json b/v2ray/fixtures/vmess_client.json new file mode 100644 index 00000000..5cf4953a --- /dev/null +++ b/v2ray/fixtures/vmess_client.json @@ -0,0 +1,29 @@ +{ + "log": { + "loglevel": "debug" + }, + "outbounds": [ + { + "protocol": "vmess", + "settings": { + "vnext": [ + { + "address": "127.0.0.1", + "port": 11082, + "users": [ + { + "id": "19ee495c-9b89-418b-951b-b285ceb9bafb", + "security": null + } + ] + } + ] + }}], + "inbounds": [ + { + "listen": "127.0.0.1", + "port": 11083, + "protocol": "socks" + } + ] +} \ No newline at end of file diff --git a/v2ray/fixtures/vmess_server.json b/v2ray/fixtures/vmess_server.json new file mode 100644 index 00000000..e6c122df --- /dev/null +++ b/v2ray/fixtures/vmess_server.json @@ -0,0 +1,29 @@ +{ + + "log": { + "loglevel": "debug" + }, + "outbounds": [ + { + "protocol": "freedom", + "settings": {} + } + ], + + "inbounds": [ + { + "port": LISTEN_PORT, + "listen":"LISTEN_ADDRESS", + "tag": "ingress", + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "19ee495c-9b89-418b-951b-b285ceb9bafb" + } + ] + } + } + ] + +} \ No newline at end of file diff --git a/v2ray/listener.go b/v2ray/listener.go index e1dccb25..000d0715 100644 --- a/v2ray/listener.go +++ b/v2ray/listener.go @@ -2,191 +2,104 @@ package v2ray import ( "context" - core "github.com/v2fly/v2ray-core/v5" - "github.com/v2fly/v2ray-core/v5/infra/conf/serial" - "io" - "log" + "fmt" + "github.com/v2fly/v2ray-core/v5/features/inbound" "net" "strings" - // The following are necessary as they register handlers in their init functions. - - // Mandatory features. Can't remove unless there are replacements. + core "github.com/v2fly/v2ray-core/v5" _ "github.com/v2fly/v2ray-core/v5/app/dispatcher" - _ "github.com/v2fly/v2ray-core/v5/app/proxyman/inbound" - _ "github.com/v2fly/v2ray-core/v5/app/proxyman/outbound" - - // Other optional features. _ "github.com/v2fly/v2ray-core/v5/app/dns" _ "github.com/v2fly/v2ray-core/v5/app/dns/fakedns" - _ "github.com/v2fly/v2ray-core/v5/app/log" + _ "github.com/v2fly/v2ray-core/v5/app/observatory" _ "github.com/v2fly/v2ray-core/v5/app/policy" + _ "github.com/v2fly/v2ray-core/v5/app/proxyman/inbound" + _ "github.com/v2fly/v2ray-core/v5/app/proxyman/outbound" _ "github.com/v2fly/v2ray-core/v5/app/reverse" _ "github.com/v2fly/v2ray-core/v5/app/router" _ "github.com/v2fly/v2ray-core/v5/app/stats" - - // Fix dependency cycle caused by core import in internet package - _ "github.com/v2fly/v2ray-core/v5/transport/internet/tagged/taggedimpl" - - // Developer preview features - _ "github.com/v2fly/v2ray-core/v5/app/observatory" - - // Inbound and outbound proxies. + _ "github.com/v2fly/v2ray-core/v5/infra/conf/geodata/memconservative" + _ "github.com/v2fly/v2ray-core/v5/infra/conf/geodata/standard" + "github.com/v2fly/v2ray-core/v5/infra/conf/serial" + _ "github.com/v2fly/v2ray-core/v5/main/formats" _ "github.com/v2fly/v2ray-core/v5/proxy/blackhole" _ "github.com/v2fly/v2ray-core/v5/proxy/dns" _ "github.com/v2fly/v2ray-core/v5/proxy/dokodemo" _ "github.com/v2fly/v2ray-core/v5/proxy/freedom" _ "github.com/v2fly/v2ray-core/v5/proxy/http" + _ "github.com/v2fly/v2ray-core/v5/proxy/hysteria2" _ "github.com/v2fly/v2ray-core/v5/proxy/shadowsocks" + _ "github.com/v2fly/v2ray-core/v5/proxy/shadowsocks2022" _ "github.com/v2fly/v2ray-core/v5/proxy/socks" _ "github.com/v2fly/v2ray-core/v5/proxy/trojan" _ "github.com/v2fly/v2ray-core/v5/proxy/vless/inbound" _ "github.com/v2fly/v2ray-core/v5/proxy/vless/outbound" - _ "github.com/v2fly/v2ray-core/v5/proxy/vmess/inbound" - _ "github.com/v2fly/v2ray-core/v5/proxy/vmess/outbound" - - // Developer preview proxies _ "github.com/v2fly/v2ray-core/v5/proxy/vlite/inbound" _ "github.com/v2fly/v2ray-core/v5/proxy/vlite/outbound" - - _ "github.com/v2fly/v2ray-core/v5/proxy/hysteria2" - _ "github.com/v2fly/v2ray-core/v5/proxy/shadowsocks2022" - - // Transports + _ "github.com/v2fly/v2ray-core/v5/proxy/vmess/inbound" + _ "github.com/v2fly/v2ray-core/v5/proxy/vmess/outbound" _ "github.com/v2fly/v2ray-core/v5/transport/internet/domainsocket" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/dtls" _ "github.com/v2fly/v2ray-core/v5/transport/internet/grpc" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/http" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/noop" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/srtp" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/tls" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/utp" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/wechat" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/wireguard" _ "github.com/v2fly/v2ray-core/v5/transport/internet/http" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/httpupgrade" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2" _ "github.com/v2fly/v2ray-core/v5/transport/internet/kcp" _ "github.com/v2fly/v2ray-core/v5/transport/internet/quic" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/assembler/packetconn" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/assembler/simple" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/assembly" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/roundtripper/httprt" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/stereotype/meek" + _ "github.com/v2fly/v2ray-core/v5/transport/internet/tagged/taggedimpl" _ "github.com/v2fly/v2ray-core/v5/transport/internet/tcp" _ "github.com/v2fly/v2ray-core/v5/transport/internet/tls" _ "github.com/v2fly/v2ray-core/v5/transport/internet/tls/utls" _ "github.com/v2fly/v2ray-core/v5/transport/internet/udp" _ "github.com/v2fly/v2ray-core/v5/transport/internet/websocket" - - // Developer preview transports - _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/assembly" - - _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/assembler/simple" - _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/roundtripper/httprt" - - _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/assembler/packetconn" - - _ "github.com/v2fly/v2ray-core/v5/transport/internet/request/stereotype/meek" - - _ "github.com/v2fly/v2ray-core/v5/transport/internet/dtls" - - _ "github.com/v2fly/v2ray-core/v5/transport/internet/httpupgrade" - _ "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2" - - // Transport headers - _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/http" - _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/noop" - _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/srtp" - _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/tls" - _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/utp" - _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/wechat" - _ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/wireguard" - - // Geo loaders - _ "github.com/v2fly/v2ray-core/v5/infra/conf/geodata/memconservative" - _ "github.com/v2fly/v2ray-core/v5/infra/conf/geodata/standard" - - // JSON, TOML, YAML config support. (jsonv4) This disable selective compile - _ "github.com/v2fly/v2ray-core/v5/main/formats" ) -type TunnelListener struct { - listener net.Listener - targetAddr string -} - -func NewTunnelListener(listenAddr, targetAddr string) (*TunnelListener, error) { - listener, err := net.Listen("tcp", listenAddr) +// NewV2RayListener creates a V2Ray listener +// the cfgJSON is a JSON string that contains the configuration of the listener in v2ray format +// it should have one inbound and one outbound protocol +// the inbound protocol should have a tag "ingress" +// the listening address and port should be "LISTEN_ADDRESS" and "LISTEN_PORT" respectively and will be replaced +// by the actual address and port +func NewV2RayListener(ctx context.Context, address, cfgJSON string) (net.Listener, error) { + host, port, err := net.SplitHostPort(address) if err != nil { return nil, err } - return &TunnelListener{listener: listener, targetAddr: targetAddr}, nil -} + configStr := strings.Replace(strings.Replace(cfgJSON, "LISTEN_ADDRESS", host, 1), "LISTEN_PORT", port, 1) -func (t *TunnelListener) Accept() (net.Conn, error) { - conn, err := t.listener.Accept() + config, err := serial.LoadJSONConfig(strings.NewReader(configStr)) if err != nil { return nil, err } - go t.handleConnection(conn) - return conn, nil -} - -func (t *TunnelListener) handleConnection(srcConn net.Conn) { - defer srcConn.Close() - - // Connect to the target application - dstConn, err := net.Dial("tcp", t.targetAddr) + server, err := core.New(config) if err != nil { - log.Println("Failed to connect to target:", err) - return + return nil, err } - defer dstConn.Close() - - // Start forwarding data between the source and destination connections - go io.Copy(dstConn, srcConn) - io.Copy(srcConn, dstConn) -} - -func (t *TunnelListener) Close() error { - return t.listener.Close() -} - -func (t *TunnelListener) Addr() net.Addr { - return t.listener.Addr() -} - -const tmp = ` -{ - "log": { - "loglevel": "debug" - }, - "outbounds": [ - { - "protocol": "freedom", - "settings": {} - } - ], - - "inbounds": [ - { - "listen": "127.0.0.1", - "port": 11082, - "protocol": "socks", - "settings": { - "followRedirect": true, - "network": "tcp,udp" - }, - "sniffing": { - "destOverride": ["http", "tls"], - "enabled": true - } - } - ] -} - -` - -// NewV2RayListener creates a V2Ray listener -func NewV2RayListener(ctx context.Context, address, cfgJSON string) (net.Listener, error) { - config, err := serial.LoadJSONConfig(strings.NewReader(tmp)) - if err != nil { + if err = server.Start(); err != nil { return nil, err } - server, err := core.New(config) + inboundManager := server.GetFeature(inbound.ManagerType()).(inbound.Manager) + h, err := inboundManager.GetHandler(ctx, "ingress") if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get handler with tag ingress: %w", err) } - if err = server.Start(); err != nil { - return nil, err + if len(h.GetWorkers()) == 0 { + return nil, fmt.Errorf("no worker found in handler with tag ingress") } - return NewTunnelListener(address, "0.0.0.0:11082") + + return h.GetWorkers()[0].Hub().GetNetListener(), nil } diff --git a/v2ray/listener_test.go b/v2ray/listener_test.go new file mode 100644 index 00000000..78db3c5e --- /dev/null +++ b/v2ray/listener_test.go @@ -0,0 +1,103 @@ +package v2ray + +import ( + "context" + "fmt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + core "github.com/v2fly/v2ray-core/v5" + "github.com/v2fly/v2ray-core/v5/infra/conf/serial" + socksProxy "golang.org/x/net/proxy" + "net" + "net/url" + "os" + "strings" + "testing" +) + +func TestListener(t *testing.T) { + tests := []struct { + name string + clientConfig string + serverConfig string + }{ + { + name: "socks", + serverConfig: "socks_server.json", clientConfig: "socks_client.json", + }, + { + name: "vmess", + serverConfig: "vmess_server.json", clientConfig: "vmess_client.json", + }} + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testServer, err := os.ReadFile("fixtures/" + tt.serverConfig) + require.NoError(t, err) + testConfig, err := os.ReadFile("fixtures/" + tt.clientConfig) + require.NoError(t, err) + + _, err = NewV2RayListener(context.Background(), "127.0.0.1:11082", string(testServer)) + + require.Nil(t, err) + + messageRequest := "hello" + expectedResponse := "world" + + // start tcp server that waits for messageRequest and responds with expectedResponse + ln, err := net.Listen("tcp", "127.0.0.1:11084") + require.NoError(t, err) + defer ln.Close() + + go func() { + conn, err := ln.Accept() + if err != nil { + t.Error(err) + return + } + defer conn.Close() + buf := make([]byte, len(messageRequest)) + + if _, err = conn.Read(buf); err != nil { + t.Error(err) + return + } + if string(buf) == messageRequest { + _, err = conn.Write([]byte(expectedResponse)) + if err != nil { + t.Error(err) + } + } + }() + + config, err := serial.LoadJSONConfig(strings.NewReader(string(testConfig))) + require.NoError(t, err) + + server, err := core.New(config) + require.NoError(t, err) + + err = server.Start() + require.NoError(t, err) + defer server.Close() + + purl, err := url.Parse(fmt.Sprintf("socks5://%s:%d", "127.0.0.1", 11083)) + require.NoError(t, err) + socksDiler, err := socksProxy.FromURL(purl, nil) + require.NoError(t, err) + conn, err := socksDiler.Dial("tcp", "127.0.0.1:11084") + require.Nil(t, err) + defer conn.Close() + + n, err := conn.Write([]byte(messageRequest)) + assert.Nil(t, err) + assert.Equal(t, len(messageRequest), n) + + buf := make([]byte, 1024) + n, err = conn.Read(buf) + assert.Nil(t, err) + assert.Equal(t, len(expectedResponse), n) + assert.Equal(t, expectedResponse, string(buf[:n])) + }) + } + +}