Compare commits

...

56 Commits

Author SHA1 Message Date
RPRX
f7c20b85dc v1.8.4 2023-08-29 07:20:10 +00:00
dyhkwong
b8bd243df5 Fix buffer.UDP destination override (#2356) 2023-08-29 07:12:36 +00:00
RPRX
e013dce1df Upgrade github.com/xtls/reality to 20230828171259
e426190d57
2023-08-28 17:37:57 +00:00
RPRX
d92002ad12 Dialer: Set TimeoutOnly for gctx and hctx
https://github.com/XTLS/Xray-core/issues/2232#issuecomment-1694570914

Thank @cty123 for testing

Fixes https://github.com/XTLS/Xray-core/issues/2232

BTW: Use `uConn.HandshakeContext(ctx)` in REALITY
2023-08-27 05:55:58 +00:00
cty
b24a4028f1 fix(app/router): fixed a bug in geoip matching with refactoring (#2489)
* Refactor the IP address matching with netipx library
* Add a regression test for previous bug

Fixes https://github.com/XTLS/Xray-core/issues/1933

---------

Co-authored-by: Loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com>
2023-08-26 15:11:37 +00:00
A1lo
10d6b06578 fix(transport): correctly release UDS locker file (#2305)
* fix(transport): correctly release UDS locker file

* use callback function to do some jobs after create listener
2023-08-26 07:35:44 -04:00
RPRX
2d5475f428 Update transport/internet/reality/reality.go
Fixes https://github.com/XTLS/Xray-core/issues/2491
2023-08-26 07:33:26 -04:00
RPRX
e02474ae15 Upgrade dependencies 2023-08-26 07:05:21 +00:00
RPRX
1a69baed17 Update workflows to use Go 1.21 2023-08-26 06:26:27 +00:00
douglarek
d616f6160d Fix go 1.21 build, see https://github.com/XTLS/Xray-core/issues/2466 2023-08-24 11:17:31 -04:00
yuhan6665
229851f621 Revert "Docker build use 1.20 go"
This reverts commit cd1d000860.
2023-08-24 11:13:12 -04:00
mengskysama
fce86aad33 fix(common): strmatcher match domain safety 2023-08-24 11:06:08 -04:00
yuhan6665
cd1d000860 Docker build use 1.20 go 2023-08-22 21:28:02 -04:00
computerscot
c1db1f4dce Add "Xray REALITY with 'steal oneself'" example to README
Step-by-step instructions for 'steal oneself'
2023-08-22 10:29:56 -04:00
dependabot[bot]
acadf5c0e9 Bump github.com/quic-go/quic-go from 0.37.6 to 0.38.0
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.37.6 to 0.38.0.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.37.6...v0.38.0)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-22 10:27:08 -04:00
dependabot[bot]
783ac10842 Bump github.com/quic-go/quic-go from 0.37.5 to 0.37.6
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.37.5 to 0.37.6.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.37.5...v0.37.6)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-20 22:28:24 -04:00
cty123
efe8f3f4d6 fix(config): fix grpc cofnig parsing when service name only has one '/' char 2023-08-20 22:19:13 -04:00
dependabot[bot]
599cfd09b0 Bump github.com/quic-go/quic-go from 0.37.4 to 0.37.5
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.37.4 to 0.37.5.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.37.4...v0.37.5)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-19 23:14:20 -04:00
iamybj
75c99e283a Update README.md
A better docker image of xray
2023-08-19 23:14:09 -04:00
cty123
a343d68944 fix(proxy): removed the udp payload length check when encryption is disabled 2023-08-19 23:13:43 -04:00
hax0r31337
f67167bb3b refactor(deps): replace github.com/golang/protobuf with google.golang.org/protobuf 2023-08-10 10:43:27 -04:00
dependabot[bot]
e584b71b60 Bump github.com/quic-go/quic-go from 0.37.3 to 0.37.4
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.37.3 to 0.37.4.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.37.3...v0.37.4)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-10 10:26:44 -04:00
dependabot[bot]
d11826ee54 Bump golang.org/x/net from 0.13.0 to 0.14.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.13.0 to 0.14.0.
- [Commits](https://github.com/golang/net/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-09 10:17:01 -04:00
dependabot[bot]
d4806c8e54 Bump github.com/quic-go/quic-go from 0.37.1 to 0.37.3
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.37.1 to 0.37.3.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.37.1...v0.37.3)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-08 10:26:17 -04:00
dependabot[bot]
cd547a3f43 Bump golang.org/x/crypto from 0.11.0 to 0.12.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.11.0 to 0.12.0.
- [Commits](https://github.com/golang/crypto/compare/v0.11.0...v0.12.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-08 10:25:42 -04:00
冬花ice
017b56adf5 Recognize .jsonc files automatically (#2398)
Closes https://github.com/XTLS/Xray-core/issues/2399
2023-08-06 06:47:31 +00:00
Loren Eteval
ce89b5d7de Add Furious to README/GUI Clients (#2405) 2023-08-06 06:30:37 +00:00
dependabot[bot]
a45c343b89 Bump golang.org/x/net from 0.12.0 to 0.13.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.12.0 to 0.13.0.
- [Commits](https://github.com/golang/net/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-02 10:12:31 -04:00
dependabot[bot]
81b27aa4cc Bump github.com/quic-go/quic-go from 0.36.2 to 0.37.1
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.36.2 to 0.37.1.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.36.2...v0.37.1)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-01 11:00:07 -04:00
dependabot[bot]
1e9d288b99 Bump google.golang.org/grpc from 1.56.2 to 1.57.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.56.2 to 1.57.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.56.2...v1.57.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-01 10:59:57 -04:00
RPRX
51769fdde1 H2 transport: Abandon client if client.Do(request) failed
See https://github.com/golang/go/issues/30702

Fixes https://github.com/XTLS/Xray-core/issues/2355
2023-07-22 06:06:25 +08:00
RPRX
e603b97ab4 Add NekoRay and V2rayU to README/GUI Clients
Closes https://github.com/XTLS/Xray-core/issues/2354
2023-07-21 14:42:09 +00:00
KatyushaScarlet
316034226c CI: Add Linux loong64 build task 2023-07-19 16:08:13 -04:00
dependabot[bot]
4a496f94e8 Bump github.com/refraction-networking/utls from 1.3.2 to 1.3.3
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.3.2 to 1.3.3.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.3.2...v1.3.3)

---
updated-dependencies:
- dependency-name: github.com/refraction-networking/utls
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 16:03:55 -04:00
cty123
b68a43f4fc fix: correct the logic of converting SocksAddr into net.Destination. 2023-07-19 16:01:35 -04:00
cty123
7aeca33729 fix: revert previous change on IsValid() function; add validation in getUoTConnection(); 2023-07-19 15:53:01 -04:00
cty123
2df418abf1 fix: Check if address is nil for IsValid() function. 2023-07-16 20:06:52 -04:00
cty123
8eb3cfe144 fix: Patch potential nil pointer deference in proxy::http::client::fillRequestHeader(). 2023-07-15 20:17:11 -04:00
dependabot[bot]
929f286c2c Bump github.com/quic-go/quic-go from 0.36.1 to 0.36.2
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.36.1 to 0.36.2.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.36.1...v0.36.2)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-13 12:48:20 -04:00
dependabot[bot]
dca57aab26 Bump google.golang.org/grpc from 1.56.1 to 1.56.2
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.56.1 to 1.56.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.56.1...v1.56.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-08 12:35:13 +00:00
RPRX
f0f3b417f7 Refactor: Fragmentation
5f5ae37571
9122d0f056
2023-07-06 16:30:39 +00:00
RPRX
6d4194415d Clean unnecessary code in Trojan 2023-07-06 15:18:05 +00:00
dependabot[bot]
846d3ebd6c Bump golang.org/x/net from 0.11.0 to 0.12.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.11.0 to 0.12.0.
- [Commits](https://github.com/golang/net/compare/v0.11.0...v0.12.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-06 06:36:02 +00:00
dependabot[bot]
a1ff507ef2 Bump golang.org/x/crypto from 0.10.0 to 0.11.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/crypto/compare/v0.10.0...v0.11.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-06 06:33:17 +00:00
dependabot[bot]
b870cc097b Bump golang.org/x/sys from 0.9.0 to 0.10.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.9.0 to 0.10.0.
- [Commits](https://github.com/golang/sys/compare/v0.9.0...v0.10.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-05 10:20:09 -04:00
dependabot[bot]
46d8bb58fc Bump github.com/quic-go/quic-go from 0.36.0 to 0.36.1 (#2286)
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.36.0 to 0.36.1.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.36.0...v0.36.1)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-04 01:21:02 +00:00
dependabot[bot]
34b68518fd Bump github.com/sagernet/sing from 0.2.6 to 0.2.7 (#2265)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.6 to 0.2.7.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.6...v0.2.7)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 08:04:42 +00:00
dependabot[bot]
fb0cd0db4d Bump google.golang.org/protobuf from 1.30.0 to 1.31.0 (#2264)
Bumps google.golang.org/protobuf from 1.30.0 to 1.31.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 08:04:26 +00:00
yuhan6665
a6c5c57930 Support regex matching with attr (#2258)
* Support regex matching with attr

* Add test case

* Optimizing regex parsing at core start

* simpliy
2023-06-27 08:04:09 +00:00
dependabot[bot]
07389eca96 Bump github.com/quic-go/quic-go from 0.35.1 to 0.36.0
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.35.1 to 0.36.0.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.35.1...v0.36.0)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-22 10:21:57 -04:00
dependabot[bot]
6152868dfe Bump google.golang.org/grpc from 1.56.0 to 1.56.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.56.0 to 1.56.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.56.0...v1.56.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-22 10:21:40 -04:00
Eken Chan
6d8fe7315f XRV should work without rawConn 2023-06-22 10:21:27 -04:00
dependabot[bot]
828a632076 Bump github.com/sagernet/sing from 0.2.5 to 0.2.6
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.2.5 to 0.2.6.
- [Commits](https://github.com/sagernet/sing/compare/v0.2.5...v0.2.6)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-21 10:10:30 -04:00
dependabot[bot]
449affc731 Bump github.com/miekg/dns from 1.1.54 to 1.1.55
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.54 to 1.1.55.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.54...v1.1.55)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-21 10:10:22 -04:00
RPRX
4f8f49024b Fix xray_test.go 2023-06-19 01:07:19 +00:00
RPRX
a9ed1a03aa Fix dns_proxy_test.go 2023-06-19 00:51:03 +00:00
87 changed files with 798 additions and 845 deletions

View File

@@ -22,6 +22,7 @@
"linux-ppc64le": { "friendlyName": "linux-ppc64le" }, "linux-ppc64le": { "friendlyName": "linux-ppc64le" },
"linux-ppc64": { "friendlyName": "linux-ppc64" }, "linux-ppc64": { "friendlyName": "linux-ppc64" },
"linux-riscv64": { "friendlyName": "linux-riscv64" }, "linux-riscv64": { "friendlyName": "linux-riscv64" },
"linux-loong64": { "friendlyName": "linux-loong64" },
"linux-s390x": { "friendlyName": "linux-s390x" }, "linux-s390x": { "friendlyName": "linux-s390x" },
"openbsd-386": { "friendlyName": "openbsd-32" }, "openbsd-386": { "friendlyName": "openbsd-32" },
"openbsd-amd64": { "friendlyName": "openbsd-64" }, "openbsd-amd64": { "friendlyName": "openbsd-64" },
@@ -31,4 +32,4 @@
"windows-amd64": { "friendlyName": "windows-64" }, "windows-amd64": { "friendlyName": "windows-64" },
"windows-arm64": { "friendlyName": "windows-arm64-v8a" }, "windows-arm64": { "friendlyName": "windows-arm64-v8a" },
"windows-arm7": { "friendlyName": "windows-arm32-v7a" } "windows-arm7": { "friendlyName": "windows-arm32-v7a" }
} }

View File

@@ -105,12 +105,14 @@ jobs:
goarch: arm goarch: arm
goarm: 7 goarm: 7
# BEGIN Other architectures # BEGIN Other architectures
# BEGIN riscv64 & ARM64 # BEGIN riscv64 & ARM64 & LOONG64
- goos: linux - goos: linux
goarch: arm64 goarch: arm64
- goos: linux - goos: linux
goarch: riscv64 goarch: riscv64
# END riscv64 & ARM64 - goos: linux
goarch: loong64
# END riscv64 & ARM64 & LOONG64
# BEGIN MIPS # BEGIN MIPS
- goos: linux - goos: linux
goarch: mips64 goarch: mips64
@@ -167,7 +169,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.20' go-version: '1.21'
check-latest: true check-latest: true
- name: Get project dependencies - name: Get project dependencies

View File

@@ -30,7 +30,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.20' go-version: '1.21'
check-latest: true check-latest: true
- name: Checkout codebase - name: Checkout codebase
uses: actions/checkout@v3 uses: actions/checkout@v3

View File

@@ -23,6 +23,7 @@
- Linux Script - Linux Script
- [XTLS/Xray-install](https://github.com/XTLS/Xray-install) - [XTLS/Xray-install](https://github.com/XTLS/Xray-install)
- Docker - Docker
- [iamybj/docker-xray](https://hub.docker.com/r/iamybj/docker-xray)
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray) - [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
- Web Panel - Web Panel
- [X-UI](https://github.com/FranzKafkaYu/x-ui), [X-UI-English](https://github.com/NidukaAkalanka/x-ui-english), [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [X-UI](https://github.com/diditra/x-ui) - [X-UI](https://github.com/FranzKafkaYu/x-ui), [X-UI-English](https://github.com/NidukaAkalanka/x-ui-english), [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [X-UI](https://github.com/diditra/x-ui)
@@ -54,6 +55,7 @@
- [XTLS Vision](https://github.com/chika0801/Xray-install) - [XTLS Vision](https://github.com/chika0801/Xray-install)
- [REALITY (English)](https://cscot.pages.dev/2023/03/02/Xray-REALITY-tutorial/) - [REALITY (English)](https://cscot.pages.dev/2023/03/02/Xray-REALITY-tutorial/)
- [XTLS-Iran-Reality (English)](https://github.com/SasukeFreestyle/XTLS-Iran-Reality) - [XTLS-Iran-Reality (English)](https://github.com/SasukeFreestyle/XTLS-Iran-Reality)
- [Xray REALITY with 'steal oneself' (English)](https://computerscot.github.io/vless-xtls-utls-reality-steal-oneself.html)
## GUI Clients ## GUI Clients
@@ -63,6 +65,8 @@
- [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray)) - [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray))
- Windows - Windows
- [v2rayN](https://github.com/2dust/v2rayN) - [v2rayN](https://github.com/2dust/v2rayN)
- [NekoRay](https://github.com/Matsuridayo/nekoray)
- [Furious](https://github.com/LorenEteval/Furious)
- [HiddifyN](https://github.com/hiddify/HiddifyN) - [HiddifyN](https://github.com/hiddify/HiddifyN)
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient) - [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
- Android - Android
@@ -73,10 +77,14 @@
- [Mango](https://github.com/arror/Mango) - [Mango](https://github.com/arror/Mango)
- [FoXray](https://apps.apple.com/app/foxray/id6448898396) - [FoXray](https://apps.apple.com/app/foxray/id6448898396)
- macOS arm64 & x64 - macOS arm64 & x64
- [V2rayU](https://github.com/yanue/V2rayU)
- [V2RayXS](https://github.com/tzmax/V2RayXS) - [V2RayXS](https://github.com/tzmax/V2RayXS)
- [Furious](https://github.com/LorenEteval/Furious)
- [FoXray](https://apps.apple.com/app/foxray/id6448898396) - [FoXray](https://apps.apple.com/app/foxray/id6448898396)
- Linux - Linux
- [v2rayA](https://github.com/v2rayA/v2rayA) - [v2rayA](https://github.com/v2rayA/v2rayA)
- [NekoRay](https://github.com/Matsuridayo/nekoray)
- [Furious](https://github.com/LorenEteval/Furious)
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX... ## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
@@ -87,6 +95,7 @@
- [xtlsapi](https://github.com/hiddify/xtlsapi) - [xtlsapi](https://github.com/hiddify/xtlsapi)
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite) - [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
- [XrayKit](https://github.com/arror/XrayKit) - [XrayKit](https://github.com/arror/XrayKit)
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
- [XrayR](https://github.com/XrayR-project/XrayR) - [XrayR](https://github.com/XrayR-project/XrayR)
- [XrayR-release](https://github.com/XrayR-project/XrayR-release) - [XrayR-release](https://github.com/XrayR-project/XrayR-release)
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board) - [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)

View File

@@ -4,7 +4,6 @@ package dispatcher
import ( import (
"context" "context"
"fmt"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -135,77 +134,10 @@ func (*DefaultDispatcher) Start() error {
// Close implements common.Closable. // Close implements common.Closable.
func (*DefaultDispatcher) Close() error { return nil } func (*DefaultDispatcher) Close() error { return nil }
func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sniffing session.SniffingRequest) (*transport.Link, *transport.Link) { func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *transport.Link) {
downOpt := pipe.OptionsFromContext(ctx) opt := pipe.OptionsFromContext(ctx)
upOpt := downOpt uplinkReader, uplinkWriter := pipe.New(opt...)
downlinkReader, downlinkWriter := pipe.New(opt...)
if network == net.Network_UDP {
var ip2domain *sync.Map // net.IP.String() => domain, this map is used by server side when client turn on fakedns
// Client will send domain address in the buffer.UDP.Address, server record all possible target IP addrs.
// When target replies, server will restore the domain and send back to client.
// Note: this map is not global but per connection context
upOpt = append(upOpt, pipe.OnTransmission(func(mb buf.MultiBuffer) buf.MultiBuffer {
for i, buffer := range mb {
if buffer.UDP == nil {
continue
}
addr := buffer.UDP.Address
if addr.Family().IsIP() {
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && fkr0.IsIPInIPPool(addr) && sniffing.Enabled {
domain := fkr0.GetDomainFromFakeDNS(addr)
if len(domain) > 0 {
buffer.UDP.Address = net.DomainAddress(domain)
newError("[fakedns client] override with domain: ", domain, " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
} else {
newError("[fakedns client] failed to find domain! :", addr.String(), " for xUDP buffer at ", i).AtWarning().WriteToLog(session.ExportIDToError(ctx))
}
}
} else {
if ip2domain == nil {
ip2domain = new(sync.Map)
newError("[fakedns client] create a new map").WriteToLog(session.ExportIDToError(ctx))
}
domain := addr.Domain()
ips, err := d.dns.LookupIP(domain, dns.IPOption{true, true, false})
if err == nil {
for _, ip := range ips {
ip2domain.Store(ip.String(), domain)
}
newError("[fakedns client] candidate ip: "+fmt.Sprintf("%v", ips), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
} else {
newError("[fakedns client] failed to look up IP for ", domain, " for xUDP buffer at ", i).Base(err).WriteToLog(session.ExportIDToError(ctx))
}
}
}
return mb
}))
downOpt = append(downOpt, pipe.OnTransmission(func(mb buf.MultiBuffer) buf.MultiBuffer {
for i, buffer := range mb {
if buffer.UDP == nil {
continue
}
addr := buffer.UDP.Address
if addr.Family().IsIP() {
if ip2domain == nil {
continue
}
if domain, found := ip2domain.Load(addr.IP().String()); found {
buffer.UDP.Address = net.DomainAddress(domain.(string))
newError("[fakedns client] restore domain: ", domain.(string), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
}
} else {
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok {
fakeIp := fkr0.GetFakeIPForDomain(addr.Domain())
buffer.UDP.Address = fakeIp[0]
newError("[fakedns client] restore FakeIP: ", buffer.UDP, fmt.Sprintf("%v", fakeIp), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
}
}
}
return mb
}))
}
uplinkReader, uplinkWriter := pipe.New(upOpt...)
downlinkReader, downlinkWriter := pipe.New(downOpt...)
inboundLink := &transport.Link{ inboundLink := &transport.Link{
Reader: downlinkReader, Reader: downlinkReader,
@@ -263,7 +195,7 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
protocolString = resComp.ProtocolForDomainResult() protocolString = resComp.ProtocolForDomainResult()
} }
for _, p := range request.OverrideDestinationForProtocol { for _, p := range request.OverrideDestinationForProtocol {
if strings.HasPrefix(protocolString, p) { if strings.HasPrefix(protocolString, p) || strings.HasPrefix(protocolString, p) {
return true return true
} }
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" && if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" &&
@@ -287,7 +219,8 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
panic("Dispatcher: Invalid destination.") panic("Dispatcher: Invalid destination.")
} }
ob := &session.Outbound{ ob := &session.Outbound{
Target: destination, OriginalTarget: destination,
Target: destination,
} }
ctx = session.ContextWithOutbound(ctx, ob) ctx = session.ContextWithOutbound(ctx, ob)
content := session.ContentFromContext(ctx) content := session.ContentFromContext(ctx)
@@ -295,9 +228,8 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
content = new(session.Content) content = new(session.Content)
ctx = session.ContextWithContent(ctx, content) ctx = session.ContextWithContent(ctx, content)
} }
sniffingRequest := content.SniffingRequest sniffingRequest := content.SniffingRequest
inbound, outbound := d.getLink(ctx, destination.Network, sniffingRequest) inbound, outbound := d.getLink(ctx)
if !sniffingRequest.Enabled { if !sniffingRequest.Enabled {
go d.routedDispatch(ctx, outbound, destination) go d.routedDispatch(ctx, outbound, destination)
} else { } else {
@@ -314,7 +246,15 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
domain := result.Domain() domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx)) newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
destination.Address = net.ParseAddress(domain) destination.Address = net.ParseAddress(domain)
if sniffingRequest.RouteOnly && result.Protocol() != "fakedns" { protocol := result.Protocol()
if resComp, ok := result.(SnifferResultComposite); ok {
protocol = resComp.ProtocolForDomainResult()
}
isFakeIP := false
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && ob.Target.Address.Family().IsIP() && fkr0.IsIPInIPPool(ob.Target.Address) {
isFakeIP = true
}
if sniffingRequest.RouteOnly && protocol != "fakedns" && protocol != "fakedns+others" && !isFakeIP {
ob.RouteTarget = destination ob.RouteTarget = destination
} else { } else {
ob.Target = destination ob.Target = destination
@@ -332,7 +272,8 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
return newError("Dispatcher: Invalid destination.") return newError("Dispatcher: Invalid destination.")
} }
ob := &session.Outbound{ ob := &session.Outbound{
Target: destination, OriginalTarget: destination,
Target: destination,
} }
ctx = session.ContextWithOutbound(ctx, ob) ctx = session.ContextWithOutbound(ctx, ob)
content := session.ContentFromContext(ctx) content := session.ContentFromContext(ctx)
@@ -356,7 +297,15 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
domain := result.Domain() domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx)) newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
destination.Address = net.ParseAddress(domain) destination.Address = net.ParseAddress(domain)
if sniffingRequest.RouteOnly && result.Protocol() != "fakedns" { protocol := result.Protocol()
if resComp, ok := result.(SnifferResultComposite); ok {
protocol = resComp.ProtocolForDomainResult()
}
isFakeIP := false
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && ob.Target.Address.Family().IsIP() && fkr0.IsIPInIPPool(ob.Target.Address) {
isFakeIP = true
}
if sniffingRequest.RouteOnly && protocol != "fakedns" && protocol != "fakedns+others" && !isFakeIP {
ob.RouteTarget = destination ob.RouteTarget = destination
} else { } else {
ob.Target = destination ob.Target = destination

View File

@@ -9,7 +9,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
v2net "github.com/xtls/xray-core/common/net" v2net "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
@@ -19,6 +18,7 @@ import (
"github.com/xtls/xray-core/features/extension" "github.com/xtls/xray-core/features/extension"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/transport/internet/tagged" "github.com/xtls/xray-core/transport/internet/tagged"
"google.golang.org/protobuf/proto"
) )
type Observer struct { type Observer struct {

View File

@@ -8,6 +8,7 @@ import (
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"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/mux" "github.com/xtls/xray-core/common/mux"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc" "github.com/xtls/xray-core/common/net/cnc"
@@ -166,6 +167,11 @@ func (h *Handler) Tag() string {
// Dispatch implements proxy.Outbound.Dispatch. // Dispatch implements proxy.Outbound.Dispatch.
func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) { func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
outbound := session.OutboundFromContext(ctx)
if outbound.Target.Network == net.Network_UDP && outbound.OriginalTarget.Address != nil && outbound.OriginalTarget.Address != outbound.Target.Address {
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: outbound.Target.Address, OriginalDest: outbound.OriginalTarget.Address}
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: outbound.Target.Address, OriginalDest: outbound.OriginalTarget.Address}
}
if h.mux != nil { if h.mux != nil {
test := func(err error) { test := func(err error) {
if err != nil { if err != nil {
@@ -175,7 +181,6 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
common.Interrupt(link.Writer) common.Interrupt(link.Writer)
} }
} }
outbound := session.OutboundFromContext(ctx)
if outbound.Target.Network == net.Network_UDP && outbound.Target.Port == 443 { if outbound.Target.Network == net.Network_UDP && outbound.Target.Port == 443 {
switch h.udp443 { switch h.udp443 {
case "reject": case "reject":

View File

@@ -11,6 +11,9 @@ import (
) )
func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) { func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) {
if dest.Address == nil {
return nil, newError("nil destination address")
}
if !dest.Address.Family().IsDomain() { if !dest.Address.Family().IsDomain() {
return nil, os.ErrInvalid return nil, os.ErrInvalid
} }

View File

@@ -4,7 +4,6 @@ import (
"context" "context"
"time" "time"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/mux" "github.com/xtls/xray-core/common/mux"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
@@ -12,6 +11,7 @@ import (
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/pipe" "github.com/xtls/xray-core/transport/pipe"
"google.golang.org/protobuf/proto"
) )
// Bridge is a component in reverse proxy, that relays connections from Portal to local address. // Bridge is a component in reverse proxy, that relays connections from Portal to local address.

View File

@@ -5,7 +5,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/golang/protobuf/proto"
"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/mux" "github.com/xtls/xray-core/common/mux"
@@ -15,6 +14,7 @@ import (
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/pipe" "github.com/xtls/xray-core/transport/pipe"
"google.golang.org/protobuf/proto"
) )
type Portal struct { type Portal struct {

View File

@@ -1,6 +1,7 @@
package router package router
import ( import (
"regexp"
"strings" "strings"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -282,18 +283,18 @@ func (m *ProtocolMatcher) Apply(ctx routing.Context) bool {
} }
type AttributeMatcher struct { type AttributeMatcher struct {
configuredKeys map[string]string configuredKeys map[string]*regexp.Regexp
} }
// Match implements attributes matching. // Match implements attributes matching.
func (m *AttributeMatcher) Match(attrs map[string]string) bool { func (m *AttributeMatcher) Match(attrs map[string]string) bool {
// headers are insensitive most likely. So we do a convert // header keys are case insensitive most likely. So we do a convert
httpHeaders := make(map[string]string) httpHeaders := make(map[string]string)
for key, value := range attrs { for key, value := range attrs {
httpHeaders[strings.ToLower(key)] = strings.ToLower(value) httpHeaders[strings.ToLower(key)] = value
} }
for key, value := range m.configuredKeys { for key, regex := range m.configuredKeys {
if a, ok := httpHeaders[key]; !ok || !strings.Contains(a, value) { if a, ok := httpHeaders[key]; !ok || !regex.MatchString(a) {
return false return false
} }
} }

View File

@@ -1,81 +1,49 @@
package router package router
import ( import (
"encoding/binary" "net/netip"
"sort" "strconv"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"go4.org/netipx"
) )
type ipv6 struct {
a uint64
b uint64
}
type GeoIPMatcher struct { type GeoIPMatcher struct {
countryCode string countryCode string
reverseMatch bool reverseMatch bool
ip4 []uint32 ip4 *netipx.IPSet
prefix4 []uint8 ip6 *netipx.IPSet
ip6 []ipv6
prefix6 []uint8
}
func normalize4(ip uint32, prefix uint8) uint32 {
return (ip >> (32 - prefix)) << (32 - prefix)
}
func normalize6(ip ipv6, prefix uint8) ipv6 {
if prefix <= 64 {
ip.a = (ip.a >> (64 - prefix)) << (64 - prefix)
ip.b = 0
} else {
ip.b = (ip.b >> (128 - prefix)) << (128 - prefix)
}
return ip
} }
func (m *GeoIPMatcher) Init(cidrs []*CIDR) error { func (m *GeoIPMatcher) Init(cidrs []*CIDR) error {
ip4Count := 0 var builder4, builder6 netipx.IPSetBuilder
ip6Count := 0
for _, cidr := range cidrs { for _, cidr := range cidrs {
ip := cidr.Ip ip := net.IP(cidr.GetIp())
ipPrefixString := ip.String() + "/" + strconv.Itoa(int(cidr.GetPrefix()))
ipPrefix, err := netip.ParsePrefix(ipPrefixString)
if err != nil {
return err
}
switch len(ip) { switch len(ip) {
case 4: case net.IPv4len:
ip4Count++ builder4.AddPrefix(ipPrefix)
case 16: case net.IPv6len:
ip6Count++ builder6.AddPrefix(ipPrefix)
default:
return newError("unexpect ip length: ", len(ip))
} }
} }
cidrList := CIDRList(cidrs) if ip4, err := builder4.IPSet(); err != nil {
sort.Sort(&cidrList) return err
} else {
m.ip4 = ip4
}
m.ip4 = make([]uint32, 0, ip4Count) if ip6, err := builder6.IPSet(); err != nil {
m.prefix4 = make([]uint8, 0, ip4Count) return err
m.ip6 = make([]ipv6, 0, ip6Count) } else {
m.prefix6 = make([]uint8, 0, ip6Count) m.ip6 = ip6
for _, cidr := range cidrList {
ip := cidr.Ip
prefix := uint8(cidr.Prefix)
switch len(ip) {
case 4:
m.ip4 = append(m.ip4, normalize4(binary.BigEndian.Uint32(ip), prefix))
m.prefix4 = append(m.prefix4, prefix)
case 16:
ip6 := ipv6{
a: binary.BigEndian.Uint64(ip[0:8]),
b: binary.BigEndian.Uint64(ip[8:16]),
}
ip6 = normalize6(ip6, prefix)
m.ip6 = append(m.ip6, ip6)
m.prefix6 = append(m.prefix6, prefix)
}
} }
return nil return nil
@@ -85,91 +53,37 @@ func (m *GeoIPMatcher) SetReverseMatch(isReverseMatch bool) {
m.reverseMatch = isReverseMatch m.reverseMatch = isReverseMatch
} }
func (m *GeoIPMatcher) match4(ip uint32) bool { func (m *GeoIPMatcher) match4(ip net.IP) bool {
if len(m.ip4) == 0 { nip, ok := netipx.FromStdIP(ip)
if !ok {
return false return false
} }
if ip < m.ip4[0] { return m.ip4.Contains(nip)
return false
}
size := uint32(len(m.ip4))
l := uint32(0)
r := size
for l < r {
x := ((l + r) >> 1)
if ip < m.ip4[x] {
r = x
continue
}
nip := normalize4(ip, m.prefix4[x])
if nip == m.ip4[x] {
return true
}
l = x + 1
}
return l > 0 && normalize4(ip, m.prefix4[l-1]) == m.ip4[l-1]
} }
func less6(a ipv6, b ipv6) bool { func (m *GeoIPMatcher) match6(ip net.IP) bool {
return a.a < b.a || (a.a == b.a && a.b < b.b) nip, ok := netipx.FromStdIP(ip)
} if !ok {
func (m *GeoIPMatcher) match6(ip ipv6) bool {
if len(m.ip6) == 0 {
return false return false
} }
if less6(ip, m.ip6[0]) { return m.ip6.Contains(nip)
return false
}
size := uint32(len(m.ip6))
l := uint32(0)
r := size
for l < r {
x := (l + r) / 2
if less6(ip, m.ip6[x]) {
r = x
continue
}
if normalize6(ip, m.prefix6[x]) == m.ip6[x] {
return true
}
l = x + 1
}
return l > 0 && normalize6(ip, m.prefix6[l-1]) == m.ip6[l-1]
} }
// Match returns true if the given ip is included by the GeoIP. // Match returns true if the given ip is included by the GeoIP.
func (m *GeoIPMatcher) Match(ip net.IP) bool { func (m *GeoIPMatcher) Match(ip net.IP) bool {
isMatched := false
switch len(ip) { switch len(ip) {
case 4: case net.IPv4len:
if m.reverseMatch { isMatched = m.match4(ip)
return !m.match4(binary.BigEndian.Uint32(ip)) case net.IPv6len:
} isMatched = m.match6(ip)
return m.match4(binary.BigEndian.Uint32(ip))
case 16:
if m.reverseMatch {
return !m.match6(ipv6{
a: binary.BigEndian.Uint64(ip[0:8]),
b: binary.BigEndian.Uint64(ip[8:16]),
})
}
return m.match6(ipv6{
a: binary.BigEndian.Uint64(ip[0:8]),
b: binary.BigEndian.Uint64(ip[8:16]),
})
default:
return false
} }
if m.reverseMatch {
return !isMatched
}
return isMatched
} }
// GeoIPMatcherContainer is a container for GeoIPMatchers. It keeps unique copies of GeoIPMatcher by country code. // GeoIPMatcherContainer is a container for GeoIPMatchers. It keeps unique copies of GeoIPMatcher by country code.

View File

@@ -5,12 +5,12 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/router" "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform" "github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
"google.golang.org/protobuf/proto"
) )
func init() { func init() {
@@ -53,7 +53,7 @@ func TestGeoIPMatcherContainer(t *testing.T) {
} }
func TestGeoIPMatcher(t *testing.T) { func TestGeoIPMatcher(t *testing.T) {
cidrList := router.CIDRList{ cidrList := []*router.CIDR{
{Ip: []byte{0, 0, 0, 0}, Prefix: 8}, {Ip: []byte{0, 0, 0, 0}, Prefix: 8},
{Ip: []byte{10, 0, 0, 0}, Prefix: 8}, {Ip: []byte{10, 0, 0, 0}, Prefix: 8},
{Ip: []byte{100, 64, 0, 0}, Prefix: 10}, {Ip: []byte{100, 64, 0, 0}, Prefix: 10},
@@ -124,8 +124,40 @@ func TestGeoIPMatcher(t *testing.T) {
} }
} }
func TestGeoIPMatcherRegression(t *testing.T) {
cidrList := []*router.CIDR{
{Ip: []byte{98, 108, 20, 0}, Prefix: 22},
{Ip: []byte{98, 108, 20, 0}, Prefix: 23},
}
matcher := &router.GeoIPMatcher{}
common.Must(matcher.Init(cidrList))
testCases := []struct {
Input string
Output bool
}{
{
Input: "98.108.22.11",
Output: true,
},
{
Input: "98.108.25.0",
Output: false,
},
}
for _, testCase := range testCases {
ip := net.ParseAddress(testCase.Input).IP()
actual := matcher.Match(ip)
if actual != testCase.Output {
t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
}
}
}
func TestGeoIPReverseMatcher(t *testing.T) { func TestGeoIPReverseMatcher(t *testing.T) {
cidrList := router.CIDRList{ cidrList := []*router.CIDR{
{Ip: []byte{8, 8, 8, 8}, Prefix: 32}, {Ip: []byte{8, 8, 8, 8}, Prefix: 32},
{Ip: []byte{91, 108, 4, 0}, Prefix: 16}, {Ip: []byte{91, 108, 4, 0}, Prefix: 16},
} }

View File

@@ -6,7 +6,6 @@ import (
"strconv" "strconv"
"testing" "testing"
"github.com/golang/protobuf/proto"
. "github.com/xtls/xray-core/app/router" . "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -18,6 +17,7 @@ import (
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
routing_session "github.com/xtls/xray-core/features/routing/session" routing_session "github.com/xtls/xray-core/features/routing/session"
"google.golang.org/protobuf/proto"
) )
func init() { func init() {
@@ -319,6 +319,19 @@ func TestRoutingRule(t *testing.T) {
}, },
}, },
}, },
{
rule: &RoutingRule{
Attributes: map[string]string{
"Custom": "p([a-z]+)ch",
},
},
test: []ruleTest{
{
input: withContent(&session.Content{Attributes: map[string]string{"custom": "peach"}}),
output: true,
},
},
},
} }
for _, test := range cases { for _, test := range cases {

View File

@@ -1,6 +1,7 @@
package router package router
import ( import (
"regexp"
"strings" "strings"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -8,45 +9,6 @@ import (
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
) )
// CIDRList is an alias of []*CIDR to provide sort.Interface.
type CIDRList []*CIDR
// Len implements sort.Interface.
func (l *CIDRList) Len() int {
return len(*l)
}
// Less implements sort.Interface.
func (l *CIDRList) Less(i int, j int) bool {
ci := (*l)[i]
cj := (*l)[j]
if len(ci.Ip) < len(cj.Ip) {
return true
}
if len(ci.Ip) > len(cj.Ip) {
return false
}
for k := 0; k < len(ci.Ip); k++ {
if ci.Ip[k] < cj.Ip[k] {
return true
}
if ci.Ip[k] > cj.Ip[k] {
return false
}
}
return ci.Prefix < cj.Prefix
}
// Swap implements sort.Interface.
func (l *CIDRList) Swap(i int, j int) {
(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
}
type Rule struct { type Rule struct {
Tag string Tag string
Balancer *Balancer Balancer *Balancer
@@ -145,9 +107,9 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
} }
if len(rr.Attributes) > 0 { if len(rr.Attributes) > 0 {
configuredKeys := make(map[string]string) configuredKeys := make(map[string]*regexp.Regexp)
for key, value := range rr.Attributes { for key, value := range rr.Attributes {
configuredKeys[strings.ToLower(key)] = strings.ToLower(value) configuredKeys[strings.ToLower(key)] = regexp.MustCompile(value)
} }
conds.Add(&AttributeMatcher{configuredKeys}) conds.Add(&AttributeMatcher{configuredKeys})
} }

38
common/buf/override.go Normal file
View File

@@ -0,0 +1,38 @@
package buf
import (
"github.com/xtls/xray-core/common/net"
)
type EndpointOverrideReader struct {
Reader
Dest net.Address
OriginalDest net.Address
}
func (r *EndpointOverrideReader) ReadMultiBuffer() (MultiBuffer, error) {
mb, err := r.Reader.ReadMultiBuffer()
if err == nil {
for _, b := range mb {
if b.UDP != nil && b.UDP.Address == r.OriginalDest {
b.UDP.Address = r.Dest
}
}
}
return mb, err
}
type EndpointOverrideWriter struct {
Writer
Dest net.Address
OriginalDest net.Address
}
func (w *EndpointOverrideWriter) WriteMultiBuffer(mb MultiBuffer) error {
for _, b := range mb {
if b.UDP != nil && b.UDP.Address == w.Dest {
b.UDP.Address = w.OriginalDest
}
}
return w.Writer.WriteMultiBuffer(mb)
}

View File

@@ -1,10 +1,9 @@
package serial package serial
import ( import (
"errors" "google.golang.org/protobuf/proto"
"reflect" "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"github.com/golang/protobuf/proto"
) )
// ToTypedMessage converts a proto Message into TypedMessage. // ToTypedMessage converts a proto Message into TypedMessage.
@@ -21,16 +20,17 @@ func ToTypedMessage(message proto.Message) *TypedMessage {
// GetMessageType returns the name of this proto Message. // GetMessageType returns the name of this proto Message.
func GetMessageType(message proto.Message) string { func GetMessageType(message proto.Message) string {
return proto.MessageName(message) return string(message.ProtoReflect().Descriptor().FullName())
} }
// GetInstance creates a new instance of the message with messageType. // GetInstance creates a new instance of the message with messageType.
func GetInstance(messageType string) (interface{}, error) { func GetInstance(messageType string) (interface{}, error) {
mType := proto.MessageType(messageType) messageTypeDescriptor := protoreflect.FullName(messageType)
if mType == nil || mType.Elem() == nil { mType, err := protoregistry.GlobalTypes.FindMessageByName(messageTypeDescriptor)
return nil, errors.New("Serial: Unknown type: " + messageType) if err != nil {
return nil, err
} }
return reflect.New(mType.Elem()).Interface(), nil return mType.New().Interface(), nil
} }
// GetInstance converts current TypedMessage into a proto Message. // GetInstance converts current TypedMessage into a proto Message.

View File

@@ -55,8 +55,9 @@ type Inbound struct {
// Outbound is the metadata of an outbound connection. // Outbound is the metadata of an outbound connection.
type Outbound struct { type Outbound struct {
// Target address of the outbound connection. // Target address of the outbound connection.
Target net.Destination OriginalTarget net.Destination
RouteTarget net.Destination Target net.Destination
RouteTarget net.Destination
// Gateway address // Gateway address
Gateway net.Address Gateway net.Address
} }

View File

@@ -18,19 +18,25 @@ func ToNetwork(network string) net.Network {
} }
func ToDestination(socksaddr M.Socksaddr, network net.Network) net.Destination { func ToDestination(socksaddr M.Socksaddr, network net.Network) net.Destination {
// IsFqdn() implicitly checks if the domain name is valid
if socksaddr.IsFqdn() { if socksaddr.IsFqdn() {
return net.Destination{ return net.Destination{
Network: network, Network: network,
Address: net.DomainAddress(socksaddr.Fqdn), Address: net.DomainAddress(socksaddr.Fqdn),
Port: net.Port(socksaddr.Port), Port: net.Port(socksaddr.Port),
} }
} else { }
// IsIP() implicitly checks if the IP address is valid
if socksaddr.IsIP() {
return net.Destination{ return net.Destination{
Network: network, Network: network,
Address: net.IPAddress(socksaddr.Addr.AsSlice()), Address: net.IPAddress(socksaddr.Addr.AsSlice()),
Port: net.Port(socksaddr.Port), Port: net.Port(socksaddr.Port),
} }
} }
return net.Destination{}
} }
func ToSocksaddr(destination net.Destination) M.Socksaddr { func ToSocksaddr(destination net.Destination) M.Socksaddr {

View File

@@ -225,7 +225,11 @@ func (ac *ACAutomaton) Match(s string) bool {
// 2. the match string is through a fail edge. NOT FULL MATCH // 2. the match string is through a fail edge. NOT FULL MATCH
// 2.1 Through a fail edge, but there exists a valid node. SUBSTR // 2.1 Through a fail edge, but there exists a valid node. SUBSTR
for i := len(s) - 1; i >= 0; i-- { for i := len(s) - 1; i >= 0; i-- {
idx := char2Index[s[i]] chr := int(s[i])
if chr >= len(char2Index) {
return false
}
idx := char2Index[chr]
fullMatch = fullMatch && ac.trie[node][idx].edgeType fullMatch = fullMatch && ac.trie[node][idx].edgeType
node = ac.trie[node][idx].nextNode node = ac.trie[node][idx].nextNode
switch ac.exists[node].matchType { switch ac.exists[node].matchType {

View File

@@ -217,6 +217,10 @@ func TestACAutomaton(t *testing.T) {
pattern: "vvgoogle.com", pattern: "vvgoogle.com",
res: true, res: true,
}, },
{
pattern: "½",
res: false,
},
} }
for _, test := range cases2Output { for _, test := range cases2Output {
if m := ac.Match(test.pattern); m != test.res { if m := ac.Match(test.pattern); m != test.res {
@@ -224,7 +228,6 @@ func TestACAutomaton(t *testing.T) {
} }
} }
} }
{ {
cases3Input := []struct { cases3Input := []struct {
pattern string pattern string

View File

@@ -4,11 +4,11 @@ import (
"io" "io"
"strings" "strings"
"github.com/golang/protobuf/proto"
"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/cmdarg" "github.com/xtls/xray-core/common/cmdarg"
"github.com/xtls/xray-core/main/confloader" "github.com/xtls/xray-core/main/confloader"
"google.golang.org/protobuf/proto"
) )
// ConfigFormat is a configurable format of Xray config file. // ConfigFormat is a configurable format of Xray config file.
@@ -57,7 +57,7 @@ func GetFormatByExtension(ext string) string {
return "yaml" return "yaml"
case "toml": case "toml":
return "toml" return "toml"
case "json": case "json", "jsonc":
return "json" return "json"
default: default:
return "" return ""

View File

@@ -21,7 +21,7 @@ import (
var ( var (
Version_x byte = 1 Version_x byte = 1
Version_y byte = 8 Version_y byte = 8
Version_z byte = 3 Version_z byte = 4
) )
var ( var (

View File

@@ -7,7 +7,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/golang/protobuf/proto"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/xtls/xray-core/app/dispatcher" "github.com/xtls/xray-core/app/dispatcher"
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
@@ -18,6 +17,7 @@ import (
"github.com/xtls/xray-core/proxy/freedom" "github.com/xtls/xray-core/proxy/freedom"
"github.com/xtls/xray-core/testing/servers/tcp" "github.com/xtls/xray-core/testing/servers/tcp"
"github.com/xtls/xray-core/testing/servers/udp" "github.com/xtls/xray-core/testing/servers/udp"
"google.golang.org/protobuf/proto"
) )
func xor(b []byte) []byte { func xor(b []byte) []byte {

View File

@@ -3,7 +3,6 @@ package core_test
import ( import (
"testing" "testing"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/dispatcher" "github.com/xtls/xray-core/app/dispatcher"
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -19,6 +18,7 @@ import (
"github.com/xtls/xray-core/proxy/vmess" "github.com/xtls/xray-core/proxy/vmess"
"github.com/xtls/xray-core/proxy/vmess/outbound" "github.com/xtls/xray-core/proxy/vmess/outbound"
"github.com/xtls/xray-core/testing/servers/tcp" "github.com/xtls/xray-core/testing/servers/tcp"
"google.golang.org/protobuf/proto"
) )
func TestXrayDependency(t *testing.T) { func TestXrayDependency(t *testing.T) {

View File

@@ -3,8 +3,8 @@ package extension
import ( import (
"context" "context"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/features" "github.com/xtls/xray-core/features"
"google.golang.org/protobuf/proto"
) )
type Observatory interface { type Observatory interface {

50
go.mod
View File

@@ -1,32 +1,32 @@
module github.com/xtls/xray-core module github.com/xtls/xray-core
go 1.20 go 1.21
require ( require (
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.3
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/miekg/dns v1.1.54 github.com/miekg/dns v1.1.55
github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml v1.9.5
github.com/pires/go-proxyproto v0.7.0 github.com/pires/go-proxyproto v0.7.0
github.com/quic-go/quic-go v0.35.1 github.com/quic-go/quic-go v0.38.1
github.com/refraction-networking/utls v1.3.2 github.com/refraction-networking/utls v1.4.3
github.com/sagernet/sing v0.2.5 github.com/sagernet/sing v0.2.9
github.com/sagernet/sing-shadowsocks v0.2.2 github.com/sagernet/sing-shadowsocks v0.2.4
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c 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.4 github.com/stretchr/testify v1.8.4
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
github.com/xtls/reality v0.0.0-20230613075828-e07c3b04b983 github.com/xtls/reality v0.0.0-20230828171259-e426190d57f6
golang.org/x/crypto v0.10.0 go4.org/netipx v0.0.0-20230824141953-6213f710f925
golang.org/x/net v0.11.0 golang.org/x/crypto v0.12.0
golang.org/x/net v0.14.0
golang.org/x/sync v0.3.0 golang.org/x/sync v0.3.0
golang.org/x/sys v0.9.0 golang.org/x/sys v0.11.0
google.golang.org/grpc v1.56.0 google.golang.org/grpc v1.57.0
google.golang.org/protobuf v1.30.0 google.golang.org/protobuf v1.31.0
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c gvisor.dev/gvisor v0.0.0-20230822212503-5bf4e5f98744
h12.io/socks v1.0.3 h12.io/socks v1.0.3
lukechampine.com/blake3 v1.2.1 lukechampine.com/blake3 v1.2.1
) )
@@ -36,24 +36,24 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
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/gaukas/godicttls v0.0.3 // indirect github.com/gaukas/godicttls v0.0.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/btree v1.1.2 // indirect github.com/google/btree v1.1.2 // indirect
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f // indirect
github.com/klauspost/compress v1.16.6 // indirect github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/onsi/ginkgo/v2 v2.11.0 // indirect github.com/onsi/ginkgo/v2 v2.12.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
go.uber.org/atomic v1.11.0 // indirect go.uber.org/atomic v1.11.0 // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
golang.org/x/mod v0.11.0 // indirect golang.org/x/mod v0.12.0 // indirect
golang.org/x/text v0.10.0 // indirect golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.10.0 // indirect golang.org/x/tools v0.12.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // 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
) )

97
go.sum
View File

@@ -27,14 +27,15 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gaukas/godicttls v0.0.3 h1:YNDIf0d9adcxOijiLrEzpfZGAkNwLRzPaG6OjU7EITk= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
github.com/gaukas/godicttls v0.0.3/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -60,8 +61,8 @@ 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-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9SN1TigNLn9ZnF3W4SYRKq2gAHs= github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f h1:pDhu5sgp8yJlEF/g6osliIIpF9K4F5jvkULXa4daRDQ=
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
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=
@@ -75,8 +76,8 @@ 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.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@@ -89,15 +90,16 @@ github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm
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/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
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.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI=
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ=
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
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=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
@@ -112,21 +114,19 @@ github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
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/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
github.com/quic-go/quic-go v0.35.1 h1:b0kzj6b/cQAf05cT0CkQubHM31wiA+xH3IBkxP62poo= github.com/refraction-networking/utls v1.4.3 h1:BdWS3BSzCwWCFfMIXP3mjLAyQkdmog7diaD/OqFbAzM=
github.com/quic-go/quic-go v0.35.1/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g= github.com/refraction-networking/utls v1.4.3/go.mod h1:4u9V/awOSBrRw6+federGmVJQfPtemEqLBXkML1b0bo=
github.com/refraction-networking/utls v1.3.2 h1:o+AkWB57mkcoW36ET7uJ002CpBWHu0KPxi6vzxvPnv8=
github.com/refraction-networking/utls v1.3.2/go.mod h1:fmoaOww2bxzzEpIKOebIsnBvjQpqP7L2vcm/9KUfm/E=
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/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.2.5 h1:N8sUluR8GZvR9DqUiH3FA3vBb4m/EDdOVTYUrDzJvmY= github.com/sagernet/sing v0.2.9 h1:3wsTz+JG5Wzy65eZnh6AuCrD2QqcRF6Iq6f7ttmJsAo=
github.com/sagernet/sing v0.2.5/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing v0.2.9/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
github.com/sagernet/sing-shadowsocks v0.2.2 h1:ezSdVhrmIcwDXmCZF3bOJVMuVtTQWpda+1Op+Ie2TA4= github.com/sagernet/sing-shadowsocks v0.2.4 h1:s/CqXlvFAZhlIoHWUwPw5CoNnQ9Ibki9pckjuugtVfY=
github.com/sagernet/sing-shadowsocks v0.2.2/go.mod h1:JIBWG6a7orB2HxBxYElViQFLUQxFVG7DuqIj8gD7uCQ= github.com/sagernet/sing-shadowsocks v0.2.4/go.mod h1:80fNKP0wnqlu85GZXV1H1vDPC/2t+dQbFggOw4XuFUM=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo= 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/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=
@@ -166,29 +166,31 @@ github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU= github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/xtls/reality v0.0.0-20230613075828-e07c3b04b983 h1:AMyzgjkh54WocjQSlCnT1LhDc/BKiUqtNOv40AkpURs= github.com/xtls/reality v0.0.0-20230828171259-e426190d57f6 h1:T+YCYGfFdzyaKTDCdZn/hEiKvsw6yUfd+e4hze0rCUw=
github.com/xtls/reality v0.0.0-20230613075828-e07c3b04b983/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y= github.com/xtls/reality v0.0.0-20230828171259-e426190d57f6/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/atomic v1.11.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=
go4.org/netipx v0.0.0-20230824141953-6213f710f925 h1:eeQDDVKFkx0g4Hyy8pHgmZaK0EqB4SD6rvKbUdN3ziQ=
go4.org/netipx v0.0.0-20230824141953-6213f710f925/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
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.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
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-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
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=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -200,8 +202,8 @@ golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
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.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
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=
@@ -225,14 +227,14 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.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/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.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
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.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
@@ -244,8 +246,8 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
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=
@@ -262,20 +264,21 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
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/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
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.56.0 h1:+y7Bs8rtMd07LeXmL3NxcTLn7mUkbKZqEpPhMNkwJEE= google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
google.golang.org/grpc v1.56.0/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0/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-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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=
@@ -286,8 +289,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-20230822212503-5bf4e5f98744 h1:tE44CyJgxEGzoPtHs9GI7ddKdgEGCREQBP54AmaVM+I=
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM= gvisor.dev/gvisor v0.0.0-20230822212503-5bf4e5f98744/go.mod h1:lYEMhXbxgudVhALYsMQrBaUAjM3NMinh8mKL1CJv7rc=
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=

View File

@@ -3,9 +3,9 @@ package conf
import ( import (
"encoding/json" "encoding/json"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/proxy/blackhole" "github.com/xtls/xray-core/proxy/blackhole"
"google.golang.org/protobuf/proto"
) )
type NoneResponse struct{} type NoneResponse struct{}

View File

@@ -1,6 +1,6 @@
package conf package conf
import "github.com/golang/protobuf/proto" import "google.golang.org/protobuf/proto"
type Buildable interface { type Buildable interface {
Build() (proto.Message, error) Build() (proto.Message, error)

View File

@@ -1,9 +1,9 @@
package conf package conf
import ( import (
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/proxy/dns" "github.com/xtls/xray-core/proxy/dns"
"google.golang.org/protobuf/proto"
) )
type DNSOutboundConfig struct { type DNSOutboundConfig struct {

View File

@@ -27,6 +27,7 @@ func TestDnsProxyConfig(t *testing.T) {
Address: net.NewIPOrDomain(net.IPAddress([]byte{8, 8, 8, 8})), Address: net.NewIPOrDomain(net.IPAddress([]byte{8, 8, 8, 8})),
Port: 53, Port: 53,
}, },
Non_IPQuery: "drop",
}, },
}, },
}) })

View File

@@ -6,7 +6,6 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/dns" "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/app/router" "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -14,6 +13,7 @@ import (
"github.com/xtls/xray-core/common/platform" "github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
. "github.com/xtls/xray-core/infra/conf" . "github.com/xtls/xray-core/infra/conf"
"google.golang.org/protobuf/proto"
) )
func init() { func init() {

View File

@@ -1,8 +1,8 @@
package conf package conf
import ( import (
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/proxy/dokodemo" "github.com/xtls/xray-core/proxy/dokodemo"
"google.golang.org/protobuf/proto"
) )
type DokodemoConfig struct { type DokodemoConfig struct {

View File

@@ -5,10 +5,10 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/golang/protobuf/proto"
v2net "github.com/xtls/xray-core/common/net" v2net "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/proxy/freedom" "github.com/xtls/xray-core/proxy/freedom"
"google.golang.org/protobuf/proto"
) )
type FreedomConfig struct { type FreedomConfig struct {
@@ -39,91 +39,89 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
} }
if c.Fragment != nil { if c.Fragment != nil {
if len(c.Fragment.Interval) == 0 || len(c.Fragment.Length) == 0 { config.Fragment = new(freedom.Fragment)
return nil, newError("Invalid interval or length")
}
intervalMinMax := strings.Split(c.Fragment.Interval, "-")
var minInterval, maxInterval int64
var err, err2 error var err, err2 error
if len(intervalMinMax) == 2 {
minInterval, err = strconv.ParseInt(intervalMinMax[0], 10, 64)
maxInterval, err2 = strconv.ParseInt(intervalMinMax[1], 10, 64)
} else {
minInterval, err = strconv.ParseInt(intervalMinMax[0], 10, 64)
maxInterval = minInterval
}
if err != nil {
return nil, newError("Invalid minimum interval: ", err).Base(err)
}
if err2 != nil {
return nil, newError("Invalid maximum interval: ", err2).Base(err2)
}
lengthMinMax := strings.Split(c.Fragment.Length, "-")
var minLength, maxLength int64
if len(lengthMinMax) == 2 {
minLength, err = strconv.ParseInt(lengthMinMax[0], 10, 64)
maxLength, err2 = strconv.ParseInt(lengthMinMax[1], 10, 64)
} else {
minLength, err = strconv.ParseInt(lengthMinMax[0], 10, 64)
maxLength = minLength
}
if err != nil {
return nil, newError("Invalid minimum length: ", err).Base(err)
}
if err2 != nil {
return nil, newError("Invalid maximum length: ", err2).Base(err2)
}
if minInterval > maxInterval {
minInterval, maxInterval = maxInterval, minInterval
}
if minLength > maxLength {
minLength, maxLength = maxLength, minLength
}
config.Fragment = &freedom.Fragment{
MinInterval: int32(minInterval),
MaxInterval: int32(maxInterval),
MinLength: int32(minLength),
MaxLength: int32(maxLength),
}
switch strings.ToLower(c.Fragment.Packets) { switch strings.ToLower(c.Fragment.Packets) {
case "tlshello": case "tlshello":
// TLS Hello Fragmentation (into multiple handshake messages) // TLS Hello Fragmentation (into multiple handshake messages)
config.Fragment.StartPacket = 0 config.Fragment.PacketsFrom = 0
config.Fragment.EndPacket = 1 config.Fragment.PacketsTo = 1
case "": case "":
// TCP Segmentation (all packets) // TCP Segmentation (all packets)
config.Fragment.StartPacket = 0 config.Fragment.PacketsFrom = 0
config.Fragment.EndPacket = 0 config.Fragment.PacketsTo = 0
default: default:
// TCP Segmentation (range) // TCP Segmentation (range)
packetRange := strings.Split(c.Fragment.Packets, "-") packetsFromTo := strings.Split(c.Fragment.Packets, "-")
var startPacket, endPacket int64 if len(packetsFromTo) == 2 {
if len(packetRange) == 2 { config.Fragment.PacketsFrom, err = strconv.ParseUint(packetsFromTo[0], 10, 64)
startPacket, err = strconv.ParseInt(packetRange[0], 10, 64) config.Fragment.PacketsTo, err2 = strconv.ParseUint(packetsFromTo[1], 10, 64)
endPacket, err2 = strconv.ParseInt(packetRange[1], 10, 64)
} else { } else {
startPacket, err = strconv.ParseInt(packetRange[0], 10, 64) config.Fragment.PacketsFrom, err = strconv.ParseUint(packetsFromTo[0], 10, 64)
endPacket = startPacket config.Fragment.PacketsTo = config.Fragment.PacketsFrom
} }
if err != nil { if err != nil {
return nil, newError("Invalid start packet: ", err).Base(err) return nil, newError("Invalid PacketsFrom").Base(err)
} }
if err2 != nil { if err2 != nil {
return nil, newError("Invalid end packet: ", err2).Base(err2) return nil, newError("Invalid PacketsTo").Base(err2)
} }
if startPacket > endPacket { if config.Fragment.PacketsFrom > config.Fragment.PacketsTo {
return nil, newError("Invalid packet range: ", c.Fragment.Packets) config.Fragment.PacketsFrom, config.Fragment.PacketsTo = config.Fragment.PacketsTo, config.Fragment.PacketsFrom
} }
if startPacket < 1 { if config.Fragment.PacketsFrom == 0 {
return nil, newError("Cannot start from packet 0") return nil, newError("PacketsFrom can't be 0")
}
}
{
if c.Fragment.Length == "" {
return nil, newError("Length can't be empty")
}
lengthMinMax := strings.Split(c.Fragment.Length, "-")
if len(lengthMinMax) == 2 {
config.Fragment.LengthMin, err = strconv.ParseUint(lengthMinMax[0], 10, 64)
config.Fragment.LengthMax, err2 = strconv.ParseUint(lengthMinMax[1], 10, 64)
} else {
config.Fragment.LengthMin, err = strconv.ParseUint(lengthMinMax[0], 10, 64)
config.Fragment.LengthMax = config.Fragment.LengthMin
}
if err != nil {
return nil, newError("Invalid LengthMin").Base(err)
}
if err2 != nil {
return nil, newError("Invalid LengthMax").Base(err2)
}
if config.Fragment.LengthMin > config.Fragment.LengthMax {
config.Fragment.LengthMin, config.Fragment.LengthMax = config.Fragment.LengthMax, config.Fragment.LengthMin
}
if config.Fragment.LengthMin == 0 {
return nil, newError("LengthMin can't be 0")
}
}
{
if c.Fragment.Interval == "" {
return nil, newError("Interval can't be empty")
}
intervalMinMax := strings.Split(c.Fragment.Interval, "-")
if len(intervalMinMax) == 2 {
config.Fragment.IntervalMin, err = strconv.ParseUint(intervalMinMax[0], 10, 64)
config.Fragment.IntervalMax, err2 = strconv.ParseUint(intervalMinMax[1], 10, 64)
} else {
config.Fragment.IntervalMin, err = strconv.ParseUint(intervalMinMax[0], 10, 64)
config.Fragment.IntervalMax = config.Fragment.IntervalMin
}
if err != nil {
return nil, newError("Invalid IntervalMin").Base(err)
}
if err2 != nil {
return nil, newError("Invalid IntervalMax").Base(err2)
}
if config.Fragment.IntervalMin > config.Fragment.IntervalMax {
config.Fragment.IntervalMin, config.Fragment.IntervalMax = config.Fragment.IntervalMax, config.Fragment.IntervalMin
} }
config.Fragment.StartPacket = int32(startPacket)
config.Fragment.EndPacket = int32(endPacket)
} }
} }

View File

@@ -4,9 +4,9 @@ import (
"encoding/json" "encoding/json"
"testing" "testing"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
. "github.com/xtls/xray-core/infra/conf" . "github.com/xtls/xray-core/infra/conf"
"google.golang.org/protobuf/proto"
) )
func loadJSON(creator func() Buildable) func(string) (proto.Message, error) { func loadJSON(creator func() Buildable) func(string) (proto.Message, error) {

View File

@@ -1,8 +1,8 @@
package conf package conf
import ( import (
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/transport/internet/grpc" "github.com/xtls/xray-core/transport/internet/grpc"
"google.golang.org/protobuf/proto"
) )
type GRPCConfig struct { type GRPCConfig struct {

View File

@@ -3,10 +3,10 @@ package conf
import ( import (
"encoding/json" "encoding/json"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/proxy/http" "github.com/xtls/xray-core/proxy/http"
"google.golang.org/protobuf/proto"
) )
type HTTPAccount struct { type HTTPAccount struct {

View File

@@ -1,8 +1,8 @@
package conf package conf
import ( import (
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/proxy/loopback" "github.com/xtls/xray-core/proxy/loopback"
"google.golang.org/protobuf/proto"
) )
type LoopbackConfig struct { type LoopbackConfig struct {

View File

@@ -1,9 +1,9 @@
package conf package conf
import ( import (
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/observatory" "github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration" "github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
"google.golang.org/protobuf/proto"
) )
type ObservatoryConfig struct { type ObservatoryConfig struct {

View File

@@ -1,8 +1,8 @@
package conf package conf
import ( import (
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/reverse" "github.com/xtls/xray-core/app/reverse"
"google.golang.org/protobuf/proto"
) )
type BridgeConfig struct { type BridgeConfig struct {

View File

@@ -6,10 +6,10 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/router" "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
"google.golang.org/protobuf/proto"
) )
type RouterRulesConfig struct { type RouterRulesConfig struct {
@@ -245,6 +245,23 @@ func loadSite(file, code string) ([]*router.Domain, error) {
return SiteCache[index].Domain, nil return SiteCache[index].Domain, nil
} }
func DecodeVarint(buf []byte) (x uint64, n int) {
for shift := uint(0); shift < 64; shift += 7 {
if n >= len(buf) {
return 0, 0
}
b := uint64(buf[n])
n++
x |= (b & 0x7F) << shift
if (b & 0x80) == 0 {
return x, n
}
}
// The number is too large to represent in a 64-bit value.
return 0, 0
}
func find(data, code []byte) []byte { func find(data, code []byte) []byte {
codeL := len(code) codeL := len(code)
if codeL == 0 { if codeL == 0 {
@@ -255,7 +272,7 @@ func find(data, code []byte) []byte {
if dataL < 2 { if dataL < 2 {
return nil return nil
} }
x, y := proto.DecodeVarint(data[1:]) x, y := DecodeVarint(data[1:])
if x == 0 && y == 0 { if x == 0 && y == 0 {
return nil return nil
} }

View File

@@ -7,13 +7,13 @@ import (
"testing" "testing"
_ "unsafe" _ "unsafe"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/router" "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform" "github.com/xtls/xray-core/common/platform"
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
. "github.com/xtls/xray-core/infra/conf" . "github.com/xtls/xray-core/infra/conf"
"google.golang.org/protobuf/proto"
) )
func init() { func init() {

View File

@@ -3,13 +3,13 @@ package conf
import ( import (
"strings" "strings"
"github.com/golang/protobuf/proto"
"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"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/proxy/shadowsocks" "github.com/xtls/xray-core/proxy/shadowsocks"
"github.com/xtls/xray-core/proxy/shadowsocks_2022" "github.com/xtls/xray-core/proxy/shadowsocks_2022"
"google.golang.org/protobuf/proto"
) )
func cipherFromString(c string) shadowsocks.CipherType { func cipherFromString(c string) shadowsocks.CipherType {

View File

@@ -4,10 +4,10 @@ import (
"encoding/json" "encoding/json"
"strings" "strings"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/proxy/socks" "github.com/xtls/xray-core/proxy/socks"
"google.golang.org/protobuf/proto"
) )
type SocksAccount struct { type SocksAccount struct {

View File

@@ -3,7 +3,6 @@ package conf
import ( import (
"sort" "sort"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/transport/internet/headers/dns" "github.com/xtls/xray-core/transport/internet/headers/dns"
"github.com/xtls/xray-core/transport/internet/headers/http" "github.com/xtls/xray-core/transport/internet/headers/http"
"github.com/xtls/xray-core/transport/internet/headers/noop" "github.com/xtls/xray-core/transport/internet/headers/noop"
@@ -12,6 +11,7 @@ import (
"github.com/xtls/xray-core/transport/internet/headers/utp" "github.com/xtls/xray-core/transport/internet/headers/utp"
"github.com/xtls/xray-core/transport/internet/headers/wechat" "github.com/xtls/xray-core/transport/internet/headers/wechat"
"github.com/xtls/xray-core/transport/internet/headers/wireguard" "github.com/xtls/xray-core/transport/internet/headers/wireguard"
"google.golang.org/protobuf/proto"
) )
type NoOpAuthenticator struct{} type NoOpAuthenticator struct{}

View File

@@ -11,7 +11,6 @@ import (
"strings" "strings"
"syscall" "syscall"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
@@ -26,6 +25,7 @@ import (
"github.com/xtls/xray-core/transport/internet/tcp" "github.com/xtls/xray-core/transport/internet/tcp"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"github.com/xtls/xray-core/transport/internet/websocket" "github.com/xtls/xray-core/transport/internet/websocket"
"google.golang.org/protobuf/proto"
) )
var ( var (

View File

@@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"testing" "testing"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
. "github.com/xtls/xray-core/infra/conf" . "github.com/xtls/xray-core/infra/conf"
@@ -18,6 +17,7 @@ import (
"github.com/xtls/xray-core/transport/internet/quic" "github.com/xtls/xray-core/transport/internet/quic"
"github.com/xtls/xray-core/transport/internet/tcp" "github.com/xtls/xray-core/transport/internet/tcp"
"github.com/xtls/xray-core/transport/internet/websocket" "github.com/xtls/xray-core/transport/internet/websocket"
"google.golang.org/protobuf/proto"
) )
func TestSocketConfig(t *testing.T) { func TestSocketConfig(t *testing.T) {

View File

@@ -6,11 +6,11 @@ import (
"strconv" "strconv"
"syscall" "syscall"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/proxy/trojan" "github.com/xtls/xray-core/proxy/trojan"
"google.golang.org/protobuf/proto"
) )
// TrojanServerTarget is configuration of a single trojan server // TrojanServerTarget is configuration of a single trojan server
@@ -30,13 +30,14 @@ type TrojanClientConfig struct {
// Build implements Buildable // Build implements Buildable
func (c *TrojanClientConfig) Build() (proto.Message, error) { func (c *TrojanClientConfig) Build() (proto.Message, error) {
config := new(trojan.ClientConfig)
if len(c.Servers) == 0 { if len(c.Servers) == 0 {
return nil, newError("0 Trojan server configured.") return nil, newError("0 Trojan server configured.")
} }
serverSpecs := make([]*protocol.ServerEndpoint, len(c.Servers)) config := &trojan.ClientConfig{
Server: make([]*protocol.ServerEndpoint, len(c.Servers)),
}
for idx, rec := range c.Servers { for idx, rec := range c.Servers {
if rec.Address == nil { if rec.Address == nil {
return nil, newError("Trojan server address is not set.") return nil, newError("Trojan server address is not set.")
@@ -47,34 +48,25 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
if rec.Password == "" { if rec.Password == "" {
return nil, newError("Trojan password is not specified.") return nil, newError("Trojan password is not specified.")
} }
account := &trojan.Account{ if rec.Flow != "" {
Password: rec.Password, return nil, newError(`Trojan doesn't support "flow" anymore.`)
Flow: rec.Flow,
} }
switch account.Flow { config.Server[idx] = &protocol.ServerEndpoint{
case "":
default:
return nil, newError(`Trojan servers: "flow" doesn't support "` + account.Flow + `" in this version`)
}
trojan := &protocol.ServerEndpoint{
Address: rec.Address.Build(), Address: rec.Address.Build(),
Port: uint32(rec.Port), Port: uint32(rec.Port),
User: []*protocol.User{ User: []*protocol.User{
{ {
Level: uint32(rec.Level), Level: uint32(rec.Level),
Email: rec.Email, Email: rec.Email,
Account: serial.ToTypedMessage(account), Account: serial.ToTypedMessage(&trojan.Account{
Password: rec.Password,
}),
}, },
}, },
} }
serverSpecs[idx] = trojan
} }
config.Server = serverSpecs
return config, nil return config, nil
} }
@@ -105,25 +97,22 @@ type TrojanServerConfig struct {
// Build implements Buildable // Build implements Buildable
func (c *TrojanServerConfig) Build() (proto.Message, error) { func (c *TrojanServerConfig) Build() (proto.Message, error) {
config := new(trojan.ServerConfig) config := &trojan.ServerConfig{
config.Users = make([]*protocol.User, len(c.Clients)) Users: make([]*protocol.User, len(c.Clients)),
}
for idx, rawUser := range c.Clients { for idx, rawUser := range c.Clients {
user := new(protocol.User) if rawUser.Flow != "" {
account := &trojan.Account{ return nil, newError(`Trojan doesn't support "flow" anymore.`)
Password: rawUser.Password,
Flow: rawUser.Flow,
} }
switch account.Flow { config.Users[idx] = &protocol.User{
case "": Level: uint32(rawUser.Level),
default: Email: rawUser.Email,
return nil, newError(`Trojan clients: "flow" doesn't support "` + account.Flow + `" in this version`) Account: serial.ToTypedMessage(&trojan.Account{
Password: rawUser.Password,
}),
} }
user.Email = rawUser.Email
user.Level = uint32(rawUser.Level)
user.Account = serial.ToTypedMessage(account)
config.Users[idx] = user
} }
if c.Fallback != nil { if c.Fallback != nil {

View File

@@ -6,7 +6,6 @@ import (
"strconv" "strconv"
"syscall" "syscall"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
@@ -14,6 +13,7 @@ import (
"github.com/xtls/xray-core/proxy/vless" "github.com/xtls/xray-core/proxy/vless"
"github.com/xtls/xray-core/proxy/vless/inbound" "github.com/xtls/xray-core/proxy/vless/inbound"
"github.com/xtls/xray-core/proxy/vless/outbound" "github.com/xtls/xray-core/proxy/vless/outbound"
"google.golang.org/protobuf/proto"
) )
type VLessInboundFallback struct { type VLessInboundFallback struct {

View File

@@ -4,13 +4,13 @@ import (
"encoding/json" "encoding/json"
"strings" "strings"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/uuid" "github.com/xtls/xray-core/common/uuid"
"github.com/xtls/xray-core/proxy/vmess" "github.com/xtls/xray-core/proxy/vmess"
"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"
"google.golang.org/protobuf/proto"
) )
type VMessAccount struct { type VMessAccount struct {

View File

@@ -4,8 +4,8 @@ import (
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/proxy/wireguard" "github.com/xtls/xray-core/proxy/wireguard"
"google.golang.org/protobuf/proto"
) )
type WireGuardPeerConfig struct { type WireGuardPeerConfig struct {

View File

@@ -5,7 +5,6 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/golang/protobuf/proto"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/xtls/xray-core/app/dispatcher" "github.com/xtls/xray-core/app/dispatcher"
"github.com/xtls/xray-core/app/log" "github.com/xtls/xray-core/app/log"
@@ -27,6 +26,7 @@ import (
"github.com/xtls/xray-core/transport/internet/http" "github.com/xtls/xray-core/transport/internet/http"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"github.com/xtls/xray-core/transport/internet/websocket" "github.com/xtls/xray-core/transport/internet/websocket"
"google.golang.org/protobuf/proto"
) )
func TestXrayConfig(t *testing.T) { func TestXrayConfig(t *testing.T) {
@@ -221,7 +221,8 @@ func TestXrayConfig(t *testing.T) {
}, },
}), }),
ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{ ProxySettings: serial.ToTypedMessage(&dns_proxy.Config{
Server: &net.Endpoint{}, Server: &net.Endpoint{},
Non_IPQuery: "drop",
}), }),
}, },
}, },

View File

@@ -113,13 +113,13 @@ func dirExists(file string) bool {
func getRegepxByFormat() string { func getRegepxByFormat() string {
switch strings.ToLower(*format) { switch strings.ToLower(*format) {
case "json": case "json":
return `^.+\.json$` return `^.+\.(json|jsonc)$`
case "toml": case "toml":
return `^.+\.toml$` return `^.+\.toml$`
case "yaml", "yml": case "yaml", "yml":
return `^.+\.(yaml|yml)$` return `^.+\.(yaml|yml)$`
default: default:
return `^.+\.(json|toml|yaml|yml)$` return `^.+\.(json|jsonc|toml|yaml|yml)$`
} }
} }

View File

@@ -125,12 +125,12 @@ type Fragment struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
MinInterval int32 `protobuf:"varint,1,opt,name=min_interval,json=minInterval,proto3" json:"min_interval,omitempty"` PacketsFrom uint64 `protobuf:"varint,1,opt,name=packets_from,json=packetsFrom,proto3" json:"packets_from,omitempty"`
MaxInterval int32 `protobuf:"varint,2,opt,name=max_interval,json=maxInterval,proto3" json:"max_interval,omitempty"` PacketsTo uint64 `protobuf:"varint,2,opt,name=packets_to,json=packetsTo,proto3" json:"packets_to,omitempty"`
MinLength int32 `protobuf:"varint,3,opt,name=min_length,json=minLength,proto3" json:"min_length,omitempty"` LengthMin uint64 `protobuf:"varint,3,opt,name=length_min,json=lengthMin,proto3" json:"length_min,omitempty"`
MaxLength int32 `protobuf:"varint,4,opt,name=max_length,json=maxLength,proto3" json:"max_length,omitempty"` LengthMax uint64 `protobuf:"varint,4,opt,name=length_max,json=lengthMax,proto3" json:"length_max,omitempty"`
StartPacket int32 `protobuf:"varint,5,opt,name=start_packet,json=startPacket,proto3" json:"start_packet,omitempty"` IntervalMin uint64 `protobuf:"varint,5,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
EndPacket int32 `protobuf:"varint,6,opt,name=end_packet,json=endPacket,proto3" json:"end_packet,omitempty"` IntervalMax uint64 `protobuf:"varint,6,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
} }
func (x *Fragment) Reset() { func (x *Fragment) Reset() {
@@ -165,44 +165,44 @@ func (*Fragment) Descriptor() ([]byte, []int) {
return file_proxy_freedom_config_proto_rawDescGZIP(), []int{1} return file_proxy_freedom_config_proto_rawDescGZIP(), []int{1}
} }
func (x *Fragment) GetMinInterval() int32 { func (x *Fragment) GetPacketsFrom() uint64 {
if x != nil { if x != nil {
return x.MinInterval return x.PacketsFrom
} }
return 0 return 0
} }
func (x *Fragment) GetMaxInterval() int32 { func (x *Fragment) GetPacketsTo() uint64 {
if x != nil { if x != nil {
return x.MaxInterval return x.PacketsTo
} }
return 0 return 0
} }
func (x *Fragment) GetMinLength() int32 { func (x *Fragment) GetLengthMin() uint64 {
if x != nil { if x != nil {
return x.MinLength return x.LengthMin
} }
return 0 return 0
} }
func (x *Fragment) GetMaxLength() int32 { func (x *Fragment) GetLengthMax() uint64 {
if x != nil { if x != nil {
return x.MaxLength return x.LengthMax
} }
return 0 return 0
} }
func (x *Fragment) GetStartPacket() int32 { func (x *Fragment) GetIntervalMin() uint64 {
if x != nil { if x != nil {
return x.StartPacket return x.IntervalMin
} }
return 0 return 0
} }
func (x *Fragment) GetEndPacket() int32 { func (x *Fragment) GetIntervalMax() uint64 {
if x != nil { if x != nil {
return x.EndPacket return x.IntervalMax
} }
return 0 return 0
} }
@@ -302,19 +302,19 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0xd0, 0x01, 0x0a, 0x08, 0x46, 0x72, 0x61, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0xd0, 0x01, 0x0a, 0x08, 0x46, 0x72, 0x61,
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73,
0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x61, 0x63,
0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x6b, 0x65, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x74, 0x73, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70, 0x61,
0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x54, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74,
0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e,
0x09, 0x6d, 0x69, 0x6e, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67,
0x6d, 0x61, 0x78, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
0x72, 0x74, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74,
0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65,
0x65, 0x6e, 0x64, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
0x52, 0x09, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0xf2, 0x02, 0x0a, 0x06, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x22, 0xf2, 0x02, 0x0a, 0x06,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65,

View File

@@ -13,12 +13,12 @@ message DestinationOverride {
} }
message Fragment { message Fragment {
int32 min_interval = 1; uint64 packets_from = 1;
int32 max_interval = 2; uint64 packets_to = 2;
int32 min_length = 3; uint64 length_min = 3;
int32 max_length = 4; uint64 length_max = 4;
int32 start_packet = 5; uint64 interval_min = 5;
int32 end_packet = 6; uint64 interval_max = 6;
} }
message Config { message Config {

View File

@@ -5,7 +5,6 @@ package freedom
import ( import (
"context" "context"
"crypto/rand" "crypto/rand"
"encoding/binary"
"io" "io"
"math/big" "math/big"
"time" "time"
@@ -13,7 +12,6 @@ import (
"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/dice" "github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/retry" "github.com/xtls/xray-core/common/retry"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
@@ -175,28 +173,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
var writer buf.Writer var writer buf.Writer
if destination.Network == net.Network_TCP { if destination.Network == net.Network_TCP {
if h.config.Fragment != nil { if h.config.Fragment != nil {
if h.config.Fragment.StartPacket == 0 && h.config.Fragment.EndPacket == 1 { newError("FRAGMENT", h.config.Fragment.PacketsFrom, h.config.Fragment.PacketsTo, h.config.Fragment.LengthMin, h.config.Fragment.LengthMax,
newError("FRAGMENT", int(h.config.Fragment.MaxLength)).WriteToLog(session.ExportIDToError(ctx)) h.config.Fragment.IntervalMin, h.config.Fragment.IntervalMax).AtDebug().WriteToLog(session.ExportIDToError(ctx))
writer = buf.NewWriter( writer = buf.NewWriter(&FragmentWriter{
&FragmentedClientHelloConn{ fragment: h.config.Fragment,
Conn: conn, writer: conn,
maxLength: int(h.config.Fragment.MaxLength), })
minInterval: time.Duration(h.config.Fragment.MinInterval) * time.Millisecond,
maxInterval: time.Duration(h.config.Fragment.MaxInterval) * time.Millisecond,
})
} else {
writer = buf.NewWriter(
&FragmentWriter{
Writer: conn,
minLength: int(h.config.Fragment.MinLength),
maxLength: int(h.config.Fragment.MaxLength),
minInterval: time.Duration(h.config.Fragment.MinInterval) * time.Millisecond,
maxInterval: time.Duration(h.config.Fragment.MaxInterval) * time.Millisecond,
startPacket: int(h.config.Fragment.StartPacket),
endPacket: int(h.config.Fragment.EndPacket),
PacketCount: 0,
})
}
} else { } else {
writer = buf.NewWriter(conn) writer = buf.NewWriter(conn)
} }
@@ -356,40 +338,66 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
} }
type FragmentWriter struct { type FragmentWriter struct {
io.Writer fragment *Fragment
minLength int writer io.Writer
maxLength int count uint64
minInterval time.Duration
maxInterval time.Duration
startPacket int
endPacket int
PacketCount int
} }
func (w *FragmentWriter) Write(buf []byte) (int, error) { func (f *FragmentWriter) Write(b []byte) (int, error) {
w.PacketCount += 1 f.count++
if (w.startPacket != 0 && (w.PacketCount < w.startPacket || w.PacketCount > w.endPacket)) || len(buf) <= w.minLength {
return w.Writer.Write(buf) if f.fragment.PacketsFrom == 0 && f.fragment.PacketsTo == 1 {
if f.count != 1 || len(b) <= 5 || b[0] != 22 {
return f.writer.Write(b)
}
recordLen := 5 + ((int(b[3]) << 8) | int(b[4]))
data := b[5:recordLen]
buf := make([]byte, 1024)
for from := 0; ; {
to := from + int(randBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax)))
if to > len(data) {
to = len(data)
}
copy(buf[:3], b)
copy(buf[5:], data[from:to])
l := to - from
from = to
buf[3] = byte(l >> 8)
buf[4] = byte(l)
_, err := f.writer.Write(buf[:5+l])
time.Sleep(time.Duration(randBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond)
if err != nil {
return 0, err
}
if from == len(data) {
if len(b) > recordLen {
n, err := f.writer.Write(b[recordLen:])
if err != nil {
return recordLen + n, err
}
}
return len(b), nil
}
}
} }
nTotal := 0 if f.fragment.PacketsFrom != 0 && (f.count < f.fragment.PacketsFrom || f.count > f.fragment.PacketsTo) {
for { return f.writer.Write(b)
randomBytesTo := int(randBetween(int64(w.minLength), int64(w.maxLength))) + nTotal }
if randomBytesTo > len(buf) { for from := 0; ; {
randomBytesTo = len(buf) to := from + int(randBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax)))
if to > len(b) {
to = len(b)
} }
n, err := w.Writer.Write(buf[nTotal:randomBytesTo]) n, err := f.writer.Write(b[from:to])
from += n
time.Sleep(time.Duration(randBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond)
if err != nil { if err != nil {
return nTotal + n, err return from, err
} }
nTotal += n if from >= len(b) {
return from, nil
if nTotal >= len(buf) {
return nTotal, nil
} }
randomInterval := randBetween(int64(w.minInterval), int64(w.maxInterval))
time.Sleep(time.Duration(randomInterval))
} }
} }
@@ -401,66 +409,3 @@ func randBetween(left int64, right int64) int64 {
bigInt, _ := rand.Int(rand.Reader, big.NewInt(right-left)) bigInt, _ := rand.Int(rand.Reader, big.NewInt(right-left))
return left + bigInt.Int64() return left + bigInt.Int64()
} }
type FragmentedClientHelloConn struct {
net.Conn
PacketCount int
minLength int
maxLength int
minInterval time.Duration
maxInterval time.Duration
}
func (c *FragmentedClientHelloConn) Write(b []byte) (n int, err error) {
if len(b) >= 5 && b[0] == 22 && c.PacketCount == 0 {
n, err = sendFragmentedClientHello(c, b, c.minLength, c.maxLength)
if err == nil {
c.PacketCount++
return n, err
}
}
return c.Conn.Write(b)
}
func sendFragmentedClientHello(conn *FragmentedClientHelloConn, clientHello []byte, minFragmentSize, maxFragmentSize int) (n int, err error) {
if len(clientHello) < 5 || clientHello[0] != 22 {
return 0, errors.New("not a valid TLS ClientHello message")
}
clientHelloLen := (int(clientHello[3]) << 8) | int(clientHello[4])
clientHelloData := clientHello[5:]
for i := 0; i < clientHelloLen; {
fragmentEnd := i + int(randBetween(int64(minFragmentSize), int64(maxFragmentSize)))
if fragmentEnd > clientHelloLen {
fragmentEnd = clientHelloLen
}
fragment := clientHelloData[i:fragmentEnd]
i = fragmentEnd
err = writeFragmentedRecord(conn, 22, fragment, clientHello)
if err != nil {
return 0, err
}
}
return len(clientHello), nil
}
func writeFragmentedRecord(c *FragmentedClientHelloConn, contentType uint8, data []byte, clientHello []byte) error {
header := make([]byte, 5)
header[0] = byte(clientHello[0])
tlsVersion := (int(clientHello[1]) << 8) | int(clientHello[2])
binary.BigEndian.PutUint16(header[1:], uint16(tlsVersion))
binary.BigEndian.PutUint16(header[3:], uint16(len(data)))
_, err := c.Conn.Write(append(header, data...))
randomInterval := randBetween(int64(c.minInterval), int64(c.maxInterval))
time.Sleep(time.Duration(randomInterval))
return err
}

View File

@@ -172,6 +172,10 @@ func fillRequestHeader(ctx context.Context, header []*Header) ([]*Header, error)
inbound := session.InboundFromContext(ctx) inbound := session.InboundFromContext(ctx)
outbound := session.OutboundFromContext(ctx) outbound := session.OutboundFromContext(ctx)
if inbound == nil || outbound == nil {
return nil, newError("missing inbound or outbound metadata from context")
}
data := struct { data := struct {
Source net.Destination Source net.Destination
Target net.Destination Target net.Destination

View File

@@ -4,6 +4,7 @@ import (
"crypto/hmac" "crypto/hmac"
"crypto/rand" "crypto/rand"
"crypto/sha256" "crypto/sha256"
"errors"
"hash/crc32" "hash/crc32"
"io" "io"
@@ -236,37 +237,37 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buff
} }
func DecodeUDPPacket(validator *Validator, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) { func DecodeUDPPacket(validator *Validator, payload *buf.Buffer) (*protocol.RequestHeader, *buf.Buffer, error) {
bs := payload.Bytes() rawPayload := payload.Bytes()
if len(bs) <= 32 { user, _, d, _, err := validator.Get(rawPayload, protocol.RequestCommandUDP)
return nil, nil, newError("len(bs) <= 32")
}
user, _, d, _, err := validator.Get(bs, protocol.RequestCommandUDP) if errors.Is(err, ErrIVNotUnique) {
switch err {
case ErrIVNotUnique:
return nil, nil, newError("failed iv check").Base(err) return nil, nil, newError("failed iv check").Base(err)
case ErrNotFound:
return nil, nil, newError("failed to match an user").Base(err)
default:
account := user.Account.(*MemoryAccount)
if account.Cipher.IsAEAD() {
payload.Clear()
payload.Write(d)
} else {
if account.Cipher.IVSize() > 0 {
iv := make([]byte, account.Cipher.IVSize())
copy(iv, payload.BytesTo(account.Cipher.IVSize()))
}
if err = account.Cipher.DecodePacket(account.Key, payload); err != nil {
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
}
}
} }
request := &protocol.RequestHeader{ if errors.Is(err, ErrNotFound) {
Version: Version, return nil, nil, newError("failed to match an user").Base(err)
User: user, }
Command: protocol.RequestCommandUDP,
if err != nil {
return nil, nil, newError("unexpected error").Base(err)
}
account, ok := user.Account.(*MemoryAccount)
if !ok {
return nil, nil, newError("expected MemoryAccount returned from validator")
}
if account.Cipher.IsAEAD() {
payload.Clear()
payload.Write(d)
} else {
if account.Cipher.IVSize() > 0 {
iv := make([]byte, account.Cipher.IVSize())
copy(iv, payload.BytesTo(account.Cipher.IVSize()))
}
if err = account.Cipher.DecodePacket(account.Key, payload); err != nil {
return nil, nil, newError("failed to decrypt UDP payload").Base(err)
}
} }
payload.SetByte(0, payload.Byte(0)&0x0F) payload.SetByte(0, payload.Byte(0)&0x0F)
@@ -276,8 +277,13 @@ func DecodeUDPPacket(validator *Validator, payload *buf.Buffer) (*protocol.Reque
return nil, nil, newError("failed to parse address").Base(err) return nil, nil, newError("failed to parse address").Base(err)
} }
request.Address = addr request := &protocol.RequestHeader{
request.Port = port Version: Version,
User: user,
Command: protocol.RequestCommandUDP,
Address: addr,
Port: port,
}
return request, payload, nil return request, payload, nil
} }

View File

@@ -23,37 +23,80 @@ func equalRequestHeader(x, y *protocol.RequestHeader) bool {
})) }))
} }
func TestUDPEncoding(t *testing.T) { func TestUDPEncodingDecoding(t *testing.T) {
request := &protocol.RequestHeader{ testRequests := []protocol.RequestHeader{
Version: Version, {
Command: protocol.RequestCommandUDP, Version: Version,
Address: net.LocalHostIP, Command: protocol.RequestCommandUDP,
Port: 1234, Address: net.LocalHostIP,
User: &protocol.MemoryUser{ Port: 1234,
Email: "love@example.com", User: &protocol.MemoryUser{
Account: toAccount(&Account{ Email: "love@example.com",
Password: "password", Account: toAccount(&Account{
CipherType: CipherType_AES_128_GCM, Password: "password",
}), CipherType: CipherType_AES_128_GCM,
}),
},
},
{
Version: Version,
Command: protocol.RequestCommandUDP,
Address: net.LocalHostIP,
Port: 1234,
User: &protocol.MemoryUser{
Email: "love@example.com",
Account: toAccount(&Account{
Password: "123",
CipherType: CipherType_NONE,
}),
},
}, },
} }
data := buf.New() for _, request := range testRequests {
common.Must2(data.WriteString("test string")) data := buf.New()
encodedData, err := EncodeUDPPacket(request, data.Bytes()) common.Must2(data.WriteString("test string"))
common.Must(err) encodedData, err := EncodeUDPPacket(&request, data.Bytes())
common.Must(err)
validator := new(Validator) validator := new(Validator)
validator.Add(request.User) validator.Add(request.User)
decodedRequest, decodedData, err := DecodeUDPPacket(validator, encodedData) decodedRequest, decodedData, err := DecodeUDPPacket(validator, encodedData)
common.Must(err) common.Must(err)
if r := cmp.Diff(decodedData.Bytes(), data.Bytes()); r != "" { if r := cmp.Diff(decodedData.Bytes(), data.Bytes()); r != "" {
t.Error("data: ", r) t.Error("data: ", r)
}
if equalRequestHeader(decodedRequest, &request) == false {
t.Error("different request")
}
}
}
func TestUDPDecodingWithPayloadTooShort(t *testing.T) {
testAccounts := []protocol.Account{
toAccount(&Account{
Password: "password",
CipherType: CipherType_AES_128_GCM,
}),
toAccount(&Account{
Password: "password",
CipherType: CipherType_NONE,
}),
} }
if equalRequestHeader(decodedRequest, request) == false { for _, account := range testAccounts {
t.Error("different request") data := buf.New()
data.WriteString("short payload")
validator := new(Validator)
validator.Add(&protocol.MemoryUser{
Account: account,
})
_, _, err := DecodeUDPPacket(validator, data)
if err == nil {
t.Fatal("expected error")
}
} }
} }

View File

@@ -80,6 +80,11 @@ func (v *Validator) Get(bs []byte, command protocol.RequestCommand) (u *protocol
for _, user := range v.users { for _, user := range v.users {
if account := user.Account.(*MemoryAccount); account.Cipher.IsAEAD() { if account := user.Account.(*MemoryAccount); account.Cipher.IsAEAD() {
// AEAD payload decoding requires the payload to be over 32 bytes
if len(bs) < 32 {
continue
}
aeadCipher := account.Cipher.(*AEADCipher) aeadCipher := account.Cipher.(*AEADCipher)
ivLen = aeadCipher.IVSize() ivLen = aeadCipher.IVSize()
iv := bs[:ivLen] iv := bs[:ivLen]

View File

@@ -204,7 +204,12 @@ func (i *MultiUserInbound) NewConnection(ctx context.Context, conn net.Conn, met
}) })
newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx)) newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
dispatcher := session.DispatcherFromContext(ctx) dispatcher := session.DispatcherFromContext(ctx)
link, err := dispatcher.Dispatch(ctx, singbridge.ToDestination(metadata.Destination, net.Network_TCP)) destination := singbridge.ToDestination(metadata.Destination, net.Network_TCP)
if !destination.IsValid() {
return newError("invalid destination")
}
link, err := dispatcher.Dispatch(ctx, destination)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -77,22 +77,12 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
defer conn.Close() defer conn.Close()
iConn := conn
statConn, ok := iConn.(*stat.CounterConnection)
if ok {
iConn = statConn.Connection
}
user := server.PickUser() user := server.PickUser()
account, ok := user.Account.(*MemoryAccount) account, ok := user.Account.(*MemoryAccount)
if !ok { if !ok {
return newError("user account is not valid") return newError("user account is not valid")
} }
connWriter := &ConnWriter{
Flow: account.Flow,
}
var newCtx context.Context var newCtx context.Context
var newCancel context.CancelFunc var newCancel context.CancelFunc
if session.TimeoutOnlyFromContext(ctx) { if session.TimeoutOnlyFromContext(ctx) {
@@ -113,9 +103,11 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn)) bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
connWriter.Writer = bufferWriter connWriter := &ConnWriter{
connWriter.Target = destination Writer: bufferWriter,
connWriter.Account = account Target: destination,
Account: account,
}
var bodyWriter buf.Writer var bodyWriter buf.Writer
if destination.Network == net.Network_UDP { if destination.Network == net.Network_UDP {

View File

@@ -13,7 +13,6 @@ import (
type MemoryAccount struct { type MemoryAccount struct {
Password string Password string
Key []byte Key []byte
Flow string
} }
// AsAccount implements protocol.AsAccount. // AsAccount implements protocol.AsAccount.
@@ -23,7 +22,6 @@ func (a *Account) AsAccount() (protocol.Account, error) {
return &MemoryAccount{ return &MemoryAccount{
Password: password, Password: password,
Key: key, Key: key,
Flow: a.Flow,
}, nil }, nil
} }

View File

@@ -27,7 +27,6 @@ type Account struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Password string `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"` Password string `protobuf:"bytes,1,opt,name=password,proto3" json:"password,omitempty"`
Flow string `protobuf:"bytes,2,opt,name=flow,proto3" json:"flow,omitempty"`
} }
func (x *Account) Reset() { func (x *Account) Reset() {
@@ -69,13 +68,6 @@ func (x *Account) GetPassword() string {
return "" return ""
} }
func (x *Account) GetFlow() string {
if x != nil {
return x.Flow
}
return ""
}
type Fallback struct { type Fallback struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -216,7 +208,7 @@ type ServerConfig struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Users []*protocol.User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` Users []*protocol.User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
Fallbacks []*Fallback `protobuf:"bytes,3,rep,name=fallbacks,proto3" json:"fallbacks,omitempty"` Fallbacks []*Fallback `protobuf:"bytes,2,rep,name=fallbacks,proto3" json:"fallbacks,omitempty"`
} }
func (x *ServerConfig) Reset() { func (x *ServerConfig) Reset() {
@@ -274,38 +266,37 @@ var file_proxy_trojan_config_proto_rawDesc = []byte{
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f,
0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x39, 0x0a, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x25, 0x0a,
0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x82, 0x01, 0x0a, 0x08, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63,
0x28, 0x09, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x82, 0x01, 0x0a, 0x08, 0x46, 0x61, 0x6c, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6c, 0x70, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x12, 0x12, 0x0a, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a,
0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69,
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72,
0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52,
0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65,
0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0c, 0x53, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73,
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x09, 0x66, 0x61, 0x6c,
0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78,
0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e,
0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62,
0x6f, 0x6a, 0x61, 0x6e, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66, 0x61, 0x63, 0x6b, 0x73, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x50, 0x01, 0x5a,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73,
0x6e, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79,
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x2f, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50,
0x72, 0x6f, 0x78, 0x79, 0x2f, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x62, 0x74, 0x6f, 0x33,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@@ -11,7 +11,6 @@ import "common/protocol/server_spec.proto";
message Account { message Account {
string password = 1; string password = 1;
string flow = 2;
} }
message Fallback { message Fallback {
@@ -29,5 +28,5 @@ message ClientConfig {
message ServerConfig { message ServerConfig {
repeated xray.common.protocol.User users = 1; repeated xray.common.protocol.User users = 1;
repeated Fallback fallbacks = 3; repeated Fallback fallbacks = 2;
} }

View File

@@ -31,7 +31,6 @@ type ConnWriter struct {
io.Writer io.Writer
Target net.Destination Target net.Destination
Account *MemoryAccount Account *MemoryAccount
Flow string
headerSent bool headerSent bool
} }

View File

@@ -234,7 +234,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
}) })
newError("received request for ", destination).WriteToLog(sid) newError("received request for ", destination).WriteToLog(sid)
return s.handleConnection(ctx, sessionPolicy, destination, clientReader, buf.NewWriter(conn), dispatcher, iConn, statConn) return s.handleConnection(ctx, sessionPolicy, destination, clientReader, buf.NewWriter(conn), dispatcher)
} }
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error { func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error {
@@ -300,7 +300,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReade
func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Session, func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Session,
destination net.Destination, destination net.Destination,
clientReader buf.Reader, clientReader buf.Reader,
clientWriter buf.Writer, dispatcher routing.Dispatcher, iConn stat.Connection, statConn *stat.CounterConnection, clientWriter buf.Writer, dispatcher routing.Dispatcher,
) error { ) error {
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)

View File

@@ -1,5 +1,3 @@
package trojan package trojan
const ( //go:generate go run github.com/xtls/xray-core/common/errors/errorgen
muxCoolAddress = "v1.mux.cool"
)

View File

@@ -3,10 +3,10 @@ package encoding
import ( import (
"io" "io"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/proxy/vless" "github.com/xtls/xray-core/proxy/vless"
"google.golang.org/protobuf/proto"
) )
func EncodeHeaderAddons(buffer *buf.Buffer, addons *Addons) error { func EncodeHeaderAddons(buffer *buf.Buffer, addons *Addons) error {

View File

@@ -247,7 +247,11 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
} }
} }
} }
reader = buf.NewReadVReader(conn, rawConn, nil) if rawConn != nil {
reader = buf.NewReadVReader(conn, rawConn, nil)
} else {
reader = buf.NewReader(conn)
}
ct = counter ct = counter
newError("XtlsRead readV").WriteToLog(session.ExportIDToError(ctx)) newError("XtlsRead readV").WriteToLog(session.ExportIDToError(ctx))
} }

View File

@@ -539,7 +539,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
var err error var err error
if rawConn != nil { if requestAddons.Flow == vless.XRV {
var counter stats.Counter var counter stats.Counter
if statConn != nil { if statConn != nil {
counter = statConn.ReadCounter counter = statConn.ReadCounter
@@ -591,7 +591,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
} }
var err error var err error
if rawConn != nil && requestAddons.Flow == vless.XRV { if requestAddons.Flow == vless.XRV {
var counter stats.Counter var counter stats.Counter
if statConn != nil { if statConn != nil {
counter = statConn.WriteCounter counter = statConn.WriteCounter

View File

@@ -247,7 +247,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
} }
var err error var err error
if rawConn != nil && requestAddons.Flow == vless.XRV { if requestAddons.Flow == vless.XRV {
if tlsConn, ok := iConn.(*tls.Conn); ok { if tlsConn, ok := iConn.(*tls.Conn); ok {
if tlsConn.ConnectionState().Version != gotls.VersionTLS13 { if tlsConn.ConnectionState().Version != gotls.VersionTLS13 {
return newError(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning() return newError(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning()
@@ -292,7 +292,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
serverReader = xudp.NewPacketReader(conn) serverReader = xudp.NewPacketReader(conn)
} }
if rawConn != nil { if requestAddons.Flow == vless.XRV {
var counter stats.Counter var counter stats.Counter
if statConn != nil { if statConn != nil {
counter = statConn.ReadCounter counter = statConn.ReadCounter

View File

@@ -14,7 +14,7 @@ import (
"github.com/sagernet/wireguard-go/tun" "github.com/sagernet/wireguard-go/tun"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
"gvisor.dev/gvisor/pkg/bufferv2" "gvisor.dev/gvisor/pkg/buffer"
"gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/header"
@@ -30,7 +30,7 @@ type netTun struct {
ep *channel.Endpoint ep *channel.Endpoint
stack *stack.Stack stack *stack.Stack
events chan tun.Event events chan tun.Event
incomingPacket chan *bufferv2.View incomingPacket chan *buffer.View
mtu int mtu int
dnsClient dns.Client dnsClient dns.Client
hasV4, hasV6 bool hasV4, hasV6 bool
@@ -48,7 +48,7 @@ func CreateNetTUN(localAddresses []netip.Addr, dnsClient dns.Client, mtu int) (t
ep: channel.New(1024, uint32(mtu), ""), ep: channel.New(1024, uint32(mtu), ""),
stack: stack.New(opts), stack: stack.New(opts),
events: make(chan tun.Event, 10), events: make(chan tun.Event, 10),
incomingPacket: make(chan *bufferv2.View), incomingPacket: make(chan *buffer.View),
dnsClient: dnsClient, dnsClient: dnsClient,
mtu: mtu, mtu: mtu,
} }
@@ -66,7 +66,7 @@ func CreateNetTUN(localAddresses []netip.Addr, dnsClient dns.Client, mtu int) (t
} }
protoAddr := tcpip.ProtocolAddress{ protoAddr := tcpip.ProtocolAddress{
Protocol: protoNumber, Protocol: protoNumber,
AddressWithPrefix: tcpip.Address(ip.AsSlice()).WithPrefix(), AddressWithPrefix: tcpip.AddrFromSlice(ip.AsSlice()).WithPrefix(),
} }
tcpipErr := dev.stack.AddProtocolAddress(1, protoAddr, stack.AddressProperties{}) tcpipErr := dev.stack.AddProtocolAddress(1, protoAddr, stack.AddressProperties{})
if tcpipErr != nil { if tcpipErr != nil {
@@ -116,7 +116,7 @@ func (tun *netTun) Write(buf []byte, offset int) (int, error) {
return 0, nil return 0, nil
} }
pkb := stack.NewPacketBuffer(stack.PacketBufferOptions{Payload: bufferv2.MakeWithData(packet)}) pkb := stack.NewPacketBuffer(stack.PacketBufferOptions{Payload: buffer.MakeWithData(packet)})
switch packet[0] >> 4 { switch packet[0] >> 4 {
case 4: case 4:
tun.ep.InjectInbound(header.IPv4ProtocolNumber, pkb) tun.ep.InjectInbound(header.IPv4ProtocolNumber, pkb)
@@ -172,7 +172,7 @@ func convertToFullAddr(endpoint netip.AddrPort) (tcpip.FullAddress, tcpip.Networ
} }
return tcpip.FullAddress{ return tcpip.FullAddress{
NIC: 1, NIC: 1,
Addr: tcpip.Address(endpoint.Addr().AsSlice()), Addr: tcpip.AddrFromSlice(endpoint.Addr().AsSlice()),
Port: endpoint.Port(), Port: endpoint.Port(),
}, protoNumber }, protoNumber
} }

View File

@@ -14,7 +14,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/golang/protobuf/proto"
"github.com/xtls/xray-core/app/dispatcher" "github.com/xtls/xray-core/app/dispatcher"
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -25,6 +24,7 @@ import (
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/units" "github.com/xtls/xray-core/common/units"
core "github.com/xtls/xray-core/core" core "github.com/xtls/xray-core/core"
"google.golang.org/protobuf/proto"
) )
func xor(b []byte) []byte { func xor(b []byte) []byte {

View File

@@ -21,8 +21,13 @@ func (c *Config) getServiceName() string {
if !strings.HasPrefix(c.ServiceName, "/") { if !strings.HasPrefix(c.ServiceName, "/") {
return url.PathEscape(c.ServiceName) return url.PathEscape(c.ServiceName)
} }
// Otherwise new custom paths // Otherwise new custom paths
rawServiceName := c.ServiceName[1:strings.LastIndex(c.ServiceName, "/")] // trim from first to last '/' lastIndex := strings.LastIndex(c.ServiceName, "/")
if lastIndex < 1 {
lastIndex = 1
}
rawServiceName := c.ServiceName[1:lastIndex] // trim from first to last '/'
serviceNameParts := strings.Split(rawServiceName, "/") serviceNameParts := strings.Split(rawServiceName, "/")
for i := range serviceNameParts { for i := range serviceNameParts {
serviceNameParts[i] = url.PathEscape(serviceNameParts[i]) serviceNameParts[i] = url.PathEscape(serviceNameParts[i])

View File

@@ -1,8 +1,9 @@
package grpc package grpc
import ( import (
"github.com/stretchr/testify/assert"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestConfig_GetServiceName(t *testing.T) { func TestConfig_GetServiceName(t *testing.T) {
@@ -31,6 +32,11 @@ func TestConfig_GetServiceName(t *testing.T) {
ServiceName: "/hello /world!/a|b", ServiceName: "/hello /world!/a|b",
Expected: "hello%20/world%21", Expected: "hello%20/world%21",
}, },
{
TestName: "path with only one '/'",
ServiceName: "/foo",
Expected: "",
},
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.TestName, func(t *testing.T) { t.Run(test.TestName, func(t *testing.T) {

View File

@@ -98,16 +98,13 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
MinConnectTimeout: 5 * time.Second, MinConnectTimeout: 5 * time.Second,
}), }),
grpc.WithContextDialer(func(gctx context.Context, s string) (gonet.Conn, error) { grpc.WithContextDialer(func(gctx context.Context, s string) (gonet.Conn, error) {
gctx = session.ContextWithID(gctx, session.IDFromContext(ctx))
gctx = session.ContextWithOutbound(gctx, session.OutboundFromContext(ctx))
rawHost, rawPort, err := net.SplitHostPort(s)
select { select {
case <-gctx.Done(): case <-gctx.Done():
return nil, gctx.Err() return nil, gctx.Err()
default: default:
} }
rawHost, rawPort, err := net.SplitHostPort(s)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -119,9 +116,14 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
return nil, err return nil, err
} }
address := net.ParseAddress(rawHost) address := net.ParseAddress(rawHost)
gctx = session.ContextWithID(gctx, session.IDFromContext(ctx))
gctx = session.ContextWithOutbound(gctx, session.OutboundFromContext(ctx))
gctx = session.ContextWithTimeoutOnly(gctx, true)
c, err := internet.DialSystem(gctx, net.TCPDestination(address, port), sockopt) c, err := internet.DialSystem(gctx, net.TCPDestination(address, port), sockopt)
if err == nil && realityConfig != nil { if err == nil && realityConfig != nil {
return reality.UClient(c, realityConfig, ctx, dest) return reality.UClient(c, realityConfig, gctx, dest)
} }
return c, err return c, err
}), }),

View File

@@ -23,7 +23,6 @@ type Listener struct {
handler internet.ConnHandler handler internet.ConnHandler
local net.Addr local net.Addr
config *Config config *Config
locker *internet.FileLocker // for unix domain socket
s *grpc.Server s *grpc.Server
} }
@@ -110,10 +109,6 @@ func Listen(ctx context.Context, address net.Address, port net.Port, settings *i
newError("failed to listen on ", address).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx)) newError("failed to listen on ", address).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
return return
} }
locker := ctx.Value(address.Domain())
if locker != nil {
listener.locker = locker.(*internet.FileLocker)
}
} else { // tcp } else { // tcp
streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{ streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{
IP: address.IP(), IP: address.IP(),

View File

@@ -53,7 +53,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
} }
transport := &http2.Transport{ transport := &http2.Transport{
DialTLS: func(network string, addr string, tlsConfig *gotls.Config) (net.Conn, error) { DialTLSContext: func(hctx context.Context, string, addr string, tlsConfig *gotls.Config) (net.Conn, error) {
rawHost, rawPort, err := net.SplitHostPort(addr) rawHost, rawPort, err := net.SplitHostPort(addr)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -67,18 +67,18 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
} }
address := net.ParseAddress(rawHost) address := net.ParseAddress(rawHost)
dctx := context.Background() hctx = session.ContextWithID(hctx, session.IDFromContext(ctx))
dctx = session.ContextWithID(dctx, session.IDFromContext(ctx)) hctx = session.ContextWithOutbound(hctx, session.OutboundFromContext(ctx))
dctx = session.ContextWithOutbound(dctx, session.OutboundFromContext(ctx)) hctx = session.ContextWithTimeoutOnly(hctx, true)
pconn, err := internet.DialSystem(dctx, net.TCPDestination(address, port), sockopt) pconn, err := internet.DialSystem(hctx, net.TCPDestination(address, port), sockopt)
if err != nil { if err != nil {
newError("failed to dial to " + addr).Base(err).AtError().WriteToLog() newError("failed to dial to " + addr).Base(err).AtError().WriteToLog()
return nil, err return nil, err
} }
if realityConfigs != nil { if realityConfigs != nil {
return reality.UClient(pconn, realityConfigs, ctx, dest) return reality.UClient(pconn, realityConfigs, hctx, dest)
} }
var cn tls.Interface var cn tls.Interface
@@ -173,6 +173,15 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
if err != nil { if err != nil {
newError("failed to dial to ", dest).Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx)) newError("failed to dial to ", dest).Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
wrc.Close() wrc.Close()
{
// Abandon `client` if `client.Do(request)` failed
// See https://github.com/golang/go/issues/30702
globalDialerAccess.Lock()
if globalDialerMap[dialerConf{dest, streamSettings}] == client {
delete(globalDialerMap, dialerConf{dest, streamSettings})
}
globalDialerAccess.Unlock()
}
return return
} }
if response.StatusCode != 200 { if response.StatusCode != 200 {

View File

@@ -27,7 +27,6 @@ type Listener struct {
handler internet.ConnHandler handler internet.ConnHandler
local net.Addr local net.Addr
config *Config config *Config
locker *internet.FileLocker // for unix domain socket
} }
func (l *Listener) Addr() net.Addr { func (l *Listener) Addr() net.Addr {
@@ -35,9 +34,6 @@ func (l *Listener) Addr() net.Addr {
} }
func (l *Listener) Close() error { func (l *Listener) Close() error {
if l.locker != nil {
l.locker.Release()
}
return l.server.Close() return l.server.Close()
} }
@@ -180,10 +176,6 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
newError("failed to listen on ", address).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx)) newError("failed to listen on ", address).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
return return
} }
locker := ctx.Value(address.Domain())
if locker != nil {
listener.locker = locker.(*internet.FileLocker)
}
} else { // tcp } else { // tcp
streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{ streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{
IP: address.IP(), IP: address.IP(),

View File

@@ -5,6 +5,7 @@ import (
"context" "context"
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"crypto/ecdh"
"crypto/ed25519" "crypto/ed25519"
"crypto/hmac" "crypto/hmac"
"crypto/rand" "crypto/rand"
@@ -134,7 +135,8 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
if config.Show { if config.Show {
fmt.Printf("REALITY localAddr: %v\thello.SessionId[:16]: %v\n", localAddr, hello.SessionId[:16]) fmt.Printf("REALITY localAddr: %v\thello.SessionId[:16]: %v\n", localAddr, hello.SessionId[:16])
} }
uConn.AuthKey = uConn.HandshakeState.State13.EcdheParams.SharedKey(config.PublicKey) publicKey, _ := ecdh.X25519().NewPublicKey(config.PublicKey)
uConn.AuthKey, _ = uConn.HandshakeState.State13.EcdheKey.ECDH(publicKey)
if uConn.AuthKey == nil { if uConn.AuthKey == nil {
return nil, errors.New("REALITY: SharedKey == nil") return nil, errors.New("REALITY: SharedKey == nil")
} }
@@ -154,7 +156,7 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
aead.Seal(hello.SessionId[:0], hello.Random[20:], hello.SessionId[:16], hello.Raw) aead.Seal(hello.SessionId[:0], hello.Random[20:], hello.SessionId[:16], hello.Raw)
copy(hello.Raw[39:], hello.SessionId) copy(hello.Raw[39:], hello.SessionId)
} }
if err := uConn.Handshake(); err != nil { if err := uConn.HandshakeContext(ctx); err != nil {
return nil, err return nil, err
} }
if config.Show { if config.Show {

View File

@@ -21,6 +21,19 @@ type DefaultListener struct {
controllers []control.Func controllers []control.Func
} }
type combinedListener struct {
net.Listener
locker *FileLocker // for unix domain socket
}
func (cl *combinedListener) Close() error {
if cl.locker != nil {
cl.locker.Release()
cl.locker = nil
}
return cl.Listener.Close()
}
func getControlFunc(ctx context.Context, sockopt *SocketConfig, controllers []control.Func) func(network, address string, c syscall.RawConn) error { func getControlFunc(ctx context.Context, sockopt *SocketConfig, controllers []control.Func) func(network, address string, c syscall.RawConn) error {
return func(network, address string, c syscall.RawConn) error { return func(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) { return c.Control(func(fd uintptr) {
@@ -44,6 +57,10 @@ func getControlFunc(ctx context.Context, sockopt *SocketConfig, controllers []co
func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *SocketConfig) (l net.Listener, err error) { func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *SocketConfig) (l net.Listener, err error) {
var lc net.ListenConfig var lc net.ListenConfig
var network, address string var network, address string
// callback is called after the Listen function returns
callback := func(l net.Listener, err error) (net.Listener, error) {
return l, err
}
switch addr := addr.(type) { switch addr := addr.(type) {
case *net.TCPAddr: case *net.TCPAddr:
@@ -58,23 +75,6 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S
network = addr.Network() network = addr.Network()
address = addr.Name address = addr.Name
if s := strings.Split(address, ","); len(s) == 2 {
address = s[0]
perm, perr := strconv.ParseUint(s[1], 8, 32)
if perr != nil {
return nil, newError("failed to parse permission: " + s[1]).Base(perr)
}
defer func(file string, permission os.FileMode) {
if err == nil {
cerr := os.Chmod(address, permission)
if cerr != nil {
err = newError("failed to set permission for " + file).Base(cerr)
}
}
}(address, os.FileMode(perm))
}
if (runtime.GOOS == "linux" || runtime.GOOS == "android") && address[0] == '@' { if (runtime.GOOS == "linux" || runtime.GOOS == "android") && address[0] == '@' {
// linux abstract unix domain socket is lockfree // linux abstract unix domain socket is lockfree
if len(address) > 1 && address[1] == '@' { if len(address) > 1 && address[1] == '@' {
@@ -84,19 +84,48 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S
address = string(fullAddr) address = string(fullAddr)
} }
} else { } else {
// split permission from address
var filePerm *os.FileMode
if s := strings.Split(address, ","); len(s) == 2 {
address = s[0]
perm, perr := strconv.ParseUint(s[1], 8, 32)
if perr != nil {
return nil, newError("failed to parse permission: " + s[1]).Base(perr)
}
mode := os.FileMode(perm)
filePerm = &mode
}
// normal unix domain socket needs lock // normal unix domain socket needs lock
locker := &FileLocker{ locker := &FileLocker{
path: address + ".lock", path: address + ".lock",
} }
err := locker.Acquire() if err := locker.Acquire(); err != nil {
if err != nil {
return nil, err return nil, err
} }
ctx = context.WithValue(ctx, address, locker)
// set callback to combine listener and set permission
callback = func(l net.Listener, err error) (net.Listener, error) {
if err != nil {
locker.Release()
return l, err
}
l = &combinedListener{Listener: l, locker: locker}
if filePerm == nil {
return l, nil
}
err = os.Chmod(address, *filePerm)
if err != nil {
l.Close()
return nil, newError("failed to set permission for " + address).Base(err)
}
return l, nil
}
} }
} }
l, err = lc.Listen(ctx, network, address) l, err = lc.Listen(ctx, network, address)
l, err = callback(l, err)
if sockopt != nil && sockopt.AcceptProxyProtocol { if sockopt != nil && sockopt.AcceptProxyProtocol {
policyFunc := func(upstream net.Addr) (proxyproto.Policy, error) { return proxyproto.REQUIRE, nil } policyFunc := func(upstream net.Addr) (proxyproto.Policy, error) { return proxyproto.REQUIRE, nil }
l = &proxyproto.Listener{Listener: l, Policy: policyFunc} l = &proxyproto.Listener{Listener: l, Policy: policyFunc}

View File

@@ -24,7 +24,6 @@ type Listener struct {
authConfig internet.ConnectionAuthenticator authConfig internet.ConnectionAuthenticator
config *Config config *Config
addConn internet.ConnHandler addConn internet.ConnHandler
locker *internet.FileLocker // for unix domain socket
} }
// ListenTCP creates a new Listener based on configurations. // ListenTCP creates a new Listener based on configurations.
@@ -51,10 +50,6 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSe
return nil, newError("failed to listen Unix Domain Socket on ", address).Base(err) return nil, newError("failed to listen Unix Domain Socket on ", address).Base(err)
} }
newError("listening Unix Domain Socket on ", address).WriteToLog(session.ExportIDToError(ctx)) newError("listening Unix Domain Socket on ", address).WriteToLog(session.ExportIDToError(ctx))
locker := ctx.Value(address.Domain())
if locker != nil {
l.locker = locker.(*internet.FileLocker)
}
} else { } else {
listener, err = internet.ListenSystem(ctx, &net.TCPAddr{ listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
IP: address.IP(), IP: address.IP(),
@@ -133,9 +128,6 @@ func (v *Listener) Addr() net.Addr {
// Close implements internet.Listener.Close. // Close implements internet.Listener.Close.
func (v *Listener) Close() error { func (v *Listener) Close() error {
if v.locker != nil {
v.locker.Release()
}
return v.listener.Close() return v.listener.Close()
} }

View File

@@ -75,7 +75,6 @@ type Listener struct {
listener net.Listener listener net.Listener
config *Config config *Config
addConn internet.ConnHandler addConn internet.ConnHandler
locker *internet.FileLocker // for unix domain socket
} }
func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, addConn internet.ConnHandler) (internet.Listener, error) { func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, addConn internet.ConnHandler) (internet.Listener, error) {
@@ -101,10 +100,6 @@ func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSet
return nil, newError("failed to listen unix domain socket(for WS) on ", address).Base(err) return nil, newError("failed to listen unix domain socket(for WS) on ", address).Base(err)
} }
newError("listening unix domain socket(for WS) on ", address).WriteToLog(session.ExportIDToError(ctx)) newError("listening unix domain socket(for WS) on ", address).WriteToLog(session.ExportIDToError(ctx))
locker := ctx.Value(address.Domain())
if locker != nil {
l.locker = locker.(*internet.FileLocker)
}
} else { // tcp } else { // tcp
listener, err = internet.ListenSystem(ctx, &net.TCPAddr{ listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
IP: address.IP(), IP: address.IP(),
@@ -153,9 +148,6 @@ func (ln *Listener) Addr() net.Addr {
// Close implements net.Listener.Close(). // Close implements net.Listener.Close().
func (ln *Listener) Close() error { func (ln *Listener) Close() error {
if ln.locker != nil {
ln.locker.Release()
}
return ln.listener.Close() return ln.listener.Close()
} }

View File

@@ -24,7 +24,6 @@ const (
type pipeOption struct { type pipeOption struct {
limit int32 // maximum buffer size in bytes limit int32 // maximum buffer size in bytes
discardOverflow bool discardOverflow bool
onTransmission func(buffer buf.MultiBuffer) buf.MultiBuffer
} }
func (o *pipeOption) isFull(curSize int32) bool { func (o *pipeOption) isFull(curSize int32) bool {
@@ -141,10 +140,6 @@ func (p *pipe) WriteMultiBuffer(mb buf.MultiBuffer) error {
return nil return nil
} }
if p.option.onTransmission != nil {
mb = p.option.onTransmission(mb)
}
for { for {
err := p.writeMultiBufferInternal(mb) err := p.writeMultiBufferInternal(mb)
if err == nil { if err == nil {

View File

@@ -3,7 +3,6 @@ package pipe
import ( import (
"context" "context"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/signal" "github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
@@ -26,12 +25,6 @@ func WithSizeLimit(limit int32) Option {
} }
} }
func OnTransmission(hook func(mb buf.MultiBuffer) buf.MultiBuffer) Option {
return func(option *pipeOption) {
option.onTransmission = hook
}
}
// DiscardOverflow returns an Option for Pipe to discard writes if full. // DiscardOverflow returns an Option for Pipe to discard writes if full.
func DiscardOverflow() Option { func DiscardOverflow() Option {
return func(opt *pipeOption) { return func(opt *pipeOption) {