mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 17:46:48 +08:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f35ded79ad | ||
![]() |
f3104b8684 | ||
![]() |
bc4de6a026 | ||
![]() |
3e4e050313 | ||
![]() |
b8e8229242 | ||
![]() |
a8fa5bf516 | ||
![]() |
4a3f3ef775 | ||
![]() |
5858726233 | ||
![]() |
b13c3f053a | ||
![]() |
2e30093ffd | ||
![]() |
1d7c40d728 | ||
![]() |
143229b148 | ||
![]() |
79eda46c62 | ||
![]() |
d87758d46f | ||
![]() |
e5e9e58d66 | ||
![]() |
0565589b8b | ||
![]() |
3cf1b7e601 | ||
![]() |
e18b52a5df | ||
![]() |
691b2b1c73 | ||
![]() |
494a10971b | ||
![]() |
34b3f0204a | ||
![]() |
18fd768166 | ||
![]() |
07d4cfd81a | ||
![]() |
d3efd2d24f |
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
@@ -115,11 +115,9 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Show workflow information
|
- name: Show workflow information
|
||||||
id: get_filename
|
|
||||||
run: |
|
run: |
|
||||||
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
|
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
|
||||||
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
|
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
|
||||||
echo "::set-output name=ASSET_NAME::$_NAME"
|
|
||||||
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
@@ -184,9 +182,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pushd build_assets || exit 1
|
pushd build_assets || exit 1
|
||||||
touch -mt $(date +%Y01010000) *
|
touch -mt $(date +%Y01010000) *
|
||||||
zip -9vr ../Xray-$ASSET_NAME.zip .
|
zip -9vr ../Xray-${{ env.ASSET_NAME }}.zip .
|
||||||
popd || exit 1
|
popd || exit 1
|
||||||
FILE=./Xray-$ASSET_NAME.zip
|
FILE=./Xray-${{ env.ASSET_NAME }}.zip
|
||||||
DGST=$FILE.dgst
|
DGST=$FILE.dgst
|
||||||
for METHOD in {"md5","sha1","sha256","sha512"}
|
for METHOD in {"md5","sha1","sha256","sha512"}
|
||||||
do
|
do
|
||||||
@@ -195,20 +193,20 @@ jobs:
|
|||||||
|
|
||||||
- name: Change the name
|
- name: Change the name
|
||||||
run: |
|
run: |
|
||||||
mv build_assets Xray-$ASSET_NAME
|
mv build_assets Xray-${{ env.ASSET_NAME }}
|
||||||
|
|
||||||
- name: Upload files to Artifacts
|
- name: Upload files to Artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: Xray-${{ steps.get_filename.outputs.ASSET_NAME }}
|
name: Xray-${{ env.ASSET_NAME }}
|
||||||
path: |
|
path: |
|
||||||
./Xray-${{ steps.get_filename.outputs.ASSET_NAME }}/*
|
./Xray-${{ env.ASSET_NAME }}/*
|
||||||
|
|
||||||
- name: Upload binaries to release
|
- name: Upload binaries to release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: ./Xray-${{ steps.get_filename.outputs.ASSET_NAME }}.zip*
|
file: ./Xray-${{ env.ASSET_NAME }}.zip*
|
||||||
tag: ${{ github.ref }}
|
tag: ${{ github.ref }}
|
||||||
file_glob: true
|
file_glob: true
|
||||||
|
@@ -2,8 +2,8 @@ package crypto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
|
"crypto/rand"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
@@ -265,7 +265,8 @@ func (w *AuthenticationWriter) seal(b []byte) (*buf.Buffer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if paddingSize > 0 {
|
if paddingSize > 0 {
|
||||||
// With size of the chunk and padding length encrypted, the content of padding doesn't matter much.
|
// These paddings will send in clear text.
|
||||||
|
// To avoid leakage of PRNG internal state, a cryptographically secure PRNG should be used.
|
||||||
paddingBytes := eb.Extend(paddingSize)
|
paddingBytes := eb.Extend(paddingSize)
|
||||||
common.Must2(rand.Read(paddingBytes))
|
common.Must2(rand.Read(paddingBytes))
|
||||||
}
|
}
|
||||||
|
@@ -355,6 +355,7 @@ func (m *ClientWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.Buffered
|
|||||||
common.Interrupt(s.input)
|
common.Interrupt(s.input)
|
||||||
common.Interrupt(s.output)
|
common.Interrupt(s.output)
|
||||||
}
|
}
|
||||||
|
common.Interrupt(s.input)
|
||||||
s.Close()
|
s.Close()
|
||||||
}
|
}
|
||||||
if meta.Option.Has(OptionData) {
|
if meta.Option.Has(OptionData) {
|
||||||
|
@@ -202,6 +202,7 @@ func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.Buffered
|
|||||||
common.Interrupt(s.input)
|
common.Interrupt(s.input)
|
||||||
common.Interrupt(s.output)
|
common.Interrupt(s.output)
|
||||||
}
|
}
|
||||||
|
common.Interrupt(s.input)
|
||||||
s.Close()
|
s.Close()
|
||||||
}
|
}
|
||||||
if meta.Option.Has(OptionData) {
|
if meta.Option.Has(OptionData) {
|
||||||
|
@@ -18,7 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "1.6.4"
|
version = "1.6.6"
|
||||||
build = "Custom"
|
build = "Custom"
|
||||||
codename = "Xray, Penetrates Everything."
|
codename = "Xray, Penetrates Everything."
|
||||||
intro = "A unified platform for anti-censorship."
|
intro = "A unified platform for anti-censorship."
|
||||||
|
41
go.mod
41
go.mod
@@ -8,25 +8,27 @@ require (
|
|||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/google/go-cmp v0.5.9
|
github.com/google/go-cmp v0.5.9
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/lucas-clemente/quic-go v0.30.0
|
github.com/lucas-clemente/quic-go v0.31.1
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.3
|
github.com/marten-seemann/qtls-go1-18 v0.1.3
|
||||||
github.com/miekg/dns v1.1.50
|
github.com/miekg/dns v1.1.50
|
||||||
github.com/pelletier/go-toml v1.9.5
|
github.com/pelletier/go-toml v1.9.5
|
||||||
github.com/pires/go-proxyproto v0.6.2
|
github.com/pires/go-proxyproto v0.6.2
|
||||||
github.com/refraction-networking/utls v1.1.5
|
github.com/refraction-networking/utls v1.2.0
|
||||||
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc
|
github.com/sagernet/sing v0.1.0
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1
|
github.com/sagernet/sing-shadowsocks v0.1.0
|
||||||
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
|
||||||
github.com/stretchr/testify v1.8.1
|
github.com/stretchr/testify v1.8.1
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||||
github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837
|
github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837
|
||||||
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2
|
go.starlark.net v0.0.0-20221205180719-3fd0dac74452
|
||||||
golang.org/x/crypto v0.2.0
|
golang.org/x/crypto v0.4.0
|
||||||
golang.org/x/net v0.2.0
|
golang.org/x/net v0.4.0
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.1.0
|
||||||
golang.org/x/sys v0.2.0
|
golang.org/x/sys v0.3.0
|
||||||
google.golang.org/grpc v1.50.1
|
google.golang.org/grpc v1.51.0
|
||||||
google.golang.org/protobuf v1.28.1
|
google.golang.org/protobuf v1.28.1
|
||||||
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
|
||||||
h12.io/socks v1.0.3
|
h12.io/socks v1.0.3
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,18 +38,23 @@ require (
|
|||||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20221112000123-84eb7ad69597 // indirect
|
github.com/google/btree v1.1.2 // indirect
|
||||||
github.com/klauspost/compress v1.15.12 // indirect
|
github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.0 // indirect
|
github.com/klauspost/compress v1.15.13 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.2 // indirect
|
||||||
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.5.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.6.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
golang.org/x/exp v0.0.0-20221111204811-129d8d6c17ab // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20221211140036-ad323defaf05 // indirect
|
||||||
golang.org/x/mod v0.7.0 // indirect
|
golang.org/x/mod v0.7.0 // indirect
|
||||||
golang.org/x/text v0.4.0 // indirect
|
golang.org/x/text v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20221111202108-142d8a6fa32e // indirect
|
golang.org/x/tools v0.4.0 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 // indirect
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
lukechampine.com/blake3 v1.1.7 // indirect
|
lukechampine.com/blake3 v1.1.7 // indirect
|
||||||
|
105
go.sum
105
go.sum
@@ -20,6 +20,7 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
|||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -61,6 +62,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
|||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
|
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
@@ -74,8 +77,10 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u
|
|||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20221112000123-84eb7ad69597 h1:BfATJjOtQYCyv2AM4mh/VFYgJjHDeXGfKdClCrUCh1w=
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||||
github.com/google/pprof v0.0.0-20221112000123-84eb7ad69597/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||||
|
github.com/google/pprof v0.0.0-20221203041831-ce31453925ec h1:fR20TYVVwhK4O7r7y+McjRYyaTH6/vjwJOajE+XhlzM=
|
||||||
|
github.com/google/pprof v0.0.0-20221203041831-ce31453925ec/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
@@ -89,20 +94,26 @@ github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0
|
|||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
|
||||||
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
|
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
|
||||||
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||||
|
github.com/klauspost/compress v1.15.13 h1:NFn1Wr8cfnenSJSA46lLq4wHCcBzKTSjnBIexDMMOV0=
|
||||||
|
github.com/klauspost/compress v1.15.13/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.0 h1:4ZexSFt8agMNzNisrsilL6RClWDC5YJnLHNIfTy4iuc=
|
github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/klauspost/cpuid/v2 v2.2.2 h1:xPMwiykqNK9VK0NYC3+jTMYv9I6Vl3YdjZgPZKG3zO0=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.2/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/lucas-clemente/quic-go v0.30.0 h1:nwLW0h8ahVQ5EPTIM7uhl/stHqQDea15oRlYKZmw2O0=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/lucas-clemente/quic-go v0.30.0/go.mod h1:ssOrRsOmdxa768Wr78vnh2B8JozgLsMzG/g+0qEC7uk=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/lucas-clemente/quic-go v0.31.1 h1:O8Od7hfioqq0PMYHDyBkxU2aA7iZ2W9pjbrWuja2YR4=
|
||||||
|
github.com/lucas-clemente/quic-go v0.31.1/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
|
||||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
|
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
|
||||||
@@ -117,8 +128,10 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
|||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||||
github.com/onsi/ginkgo/v2 v2.5.0 h1:TRtrvv2vdQqzkwrQ1ke6vtXf7IK34RBUJafIy1wMwls=
|
github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw=
|
||||||
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
|
||||||
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
|
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
|
||||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||||
@@ -127,6 +140,7 @@ github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoU
|
|||||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
||||||
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8=
|
||||||
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
|
||||||
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
@@ -135,15 +149,19 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
|
|||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/refraction-networking/utls v1.1.5 h1:JtrojoNhbUQkBqEg05sP3gDgDj6hIEAAVKbI9lx4n6w=
|
github.com/refraction-networking/utls v1.2.0 h1:U5f8wkij2NVinfLuJdFP3gCMwIHs+EzvhxmYdXgiapo=
|
||||||
github.com/refraction-networking/utls v1.1.5/go.mod h1:jRQxtYi7nkq1p28HF2lwOH5zQm9aC8rpK0O9lIIzGh8=
|
github.com/refraction-networking/utls v1.2.0/go.mod h1:NPq+cVqzH7D1BeOkmOcb5O/8iVewAsiVt2x1/eO0hgQ=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
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/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc h1:x7H64IiqyrpxPWl/KrWkknzEK4GmpqgfZeVKFVw6E/M=
|
github.com/sagernet/sing v0.1.0 h1:FGmaP2BVPYO2IyC/3R1DaQa/zr+kOKHRgWqrmOF+Gu8=
|
||||||
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
|
github.com/sagernet/sing v0.1.0/go.mod h1:zvgDYKI+vCAW9RyfyrKTgleI+DOa8lzHMPC7VZo3OL4=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1 h1:RYvOc69eSNMN0dwVugrDts41Nn7Ar/C/n/fvytvFcp4=
|
github.com/sagernet/sing-shadowsocks v0.1.0 h1:cDmmOkA11fzVdhyCZQEeI3ozQz+59rj8+rqPb91xux4=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1/go.mod h1:NqZjiXszgVCMQ4gVDa2V+drhS8NMfGqUqDF86EacEFc=
|
github.com/sagernet/sing-shadowsocks v0.1.0/go.mod h1:O5LtOs8Ivw686FqLpO0Zu+A0ROVE15VeqEK3yDRRAms=
|
||||||
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
||||||
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
@@ -192,18 +210,23 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
|||||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||||
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2 h1:5/KzhcSqd4UgY51l17r7C5g/JiE6DRw1Vq7VJfQHuMc=
|
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2 h1:5/KzhcSqd4UgY51l17r7C5g/JiE6DRw1Vq7VJfQHuMc=
|
||||||
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2/go.mod h1:kIVgS18CjmEC3PqMd5kaJSGEifyV/CeB9x506ZJ1Vbk=
|
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2/go.mod h1:kIVgS18CjmEC3PqMd5kaJSGEifyV/CeB9x506ZJ1Vbk=
|
||||||
|
go.starlark.net v0.0.0-20221205180719-3fd0dac74452 h1:JZtNuL6LPB+scU5yaQ6hqRlJFRiddZm2FwRt2AQqtHA=
|
||||||
|
go.starlark.net v0.0.0-20221205180719-3fd0dac74452/go.mod h1:kIVgS18CjmEC3PqMd5kaJSGEifyV/CeB9x506ZJ1Vbk=
|
||||||
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
|
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
|
||||||
golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE=
|
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||||
golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20221111204811-129d8d6c17ab h1:1S7USr8/C0Sgk4egxq4zZ07zYt2Xh1IiFp8hUMXH/us=
|
golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 h1:yZNXmy+j/JpX19vZkVktWqAo7Gny4PBWYYK3zskGpx4=
|
||||||
golang.org/x/exp v0.0.0-20221111204811-129d8d6c17ab/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
|
golang.org/x/exp v0.0.0-20221211140036-ad323defaf05 h1:T8EldfGCcveFMewH5xAYxxoX3PSQMrsechlUGVFlQBU=
|
||||||
|
golang.org/x/exp v0.0.0-20221211140036-ad323defaf05/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
@@ -224,10 +247,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
|
||||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@@ -255,21 +276,22 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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=
|
|
||||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
|
||||||
|
golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -282,6 +304,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|||||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
|
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
|
||||||
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
||||||
|
golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4=
|
||||||
|
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -300,16 +324,18 @@ google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk
|
|||||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto v0.0.0-20221111202108-142d8a6fa32e h1:azcyH5lGzGy7pkLCbhPe0KkKxsM7c6UA/FZIXImKE7M=
|
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c=
|
||||||
google.golang.org/genproto v0.0.0-20221111202108-142d8a6fa32e/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||||
|
google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 h1:jmIfw8+gSvXcZSgaFAGyInDXeWzUhvYH57G/5GKMn70=
|
||||||
|
google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||||
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@@ -323,7 +349,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
|||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@@ -334,6 +361,8 @@ gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||||
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4=
|
||||||
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
|
||||||
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
|
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
|
||||||
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
|
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
@@ -52,7 +53,15 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
account.Id = u.String()
|
account.Id = u.String()
|
||||||
|
|
||||||
switch account.Flow {
|
accountFlow := account.Flow
|
||||||
|
flows := strings.Split(account.Flow, ",")
|
||||||
|
for _, f := range flows {
|
||||||
|
t := strings.TrimSpace(f)
|
||||||
|
if t != "none" {
|
||||||
|
accountFlow = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch accountFlow {
|
||||||
case "", vless.XRO, vless.XRD, vless.XRV:
|
case "", vless.XRO, vless.XRD, vless.XRV:
|
||||||
case vless.XRS:
|
case vless.XRS:
|
||||||
return nil, newError(`VLESS clients: inbound doesn't support "xtls-rprx-splice" in this version, please use "xtls-rprx-direct" instead`)
|
return nil, newError(`VLESS clients: inbound doesn't support "xtls-rprx-splice" in this version, please use "xtls-rprx-direct" instead`)
|
||||||
|
111
infra/conf/wireguard.go
Normal file
111
infra/conf/wireguard.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/xtls/xray-core/proxy/wireguard"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WireGuardPeerConfig struct {
|
||||||
|
PublicKey string `json:"publicKey"`
|
||||||
|
PreSharedKey string `json:"preSharedKey"`
|
||||||
|
Endpoint string `json:"endpoint"`
|
||||||
|
KeepAlive int `json:"keepAlive"`
|
||||||
|
AllowedIPs []string `json:"allowedIPs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *WireGuardPeerConfig) Build() (proto.Message, error) {
|
||||||
|
var err error
|
||||||
|
config := new(wireguard.PeerConfig)
|
||||||
|
|
||||||
|
config.PublicKey, err = parseWireGuardKey(c.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.PreSharedKey != "" {
|
||||||
|
config.PreSharedKey, err = parseWireGuardKey(c.PreSharedKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config.PreSharedKey = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Endpoint = c.Endpoint
|
||||||
|
// default 0
|
||||||
|
config.KeepAlive = int32(c.KeepAlive)
|
||||||
|
if c.AllowedIPs == nil {
|
||||||
|
config.AllowedIps = []string{"0.0.0.0/0", "::0/0"}
|
||||||
|
} else {
|
||||||
|
config.AllowedIps = c.AllowedIPs
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type WireGuardConfig struct {
|
||||||
|
SecretKey string `json:"secretKey"`
|
||||||
|
Address []string `json:"address"`
|
||||||
|
Peers []*WireGuardPeerConfig `json:"peers"`
|
||||||
|
MTU int `json:"mtu"`
|
||||||
|
NumWorkers int `json:"workers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *WireGuardConfig) Build() (proto.Message, error) {
|
||||||
|
config := new(wireguard.DeviceConfig)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
config.SecretKey, err = parseWireGuardKey(c.SecretKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Address == nil {
|
||||||
|
// bogon ips
|
||||||
|
config.Endpoint = []string{"10.0.0.1", "fd59:7153:2388:b5fd:0000:0000:0000:0001"}
|
||||||
|
} else {
|
||||||
|
config.Endpoint = c.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Peers != nil {
|
||||||
|
config.Peers = make([]*wireguard.PeerConfig, len(c.Peers))
|
||||||
|
for i, p := range c.Peers {
|
||||||
|
msg, err := p.Build()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config.Peers[i] = msg.(*wireguard.PeerConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.MTU == 0 {
|
||||||
|
config.Mtu = 1420
|
||||||
|
} else {
|
||||||
|
config.Mtu = int32(c.MTU)
|
||||||
|
}
|
||||||
|
// these a fallback code exists in github.com/nanoda0523/wireguard-go code,
|
||||||
|
// we don't need to process fallback manually
|
||||||
|
config.NumWorkers = int32(c.NumWorkers)
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseWireGuardKey(str string) (string, error) {
|
||||||
|
if len(str) != 64 {
|
||||||
|
// may in base64 form
|
||||||
|
dat, err := base64.StdEncoding.DecodeString(str)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(dat) != 32 {
|
||||||
|
return "", newError("key should be 32 bytes: " + str)
|
||||||
|
}
|
||||||
|
return hex.EncodeToString(dat), err
|
||||||
|
} else {
|
||||||
|
// already hex form
|
||||||
|
return str, nil
|
||||||
|
}
|
||||||
|
}
|
49
infra/conf/wireguard_test.go
Normal file
49
infra/conf/wireguard_test.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package conf_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/xtls/xray-core/infra/conf"
|
||||||
|
"github.com/xtls/xray-core/proxy/wireguard"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWireGuardOutbound(t *testing.T) {
|
||||||
|
creator := func() Buildable {
|
||||||
|
return new(WireGuardConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
runMultiTestCase(t, []TestCase{
|
||||||
|
{
|
||||||
|
Input: `{
|
||||||
|
"secretKey": "uJv5tZMDltsiYEn+kUwb0Ll/CXWhMkaSCWWhfPEZM3A=",
|
||||||
|
"address": ["10.1.1.1", "fd59:7153:2388:b5fd:0000:0000:1234:0001"],
|
||||||
|
"peers": [
|
||||||
|
{
|
||||||
|
"publicKey": "6e65ce0be17517110c17d77288ad87e7fd5252dcc7d09b95a39d61db03df832a",
|
||||||
|
"endpoint": "127.0.0.1:1234"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mtu": 1300,
|
||||||
|
"workers": 2
|
||||||
|
}`,
|
||||||
|
Parser: loadJSON(creator),
|
||||||
|
Output: &wireguard.DeviceConfig{
|
||||||
|
// key converted into hex form
|
||||||
|
SecretKey: "b89bf9b5930396db226049fe914c1bd0b97f0975a13246920965a17cf1193370",
|
||||||
|
Endpoint: []string{"10.1.1.1", "fd59:7153:2388:b5fd:0000:0000:1234:0001"},
|
||||||
|
Peers: []*wireguard.PeerConfig{
|
||||||
|
{
|
||||||
|
// also can read from hex form directly
|
||||||
|
PublicKey: "6e65ce0be17517110c17d77288ad87e7fd5252dcc7d09b95a39d61db03df832a",
|
||||||
|
PreSharedKey: "0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
Endpoint: "127.0.0.1:1234",
|
||||||
|
KeepAlive: 0,
|
||||||
|
AllowedIps: []string{"0.0.0.0/0", "::0/0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Mtu: 1300,
|
||||||
|
NumWorkers: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
@@ -40,6 +40,7 @@ var (
|
|||||||
"trojan": func() interface{} { return new(TrojanClientConfig) },
|
"trojan": func() interface{} { return new(TrojanClientConfig) },
|
||||||
"mtproto": func() interface{} { return new(MTProtoClientConfig) },
|
"mtproto": func() interface{} { return new(MTProtoClientConfig) },
|
||||||
"dns": func() interface{} { return new(DNSOutboundConfig) },
|
"dns": func() interface{} { return new(DNSOutboundConfig) },
|
||||||
|
"wireguard": func() interface{} { return new(WireGuardConfig) },
|
||||||
}, "protocol", "settings")
|
}, "protocol", "settings")
|
||||||
|
|
||||||
ctllog = log.New(os.Stderr, "xctl> ", 0)
|
ctllog = log.New(os.Stderr, "xctl> ", 0)
|
||||||
|
@@ -48,6 +48,7 @@ import (
|
|||||||
_ "github.com/xtls/xray-core/proxy/vless/outbound"
|
_ "github.com/xtls/xray-core/proxy/vless/outbound"
|
||||||
_ "github.com/xtls/xray-core/proxy/vmess/inbound"
|
_ "github.com/xtls/xray-core/proxy/vmess/inbound"
|
||||||
_ "github.com/xtls/xray-core/proxy/vmess/outbound"
|
_ "github.com/xtls/xray-core/proxy/vmess/outbound"
|
||||||
|
_ "github.com/xtls/xray-core/proxy/wireguard"
|
||||||
|
|
||||||
// Transports
|
// Transports
|
||||||
_ "github.com/xtls/xray-core/transport/internet/domainsocket"
|
_ "github.com/xtls/xray-core/transport/internet/domainsocket"
|
||||||
|
29
proxy/shadowsocks_2022/config.go
Normal file
29
proxy/shadowsocks_2022/config.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package shadowsocks_2022
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MemoryAccount is an account type converted from Account.
|
||||||
|
type MemoryAccount struct {
|
||||||
|
Key string
|
||||||
|
Email string
|
||||||
|
Level int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsAccount implements protocol.AsAccount.
|
||||||
|
func (u *User) AsAccount() (protocol.Account, error) {
|
||||||
|
return &MemoryAccount{
|
||||||
|
Key: u.GetKey(),
|
||||||
|
Email: u.GetEmail(),
|
||||||
|
Level: u.GetLevel(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equals implements protocol.Account.Equals().
|
||||||
|
func (a *MemoryAccount) Equals(another protocol.Account) bool {
|
||||||
|
if account, ok := another.(*MemoryAccount); ok {
|
||||||
|
return a.Key == account.Key
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@@ -11,6 +11,7 @@ import (
|
|||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
|
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||||
C "github.com/sagernet/sing/common"
|
C "github.com/sagernet/sing/common"
|
||||||
@@ -13,6 +15,7 @@ import (
|
|||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
@@ -31,6 +34,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MultiUserInbound struct {
|
type MultiUserInbound struct {
|
||||||
|
sync.Mutex
|
||||||
networks []net.Network
|
networks []net.Network
|
||||||
users []*User
|
users []*User
|
||||||
service *shadowaead_2022.MultiService[int]
|
service *shadowaead_2022.MultiService[int]
|
||||||
@@ -78,6 +82,73 @@ func NewMultiServer(ctx context.Context, config *MultiUserServerConfig) (*MultiU
|
|||||||
return inbound, nil
|
return inbound, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddUser implements proxy.UserManager.AddUser().
|
||||||
|
func (i *MultiUserInbound) AddUser(ctx context.Context, u *protocol.MemoryUser) error {
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
|
||||||
|
account := u.Account.(*MemoryAccount)
|
||||||
|
if account.Email != "" {
|
||||||
|
for idx := range i.users {
|
||||||
|
if i.users[idx].Email == account.Email {
|
||||||
|
return newError("User ", account.Email, " already exists.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i.users = append(i.users, &User{
|
||||||
|
Key: account.Key,
|
||||||
|
Email: strings.ToLower(account.Email),
|
||||||
|
Level: account.Level,
|
||||||
|
})
|
||||||
|
|
||||||
|
// sync to multi service
|
||||||
|
// Considering implements shadowsocks2022 in xray-core may have better performance.
|
||||||
|
i.service.UpdateUsersWithPasswords(
|
||||||
|
C.MapIndexed(i.users, func(index int, it *User) int { return index }),
|
||||||
|
C.Map(i.users, func(it *User) string { return it.Key }),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveUser implements proxy.UserManager.RemoveUser().
|
||||||
|
func (i *MultiUserInbound) RemoveUser(ctx context.Context, email string) error {
|
||||||
|
if email == "" {
|
||||||
|
return newError("Email must not be empty.")
|
||||||
|
}
|
||||||
|
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
|
||||||
|
email = strings.ToLower(email)
|
||||||
|
idx := -1
|
||||||
|
for ii, u := range i.users {
|
||||||
|
if strings.EqualFold(u.Email, email) {
|
||||||
|
idx = ii
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx == -1 {
|
||||||
|
return newError("User ", email, " not found.")
|
||||||
|
}
|
||||||
|
|
||||||
|
ulen := len(i.users)
|
||||||
|
|
||||||
|
i.users[idx] = i.users[ulen-1]
|
||||||
|
i.users[ulen-1] = nil
|
||||||
|
i.users = i.users[:ulen-1]
|
||||||
|
|
||||||
|
// sync to multi service
|
||||||
|
// Considering implements shadowsocks2022 in xray-core may have better performance.
|
||||||
|
i.service.UpdateUsersWithPasswords(
|
||||||
|
C.MapIndexed(i.users, func(index int, it *User) int { return index }),
|
||||||
|
C.Map(i.users, func(it *User) string { return it.Key }),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (i *MultiUserInbound) Network() []net.Network {
|
func (i *MultiUserInbound) Network() []net.Network {
|
||||||
return i.networks
|
return i.networks
|
||||||
}
|
}
|
||||||
|
@@ -247,7 +247,9 @@ func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// XtlsRead filter and read xtls protocol
|
// XtlsRead filter and read xtls protocol
|
||||||
func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn, counter stats.Counter, ctx context.Context, userUUID []byte, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool) error {
|
func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn,
|
||||||
|
counter stats.Counter, ctx context.Context, userUUID []byte, numberOfPacketToFilter *int, enableXtls *bool,
|
||||||
|
isTLS12orAbove *bool, isTLS *bool, cipher *uint16, remainingServerHello *int32) error {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
var ct stats.Counter
|
var ct stats.Counter
|
||||||
filterUUID := true
|
filterUUID := true
|
||||||
@@ -258,8 +260,8 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
|||||||
for {
|
for {
|
||||||
if shouldSwitchToDirectCopy {
|
if shouldSwitchToDirectCopy {
|
||||||
shouldSwitchToDirectCopy = false
|
shouldSwitchToDirectCopy = false
|
||||||
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil {
|
if _, ok := inbound.User.Account.(*vless.MemoryAccount); inbound.User.Account == nil || ok {
|
||||||
iConn := inbound.Conn
|
iConn := inbound.Conn
|
||||||
statConn, ok := iConn.(*stat.CounterConnection)
|
statConn, ok := iConn.(*stat.CounterConnection)
|
||||||
if ok {
|
if ok {
|
||||||
@@ -279,11 +281,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
|||||||
statConn.WriteCounter.Add(w)
|
statConn.WriteCounter.Add(w)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
} else {
|
|
||||||
panic("XTLS Splice: not TCP inbound")
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// panic("XTLS Splice: nil inbound or nil inbound.Conn")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader = buf.NewReadVReader(conn, rawConn, nil)
|
reader = buf.NewReadVReader(conn, rawConn, nil)
|
||||||
@@ -306,7 +304,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if *numberOfPacketToFilter > 0 {
|
if *numberOfPacketToFilter > 0 {
|
||||||
XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, ctx)
|
XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx)
|
||||||
}
|
}
|
||||||
if ct != nil {
|
if ct != nil {
|
||||||
ct.Add(int64(buffer.Len()))
|
ct.Add(int64(buffer.Len()))
|
||||||
@@ -328,7 +326,9 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
|||||||
}
|
}
|
||||||
|
|
||||||
// XtlsWrite filter and write xtls protocol
|
// XtlsWrite filter and write xtls protocol
|
||||||
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, counter stats.Counter, ctx context.Context, userUUID *[]byte, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool) error {
|
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, counter stats.Counter,
|
||||||
|
ctx context.Context, userUUID *[]byte, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool,
|
||||||
|
cipher *uint16, remainingServerHello *int32) error {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
var ct stats.Counter
|
var ct stats.Counter
|
||||||
filterTlsApplicationData := true
|
filterTlsApplicationData := true
|
||||||
@@ -337,7 +337,7 @@ func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdate
|
|||||||
buffer, err := reader.ReadMultiBuffer()
|
buffer, err := reader.ReadMultiBuffer()
|
||||||
if !buffer.IsEmpty() {
|
if !buffer.IsEmpty() {
|
||||||
if *numberOfPacketToFilter > 0 {
|
if *numberOfPacketToFilter > 0 {
|
||||||
XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, ctx)
|
XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx)
|
||||||
}
|
}
|
||||||
if filterTlsApplicationData && *isTLS {
|
if filterTlsApplicationData && *isTLS {
|
||||||
buffer = ReshapeMultiBuffer(ctx, buffer)
|
buffer = ReshapeMultiBuffer(ctx, buffer)
|
||||||
@@ -399,40 +399,53 @@ func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdate
|
|||||||
}
|
}
|
||||||
|
|
||||||
// XtlsFilterTls filter and recognize tls 1.3 and other info
|
// XtlsFilterTls filter and recognize tls 1.3 and other info
|
||||||
func XtlsFilterTls(buffer buf.MultiBuffer, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool, ctx context.Context) {
|
func XtlsFilterTls(buffer buf.MultiBuffer, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool,
|
||||||
|
cipher *uint16, remainingServerHello *int32, ctx context.Context) {
|
||||||
for _, b := range buffer {
|
for _, b := range buffer {
|
||||||
*numberOfPacketToFilter--
|
*numberOfPacketToFilter--
|
||||||
if b.Len() >= 6 {
|
if b.Len() >= 6 {
|
||||||
startsBytes := b.BytesTo(6)
|
startsBytes := b.BytesTo(6)
|
||||||
if bytes.Equal(tlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == 0x02 {
|
if bytes.Equal(tlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == 0x02 {
|
||||||
total := (int(startsBytes[3])<<8 | int(startsBytes[4])) + 5
|
*remainingServerHello = (int32(startsBytes[3])<<8 | int32(startsBytes[4])) + 5
|
||||||
if b.Len() >= int32(total) && total >= 74 {
|
*isTLS12orAbove = true
|
||||||
if bytes.Contains(b.BytesTo(int32(total)), tls13SupportedVersions) {
|
*isTLS = true
|
||||||
sessionIdLen := int32(b.Byte(43))
|
if b.Len() >= 79 && *remainingServerHello >= 79 {
|
||||||
cipherSuite := b.BytesRange(43 + sessionIdLen + 1, 43 + sessionIdLen + 3)
|
sessionIdLen := int32(b.Byte(43))
|
||||||
cipherNum := uint16(cipherSuite[0]) << 8 | uint16(cipherSuite[1])
|
cipherSuite := b.BytesRange(43 + sessionIdLen + 1, 43 + sessionIdLen + 3)
|
||||||
v, ok := Tls13CipherSuiteDic[cipherNum]
|
*cipher = uint16(cipherSuite[0]) << 8 | uint16(cipherSuite[1])
|
||||||
if !ok {
|
} else {
|
||||||
v = "Unknown cipher!"
|
newError("XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx))
|
||||||
} else if (v != "TLS_AES_128_CCM_8_SHA256") {
|
|
||||||
*enableXtls = true
|
|
||||||
}
|
|
||||||
newError("XtlsFilterTls13 found tls 1.3! ", buffer.Len(), " ", v).WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
} else {
|
|
||||||
newError("XtlsFilterTls13 found tls 1.2! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
}
|
|
||||||
*isTLS12orAbove = true
|
|
||||||
*isTLS = true
|
|
||||||
*numberOfPacketToFilter = 0
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
} else if bytes.Equal(tlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == 0x01 {
|
} else if bytes.Equal(tlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == 0x01 {
|
||||||
*isTLS = true
|
*isTLS = true
|
||||||
newError("XtlsFilterTls13 found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
newError("XtlsFilterTls found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if *remainingServerHello > 0 {
|
||||||
|
end := *remainingServerHello
|
||||||
|
if end > b.Len() {
|
||||||
|
end = b.Len()
|
||||||
|
}
|
||||||
|
*remainingServerHello -= b.Len()
|
||||||
|
if bytes.Contains(b.BytesTo(end), tls13SupportedVersions) {
|
||||||
|
v, ok := Tls13CipherSuiteDic[*cipher]
|
||||||
|
if !ok {
|
||||||
|
v = "Old cipher: " + strconv.FormatUint(uint64(*cipher), 16)
|
||||||
|
} else if (v != "TLS_AES_128_CCM_8_SHA256") {
|
||||||
|
*enableXtls = true
|
||||||
|
}
|
||||||
|
newError("XtlsFilterTls found tls 1.3! ", b.Len(), " ", v).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
*numberOfPacketToFilter = 0
|
||||||
|
return
|
||||||
|
} else if *remainingServerHello <= 0 {
|
||||||
|
newError("XtlsFilterTls found tls 1.2! ", b.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
*numberOfPacketToFilter = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newError("XtlsFilterTls inconclusive server hello ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
if *numberOfPacketToFilter <= 0 {
|
if *numberOfPacketToFilter <= 0 {
|
||||||
newError("XtlsFilterTls13 stop filtering", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
newError("XtlsFilterTls stop filtering", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -441,10 +441,20 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
|
|
||||||
var netConn net.Conn
|
var netConn net.Conn
|
||||||
var rawConn syscall.RawConn
|
var rawConn syscall.RawConn
|
||||||
|
allowNoneFlow := false
|
||||||
|
accountFlow := account.Flow
|
||||||
|
flows := strings.Split(account.Flow, ",")
|
||||||
|
for _, f := range flows {
|
||||||
|
t := strings.TrimSpace(f)
|
||||||
|
if t == "none" {
|
||||||
|
allowNoneFlow = true
|
||||||
|
} else {
|
||||||
|
accountFlow = t
|
||||||
|
}
|
||||||
|
}
|
||||||
switch requestAddons.Flow {
|
switch requestAddons.Flow {
|
||||||
case vless.XRO, vless.XRD, vless.XRV:
|
case vless.XRO, vless.XRD, vless.XRV:
|
||||||
if account.Flow == requestAddons.Flow {
|
if accountFlow == requestAddons.Flow {
|
||||||
switch request.Command {
|
switch request.Command {
|
||||||
case protocol.RequestCommandMux:
|
case protocol.RequestCommandMux:
|
||||||
return newError(requestAddons.Flow + " doesn't support Mux").AtWarning()
|
return newError(requestAddons.Flow + " doesn't support Mux").AtWarning()
|
||||||
@@ -481,7 +491,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
} else {
|
} else {
|
||||||
return newError(account.ID.String() + " is not able to use " + requestAddons.Flow).AtWarning()
|
return newError(account.ID.String() + " is not able to use " + requestAddons.Flow).AtWarning()
|
||||||
}
|
}
|
||||||
case "":
|
case "", "none":
|
||||||
|
if accountFlow == vless.XRV && !allowNoneFlow && request.Command == protocol.RequestCommandTCP {
|
||||||
|
return newError(account.ID.String() + " is not able to use " + vless.XRV +
|
||||||
|
". Note the pure tls proxy has certain tls in tls characters. Append \",none\" in flow to suppress").AtWarning()
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return newError("unknown request flow " + requestAddons.Flow).AtWarning()
|
return newError("unknown request flow " + requestAddons.Flow).AtWarning()
|
||||||
}
|
}
|
||||||
@@ -511,6 +525,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
enableXtls := false
|
enableXtls := false
|
||||||
isTLS12orAbove := false
|
isTLS12orAbove := false
|
||||||
isTLS := false
|
isTLS := false
|
||||||
|
var cipher uint16 = 0
|
||||||
|
var remainingServerHello int32 = -1
|
||||||
numberOfPacketToFilter := 8
|
numberOfPacketToFilter := 8
|
||||||
|
|
||||||
postRequest := func() error {
|
postRequest := func() error {
|
||||||
@@ -529,7 +545,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
//TODO enable splice
|
//TODO enable splice
|
||||||
ctx = session.ContextWithInbound(ctx, nil)
|
ctx = session.ContextWithInbound(ctx, nil)
|
||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
err = encoding.XtlsRead(clientReader, serverWriter, timer, netConn, rawConn, counter, ctx, account.ID.Bytes(), &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS)
|
err = encoding.XtlsRead(clientReader, serverWriter, timer, netConn, rawConn, counter, ctx, account.ID.Bytes(),
|
||||||
|
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||||
} else {
|
} else {
|
||||||
err = encoding.ReadV(clientReader, serverWriter, timer, iConn.(*xtls.Conn), rawConn, counter, ctx)
|
err = encoding.ReadV(clientReader, serverWriter, timer, iConn.(*xtls.Conn), rawConn, counter, ctx)
|
||||||
}
|
}
|
||||||
@@ -561,7 +578,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
return err1 // ...
|
return err1 // ...
|
||||||
}
|
}
|
||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, ctx)
|
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello, ctx)
|
||||||
if isTLS {
|
if isTLS {
|
||||||
multiBuffer = encoding.ReshapeMultiBuffer(ctx, multiBuffer)
|
multiBuffer = encoding.ReshapeMultiBuffer(ctx, multiBuffer)
|
||||||
for i, b := range multiBuffer {
|
for i, b := range multiBuffer {
|
||||||
@@ -583,7 +600,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
if statConn != nil {
|
if statConn != nil {
|
||||||
counter = statConn.WriteCounter
|
counter = statConn.WriteCounter
|
||||||
}
|
}
|
||||||
err = encoding.XtlsWrite(serverReader, clientWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS)
|
err = encoding.XtlsWrite(serverReader, clientWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter,
|
||||||
|
&enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||||
} else {
|
} else {
|
||||||
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
|
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
|
||||||
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
|
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
|
||||||
|
@@ -5,6 +5,7 @@ package outbound
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
@@ -193,6 +194,8 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
enableXtls := false
|
enableXtls := false
|
||||||
isTLS12orAbove := false
|
isTLS12orAbove := false
|
||||||
isTLS := false
|
isTLS := false
|
||||||
|
var cipher uint16 = 0
|
||||||
|
var remainingServerHello int32 = -1
|
||||||
numberOfPacketToFilter := 8
|
numberOfPacketToFilter := 8
|
||||||
|
|
||||||
if request.Command == protocol.RequestCommandUDP && h.cone && request.Port != 53 && request.Port != 443 {
|
if request.Command == protocol.RequestCommandUDP && h.cone && request.Port != 53 && request.Port != 443 {
|
||||||
@@ -215,20 +218,26 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
serverWriter = xudp.NewPacketWriter(serverWriter, target)
|
serverWriter = xudp.NewPacketWriter(serverWriter, target)
|
||||||
}
|
}
|
||||||
userUUID := account.ID.Bytes()
|
userUUID := account.ID.Bytes()
|
||||||
multiBuffer, err1 := clientReader.ReadMultiBuffer()
|
timeoutReader, ok := clientReader.(buf.TimeoutReader)
|
||||||
if err1 != nil {
|
if ok {
|
||||||
return err1 // ...
|
multiBuffer, err1 := timeoutReader.ReadMultiBufferTimeout(time.Millisecond*500)
|
||||||
}
|
if err1 == nil {
|
||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, ctx)
|
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello, ctx)
|
||||||
if isTLS {
|
if isTLS {
|
||||||
for i, b := range multiBuffer {
|
for i, b := range multiBuffer {
|
||||||
multiBuffer[i] = encoding.XtlsPadding(b, 0x00, &userUUID, ctx)
|
multiBuffer[i] = encoding.XtlsPadding(b, 0x00, &userUUID, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if err := serverWriter.WriteMultiBuffer(multiBuffer); err != nil {
|
||||||
|
return err // ...
|
||||||
|
}
|
||||||
|
} else if err1 != buf.ErrReadTimeout {
|
||||||
|
return err1
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
if err := serverWriter.WriteMultiBuffer(multiBuffer); err != nil {
|
newError("Reader is not timeout reader, will send out vless header separately from first payload").AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
||||||
return err // ...
|
|
||||||
}
|
}
|
||||||
// Flush; bufferWriter.WriteMultiBufer now is bufferWriter.writer.WriteMultiBuffer
|
// Flush; bufferWriter.WriteMultiBufer now is bufferWriter.writer.WriteMultiBuffer
|
||||||
if err := bufferWriter.SetBuffered(false); err != nil {
|
if err := bufferWriter.SetBuffered(false); err != nil {
|
||||||
@@ -241,7 +250,8 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
if statConn != nil {
|
if statConn != nil {
|
||||||
counter = statConn.WriteCounter
|
counter = statConn.WriteCounter
|
||||||
}
|
}
|
||||||
err = encoding.XtlsWrite(clientReader, serverWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS)
|
err = encoding.XtlsWrite(clientReader, serverWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter,
|
||||||
|
&enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||||
} else {
|
} else {
|
||||||
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBufer
|
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBufer
|
||||||
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
|
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
|
||||||
@@ -277,8 +287,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
counter = statConn.ReadCounter
|
counter = statConn.ReadCounter
|
||||||
}
|
}
|
||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
err = encoding.XtlsRead(serverReader, clientWriter, timer, netConn, rawConn, counter, ctx, account.ID.Bytes(), &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS)
|
err = encoding.XtlsRead(serverReader, clientWriter, timer, netConn, rawConn, counter, ctx, account.ID.Bytes(),
|
||||||
|
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||||
} else {
|
} else {
|
||||||
|
if requestAddons.Flow != vless.XRS {
|
||||||
|
ctx = session.ContextWithInbound(ctx, nil)
|
||||||
|
}
|
||||||
err = encoding.ReadV(serverReader, clientWriter, timer, iConn.(*xtls.Conn), rawConn, counter, ctx)
|
err = encoding.ReadV(serverReader, clientWriter, timer, iConn.(*xtls.Conn), rawConn, counter, ctx)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
254
proxy/wireguard/bind.go
Normal file
254
proxy/wireguard/bind.go
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
package wireguard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/sagernet/wireguard-go/conn"
|
||||||
|
xnet "github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
)
|
||||||
|
|
||||||
|
type netReadInfo struct {
|
||||||
|
// status
|
||||||
|
waiter sync.WaitGroup
|
||||||
|
// param
|
||||||
|
buff []byte
|
||||||
|
// result
|
||||||
|
bytes int
|
||||||
|
endpoint conn.Endpoint
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
type netBindClient struct {
|
||||||
|
workers int
|
||||||
|
dialer internet.Dialer
|
||||||
|
dns dns.Client
|
||||||
|
dnsOption dns.IPOption
|
||||||
|
|
||||||
|
readQueue chan *netReadInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *netBindClient) ParseEndpoint(s string) (conn.Endpoint, error) {
|
||||||
|
ipStr, port, _, err := splitAddrPort(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var addr net.IP
|
||||||
|
if IsDomainName(ipStr) {
|
||||||
|
ips, err := n.dns.LookupIP(ipStr, n.dnsOption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if len(ips) == 0 {
|
||||||
|
return nil, dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
addr = ips[0]
|
||||||
|
} else {
|
||||||
|
addr = net.ParseIP(ipStr)
|
||||||
|
}
|
||||||
|
if addr == nil {
|
||||||
|
return nil, errors.New("failed to parse ip: " + ipStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ip xnet.Address
|
||||||
|
if p4 := addr.To4(); len(p4) == net.IPv4len {
|
||||||
|
ip = xnet.IPAddress(p4[:])
|
||||||
|
} else {
|
||||||
|
ip = xnet.IPAddress(addr[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := xnet.Destination{
|
||||||
|
Address: ip,
|
||||||
|
Port: xnet.Port(port),
|
||||||
|
Network: xnet.Network_UDP,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &netEndpoint{
|
||||||
|
dst: dst,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bind *netBindClient) Open(uport uint16) ([]conn.ReceiveFunc, uint16, error) {
|
||||||
|
bind.readQueue = make(chan *netReadInfo)
|
||||||
|
|
||||||
|
fun := func(buff []byte) (cap int, ep conn.Endpoint, err error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
cap = 0
|
||||||
|
ep = nil
|
||||||
|
err = errors.New("channel closed")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
r := &netReadInfo{
|
||||||
|
buff: buff,
|
||||||
|
}
|
||||||
|
r.waiter.Add(1)
|
||||||
|
bind.readQueue <- r
|
||||||
|
r.waiter.Wait() // wait read goroutine done, or we will miss the result
|
||||||
|
return r.bytes, r.endpoint, r.err
|
||||||
|
}
|
||||||
|
workers := bind.workers
|
||||||
|
if workers <= 0 {
|
||||||
|
workers = 1
|
||||||
|
}
|
||||||
|
arr := make([]conn.ReceiveFunc, workers)
|
||||||
|
for i := 0; i < workers; i++ {
|
||||||
|
arr[i] = fun
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr, uint16(uport), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bind *netBindClient) Close() error {
|
||||||
|
if bind.readQueue != nil {
|
||||||
|
close(bind.readQueue)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bind *netBindClient) connectTo(endpoint *netEndpoint) error {
|
||||||
|
c, err := bind.dialer.Dial(context.Background(), endpoint.dst)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
endpoint.conn = c
|
||||||
|
|
||||||
|
go func(readQueue <-chan *netReadInfo, endpoint *netEndpoint) {
|
||||||
|
for {
|
||||||
|
v, ok := <-readQueue
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i, err := c.Read(v.buff)
|
||||||
|
v.bytes = i
|
||||||
|
v.endpoint = endpoint
|
||||||
|
v.err = err
|
||||||
|
v.waiter.Done()
|
||||||
|
if err != nil && errors.Is(err, io.EOF) {
|
||||||
|
endpoint.conn = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(bind.readQueue, endpoint)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bind *netBindClient) Send(buff []byte, endpoint conn.Endpoint) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
nend, ok := endpoint.(*netEndpoint)
|
||||||
|
if !ok {
|
||||||
|
return conn.ErrWrongEndpointType
|
||||||
|
}
|
||||||
|
|
||||||
|
if nend.conn == nil {
|
||||||
|
err = bind.connectTo(nend)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = nend.conn.Write(buff)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bind *netBindClient) SetMark(mark uint32) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type netEndpoint struct {
|
||||||
|
dst xnet.Destination
|
||||||
|
conn net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (netEndpoint) ClearSrc() {}
|
||||||
|
|
||||||
|
func (e netEndpoint) DstIP() netip.Addr {
|
||||||
|
return toNetIpAddr(e.dst.Address)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e netEndpoint) SrcIP() netip.Addr {
|
||||||
|
return netip.Addr{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e netEndpoint) DstToBytes() []byte {
|
||||||
|
var dat []byte
|
||||||
|
if e.dst.Address.Family().IsIPv4() {
|
||||||
|
dat = e.dst.Address.IP().To4()[:]
|
||||||
|
} else {
|
||||||
|
dat = e.dst.Address.IP().To16()[:]
|
||||||
|
}
|
||||||
|
dat = append(dat, byte(e.dst.Port), byte(e.dst.Port>>8))
|
||||||
|
return dat
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e netEndpoint) DstToString() string {
|
||||||
|
return e.dst.NetAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e netEndpoint) SrcToString() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func toNetIpAddr(addr xnet.Address) netip.Addr {
|
||||||
|
if addr.Family().IsIPv4() {
|
||||||
|
ip := addr.IP()
|
||||||
|
return netip.AddrFrom4([4]byte{ip[0], ip[1], ip[2], ip[3]})
|
||||||
|
} else {
|
||||||
|
ip := addr.IP()
|
||||||
|
arr := [16]byte{}
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
arr[i] = ip[i]
|
||||||
|
}
|
||||||
|
return netip.AddrFrom16(arr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringsLastIndexByte(s string, b byte) int {
|
||||||
|
for i := len(s) - 1; i >= 0; i-- {
|
||||||
|
if s[i] == b {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitAddrPort(s string) (ip string, port uint16, v6 bool, err error) {
|
||||||
|
i := stringsLastIndexByte(s, ':')
|
||||||
|
if i == -1 {
|
||||||
|
return "", 0, false, errors.New("not an ip:port")
|
||||||
|
}
|
||||||
|
|
||||||
|
ip = s[:i]
|
||||||
|
portStr := s[i+1:]
|
||||||
|
if len(ip) == 0 {
|
||||||
|
return "", 0, false, errors.New("no IP")
|
||||||
|
}
|
||||||
|
if len(portStr) == 0 {
|
||||||
|
return "", 0, false, errors.New("no port")
|
||||||
|
}
|
||||||
|
port64, err := strconv.ParseUint(portStr, 10, 16)
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, false, errors.New("invalid port " + strconv.Quote(portStr) + " parsing " + strconv.Quote(s))
|
||||||
|
}
|
||||||
|
port = uint16(port64)
|
||||||
|
if ip[0] == '[' {
|
||||||
|
if len(ip) < 2 || ip[len(ip)-1] != ']' {
|
||||||
|
return "", 0, false, errors.New("missing ]")
|
||||||
|
}
|
||||||
|
ip = ip[1 : len(ip)-1]
|
||||||
|
v6 = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip, port, v6, nil
|
||||||
|
}
|
294
proxy/wireguard/config.pb.go
Normal file
294
proxy/wireguard/config.pb.go
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.28.1
|
||||||
|
// protoc v3.21.9
|
||||||
|
// source: proxy/wireguard/config.proto
|
||||||
|
|
||||||
|
package wireguard
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type PeerConfig struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
PublicKey string `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||||
|
PreSharedKey string `protobuf:"bytes,2,opt,name=pre_shared_key,json=preSharedKey,proto3" json:"pre_shared_key,omitempty"`
|
||||||
|
Endpoint string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
|
||||||
|
KeepAlive int32 `protobuf:"varint,4,opt,name=keep_alive,json=keepAlive,proto3" json:"keep_alive,omitempty"`
|
||||||
|
AllowedIps []string `protobuf:"bytes,5,rep,name=allowed_ips,json=allowedIps,proto3" json:"allowed_ips,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PeerConfig) Reset() {
|
||||||
|
*x = PeerConfig{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proxy_wireguard_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PeerConfig) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*PeerConfig) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *PeerConfig) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proxy_wireguard_config_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use PeerConfig.ProtoReflect.Descriptor instead.
|
||||||
|
func (*PeerConfig) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proxy_wireguard_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PeerConfig) GetPublicKey() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.PublicKey
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PeerConfig) GetPreSharedKey() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.PreSharedKey
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PeerConfig) GetEndpoint() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Endpoint
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PeerConfig) GetKeepAlive() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.KeepAlive
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PeerConfig) GetAllowedIps() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.AllowedIps
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeviceConfig struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
SecretKey string `protobuf:"bytes,1,opt,name=secret_key,json=secretKey,proto3" json:"secret_key,omitempty"`
|
||||||
|
Endpoint []string `protobuf:"bytes,2,rep,name=endpoint,proto3" json:"endpoint,omitempty"`
|
||||||
|
Peers []*PeerConfig `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"`
|
||||||
|
Mtu int32 `protobuf:"varint,4,opt,name=mtu,proto3" json:"mtu,omitempty"`
|
||||||
|
NumWorkers int32 `protobuf:"varint,5,opt,name=num_workers,json=numWorkers,proto3" json:"num_workers,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeviceConfig) Reset() {
|
||||||
|
*x = DeviceConfig{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proxy_wireguard_config_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeviceConfig) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DeviceConfig) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *DeviceConfig) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proxy_wireguard_config_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use DeviceConfig.ProtoReflect.Descriptor instead.
|
||||||
|
func (*DeviceConfig) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proxy_wireguard_config_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeviceConfig) GetSecretKey() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.SecretKey
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeviceConfig) GetEndpoint() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Endpoint
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeviceConfig) GetPeers() []*PeerConfig {
|
||||||
|
if x != nil {
|
||||||
|
return x.Peers
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeviceConfig) GetMtu() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Mtu
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DeviceConfig) GetNumWorkers() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.NumWorkers
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_proxy_wireguard_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_proxy_wireguard_config_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72,
|
||||||
|
0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14,
|
||||||
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x77, 0x69, 0x72, 0x65, 0x67,
|
||||||
|
0x75, 0x61, 0x72, 0x64, 0x22, 0xad, 0x01, 0x0a, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e,
|
||||||
|
0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65,
|
||||||
|
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b,
|
||||||
|
0x65, 0x79, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x72, 0x65, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64,
|
||||||
|
0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x53,
|
||||||
|
0x68, 0x61, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70,
|
||||||
|
0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70,
|
||||||
|
0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x61, 0x6c, 0x69,
|
||||||
|
0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x41, 0x6c,
|
||||||
|
0x69, 0x76, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x69,
|
||||||
|
0x70, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65,
|
||||||
|
0x64, 0x49, 0x70, 0x73, 0x22, 0xb4, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43,
|
||||||
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f,
|
||||||
|
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65,
|
||||||
|
0x74, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
|
0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
|
0x12, 0x36, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||||
|
0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x77, 0x69, 0x72,
|
||||||
|
0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
|
0x67, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18,
|
||||||
|
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x75,
|
||||||
|
0x6d, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||||
|
0x0a, 0x6e, 0x75, 0x6d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x42, 0x5e, 0x0a, 0x18, 0x63,
|
||||||
|
0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x77, 0x69,
|
||||||
|
0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x50, 0x01, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||||
|
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
|
||||||
|
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x77, 0x69, 0x72, 0x65, 0x67,
|
||||||
|
0x75, 0x61, 0x72, 0x64, 0xaa, 0x02, 0x14, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78,
|
||||||
|
0x79, 0x2e, 0x57, 0x69, 0x72, 0x65, 0x47, 0x75, 0x61, 0x72, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||||
|
0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_proxy_wireguard_config_proto_rawDescOnce sync.Once
|
||||||
|
file_proxy_wireguard_config_proto_rawDescData = file_proxy_wireguard_config_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_proxy_wireguard_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_proxy_wireguard_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_proxy_wireguard_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_proxy_wireguard_config_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_proxy_wireguard_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_proxy_wireguard_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||||
|
var file_proxy_wireguard_config_proto_goTypes = []interface{}{
|
||||||
|
(*PeerConfig)(nil), // 0: xray.proxy.wireguard.PeerConfig
|
||||||
|
(*DeviceConfig)(nil), // 1: xray.proxy.wireguard.DeviceConfig
|
||||||
|
}
|
||||||
|
var file_proxy_wireguard_config_proto_depIdxs = []int32{
|
||||||
|
0, // 0: xray.proxy.wireguard.DeviceConfig.peers:type_name -> xray.proxy.wireguard.PeerConfig
|
||||||
|
1, // [1:1] is the sub-list for method output_type
|
||||||
|
1, // [1:1] is the sub-list for method input_type
|
||||||
|
1, // [1:1] is the sub-list for extension type_name
|
||||||
|
1, // [1:1] is the sub-list for extension extendee
|
||||||
|
0, // [0:1] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_proxy_wireguard_config_proto_init() }
|
||||||
|
func file_proxy_wireguard_config_proto_init() {
|
||||||
|
if File_proxy_wireguard_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_proxy_wireguard_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*PeerConfig); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_proxy_wireguard_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*DeviceConfig); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_proxy_wireguard_config_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 2,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_proxy_wireguard_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_proxy_wireguard_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_proxy_wireguard_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_proxy_wireguard_config_proto = out.File
|
||||||
|
file_proxy_wireguard_config_proto_rawDesc = nil
|
||||||
|
file_proxy_wireguard_config_proto_goTypes = nil
|
||||||
|
file_proxy_wireguard_config_proto_depIdxs = nil
|
||||||
|
}
|
23
proxy/wireguard/config.proto
Normal file
23
proxy/wireguard/config.proto
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.proxy.wireguard;
|
||||||
|
option csharp_namespace = "Xray.Proxy.WireGuard";
|
||||||
|
option go_package = "github.com/xtls/xray-core/proxy/wireguard";
|
||||||
|
option java_package = "com.xray.proxy.wireguard";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
message PeerConfig {
|
||||||
|
string public_key = 1;
|
||||||
|
string pre_shared_key = 2;
|
||||||
|
string endpoint = 3;
|
||||||
|
int32 keep_alive = 4;
|
||||||
|
repeated string allowed_ips = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeviceConfig {
|
||||||
|
string secret_key = 1;
|
||||||
|
repeated string endpoint = 2;
|
||||||
|
repeated PeerConfig peers = 3;
|
||||||
|
int32 mtu = 4;
|
||||||
|
int32 num_workers = 5;
|
||||||
|
}
|
9
proxy/wireguard/errors.generated.go
Normal file
9
proxy/wireguard/errors.generated.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package wireguard
|
||||||
|
|
||||||
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
||||||
|
type errPathObjHolder struct{}
|
||||||
|
|
||||||
|
func newError(values ...interface{}) *errors.Error {
|
||||||
|
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
||||||
|
}
|
303
proxy/wireguard/tun.go
Normal file
303
proxy/wireguard/tun.go
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package wireguard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/sagernet/wireguard-go/tun"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
|
"gvisor.dev/gvisor/pkg/bufferv2"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type netTun struct {
|
||||||
|
ep *channel.Endpoint
|
||||||
|
stack *stack.Stack
|
||||||
|
events chan tun.Event
|
||||||
|
incomingPacket chan *bufferv2.View
|
||||||
|
mtu int
|
||||||
|
dnsClient dns.Client
|
||||||
|
hasV4, hasV6 bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Net netTun
|
||||||
|
|
||||||
|
func CreateNetTUN(localAddresses []netip.Addr, dnsClient dns.Client, mtu int) (tun.Device, *Net, error) {
|
||||||
|
opts := stack.Options{
|
||||||
|
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
|
||||||
|
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol},
|
||||||
|
HandleLocal: true,
|
||||||
|
}
|
||||||
|
dev := &netTun{
|
||||||
|
ep: channel.New(1024, uint32(mtu), ""),
|
||||||
|
stack: stack.New(opts),
|
||||||
|
events: make(chan tun.Event, 10),
|
||||||
|
incomingPacket: make(chan *bufferv2.View),
|
||||||
|
dnsClient: dnsClient,
|
||||||
|
mtu: mtu,
|
||||||
|
}
|
||||||
|
dev.ep.AddNotify(dev)
|
||||||
|
tcpipErr := dev.stack.CreateNIC(1, dev.ep)
|
||||||
|
if tcpipErr != nil {
|
||||||
|
return nil, nil, fmt.Errorf("CreateNIC: %v", tcpipErr)
|
||||||
|
}
|
||||||
|
for _, ip := range localAddresses {
|
||||||
|
var protoNumber tcpip.NetworkProtocolNumber
|
||||||
|
if ip.Is4() {
|
||||||
|
protoNumber = ipv4.ProtocolNumber
|
||||||
|
} else if ip.Is6() {
|
||||||
|
protoNumber = ipv6.ProtocolNumber
|
||||||
|
}
|
||||||
|
protoAddr := tcpip.ProtocolAddress{
|
||||||
|
Protocol: protoNumber,
|
||||||
|
AddressWithPrefix: tcpip.Address(ip.AsSlice()).WithPrefix(),
|
||||||
|
}
|
||||||
|
tcpipErr := dev.stack.AddProtocolAddress(1, protoAddr, stack.AddressProperties{})
|
||||||
|
if tcpipErr != nil {
|
||||||
|
return nil, nil, fmt.Errorf("AddProtocolAddress(%v): %v", ip, tcpipErr)
|
||||||
|
}
|
||||||
|
if ip.Is4() {
|
||||||
|
dev.hasV4 = true
|
||||||
|
} else if ip.Is6() {
|
||||||
|
dev.hasV6 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if dev.hasV4 {
|
||||||
|
dev.stack.AddRoute(tcpip.Route{Destination: header.IPv4EmptySubnet, NIC: 1})
|
||||||
|
}
|
||||||
|
if dev.hasV6 {
|
||||||
|
dev.stack.AddRoute(tcpip.Route{Destination: header.IPv6EmptySubnet, NIC: 1})
|
||||||
|
}
|
||||||
|
|
||||||
|
dev.events <- tun.EventUp
|
||||||
|
return dev, (*Net)(dev), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *netTun) Name() (string, error) {
|
||||||
|
return "go", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *netTun) File() *os.File {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *netTun) Events() chan tun.Event {
|
||||||
|
return tun.events
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *netTun) Read(buf []byte, offset int) (int, error) {
|
||||||
|
view, ok := <-tun.incomingPacket
|
||||||
|
if !ok {
|
||||||
|
return 0, os.ErrClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
return view.Read(buf[offset:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *netTun) Write(buf []byte, offset int) (int, error) {
|
||||||
|
packet := buf[offset:]
|
||||||
|
if len(packet) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pkb := stack.NewPacketBuffer(stack.PacketBufferOptions{Payload: bufferv2.MakeWithData(packet)})
|
||||||
|
switch packet[0] >> 4 {
|
||||||
|
case 4:
|
||||||
|
tun.ep.InjectInbound(header.IPv4ProtocolNumber, pkb)
|
||||||
|
case 6:
|
||||||
|
tun.ep.InjectInbound(header.IPv6ProtocolNumber, pkb)
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *netTun) WriteNotify() {
|
||||||
|
pkt := tun.ep.Read()
|
||||||
|
if pkt == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
view := pkt.ToView()
|
||||||
|
pkt.DecRef()
|
||||||
|
|
||||||
|
tun.incomingPacket <- view
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *netTun) Flush() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *netTun) Close() error {
|
||||||
|
tun.stack.RemoveNIC(1)
|
||||||
|
|
||||||
|
if tun.events != nil {
|
||||||
|
close(tun.events)
|
||||||
|
}
|
||||||
|
|
||||||
|
tun.ep.Close()
|
||||||
|
|
||||||
|
if tun.incomingPacket != nil {
|
||||||
|
close(tun.incomingPacket)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *netTun) MTU() (int, error) {
|
||||||
|
return tun.mtu, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToFullAddr(endpoint netip.AddrPort) (tcpip.FullAddress, tcpip.NetworkProtocolNumber) {
|
||||||
|
var protoNumber tcpip.NetworkProtocolNumber
|
||||||
|
if endpoint.Addr().Is4() {
|
||||||
|
protoNumber = ipv4.ProtocolNumber
|
||||||
|
} else {
|
||||||
|
protoNumber = ipv6.ProtocolNumber
|
||||||
|
}
|
||||||
|
return tcpip.FullAddress{
|
||||||
|
NIC: 1,
|
||||||
|
Addr: tcpip.Address(endpoint.Addr().AsSlice()),
|
||||||
|
Port: endpoint.Port(),
|
||||||
|
}, protoNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) DialContextTCPAddrPort(ctx context.Context, addr netip.AddrPort) (*gonet.TCPConn, error) {
|
||||||
|
fa, pn := convertToFullAddr(addr)
|
||||||
|
return gonet.DialContextTCP(ctx, net.stack, fa, pn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) DialContextTCP(ctx context.Context, addr *net.TCPAddr) (*gonet.TCPConn, error) {
|
||||||
|
if addr == nil {
|
||||||
|
return net.DialContextTCPAddrPort(ctx, netip.AddrPort{})
|
||||||
|
}
|
||||||
|
ip, _ := netip.AddrFromSlice(addr.IP)
|
||||||
|
return net.DialContextTCPAddrPort(ctx, netip.AddrPortFrom(ip, uint16(addr.Port)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) DialTCPAddrPort(addr netip.AddrPort) (*gonet.TCPConn, error) {
|
||||||
|
fa, pn := convertToFullAddr(addr)
|
||||||
|
return gonet.DialTCP(net.stack, fa, pn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) DialTCP(addr *net.TCPAddr) (*gonet.TCPConn, error) {
|
||||||
|
if addr == nil {
|
||||||
|
return net.DialTCPAddrPort(netip.AddrPort{})
|
||||||
|
}
|
||||||
|
ip, _ := netip.AddrFromSlice(addr.IP)
|
||||||
|
return net.DialTCPAddrPort(netip.AddrPortFrom(ip, uint16(addr.Port)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) ListenTCPAddrPort(addr netip.AddrPort) (*gonet.TCPListener, error) {
|
||||||
|
fa, pn := convertToFullAddr(addr)
|
||||||
|
return gonet.ListenTCP(net.stack, fa, pn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) ListenTCP(addr *net.TCPAddr) (*gonet.TCPListener, error) {
|
||||||
|
if addr == nil {
|
||||||
|
return net.ListenTCPAddrPort(netip.AddrPort{})
|
||||||
|
}
|
||||||
|
ip, _ := netip.AddrFromSlice(addr.IP)
|
||||||
|
return net.ListenTCPAddrPort(netip.AddrPortFrom(ip, uint16(addr.Port)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) DialUDPAddrPort(laddr, raddr netip.AddrPort) (*gonet.UDPConn, error) {
|
||||||
|
var lfa, rfa *tcpip.FullAddress
|
||||||
|
var pn tcpip.NetworkProtocolNumber
|
||||||
|
if laddr.IsValid() || laddr.Port() > 0 {
|
||||||
|
var addr tcpip.FullAddress
|
||||||
|
addr, pn = convertToFullAddr(laddr)
|
||||||
|
lfa = &addr
|
||||||
|
}
|
||||||
|
if raddr.IsValid() || raddr.Port() > 0 {
|
||||||
|
var addr tcpip.FullAddress
|
||||||
|
addr, pn = convertToFullAddr(raddr)
|
||||||
|
rfa = &addr
|
||||||
|
}
|
||||||
|
return gonet.DialUDP(net.stack, lfa, rfa, pn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) ListenUDPAddrPort(laddr netip.AddrPort) (*gonet.UDPConn, error) {
|
||||||
|
return net.DialUDPAddrPort(laddr, netip.AddrPort{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) DialUDP(laddr, raddr *net.UDPAddr) (*gonet.UDPConn, error) {
|
||||||
|
var la, ra netip.AddrPort
|
||||||
|
if laddr != nil {
|
||||||
|
ip, _ := netip.AddrFromSlice(laddr.IP)
|
||||||
|
la = netip.AddrPortFrom(ip, uint16(laddr.Port))
|
||||||
|
}
|
||||||
|
if raddr != nil {
|
||||||
|
ip, _ := netip.AddrFromSlice(raddr.IP)
|
||||||
|
ra = netip.AddrPortFrom(ip, uint16(raddr.Port))
|
||||||
|
}
|
||||||
|
return net.DialUDPAddrPort(la, ra)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (net *Net) ListenUDP(laddr *net.UDPAddr) (*gonet.UDPConn, error) {
|
||||||
|
return net.DialUDP(laddr, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Net) HasV4() bool {
|
||||||
|
return n.hasV4
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Net) HasV6() bool {
|
||||||
|
return n.hasV6
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsDomainName(s string) bool {
|
||||||
|
l := len(s)
|
||||||
|
if l == 0 || l > 254 || l == 254 && s[l-1] != '.' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
last := byte('.')
|
||||||
|
nonNumeric := false
|
||||||
|
partlen := 0
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
c := s[i]
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_':
|
||||||
|
nonNumeric = true
|
||||||
|
partlen++
|
||||||
|
case '0' <= c && c <= '9':
|
||||||
|
partlen++
|
||||||
|
case c == '-':
|
||||||
|
if last == '.' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
partlen++
|
||||||
|
nonNumeric = true
|
||||||
|
case c == '.':
|
||||||
|
if last == '.' || last == '-' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if partlen > 63 || partlen == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
partlen = 0
|
||||||
|
}
|
||||||
|
last = c
|
||||||
|
}
|
||||||
|
if last == '-' || partlen > 63 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return nonNumeric
|
||||||
|
}
|
263
proxy/wireguard/wireguard.go
Normal file
263
proxy/wireguard/wireguard.go
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Some of codes are copied from https://github.com/octeep/wireproxy, license below.
|
||||||
|
|
||||||
|
Copyright (c) 2022 Wind T.F. Wong <octeep@pm.me>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
package wireguard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sagernet/wireguard-go/device"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/log"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/signal"
|
||||||
|
"github.com/xtls/xray-core/common/task"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
|
"github.com/xtls/xray-core/features/policy"
|
||||||
|
"github.com/xtls/xray-core/transport"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handler is an outbound connection that silently swallow the entire payload.
|
||||||
|
type Handler struct {
|
||||||
|
conf *DeviceConfig
|
||||||
|
net *Net
|
||||||
|
bind *netBindClient
|
||||||
|
policyManager policy.Manager
|
||||||
|
dns dns.Client
|
||||||
|
// cached configuration
|
||||||
|
ipc string
|
||||||
|
endpoints []netip.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new wireguard handler.
|
||||||
|
func New(ctx context.Context, conf *DeviceConfig) (*Handler, error) {
|
||||||
|
v := core.MustFromContext(ctx)
|
||||||
|
|
||||||
|
endpoints, err := parseEndpoints(conf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Handler{
|
||||||
|
conf: conf,
|
||||||
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
|
dns: v.GetFeature(dns.ClientType()).(dns.Client),
|
||||||
|
ipc: createIPCRequest(conf),
|
||||||
|
endpoints: endpoints,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process implements OutboundHandler.Dispatch().
|
||||||
|
func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||||
|
if h.bind == nil || h.bind.dialer != dialer || h.net == nil {
|
||||||
|
log.Record(&log.GeneralMessage{
|
||||||
|
Severity: log.Severity_Info,
|
||||||
|
Content: "switching dialer",
|
||||||
|
})
|
||||||
|
// bind := conn.NewStdNetBind() // TODO: conn.Bind wrapper for dialer
|
||||||
|
bind := &netBindClient{
|
||||||
|
dialer: dialer,
|
||||||
|
workers: int(h.conf.NumWorkers),
|
||||||
|
dns: h.dns,
|
||||||
|
}
|
||||||
|
|
||||||
|
net, err := h.makeVirtualTun(bind)
|
||||||
|
if err != nil {
|
||||||
|
bind.Close()
|
||||||
|
return newError("failed to create virtual tun interface").Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.net = net
|
||||||
|
if h.bind != nil {
|
||||||
|
h.bind.Close()
|
||||||
|
}
|
||||||
|
h.bind = bind
|
||||||
|
}
|
||||||
|
|
||||||
|
outbound := session.OutboundFromContext(ctx)
|
||||||
|
if outbound == nil || !outbound.Target.IsValid() {
|
||||||
|
return newError("target not specified")
|
||||||
|
}
|
||||||
|
// Destination of the inner request.
|
||||||
|
destination := outbound.Target
|
||||||
|
command := protocol.RequestCommandTCP
|
||||||
|
if destination.Network == net.Network_UDP {
|
||||||
|
command = protocol.RequestCommandUDP
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve dns
|
||||||
|
addr := destination.Address
|
||||||
|
if addr.Family().IsDomain() {
|
||||||
|
ips, err := h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
||||||
|
IPv4Enable: h.net.HasV4(),
|
||||||
|
IPv6Enable: h.net.HasV6(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return newError("failed to lookup DNS").Base(err)
|
||||||
|
} else if len(ips) == 0 {
|
||||||
|
return dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
addr = net.IPAddress(ips[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
p := h.policyManager.ForLevel(0)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
timer := signal.CancelAfterInactivity(ctx, cancel, p.Timeouts.ConnectionIdle)
|
||||||
|
addrPort := netip.AddrPortFrom(toNetIpAddr(addr), destination.Port.Value())
|
||||||
|
|
||||||
|
var requestFunc func() error
|
||||||
|
var responseFunc func() error
|
||||||
|
|
||||||
|
if command == protocol.RequestCommandTCP {
|
||||||
|
conn, err := h.net.DialContextTCPAddrPort(ctx, addrPort)
|
||||||
|
if err != nil {
|
||||||
|
return newError("failed to create TCP connection").Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
requestFunc = func() error {
|
||||||
|
defer timer.SetTimeout(p.Timeouts.DownlinkOnly)
|
||||||
|
return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer))
|
||||||
|
}
|
||||||
|
responseFunc = func() error {
|
||||||
|
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
|
||||||
|
return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
|
||||||
|
}
|
||||||
|
} else if command == protocol.RequestCommandUDP {
|
||||||
|
conn, err := h.net.DialUDPAddrPort(netip.AddrPort{}, addrPort)
|
||||||
|
if err != nil {
|
||||||
|
return newError("failed to create UDP connection").Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
requestFunc = func() error {
|
||||||
|
defer timer.SetTimeout(p.Timeouts.DownlinkOnly)
|
||||||
|
return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer))
|
||||||
|
}
|
||||||
|
responseFunc = func() error {
|
||||||
|
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
|
||||||
|
return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
responseDonePost := task.OnSuccess(responseFunc, task.Close(link.Writer))
|
||||||
|
if err := task.Run(ctx, requestFunc, responseDonePost); err != nil {
|
||||||
|
return newError("connection ends").Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialize the config into an IPC request
|
||||||
|
func createIPCRequest(conf *DeviceConfig) string {
|
||||||
|
var request bytes.Buffer
|
||||||
|
|
||||||
|
request.WriteString(fmt.Sprintf("private_key=%s\n", conf.SecretKey))
|
||||||
|
|
||||||
|
for _, peer := range conf.Peers {
|
||||||
|
request.WriteString(fmt.Sprintf("public_key=%s\nendpoint=%s\npersistent_keepalive_interval=%d\npreshared_key=%s\n",
|
||||||
|
peer.PublicKey, peer.Endpoint, peer.KeepAlive, peer.PreSharedKey))
|
||||||
|
|
||||||
|
for _, ip := range peer.AllowedIps {
|
||||||
|
request.WriteString(fmt.Sprintf("allowed_ip=%s\n", ip))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return request.String()[:request.Len()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert endpoint string to netip.Addr
|
||||||
|
func parseEndpoints(conf *DeviceConfig) ([]netip.Addr, error) {
|
||||||
|
endpoints := make([]netip.Addr, len(conf.Endpoint))
|
||||||
|
for i, str := range conf.Endpoint {
|
||||||
|
var addr netip.Addr
|
||||||
|
if strings.Contains(str, "/") {
|
||||||
|
prefix, err := netip.ParsePrefix(str)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
addr = prefix.Addr()
|
||||||
|
if prefix.Bits() != addr.BitLen() {
|
||||||
|
return nil, newError("interface address subnet should be /32 for IPv4 and /128 for IPv6")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
addr, err = netip.ParseAddr(str)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpoints[i] = addr
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoints, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates a tun interface on netstack given a configuration
|
||||||
|
func (h *Handler) makeVirtualTun(bind *netBindClient) (*Net, error) {
|
||||||
|
tun, tnet, err := CreateNetTUN(h.endpoints, h.dns, int(h.conf.Mtu))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bind.dnsOption.IPv4Enable = tnet.HasV4()
|
||||||
|
bind.dnsOption.IPv6Enable = tnet.HasV6()
|
||||||
|
|
||||||
|
// dev := device.NewDevice(tun, conn.NewDefaultBind(), nil /* device.NewLogger(device.LogLevelVerbose, "") */)
|
||||||
|
dev := device.NewDevice(tun, bind, &device.Logger{
|
||||||
|
Verbosef: func(format string, args ...any) {
|
||||||
|
log.Record(&log.GeneralMessage{
|
||||||
|
Severity: log.Severity_Debug,
|
||||||
|
Content: fmt.Sprintf(format, args...),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Errorf: func(format string, args ...any) {
|
||||||
|
log.Record(&log.GeneralMessage{
|
||||||
|
Severity: log.Severity_Error,
|
||||||
|
Content: fmt.Sprintf(format, args...),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}, int(h.conf.NumWorkers))
|
||||||
|
err = dev.IpcSet(h.ipc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dev.Up()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tnet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
common.Must(common.RegisterConfig((*DeviceConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
|
return New(ctx, config.(*DeviceConfig))
|
||||||
|
}))
|
||||||
|
}
|
@@ -142,6 +142,8 @@ func (s *clientConnections) openConnection(ctx context.Context, destAddr net.Add
|
|||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
ConnectionIDLength: 12,
|
ConnectionIDLength: 12,
|
||||||
KeepAlivePeriod: 0,
|
KeepAlivePeriod: 0,
|
||||||
|
HandshakeIdleTimeout: time.Second * 8,
|
||||||
|
MaxIdleTimeout: time.Second * 300,
|
||||||
Tracer: qlog.NewTracer(func(_ logging.Perspective, connID []byte) io.WriteCloser {
|
Tracer: qlog.NewTracer(func(_ logging.Perspective, connID []byte) io.WriteCloser {
|
||||||
return &QlogWriter{connID: connID}
|
return &QlogWriter{connID: connID}
|
||||||
}),
|
}),
|
||||||
|
@@ -106,6 +106,8 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
ConnectionIDLength: 12,
|
ConnectionIDLength: 12,
|
||||||
KeepAlivePeriod: 0,
|
KeepAlivePeriod: 0,
|
||||||
|
HandshakeIdleTimeout: time.Second * 8,
|
||||||
|
MaxIdleTimeout: time.Second * 300,
|
||||||
MaxIncomingStreams: 32,
|
MaxIncomingStreams: 32,
|
||||||
MaxIncomingUniStreams: -1,
|
MaxIncomingUniStreams: -1,
|
||||||
Tracer: qlog.NewTracer(func(_ logging.Perspective, connID []byte) io.WriteCloser {
|
Tracer: qlog.NewTracer(func(_ logging.Perspective, connID []byte) io.WriteCloser {
|
||||||
|
Reference in New Issue
Block a user