Compare commits

..

456 Commits

Author SHA1 Message Date
RPRX
b6b51c51c8 v25.7.26
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-07-26 09:07:56 +00:00
风扇滑翔翼
fb7a9d8d61 TLS client & server: Support Encrypted Client Hello (ECH) (#3813)
b9a72a4a26

---------

Co-authored-by: yuhan6665 <1588741+yuhan6665@users.noreply.github.com>
2025-07-26 08:47:27 +00:00
nobody
3fe02a658a Commands: Add adu/rmu inbound user management to API (#4943)
Co-authored-by: nobody <nobody@nowhere.mars>
2025-07-26 08:40:04 +00:00
RPRX
5f93ff6c3a REALITY config: mldsa65Seed and privateKey can not be the same value
Otherwise the point of using ML-DSA-65 is lost.
2025-07-26 08:36:58 +00:00
patterniha
10376f5b4d Freedom UDP: Fix some cone uses like STUN,... when address is domain (#4942)
https://github.com/XTLS/Xray-core/issues/2962#issuecomment-3120472154
2025-07-26 01:59:15 +00:00
风扇滑翔翼
1ea00fad81 UDP listener: Allow listening on "localhost" (#4940)
Fixes https://github.com/XTLS/Xray-core/issues/4939
2025-07-26 01:27:35 +00:00
RPRX
cfcf2a63d1 v25.7.25
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-07-25 14:59:43 +00:00
Meow
66025f2889 Workflows: Fix github.ref_name sometimes is empty when building Docker images (#4937)
From https://github.com/XTLS/Xray-core/pull/4809
2025-07-25 14:47:12 +00:00
风扇滑翔翼
c9cd26d6d3 UDP: Remove removeRay()'s error log (#4936)
From https://github.com/XTLS/Xray-core/pull/4899
2025-07-25 14:40:26 +00:00
RPRX
caee152adf Update github.com/xtls/reality to 20250725142056
5b52a03d4f
2025-07-25 14:28:47 +00:00
风扇滑翔翼
eb433d9462 Inbounds & Outbounds: TCP KeepAlive better default value (#4931)
From https://github.com/XTLS/Xray-core/pull/4927
2025-07-25 12:06:05 +00:00
风扇滑翔翼
87d8b97d9a Commands: Output certificate chain's total length in tls ping (#4933)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-07-25 10:18:26 +00:00
风扇滑翔翼
9d15ecf1f9 REALITY client: Fix log when printing "is using X25519MLKEM768..." (#4929) 2025-07-25 07:11:35 +00:00
RPRX
4f45c5faa5 v25.7.24
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-07-24 02:19:08 +00:00
RPRX
26de58933f README.md: Update Donation & NFTs
https://opensea.io/collection/xtls
2025-07-24 02:08:03 +00:00
RPRX
31b508d372 REALITY config: Convert mldsa65Seed to its private key later 2025-07-24 01:31:07 +00:00
风扇滑翔翼
955a569181 REALITY config: Allow mldsa65 fields to be empty (#4924) 2025-07-24 01:15:48 +00:00
RPRX
d141d01d0c v25.7.23
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-07-23 12:55:05 +00:00
patterniha
4e826abebf Chore: Three small fixes (#4922) 2025-07-23 12:53:37 +00:00
RPRX
4433641e30 Update github.com/xtls/reality to 20250723121014
c6320729d9
2025-07-23 12:39:10 +00:00
RPRX
a196a16c55 README.md: Add Project X NFT's image & link
https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1
2025-07-23 12:21:40 +00:00
Stan B.
8c0bf15901 README.md: Add GoXRay to macOS & Linux Clients (#4260)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-07-23 12:17:18 +00:00
Happ-dev
dbd9125686 README.md: Add Happ to macOS x64 & tvOS Clients (#4921)
Co-authored-by: y.sivushkin <y.sivushkin@corp.101xp.com>
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-07-23 10:52:59 +00:00
j2rong4cn
923b5d7229 DNS hosts: Support returning RCode (#4681) 2025-07-23 10:11:43 +00:00
风扇滑翔翼
f90fae22aa UDP: Fix removeRay will close a connEntry that not belongs to it (#4899) 2025-07-23 10:10:12 +00:00
patterniha
b065595f58 Reverse: portal-worker should not be closed before making sure there is at least one other active worker (#4869) 2025-07-23 10:09:17 +00:00
patterniha
308f8a7459 MUX: Refine and Fix some occasional problems (#4861)
Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
2025-07-23 10:09:04 +00:00
patterniha
050f596e8f Freedom: Fix UDP reply mismatch-address (#4816) 2025-07-23 10:07:24 +00:00
风扇滑翔翼
3b47d0846e Freedom: Cache UDP resolve result (#4804) 2025-07-23 10:02:27 +00:00
dependabot[bot]
7f23a1cb65 Bump google.golang.org/grpc from 1.73.0 to 1.74.2 (#4919)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.73.0 to 1.74.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.73.0...v1.74.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.74.2
  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>
2025-07-23 02:37:58 +00:00
RPRX
446315cf1f REALITY protocol: Add optional Post-Quantum ML-DSA-65 verification for cert's ExtraExtensions (#4915)
00881f6740
2025-07-23 02:29:11 +00:00
RPRX
eed05549fc Revert "Bump google.golang.org/grpc from 1.73.0 to 1.74.0 (#4905)" (#4914)
This reverts commit 6afd721ced.
2025-07-21 04:55:43 +00:00
dependabot[bot]
2b4a8d235b Bump github.com/quic-go/quic-go from 0.53.0 to 0.54.0 (#4913)
---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-version: 0.54.0
  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>
2025-07-21 02:19:47 +00:00
风扇滑翔翼
83686ebfaa DNS outbound: Prevent panic from rejecting invalid domain (#4903)
Fixes https://github.com/XTLS/Xray-core/pull/4824#issuecomment-3078811352
2025-07-19 01:52:26 +00:00
Meow
79c6f99384 Workflows: Cleaner Docker builds, support for manual exec and pre-release (#4809) 2025-07-19 01:29:25 +00:00
Random Guy
ca8ef209a7 Stats API: Return status "not found" instead of "unknown" (#4860) 2025-07-19 01:21:18 +00:00
风扇滑翔翼
cbcab89c7e Commands: Display Post-Quantum key exchange in tls ping (#4857)
https://github.com/XTLS/Xray-core/pull/4857#issuecomment-3064964301
2025-07-19 01:14:56 +00:00
xqzr
abd551e9f7 VLESS fallbacks: dest defaults to "127.0.0.1" -> "localhost" (#4840)
https://github.com/XTLS/Xray-examples/issues/234#issuecomment-3091319391
2025-07-19 00:47:43 +00:00
o_O
10dbeb4335 README.md: Add AnyPortal to GUI Clients (#4902) 2025-07-19 00:33:46 +00:00
dependabot[bot]
6afd721ced Bump google.golang.org/grpc from 1.73.0 to 1.74.0 (#4905)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.73.0 to 1.74.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.73.0...v1.74.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.74.0
  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>
2025-07-19 00:27:18 +00:00
dependabot[bot]
5c0bc361d3 Bump golang.org/x/net from 0.41.0 to 0.42.0 (#4892)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.41.0 to 0.42.0.
- [Commits](https://github.com/golang/net/compare/v0.41.0...v0.42.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.42.0
  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>
2025-07-19 00:27:00 +00:00
xDragonZ
3a2ac9d0bf Bump quic-go to v0.53.0 & update codes (#4906) 2025-07-19 00:21:18 +00:00
RPRX
1785178762 REALITY server: Three types of ALPN for post-handshake records detection & imitation; Two fixes
https://github.com/XTLS/Xray-core/issues/4778#issuecomment-3072047745

Closes https://github.com/XTLS/Xray-core/issues/4788

---------

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

Fixes https://github.com/XTLS/Xray-core/issues/4845
2025-07-19 00:06:59 +00:00
dependabot[bot]
1976d02ec9 Bump golang.org/x/sys from 0.33.0 to 0.34.0 (#4882)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.33.0 to 0.34.0.
- [Commits](https://github.com/golang/sys/compare/v0.33.0...v0.34.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.34.0
  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>
2025-07-11 13:01:47 -04:00
dependabot[bot]
3ba733079e Bump golang.org/x/crypto from 0.39.0 to 0.40.0 (#4885)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.39.0 to 0.40.0.
- [Commits](https://github.com/golang/crypto/compare/v0.39.0...v0.40.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.40.0
  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>
2025-07-11 13:01:32 -04:00
dependabot[bot]
6a8a85f83a Bump golang.org/x/sync from 0.15.0 to 0.16.0 (#4881)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.15.0 to 0.16.0.
- [Commits](https://github.com/golang/sync/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.16.0
  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>
2025-07-11 12:55:05 -04:00
dependabot[bot]
409e4e8f12 Bump github.com/miekg/dns from 1.1.66 to 1.1.67 (#4880)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.66 to 1.1.67.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.66...v1.1.67)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-version: 1.1.67
  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>
2025-07-11 12:54:33 -04:00
Jesus
486d005986 API: add option to fetch only tags from ListInbounds (#4870)
* feat: add new method for get only inbound tags from core. ListTags.

* refactor: simplify creating response.

* refactor: move getting tags in already exist method via option.
2025-07-11 12:52:51 -04:00
isluckys
cb1afb33e6 common: fix task leak in timer (#4831)
signal包里面SetTimeout方法并发时可能会出现task close以后执行start导致泄露
2025-06-23 08:47:27 -04:00
风扇滑翔翼
38ed2cc387 DNS: Add new nonIPQuery "reject" (#4824) 2025-06-22 22:48:24 -04:00
fL1pSt3r
b043db8260 API: Fix issue with inbounduser not finding emails with uppercase letters (#4818) 2025-06-22 21:57:02 -04:00
Jesus
27742da2c6 BurstObservatory: add option to set http method for burst check (#4835)
* feat: add options to set method for burst check.

* chore: gen proto.

* chore: change protoc-gen-go to latest.

* revert

---------

Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
2025-06-22 21:48:49 -04:00
RPRX
fbae89d017 v25.6.8
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-06-08 13:53:03 +00:00
ketetefid
58c28b4aeb README.md: Add GorzRay to Linux Clients (#4767) 2025-06-08 13:51:39 +00:00
Yury Kastov
ca1c4b63f6 README.md: Add xtls-sdk to Xray Wrapper (#4793)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-06-08 13:47:23 +00:00
Meow
18ab291e0c REALITY: Add rate limiting to fallback handling via token bucket (#4553)
https://github.com/XTLS/REALITY/pull/12
2025-06-08 13:43:55 +00:00
RPRX
e011b746dc RAW transport hub.go: Call REALITY's DetectPostHandshakeRecordsLens() in advance
https://github.com/XTLS/Xray-core/issues/4778#issuecomment-2953455751
2025-06-08 05:01:31 +00:00
TonyMa1
f4b23c6565 README.md: Add DeepWiki badge to Contributing (#4777)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-06-08 04:51:10 +00:00
Meow
7d36cad3e0 Docker: Fix geodata directory permissions issue (#4790)
Fixes https://github.com/XTLS/Xray-core/issues/4747#issuecomment-2953519012
2025-06-08 04:49:26 +00:00
Meow
a576a4b183 Tests: Real fix for TestCommanderListHandlers (#4792)
Completes 402067d281
2025-06-08 04:47:04 +00:00
RPRX
f38d3f786a v25.6.7
Announcement of NFTs by Project X: #3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: #4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-06-07 13:37:24 +00:00
Meow
402067d281 Tests: Fix TestCommanderListHandlers (#4789) 2025-06-07 13:24:39 +00:00
patterniha
97fdcb4228 New feature: Happy Eyeballs (RFC 8305) (#4667)
Closes https://github.com/XTLS/Xray-core/issues/4473
2025-06-07 13:20:06 +00:00
RPRX
bfbccc2721 Update github.com/xtls/reality to 20250607105625
https://github.com/XTLS/Xray-core/issues/4778#issuecomment-2952355740

https://github.com/XTLS/Xray-core/issues/4741#issuecomment-2919838784
2025-06-07 11:22:12 +00:00
lhear
f67c70c4a2 README.md: Add SimpleXray to Android Clients (#4761) 2025-06-07 09:49:13 +00:00
vpainless
83e5fa4f3c README.md: Add VPainLess to One Click (#4782)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-06-07 09:33:20 +00:00
patterniha
4e1a6f0fd1 Sniffer-destOverride: Remove fakedns+others option (#4739)
https://github.com/XTLS/Xray-core/pull/4726#issuecomment-2886494540
2025-06-07 09:01:57 +00:00
RPRX
ab0b9a6220 REALITY practice: Detect & imitate target's post-handshake records
Fixes https://github.com/XTLS/Xray-core/issues/4778
2025-06-07 08:59:39 +00:00
yuhan6665
b80e319655 README.md: Add Amnezia VPN to Others (#4718) 2025-06-06 02:04:17 +00:00
patterniha
6232e230d9 DNS New Features: disableCache, finalQuery, unexpectedIPs, "*", UseSystem-queryStrategy, useSystemHosts (#4666) 2025-06-06 01:59:16 +00:00
Aubrey Yang
028e1114e6 Outbound: Fix sendthrough srcip precheck (#4750)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-06-06 01:54:15 +00:00
Sergey Gorbunov
af7a76da67 API: Add ListInbounds and ListOutbounds (#4723) 2025-06-06 01:51:48 +00:00
Meow
d44c78b819 Workflows: Refactor docker (#4738)
* Workflows: Rewrite Docker image build process

* Docker: Merge Multi-Arch Manifests
2025-06-06 01:50:05 +00:00
Tamim Hossain
d0c80fc80d Core: Export the running bool (#4775) 2025-06-06 01:48:19 +00:00
dependabot[bot]
1f49bfc6a5 Bump golang.org/x/net from 0.40.0 to 0.41.0 (#4786)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.40.0 to 0.41.0.
- [Commits](https://github.com/golang/net/compare/v0.40.0...v0.41.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.41.0
  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>
2025-06-06 01:46:30 +00:00
dependabot[bot]
dd52732e1f Bump google.golang.org/grpc from 1.72.2 to 1.73.0 (#4783)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.72.2 to 1.73.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.2...v1.73.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.73.0
  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>
2025-06-06 01:46:16 +00:00
dependabot[bot]
4af53ab364 Bump google.golang.org/grpc from 1.72.1 to 1.72.2 (#4763)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.72.1 to 1.72.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.1...v1.72.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.2
  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>
2025-06-04 13:51:39 +00:00
风扇滑翔翼
462bc3cfba BurstObservatory: Fix nil panic when pingConfig is missing (#4757)
Fixes https://github.com/XTLS/Xray-core/issues/4756
2025-06-04 12:37:43 +00:00
yuhan6665
84c8e24a6c Update reality to 20250527 2025-05-26 21:55:30 -04:00
dependabot[bot]
9fe4ee75b7 Bump github.com/quic-go/quic-go from 0.51.0 to 0.52.0 (#4752)
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.51.0 to 0.52.0.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.51.0...v0.52.0)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-version: 0.52.0
  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>
2025-05-26 01:33:50 +00:00
yiguodev
f1116cee60 README.md: Rename FoXray to OneXray in GUI Clients (#4754)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-05-26 01:31:19 +00:00
RPRX
800b8b50cc v25.5.16
Announcement of NFTs by Project X: #3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: #4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-05-16 12:18:34 +00:00
风扇滑翔翼
ef1c165cc5 QUIC sniffer: Fix potential slice panic (#4732)
Fixes https://github.com/XTLS/Xray-core/issues/3914#issuecomment-2853392827
2025-05-16 12:08:29 +00:00
patterniha
bb0e561caf Sniffer: Fix potential infinite loop (#4726)
Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
2025-05-16 12:04:54 +00:00
RPRX
09d84c42e9 REALITY protocol: Remove ChaCha20-Poly1305 support for REALITY's session id auth
https://github.com/XTLS/Xray-core/pull/3813#issuecomment-2885686468

https://github.com/XTLS/REALITY/pull/4#issuecomment-2885815235

Reverts 65b467e448
2025-05-16 07:29:05 +00:00
RPRX
7ddc4a2525 REALITY practice: Support X25519MLKEM768 for TLS' communication
https://github.com/XTLS/Xray-core/pull/3813#issuecomment-2873889724
2025-05-16 04:08:38 +00:00
patterniha
882975ce5a DNS Host: Removing code that was not being executed and should not be executed. (#4721)
* Removing a piece of code that was not being executed and should not be executed.

* Remove d.dns

---------

Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
2025-05-15 10:15:03 -04:00
dependabot[bot]
30bf7be429 Bump google.golang.org/grpc from 1.72.0 to 1.72.1 (#4729)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.72.0 to 1.72.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.0...v1.72.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.1
  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>
2025-05-15 10:12:49 -04:00
dependabot[bot]
c53c1bfc51 Bump github.com/refraction-networking/utls from 1.7.2 to 1.7.3 (#4730)
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.7.2 to 1.7.3.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.7.2...v1.7.3)

---
updated-dependencies:
- dependency-name: github.com/refraction-networking/utls
  dependency-version: 1.7.3
  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>
2025-05-15 10:11:39 -04:00
dependabot[bot]
72170d8b6b Bump github.com/vishvananda/netlink from 1.3.0 to 1.3.1 (#4719)
Bumps [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/vishvananda/netlink/releases)
- [Commits](https://github.com/vishvananda/netlink/compare/v1.3.0...v1.3.1)

---
updated-dependencies:
- dependency-name: github.com/vishvananda/netlink
  dependency-version: 1.3.1
  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>
2025-05-11 20:55:45 -04:00
dependabot[bot]
e9b3c53a0d Bump github.com/refraction-networking/utls from 1.7.1 to 1.7.2 (#4710)
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.7.1 to 1.7.2.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.7.1...v1.7.2)

---
updated-dependencies:
- dependency-name: github.com/refraction-networking/utls
  dependency-version: 1.7.2
  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>
2025-05-09 10:32:00 -04:00
dependabot[bot]
7afed1e74d Bump lukechampine.com/blake3 from 1.4.0 to 1.4.1 (#4709)
Bumps [lukechampine.com/blake3](https://github.com/lukechampine/blake3) from 1.4.0 to 1.4.1.
- [Commits](https://github.com/lukechampine/blake3/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: lukechampine.com/blake3
  dependency-version: 1.4.1
  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>
2025-05-09 10:31:28 -04:00
dependabot[bot]
6ed636840b Bump actions/github-script from 6 to 7 (#4708)
Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 10:29:52 -04:00
Meow
f0dfbc2e66 Workflows: Ensure Geodat exists (#4680) 2025-05-08 15:44:54 -04:00
dependabot[bot]
0d0fe7ef7a Bump github.com/miekg/dns from 1.1.65 to 1.1.66 (#4707)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.65 to 1.1.66.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.65...v1.1.66)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-version: 1.1.66
  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>
2025-05-08 14:48:12 -04:00
patterniha
59aa5e1b88 DNS: temporary appending hosts results (#4702) 2025-05-06 18:11:08 -04:00
dependabot[bot]
3e52f73e3c Bump golang.org/x/net from 0.39.0 to 0.40.0 (#4698)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.39.0 to 0.40.0.
- [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.40.0
  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>
2025-05-06 17:56:07 -04:00
dependabot[bot]
d4ca42715a Bump github.com/pires/go-proxyproto from 0.8.0 to 0.8.1 (#4695)
Bumps [github.com/pires/go-proxyproto](https://github.com/pires/go-proxyproto) from 0.8.0 to 0.8.1.
- [Release notes](https://github.com/pires/go-proxyproto/releases)
- [Commits](https://github.com/pires/go-proxyproto/compare/v0.8.0...v0.8.1)

---
updated-dependencies:
- dependency-name: github.com/pires/go-proxyproto
  dependency-version: 0.8.1
  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>
2025-05-06 17:55:42 -04:00
A1lo
c847c21f3b Workflows: Authenticating the GitHub API call with GitHub token (#4703) 2025-05-06 17:54:14 -04:00
RPRX
87ab8e5128 v25.4.30
Announcement of NFTs by Project X: #3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: #4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-04-30 04:40:58 +00:00
patterniha
54c6513fd4 DNS: Extend hosts Abilities (#4673) 2025-04-30 04:32:52 +00:00
Aubrey Yang
5e6a5ae01d Improve random IP compatibility: support IPv4, add srcip option, and sync client source IP via sendthrough (#4671) 2025-04-30 04:32:02 +00:00
Pk-web6936
19ba9cbe91 Chore: Update gVisor to the latest version; Fmt .go files (#4663) 2025-04-29 11:32:23 +00:00
j2rong4cn
16641fc4b5 Workflows: Build Android(7+) using NDK; Add Android(7+) amd64 build (#4664)
Makes net.LookupIP() work on Android builds
2025-04-29 11:29:52 +00:00
patterniha
aa4134f4a6 DNS: Fix some bugs; Refactors; Optimizations (#4659) 2025-04-29 08:39:57 +00:00
patterniha
1c4e246788 Sockopt: Fix some domainStrategy & dialerProxy bugs (#4661) 2025-04-29 08:33:36 +00:00
j2rong4cn
d9ebb9b2dc QUIC sniffer: Optimize the code (#4655)
Based on 2eed70e17d
2025-04-29 08:04:04 +00:00
RPRX
2eed70e17d buffer.go: Ensure extended part by Extend() & Resize() are all-zero
https://github.com/XTLS/Xray-core/pull/4655#issuecomment-2837693439
2025-04-29 07:33:37 +00:00
j2rong4cn
58c48664e2 QUIC sniffer: Full support for handling multiple initial packets (#4642)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Co-authored-by: Vigilans <vigilans@foxmail.com>
Co-authored-by: Shelikhoo <xiaokangwang@outlook.com>
Co-authored-by: dyhkwong <50692134+dyhkwong@users.noreply.github.com>
2025-04-28 10:03:03 +00:00
yuhan6665
a608c5a1db uTLS: Add new fingerprints
PSK extension, Post-Quantum Key Agreement, ML-KEM
2025-04-26 12:31:41 -04:00
dependabot[bot]
0dd74cf072 Bump github.com/refraction-networking/utls from 1.6.7 to 1.7.1
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.6.7 to 1.7.1.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.6.7...v1.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-25 00:14:52 +00:00
peter zhang
922ae98a4a DNS log: Optimize IP address display (#4630) 2025-04-23 03:10:20 +00:00
dependabot[bot]
800b33c626 Bump github.com/quic-go/quic-go from 0.50.1 to 0.51.0 (#4634)
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.50.1 to 0.51.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.50.1...v0.51.0)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-version: 0.51.0
  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>
2025-04-23 02:58:09 +00:00
dependabot[bot]
0563c9750e Bump google.golang.org/grpc from 1.71.1 to 1.72.0 (#4640)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.71.1 to 1.72.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.1...v1.72.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.0
  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>
2025-04-23 02:57:57 +00:00
xqzr
907a182f64 Sockopt: Fix Windows IP_MULTICAST_IF & IPV6_MULTICAST_IF (#4627)
Completes https://github.com/XTLS/Xray-core/pull/4568
2025-04-19 09:30:12 +00:00
RPRX
0995fa41fe XHTTP client: Set packet-up as the default mode (auto) when using TLS
https://t.me/projectXtls/929
2025-04-18 06:18:51 +00:00
RPRX
2916b1b977 README.md: Rename Clash.Meta to mihomo in Others 2025-04-18 03:57:14 +00:00
RPRX
8212325980 README.md: Add Loon to Others
https://t.me/LoonNews/1662
2025-04-18 03:18:38 +00:00
风扇滑翔翼
5f3ae64f0c Sockopt: Allow customSockopt work for Windows & Darwin (#4576)
* Sockopt: Add custom sockopt on Windows & Darwin

* fix windows udp by the way

* use resolved addr

https://github.com/XTLS/Xray-core/pull/4504#issuecomment-2769153797
2025-04-18 02:30:47 +00:00
Cl-He-O
7a2f42f8d5 Fix issues related to android client (#4616)
* WireGuard: Fix tunnel not closed

* Dialer: Apply controllers in lc.Control
2025-04-14 11:08:26 -04:00
dependabot[bot]
53552d73cc Bump github.com/cloudflare/circl from 1.6.0 to 1.6.1 (#4602)
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.6.0 to 1.6.1.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.6.0...v1.6.1)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  dependency-version: 1.6.1
  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>
2025-04-13 00:55:00 -04:00
dependabot[bot]
19e884bebf Bump golang.org/x/net from 0.38.0 to 0.39.0 (#4598)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.38.0 to 0.39.0.
- [Commits](https://github.com/golang/net/compare/v0.38.0...v0.39.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.39.0
  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>
2025-04-08 11:17:36 -04:00
xqzr
78a1e37e89 Sockopt: Use Windows syscall (#4581) 2025-04-07 11:50:07 -04:00
Ragavendaran Puliyadi
2d3126b752 Config: Implement missing MarshalJSON for structs having custom UnmarshalJSON (#4585)
* conf: implement MarshalJSON for FakeDNSConfig

* conf: Rewrite MarshalJSON for PortList
decouple PortRange from PortList.

* conf: implement MarshalJSON for HostAddress

* conf: Add MarshalJSON comments and use pointers.
2025-04-07 11:46:49 -04:00
dependabot[bot]
0dbab7bcd7 Bump golang.org/x/crypto from 0.36.0 to 0.37.0 (#4597)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.36.0 to 0.37.0.
- [Commits](https://github.com/golang/crypto/compare/v0.36.0...v0.37.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.37.0
  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>
2025-04-07 10:56:44 -04:00
dependabot[bot]
ab15822ee3 Bump golang.org/x/sync from 0.12.0 to 0.13.0 (#4596)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.12.0 to 0.13.0.
- [Commits](https://github.com/golang/sync/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.13.0
  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>
2025-04-07 10:56:34 -04:00
dependabot[bot]
8b2fe32a33 Bump golang.org/x/sys from 0.31.0 to 0.32.0 (#4595)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.31.0 to 0.32.0.
- [Commits](https://github.com/golang/sys/compare/v0.31.0...v0.32.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.32.0
  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>
2025-04-07 10:52:54 -04:00
dependabot[bot]
dd2a40e64d Bump google.golang.org/grpc from 1.71.0 to 1.71.1 (#4577)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.71.0 to 1.71.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.0...v1.71.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 10:30:33 -04:00
dependabot[bot]
33a4336b1d Bump github.com/miekg/dns from 1.1.64 to 1.1.65 (#4594)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.64 to 1.1.65.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.64...v1.1.65)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-version: 1.1.65
  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>
2025-04-07 10:29:49 -04:00
RPRX
ab5d7cf3d2 v25.3.31
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-03-31 12:33:38 +00:00
xqzr
2abeda9c42 Sockopt: Allow listen v6only work for Windows & Darwin (#4571)
Completes https://github.com/XTLS/Xray-core/pull/1677

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-03-31 12:22:16 +00:00
92613hjh
63eb0539b3 Sockopt: Fix Darwin (macOS, iOS...) UDP interface bind (#4530)
Fixes https://github.com/XTLS/Xray-core/issues/4007
2025-03-31 11:19:06 +00:00
RPRX
8284a0ef8f Dialer: Do not use ListenSystemPacket() when dialing UDP
https://github.com/XTLS/Xray-core/pull/4530#issuecomment-2765744961
2025-03-31 10:09:33 +00:00
Ilya Gulya
17207fc5e4 WireGuard: Improve config error handling; Prevent panic in case of errors during server initialization (#4566)
https://github.com/XTLS/Xray-core/pull/4566#issuecomment-2764779273
2025-03-30 22:55:21 +00:00
xqzr
52a2c63682 Sockopt: Fix Windows Multicast interface bind (#4568)
https://github.com/XTLS/Xray-core/pull/4568#issuecomment-2763492336
2025-03-30 20:51:36 +00:00
patterniha
1685c61e44 DNS: Use cache for NXDOMAIN (rcode 3 error) (#4560)
https://github.com/XTLS/Xray-core/pull/4558#issuecomment-2759007356
2025-03-29 14:29:48 +00:00
Pk-web6936
681e943848 Chore: Optimize .gitignore (#4564) 2025-03-29 13:46:26 +00:00
dependabot[bot]
8530bdb0de Bump golang.org/x/net from 0.37.0 to 0.38.0 (#4561)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.37.0 to 0.38.0.
- [Commits](https://github.com/golang/net/compare/v0.37.0...v0.38.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-29 13:42:20 +00:00
风扇滑翔翼
29e37e8a82 HTTP inbound: Directly forward plain HTTP 1xx response header (#4547)
Fixes https://github.com/XTLS/Xray-core/issues/4545
2025-03-26 12:30:48 +00:00
dependabot[bot]
e129b1e90d Bump google.golang.org/protobuf from 1.36.5 to 1.36.6 (#4549)
Bumps google.golang.org/protobuf from 1.36.5 to 1.36.6.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  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>
2025-03-26 12:20:17 +00:00
patterniha
5922caff89 DNS: Add expectedIPs as an alias of expectIPs (#4551)
https://github.com/XTLS/Xray-core/discussions/1903#discussioncomment-5543921
2025-03-26 12:18:58 +00:00
Meo597
4afe2d0cff DNS: Support returning upstream TTL to clients (#4526)
Closes https://github.com/XTLS/Xray-core/issues/4527
2025-03-24 13:33:56 +00:00
patterniha
2d3210e4b8 Env: Add XRAY_LOCATION_CERT variable (#4536)
https://github.com/XTLS/Xray-core/issues/4531#issuecomment-2746155941

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

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-03-24 13:02:35 +00:00
dependabot[bot]
673a9ae063 Bump github.com/quic-go/quic-go from 0.50.0 to 0.50.1 (#4539)
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.50.0 to 0.50.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.50.0...v0.50.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>
2025-03-24 09:49:58 +00:00
RPRX
607c2a6d31 DNS DoH: Use EDNS0 with 100-300 padding by default (body padding)
https://github.com/XTLS/Xray-core/pull/4516#issuecomment-2744093003
2025-03-21 20:13:09 +00:00
风扇滑翔翼
b585b26f29 Sockopt: Fix Windows UDP interface bind; Allow customSockopt work for UDP (#4504) 2025-03-21 10:48:46 +00:00
patterniha
1067171e6a DNS: Add timeoutMs for DnsServerObject (#4523) 2025-03-21 10:24:58 +00:00
风扇滑翔翼
86a225cda1 DNS: Retry with EDNS0 when response is truncated (#4516) 2025-03-21 08:58:51 +00:00
风扇滑翔翼
6f8e253dec DNS: Add tag for DnsServerObject (#4515)
Closes https://github.com/XTLS/Xray-core/issues/4505
2025-03-21 08:58:24 +00:00
patterniha
6a211a0bb9 DNS: Add allowUnexpectedIPs for DnsServerObject (#4497)
Closes https://github.com/XTLS/Xray-core/issues/4424
2025-03-20 12:09:02 +00:00
风扇滑翔翼
335845a9b2 DNS: Ensure order for DNS server match (#4510)
Fixes https://github.com/XTLS/Xray-core/issues/4508
2025-03-20 11:21:21 +00:00
风扇滑翔翼
b70d0abebe API: Fix data race in online ipList (#4513)
Fixes https://github.com/XTLS/Xray-core/issues/4512
2025-03-20 11:12:36 +00:00
dependabot[bot]
3d21128159 Bump github.com/miekg/dns from 1.1.63 to 1.1.64 (#4506)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.63 to 1.1.64.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.63...v1.1.64)

---
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 11:06:51 +00:00
Nikita Korotaev
eca99771ca README.md: Add Remnawave to Web Panels (#4498) 2025-03-20 10:50:43 +00:00
RPRX
2cba2c4d59 v25.3.6
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-03-06 13:50:15 +00:00
Happ-dev
306fa51475 README.md: Add Happ to iOS clients (#4465) 2025-03-06 12:27:25 +00:00
dependabot[bot]
6d6f1c6967 Bump golang.org/x/net from 0.36.0 to 0.37.0 (#4469)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.36.0 to 0.37.0.
- [Commits](https://github.com/golang/net/compare/v0.36.0...v0.37.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-06 10:59:49 +00:00
dependabot[bot]
152959824f Bump google.golang.org/grpc from 1.70.0 to 1.71.0 (#4463)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.70.0 to 1.71.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.70.0...v1.71.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-05 09:23:38 +00:00
dependabot[bot]
a977b6357e Bump golang.org/x/net from 0.35.0 to 0.36.0 (#4462)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.35.0 to 0.36.0.
- [Commits](https://github.com/golang/net/compare/v0.35.0...v0.36.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-05 09:23:31 +00:00
RPRX
16eee1b89c Mux server: Clone the session.Content attached on ctx as well
https://github.com/XTLS/Xray-core/pull/3908#issuecomment-2696911994

Fixes https://github.com/XTLS/Xray-core/pull/3904 for good
2025-03-04 11:01:03 +00:00
RPRX
dde0a4f272 REALITY config: Add password as an alias of publicKey
https://github.com/XTLS/Xray-core/issues/4458#issuecomment-2696181682
2025-03-04 05:29:03 +00:00
RPRX
e15dff94b5 v25.3.3
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-03-03 15:30:22 +00:00
RPRX
e466b0497c DNS DoH: Use Chrome's fingerprint & keepAlivePeriod, Add header padding by default
https://github.com/XTLS/Xray-core/discussions/4430#discussioncomment-12374292
2025-03-03 14:45:12 +00:00
j3l11234
b9cb93d3c2 Sockopt: Add addressPortStrategy (query SRV or TXT) (#4416)
Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
2025-03-02 13:07:55 +00:00
RPRX
8d46f7e14c TLS fingerprints: Refine "random" & "randomized", Add "randomizednoalpn"
https://github.com/XTLS/Xray-core/issues/4436#issuecomment-2687801214
2025-03-02 13:02:47 +00:00
A1lo
4b616f5cd0 XHTTP server: Switch to Go 1.24 native h2c support (#4451) 2025-03-02 13:02:40 +00:00
dependabot[bot]
06b4a7ce4d Bump lukechampine.com/blake3 from 1.3.0 to 1.4.0 (#4439)
Bumps [lukechampine.com/blake3](https://github.com/lukechampine/blake3) from 1.3.0 to 1.4.0.
- [Commits](https://github.com/lukechampine/blake3/compare/v1.3.0...v1.4.0)

---
updated-dependencies:
- dependency-name: lukechampine.com/blake3
  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>
2025-02-25 13:26:54 +00:00
dependabot[bot]
4c12e1686b Bump golang.org/x/crypto from 0.33.0 to 0.35.0 (#4438)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.33.0 to 0.35.0.
- [Commits](https://github.com/golang/crypto/compare/v0.33.0...v0.35.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 13:26:32 +00:00
dependabot[bot]
225d151cd3 Bump github.com/google/go-cmp from 0.6.0 to 0.7.0 (#4433)
Bumps [github.com/google/go-cmp](https://github.com/google/go-cmp) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/google/go-cmp/releases)
- [Commits](https://github.com/google/go-cmp/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: github.com/google/go-cmp
  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>
2025-02-25 13:26:00 +00:00
风扇滑翔翼
d451078e72 Chore: Fix tests (#4440) 2025-02-25 13:11:37 +00:00
RPRX
ce2384cccc Use Go 1.24 2025-02-25 11:35:25 +00:00
RPRX
be43f66b63 v25.2.21
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-02-21 07:58:31 +00:00
dependabot[bot]
71a6d89c23 Bump github.com/quic-go/quic-go from 0.49.0 to 0.50.0 (#4420)
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.49.0 to 0.50.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.49.0...v0.50.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-21 06:34:33 +00:00
lastrise
89792aee9d Outbound: Add outbound sendThrough origin behavior (#4349)
* added support of sending through origin for outbounds

* added strings package import

* usage of net.SplitHostPort instead of manual splitting

---------

Co-authored-by: poly <poly@>
2025-02-20 15:15:59 -05:00
RPRX
b786a50aee XHTTP server: Fix stream-up "single POST problem", Use united httpServerConn instead of recover()
https://github.com/XTLS/Xray-core/issues/4373#issuecomment-2671795675

https://github.com/XTLS/Xray-core/issues/4406#issuecomment-2668041926
2025-02-20 16:28:06 +00:00
风扇滑翔翼
b38a53e629 UDS: Use UnixListenerWrapper & UnixConnWrapper (#4413)
Fixes https://github.com/XTLS/Xray-core/issues/4411

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-02-19 11:31:29 +00:00
RPRX
52381a3c03 v25.2.18
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-02-18 11:55:07 +00:00
风扇滑翔翼
4b01eb4398 Metrics: Add direct listen (#4409) 2025-02-18 11:32:48 +00:00
RPRX
c5de08bea6 XHTTP client: Revert "Add back minimal path padding for compatibility"
Reverts efdc70fbf7
2025-02-18 11:11:36 +00:00
RPRX
8cb63db6c0 XHTTP server: Set remoteAddr & localAddr correctly
Completes 22c50a70c6
2025-02-18 10:50:50 +00:00
yuhan6665
eef74b2c7d XTLS: More separate uplink/downlink flags for splice copy (#4407)
- In 03131c72db new flags were added for uplink/downlink, but that was not suffcient
- Now that the traffic state contains all possible info
- Each inbound and outbound is responsible to set their own CanSpliceCopy flag. Note that this also open up more splice usage. E.g. socks in -> freedom out
- Fixes https://github.com/XTLS/Xray-core/issues/4033
2025-02-18 08:37:52 +00:00
Bill Zhong
a1714cc4ce API: Improve cli usage descriptions (#4401) 2025-02-18 08:36:39 +00:00
𐲓𐳛𐳪𐳂𐳐 𐲀𐳢𐳦𐳫𐳢 𐲥𐳔𐳛𐳪𐳌𐳑𐳖𐳇
958b13ebb5 Build: End of the easily mistaken 'Makefile' (#4395)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-02-18 08:33:05 +00:00
风扇滑翔翼
22c50a70c6 UDS: Make all remote addr 0.0.0.0 (#4390)
https://github.com/XTLS/Xray-core/pull/4389#issuecomment-2656360673

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-02-13 14:01:33 +00:00
yiguous
94c7970fd6 Config: Correctly marshal PortList and NameServerConfig to JSON (#4386) 2025-02-12 14:55:16 +00:00
𐲓𐳛𐳪𐳂𐳐 𐲀𐳢𐳦𐳫𐳢 𐲥𐳔𐳛𐳪𐳌𐳑𐳖𐳇
a71762b5da Workflows: Fix Actions' manual dispatch for assets update (#4378) 2025-02-11 13:19:03 +00:00
dependabot[bot]
5033cbceea Bump golang.org/x/net from 0.34.0 to 0.35.0 (#4382)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.34.0 to 0.35.0.
- [Commits](https://github.com/golang/net/compare/v0.34.0...v0.35.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 13:14:22 +00:00
RPRX
dcd7e92c45 XHTTP server: Finish stream-up's HTTP POST when its request.Body is closed
https://github.com/XTLS/Xray-core/issues/4373#issuecomment-2647908310

Fixes https://github.com/XTLS/Xray-core/issues/4373
2025-02-10 13:56:13 +00:00
dependabot[bot]
2d7ca4a6a6 Bump golang.org/x/crypto from 0.32.0 to 0.33.0 (#4375)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.32.0 to 0.33.0.
- [Commits](https://github.com/golang/crypto/compare/v0.32.0...v0.33.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 08:30:42 +00:00
RPRX
925a985cc0 Commands: Use ".crt" & ".key" suffixes when generating TLS certificates
https://github.com/XTLS/Xray-core/issues/4313#issuecomment-2645844058
2025-02-08 18:29:54 +00:00
RPRX
613c63b165 DNS DoH h2c Remote: Add verifyPeerCertInNames "fromMitm" support
https://github.com/XTLS/Xray-core/issues/4313#issuecomment-2645838663
2025-02-08 18:05:41 +00:00
RPRX
d4c7cd02fd MITM freedom RAW TLS: Allow "fromMitm" to be written at any position in verifyPeerCertInNames, Add checking for alpn "fromMitm"
https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2643340434
2025-02-08 12:11:25 +00:00
𐲓𐳛𐳪𐳂𐳐 𐲀𐳢𐳦𐳫𐳢 𐲥𐳔𐳛𐳪𐳌𐳑𐳖𐳇
db5f18b98c Workflows: Reduce Geodata update frequency (#4369) 2025-02-08 08:07:46 +00:00
RPRX
c81d8e488a Geofiles: Switch to Loyalsoldier's v2ray-rules-dat
https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2643351198
2025-02-08 04:47:43 +00:00
Daniel Lavrushin
1d9e6bc2f3 README.md: Add XrayUI to Asuswrt-Merlin clients (#4355) 2025-02-07 13:57:52 +00:00
Artur Melanchyk
ae327eb7e6 Chore: Make some Maps into real Sets (#4362) 2025-02-07 13:48:33 +00:00
Maxim Plotnikov
e893fa1828 API: Add user IPs and access times tracking (#4360) 2025-02-07 12:19:47 +00:00
dependabot[bot]
1982c2366e Bump google.golang.org/protobuf from 1.36.4 to 1.36.5 (#4363)
Bumps google.golang.org/protobuf from 1.36.4 to 1.36.5.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  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>
2025-02-07 10:09:50 +00:00
RPRX
117de1fd3c MITM freedom RAW TLS: Report website with unexpected Negotiated Protocol / invalid Domain Fronting certificate
https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2639965524

Needs `"alpn": ["fromMitm"]` / `"verifyPeerCertInNames": ["fromMitm", ...]`.
2025-02-07 08:15:40 +00:00
dependabot[bot]
07c35ed52a Bump github.com/cloudflare/circl from 1.5.0 to 1.6.0 (#4352)
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.5.0 to 1.6.0.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  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>
2025-02-06 11:31:13 +00:00
dependabot[bot]
e17c068821 Bump golang.org/x/sync from 0.10.0 to 0.11.0 (#4351)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/sync/compare/v0.10.0...v0.11.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  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>
2025-02-06 11:30:58 +00:00
dependabot[bot]
88d40d6367 Bump golang.org/x/sys from 0.29.0 to 0.30.0 (#4350)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.29.0 to 0.30.0.
- [Commits](https://github.com/golang/sys/compare/v0.29.0...v0.30.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-06 11:28:02 +00:00
RPRX
527caa3711 Log: Add microseconds for golang's standard logger
Completes 5679d717ee
2025-02-06 07:50:48 +00:00
RPRX
c6a31f457c MITM: Allow using local received SNI in the outgoing serverName & verifyPeerCertInNames
https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2637370175

Local received SNI was sent by browser/app.

In freedom RAW's `tlsSettings`, set `"serverName": "fromMitm"` to forward it to the real website.

In freedom RAW's `tlsSettings`, set `"verifyPeerCertInNames": ["fromMitm"]` to use all possible names to verify the certificate.
2025-02-06 07:37:30 +00:00
RPRX
9b7841178a MITM: Allow forwarding local negotiated ALPN http/1.1 to the real website
https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2633656408

https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2633865039

Local negotiated ALPN http/1.1 was sent by browser/app or is written in dokodemo-door RAW's `tlsSettings`.

Set `"alpn": ["fromMitm"]` in freedom RAW's `tlsSettings` to forward it to the real website.
2025-02-04 15:10:08 +00:00
RPRX
480c7d7db7 README.md: Add Project XHTTP (Persian) to Telegram
https://t.me/projectXhttp
2025-02-01 16:51:28 +00:00
auvred
c2f6c89987 Commands: Fix ambiguous printing of private x25519 key (#4343) 2025-02-01 14:45:34 +00:00
RPRX
0a8470cb14 v25.1.30
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-01-30 10:57:37 +00:00
RPRX
efdc70fbf7 XHTTP client: Add back minimal path padding for compatibility
It should be reverted in the future.
2025-01-30 10:45:12 +00:00
dependabot[bot]
f35fb08aeb Bump google.golang.org/protobuf from 1.36.3 to 1.36.4 (#4331)
Bumps google.golang.org/protobuf from 1.36.3 to 1.36.4.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  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>
2025-01-27 20:45:59 +00:00
dependabot[bot]
1bb0beaa43 Bump github.com/miekg/dns from 1.1.62 to 1.1.63 (#4330)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.62 to 1.1.63.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.62...v1.1.63)

---
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 20:45:47 +00:00
yuhan6665
03131c72db XTLS Vision: Use separate uplink/downlink flag for direct copy (#4329)
Fixes https://github.com/XTLS/Xray-core/issues/4033
2025-01-27 20:44:33 +00:00
Sergey Kutovoy
7b59379d73 README.md: Add xray-checker to Xray Tools (#4319)
https://github.com/XTLS/Xray-core/discussions/4316
2025-01-26 15:59:34 +00:00
RPRX
a7a83624c5 Upgrade quic-go to official v0.49.0
https://github.com/quic-go/quic-go/releases/tag/v0.49.0
https://github.com/quic-go/quic-go/pull/4749
https://github.com/quic-go/quic-go/pull/4798
2025-01-26 11:47:30 +00:00
风扇滑翔翼
3a7a78ff3a UDS: Keep valid source addr (#4325)
Fixes https://github.com/XTLS/Xray-core/issues/4324
2025-01-26 11:08:36 +00:00
RPRX
5679d717ee Log: Add microseconds for all kinds of logs
https://github.com/XTLS/Xray-core/issues/4313#issuecomment-2613932895
2025-01-25 11:52:44 +00:00
RPRX
740a6b0dcd RAW: Allow setting ALPN http/1.1 for non-REALITY uTLS
https://github.com/XTLS/Xray-core/issues/4313#issuecomment-2611889517
2025-01-25 11:15:42 +00:00
RPRX
2522cfd7be DNS DoH: Add h2c Remote mode (with TLS serverNameToVerify)
https://github.com/XTLS/Xray-core/issues/4313#issuecomment-2609339864

Applies https://github.com/refraction-networking/utls/pull/161

Closes https://github.com/XTLS/Xray-core/issues/4313
2025-01-25 10:51:44 +00:00
dependabot[bot]
a0822cb440 Bump google.golang.org/grpc from 1.69.4 to 1.70.0 (#4322)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.69.4 to 1.70.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.4...v1.70.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-24 07:24:33 +00:00
RPRX
ca9a902213 XHTTP server: Add scStreamUpServerSecs, enabled by default (#4306)
Fixes https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11682833
2025-01-19 13:32:07 +00:00
风扇滑翔翼
f4fd8b8fad DNS: Implement queryStrategy for "localhost" (#4303)
Fixes https://github.com/XTLS/Xray-core/issues/4302
2025-01-19 07:39:54 +00:00
rPDmYQ
14a6636a41 XHTTP client: Move x_padding into Referer header (#4298)
""Breaking"": Update the server side first, then client
2025-01-18 12:05:19 +00:00
rPDmYQ
30cb22afb1 Mixed inbound: Handle immediately closing connection gracefully (#4297)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-01-17 13:37:40 +00:00
nobody
66dd7808b6 Commands: Fix dumping merged config for XHTTP (#4290)
Fixes https://github.com/XTLS/Xray-core/issues/4287
2025-01-17 10:40:36 +00:00
dependabot[bot]
f1ff454e67 Bump google.golang.org/protobuf from 1.36.2 to 1.36.3 (#4295)
Bumps google.golang.org/protobuf from 1.36.2 to 1.36.3.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  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>
2025-01-16 13:21:31 +00:00
dependabot[bot]
4576f56ec8 Bump google.golang.org/grpc from 1.69.2 to 1.69.4 (#4288)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.69.2 to 1.69.4.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.2...v1.69.4)

---
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 22:48:36 -05:00
dashangcun
9b1855f719 chore: fix struct field name in comment (#4284)
Signed-off-by: dashangcun <907225865@qq.com>
2025-01-14 09:56:22 -05:00
风扇滑翔翼
3e590a4eb1 Freedom: Don't use rawConn copy when using utls (#4272) 2025-01-12 14:10:39 -05:00
dependabot[bot]
ef4a3c1cae Bump google.golang.org/protobuf from 1.36.1 to 1.36.2 (#4268)
Bumps google.golang.org/protobuf from 1.36.1 to 1.36.2.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  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>
2025-01-10 02:02:00 +00:00
dependabot[bot]
5635254ebc Bump golang.org/x/net from 0.33.0 to 0.34.0 (#4262)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.33.0 to 0.34.0.
- [Commits](https://github.com/golang/net/compare/v0.33.0...v0.34.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 02:00:22 +00:00
RPRX
ce6c0dc690 XHTTP XMUX: Abandon client if client.Do(req) failed (#4253)
51769fdde1
2025-01-06 14:06:11 +00:00
𐲓𐳛𐳪𐳂𐳐 𐲀𐳢𐳦𐳫𐳢 𐲥𐳔𐳛𐳪𐳌𐳑𐳖𐳇
aeb12d9e3b Build: Update GeoIP/GeoSite Cache per hour (#4247) 2025-01-05 06:37:50 +00:00
Hossin Asaadi
de53a3b94e Upgrade gVisor to a newer version (#3903) 2025-01-03 15:50:23 +00:00
RPRX
2f52aa7ed8 Freedom noises: Support RawURLEncoding for "base64"
In case we want to share `noises` via sharing link.
2025-01-02 09:45:46 +00:00
GFW-knocker
ca50c9cbe6 Freedom noises: Support "hex" as type & packet (#4239)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-01-02 09:17:03 +00:00
风扇滑翔翼
33186ca5e6 Freedom noises: Change legacy variable name (#4238)
Closes https://github.com/XTLS/Xray-core/issues/4237
2025-01-02 08:21:32 +00:00
RPRX
e80ca67fee v25.1.1
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2025-01-01 12:03:05 +00:00
RPRX
dd4ba823f5 Workflows: Trigger all Build & Test on all branches & files
https://github.com/XTLS/Xray-core/pull/4192#issuecomment-2566960668
2025-01-01 11:51:32 +00:00
GFW-knocker
0658c9545b Freedom config: Fix noises delay (#4233)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-01-01 11:49:08 +00:00
yiguous
480eac7235 Config: Correctly marshal Int32Range to JSON (#4234)
Fixes https://github.com/XTLS/libXray/issues/62
2025-01-01 10:29:34 +00:00
RPRX
8a6a5385ff Upgrade quic-go to patched v0.48.2
* Change module path
* Add traceWroteRequest & traceGotConn
* http3: allow concurrent calls to Body.Close (https://github.com/quic-go/quic-go/pull/4798)
2025-01-01 09:23:14 +00:00
dependabot[bot]
5178dc500a Bump github.com/cloudflare/circl from 1.4.0 to 1.5.0 (#3899)
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.4.0 to 1.5.0.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.4.0...v1.5.0)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  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>
2025-01-01 08:22:00 +00:00
dependabot[bot]
1a1c49de36 Bump google.golang.org/grpc from 1.67.1 to 1.69.2 (#4181)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.1 to 1.69.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.67.1...v1.69.2)

---
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 08:19:48 +00:00
𐲓𐳛𐳪𐳂𐳐 𐲀𐳢𐳦𐳫𐳢 𐲥𐳔𐳛𐳪𐳌𐳑𐳖𐳇
c8b17ad18d Build: Use patched newer Go version to build Windows 7 assets (#4192)
https://github.com/XTLS/go-win7
2025-01-01 08:06:35 +00:00
RPRX
4be32e99b2 v24.12.31
XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
2024-12-31 12:12:03 +00:00
RPRX
5af90684c4 Inbounds config: Add mixed as an alias of socks
https://github.com/XTLS/Xray-core/pull/3682#issuecomment-2292600144
2024-12-31 11:55:16 +00:00
RPRX
369d8944cf Sockopt config: Add penetrate for XHTTP U-D-S, Remove tcpNoDelay
Now `sockopt` can be shared via `extra`, and be replaced with upload's forcibly.

Closes https://github.com/XTLS/Xray-core/issues/4227
2024-12-31 11:10:17 +00:00
RPRX
4ce65fc74c XHTTP XMUX: cMaxLifetimeMs -> hMaxReusableSecs, Refactor default values
"xmux": {
    "maxConcurrency": "16-32",
    "maxConnections": 0,
    "cMaxReuseTimes": 0,
    "hMaxRequestTimes": "600-900",
    "hMaxReusableSecs": "1800-3000",
    "hKeepAlivePeriod": 0
}

Fixes https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11685057
2024-12-31 10:00:19 +00:00
RPRX
93f72db9fd v24.12.28
XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
2024-12-28 13:57:23 +00:00
RPRX
ff4331a7a8 XHTTP XMUX: Increase the default value for cMaxReuseTimes
"64-128" -> "256-512"
2024-12-28 08:20:59 +00:00
RPRX
a8559a1b46 Dokodemo TPROXY: Interrupt UDP download if upload timeouts
https://github.com/XTLS/Xray-core/issues/4194#issuecomment-2564156340

Fixes https://github.com/XTLS/Xray-core/issues/4194
2024-12-28 04:06:49 +00:00
yuhan6665
42aea01fb5 Core: Add mutex to injection resolution (#4206)
* Revert "Add RequireFeaturesAsync() that works regardless order of app init"

* Add mutex to injection resolution

- Turns out we already support async DI resolution regardless of feature ordering
Previous code contain a race condition causing some resolution is lost
- Note that the new mutex cover s.pendingResolutions and s.features
but must not cover callbackResolution() due to deadlock
- Refactor some method names and simplify code

* Add OptionalFeatures injection

For example OptionalFeatures() is useful for fakedns module
2024-12-26 12:55:12 +00:00
dependabot[bot]
a7909f8671 Bump google.golang.org/protobuf from 1.36.0 to 1.36.1 (#4203)
Bumps google.golang.org/protobuf from 1.36.0 to 1.36.1.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  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>
2024-12-24 13:03:17 +00:00
leo
b287d6419b chore: use errors.New to replace fmt.Errorf with no parameters (#4204)
Signed-off-by: RiceChuan <lc582041246@gmail.com>
2024-12-24 00:17:00 -05:00
dependabot[bot]
d54d20abea Bump golang.org/x/net from 0.32.0 to 0.33.0 (#4182)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.32.0 to 0.33.0.
- [Commits](https://github.com/golang/net/compare/v0.32.0...v0.33.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-22 09:21:06 +00:00
maoxikun
868799ef04 DNS: Always use a DNS Message ID of 0 for DoH and DoQ (#4193)
Co-authored-by: dyhkwong <50692134+dyhkwong@users.noreply.github.com>
2024-12-22 09:19:09 +00:00
RPRX
db934f0832 XHTTP client: Merge Open* into OpenStream(), and more
https://github.com/XTLS/Xray-core/issues/4148#issuecomment-2557066988
2024-12-20 14:35:33 +00:00
RPRX
53b04d560b XHTTP client: Make H3 httptrace work on v2rayNG
Introduced in https://github.com/XTLS/Xray-core/pull/4150
2024-12-20 07:19:41 +00:00
RPRX
1410b6335b XHTTP XMUX: Fix OpenUsage never gets reduced
Introduced in https://github.com/XTLS/Xray-core/pull/4163
2024-12-20 06:19:10 +00:00
RPRX
cab2fdefd3 v24.12.18
XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
2024-12-18 13:39:35 +00:00
RPRX
ff8b66aacb XHTTP client: scMaxEachPostBytes should be bigger than buf.Size (8192)
To avoid no size limit.
2024-12-18 13:25:34 +00:00
dependabot[bot]
15318976f6 Bump google.golang.org/protobuf from 1.35.2 to 1.36.0 (#4175)
Bumps google.golang.org/protobuf from 1.35.2 to 1.36.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>
2024-12-18 11:43:48 +00:00
dependabot[bot]
a168f5360e Bump golang.org/x/crypto from 0.30.0 to 0.31.0 (#4156)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.30.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.30.0...v0.31.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-18 11:32:11 +00:00
RPRX
9dbdf92c27 XHTTP downloadSettings: Inherit sockopt if its own doesn't exist (e.g., in extra)
If you want `downloadSettings` to use its own `sockopt`, make sure that `extra` doesn't exist.
2024-12-18 11:22:29 +00:00
RPRX
96fb680d45 REALITY, TLS config: Set "chrome" as the default fingerprint
Other VLESS implementations should follow this change.
2024-12-17 11:02:51 +00:00
珐琅彩山水佩奇童车游春马蹄杯
5836afc41f WebSocket config: Fix headers (#4177)
Fixes https://github.com/XTLS/Xray-core/issues/4176
2024-12-17 08:53:16 +00:00
RPRX
7d0a80b501 v24.12.15 2024-12-15 12:36:19 +00:00
RPRX
73e0d4a666 XHTTP XMUX: Add hMaxRequestTimes and hKeepAlivePeriod (#4163)
Fixes https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11492833
2024-12-15 05:43:10 +00:00
RPRX
7463561856 XHTTP client: Add decideHTTPVersion() and more logs
https://github.com/XTLS/Xray-core/pull/4150#issuecomment-2537981368
2024-12-12 12:19:18 +00:00
RPRX
743435d6e6 Core: Fix startup error when dns exists but fakedns doesn't
Fixes https://github.com/XTLS/Xray-core/issues/4155
2024-12-12 06:56:05 +00:00
RPRX
8cd9a74376 XHTTP client: Refactor "packet-up" mode, chasing "stream-up" (#4150)
* Add wroteRequest (waiting for new quic-go)

* Use XTLS/quic-go instead

* Client doesn't need `scMaxConcurrentPosts` anymore

* GotConn is available in H3

* `scMaxConcurrentPosts` -> `scMaxBufferedPosts` (server only, 30 by default)

Fixes https://github.com/XTLS/Xray-core/issues/4100
2024-12-11 14:05:39 +00:00
Andi
6be3c35db8 Chore: "io/ioutil" -> "io" (#4143)
Signed-off-by: ChengenH <hce19970702@gmail.com>
2024-12-11 02:02:23 +00:00
yuhan6665
0e2304c403 Core: Fix memory leaks with RequireFeatures() (#4095)
Fixes https://github.com/XTLS/Xray-core/issues/4054
Fixes https://github.com/XTLS/Xray-core/issues/3338
Fixes https://github.com/XTLS/Xray-core/issues/3221
2024-12-11 01:07:52 +00:00
RPRX
a2b773135a XHTTP, WS, HU: Forbid "host" in headers, read serverName instead (#4142)
WebSocket's config files should be updated ASAP.
2024-12-11 00:58:14 +00:00
RPRX
9cb6816383 README.md: Update Donation & NFTs 2024-12-07 14:43:38 +00:00
RPRX
46d8d9ef02 XHTTP server: Forbid Mux.Cool except pure XUDP (#4128)
https://github.com/XTLS/Xray-core/discussions/4113#discussioncomment-11491701
2024-12-07 04:45:45 +00:00
dependabot[bot]
34141c940e Bump golang.org/x/net from 0.31.0 to 0.32.0 (#4110)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.31.0 to 0.32.0.
- [Commits](https://github.com/golang/net/compare/v0.31.0...v0.32.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-06 23:55:10 +00:00
风扇滑翔翼
3e7002d24c WireGuard inbound: Add missing inbound session information back (#4126)
Fixes https://github.com/XTLS/Xray-core/issues/4121
2024-12-06 23:50:26 +00:00
RPRX
ae62a0fb52 Transport: Remove HTTP
Migrated to XHTTP "stream-one" mode.
2024-12-02 09:56:16 +00:00
RPRX
98a72b6fb4 v24.11.30
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2024-11-30 04:16:35 +00:00
hr567
4f6f12616c WebSocket config: Add heartbeatPeriod for client & server (#4065)
https://github.com/XTLS/Xray-core/pull/4065#issuecomment-2502627154

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-11-29 02:08:08 +00:00
风扇滑翔翼
c87cf8ff52 XHTTP config: Add keepAlivePeriod for client (#4075)
Closes https://github.com/XTLS/Xray-core/issues/4053

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-11-29 02:05:11 +00:00
RPRX
f7bd98b13c XHTTP: Add "stream-one" mode for client & server (#4071)
""Breaking"": Client uses "stream-one" mode by default when using **REALITY** ("stream-up" if "downloadSettings" exists)
2024-11-27 20:19:18 +00:00
Aleksandr
d8934cf839 Chore: Improved log messaging (#4050)
* update log messages

* Update inbound.go
2024-11-25 11:16:29 -05:00
zonescape
ce8c415d43 Test: Remove temporary directory afterwards (#4045) 2024-11-24 23:00:00 -05:00
zonescape
034a485afe Chore: Refactor tests in app/router (#4019) 2024-11-24 22:53:31 -05:00
dependabot[bot]
384d07999c Bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#4060)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  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>
2024-11-24 22:37:28 -05:00
RPRX
513f18bf53 v24.11.21 2024-11-21 05:47:07 +00:00
RPRX
817fa72874 XHTTP client: Add gRPC header to "stream-up" mode by default (#4042)
""Breaking"": Client uses "stream-up" mode by default when using **TLS H2** or REALITY
2024-11-21 05:45:49 +00:00
风扇滑翔翼
0a252ac15d HTTP transport: Use dest as Host if not set (#4038) 2024-11-21 05:42:19 +00:00
zonescape
6ba0dbafd7 Test: Delete temporary file afterwards (#4028) 2024-11-20 05:03:39 +00:00
风扇滑翔翼
59e5d24280 WireGuard inbound: Fix leaking session information between requests (#4030)
Fixes https://github.com/XTLS/Xray-core/issues/3948 https://github.com/XTLS/Xray-core/issues/4025
2024-11-20 05:00:40 +00:00
dependabot[bot]
7d3d6b05e3 Bump github.com/sagernet/sing from 0.5.0 to 0.5.1 (#4026)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.5.0 to 0.5.1.
- [Commits](https://github.com/sagernet/sing/compare/v0.5.0...v0.5.1)

---
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>
2024-11-19 03:19:34 +00:00
yiguous
55e045d098 Config: Correctly marshal Address to JSON (#4021) 2024-11-19 03:18:47 +00:00
dependabot[bot]
5a96ef632d Bump google.golang.org/protobuf from 1.35.1 to 1.35.2 (#4018)
Bumps google.golang.org/protobuf from 1.35.1 to 1.35.2.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  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>
2024-11-18 05:08:03 +00:00
RPRX
1f570d9cef XHTTP test: Fix Test_maxUpload
https://github.com/XTLS/Xray-core/pull/3260#issuecomment-2481946715
2024-11-18 04:53:21 +00:00
RPRX
2d7b0e8cd4 XHTTP client: Fix upload issue in "packet-up" mode inherited from SplitHTTP
Fixes https://github.com/XTLS/Xray-core/issues/3972
2024-11-17 06:03:25 +00:00
zonescape
ec1fd008c4 Chore: Refactor infra/conf.TestToCidrList() (#4017) 2024-11-14 11:04:17 -05:00
风扇滑翔翼
17825b25f2 WireGuard kernelTun: Fix multi-outbounds not work (#4015)
Fixes https://github.com/XTLS/Xray-core/issues/2817
2024-11-14 00:13:27 +00:00
zonescape
83ae38497b Chore: Drop dead code in test (#4012) 2024-11-13 10:41:54 -05:00
pinglanlu
7b4a686b74 Chore: Use a more direct and less error-prone return value (#4008)
Signed-off-by: pinglanlu <pinglanlu@outlook.com>
2024-11-12 10:44:41 -05:00
lxsq
48ac662298 Update Dockerfile to Use Multiple Config Files (#4010) 2024-11-12 10:41:42 -05:00
RPRX
1a238cbb7d REALITY client: Log invalid connections at warning level
Closes https://github.com/XTLS/Xray-core/issues/4001
2024-11-12 06:42:52 +00:00
zonescape
44b1dd0e67 Test: Change address for DNS over QUIC tests (#4002)
dns.adguard.com can be blocked in some places
2024-11-11 14:43:57 -05:00
RPRX
0df2446f82 v24.11.11 2024-11-11 04:22:33 +00:00
dependabot[bot]
85b3c2328f Bump golang.org/x/net from 0.30.0 to 0.31.0 (#3999)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.30.0 to 0.31.0.
- [Commits](https://github.com/golang/net/compare/v0.30.0...v0.31.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 04:21:50 +00:00
风扇滑翔翼
571777483b TLS: Add CurvePreferences (to enable kyber768) (#3991)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-11-11 04:21:28 +00:00
风扇滑翔翼
1ffb8a92cd Sniff: Prevent crash on QUIC sniffer panic (#3978)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-11-11 04:20:54 +00:00
RPRX
480748403a Chore: Fix versions in some *.pb.go files
47fad1fbfd
2024-11-11 03:27:30 +00:00
RPRX
bd0841a75b XHTTP config: Add "extra" for sharing extra fields (#4000) 2024-11-11 02:50:39 +00:00
zonescape
83bab5dd90 Chore: Run gofmt (#3990) 2024-11-09 11:16:11 +00:00
RPRX
bc4bf3d38f XHTTP: Add "stream-up" mode for client & server (#3994) 2024-11-09 11:05:41 +00:00
dependabot[bot]
94c02f090e Bump golang.org/x/sys from 0.26.0 to 0.27.0 (#3987)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.26.0 to 0.27.0.
- [Commits](https://github.com/golang/sys/compare/v0.26.0...v0.27.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 10:29:50 -05:00
dependabot[bot]
5af750b336 Bump golang.org/x/crypto from 0.28.0 to 0.29.0 (#3986)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.28.0 to 0.29.0.
- [Commits](https://github.com/golang/crypto/compare/v0.28.0...v0.29.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 10:29:35 -05:00
dependabot[bot]
6cb58d9315 Bump golang.org/x/sync from 0.8.0 to 0.9.0 (#3985)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.8.0 to 0.9.0.
- [Commits](https://github.com/golang/sync/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  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>
2024-11-08 10:25:47 -05:00
dependabot[bot]
8cd3f5448d Bump github.com/sagernet/sing from 0.4.3 to 0.5.0 (#3971)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.4.3 to 0.5.0.
- [Commits](https://github.com/sagernet/sing/compare/v0.4.3...v0.5.0)

---
updated-dependencies:
- dependency-name: github.com/sagernet/sing
  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>
2024-11-08 10:25:09 -05:00
zonescape
b98f29bf3e Chore: Fix some comments (#3979) 2024-11-07 11:00:04 -05:00
RPRX
6877ca5201 XHTTP client: Allow different paths in U-D-S (#3977) 2024-11-07 03:50:28 +00:00
zonescape
71cfea8aae Chore: Fix some spelling errors (#3976) 2024-11-06 10:42:43 -05:00
RPRX
afc7ec5506 v24.11.5 2024-11-05 00:50:45 +00:00
风扇滑翔翼
057e6284b2 UDS: prevent crash when proxy udp (#3967)
* net: Prevent nil pointer err in NetAddr()

* Fix dsworker saddr problem
2024-11-04 10:39:04 -05:00
tcpdumppy
ccc4b7b2cf Test: Fix incorrect output format (#3968) 2024-11-04 10:36:42 -05:00
RPRX
9fbb6fbb3b XHTTP client: Move dest2 into MemoryStreamConfig as well 2024-11-04 05:00:18 +00:00
Hossin Asaadi
2c72864935 API: Add user online stats (#3637)
* add statsUserOnline bool to policy

* add OnlineMap struct to stats

* apply UserOnline functionality to dispatcher

* add statsonline api command

* fix comments

* Update app/stats/online_map.go

Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>

* improve AddIP

* regenerate pb

---------

Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-11-03 08:44:15 -05:00
RPRX
e3276df725 XHTTP client: Enable XMUX for download in U-D-S (#3965) 2024-11-03 07:25:41 +00:00
yuhan6665
85a1c33709 API: Add new Get Inbound User (#3644)
* Add GetInboundUser in proto

* Add get user logic for all existing inbounds

* Add inbounduser command

* Add option to get all users

* Fix shadowsocks2022 config

* Fix init users in shadowsocks2022

* Fix copy

* Add inbound user count command

This api costs much less than get inbound user, could be useful in some case

* Update from latest main
2024-11-03 00:25:23 -04:00
风扇滑翔翼
b7aacd3245 Wireguard inbound: Do not use kernel TUN (#3960)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-11-02 21:07:17 +00:00
RPRX
4ec5c78c34 v24.10.31 2024-10-31 07:58:31 +00:00
RPRX
b30e05d1bc XHTTP: The real upload / download splitting (#3955)
* SplitHTTP client: Add real upload / download splitting

* Transport: Add XHTTP as an alias of SplitHTTP

* XHTTP config: Use `downloadSettings` instead
2024-10-31 07:31:19 +00:00
mmmray
e733148c0b REALITY: Unblock SplitHTTP transport (#3816)
https://github.com/XTLS/Xray-core/pull/3816#issuecomment-2445694775
2024-10-30 02:31:05 +00:00
风扇滑翔翼
9f8bb47633 Fix: Apply mutex when visiting Attributes as well (#3921)
https://github.com/XTLS/Xray-core/pull/3921#issuecomment-2445689462
2024-10-30 02:26:43 +00:00
RPRX
ceb6eac8e7 WireGuard createTun: Add more logs 2024-10-30 02:20:55 +00:00
RPRX
cf182b0482 README.md: Update WARNING for Web Panel
https://github.com/XTLS/Xray-core/pull/3884#issuecomment-2439606000
2024-10-27 00:39:20 +00:00
RPRX
94338c94e9 README.md: Only list secure web panels (#3884)
* README.md: Only list secure web panels

* List Marzban

* List Xray-UI

* List Hiddify

* Add warning

* Update warning
2024-10-24 02:06:31 +00:00
RPRX
e4939dc1db Config: Prefer newer alias (REALITY target, RAW) 2024-10-18 02:18:06 +00:00
RPRX
8809cbda81 Transport: Remove GUN (an alias of gRPC) 2024-10-18 01:17:13 +00:00
RPRX
9bdf72d658 WireGuard config: Replace kernelMode with noKernelTun
https://github.com/XTLS/Xray-core/pull/3871#issuecomment-2420770309
2024-10-18 00:10:09 +00:00
yuhan6665
b0272c172a README.md: Add wulabing/xray_docker to Docker 2024-10-16 23:20:11 -04:00
RPRX
25c7bc0c82 v24.10.16 2024-10-16 04:07:51 +00:00
RPRX
47fad1fbfd Chore: Generate *.pb.go files with protoc v5.28.2
Download https://github.com/protocolbuffers/protobuf/releases/tag/v28.2
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.35.1
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.5.1
(Xray-core/) go run ./infra/vprotogen
2024-10-16 04:06:21 +00:00
RPRX
897521defd XMUX: Change to non-infinity-reuse default values (#3919) 2024-10-16 03:47:41 +00:00
风扇滑翔翼
86257531ee Routing: Add mutex for Attributes temporarily (#3908)
https://github.com/XTLS/Xray-core/pull/3908#issuecomment-2412859858
2024-10-15 04:22:32 +00:00
风扇滑翔翼
82bd5f3046 Refactor: Use struct Int32Range widely (#3867)
https://github.com/XTLS/Xray-core/pull/3867#issuecomment-2412847316
2024-10-15 04:12:17 +00:00
チセ
19f3f709b2 WireGuard kernelTun: Check Capabilities instead of checking UID (#3871)
https://github.com/XTLS/Xray-core/pull/3871#issuecomment-2412820323

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-10-15 03:30:29 +00:00
yuhan6665
6a70ae6408 HTTP transport: Fix an issue when HTTP client start fail with 403 (#3910)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-10-15 02:55:48 +00:00
mmmray
8c180b9cfd Browser Dialer: Revert changes to event listeners (#3906)
https://github.com/XTLS/Xray-core/issues/3882#issuecomment-2396167708

This does not fix the linked issue, just a random bug I found.
2024-10-13 05:22:15 +00:00
vnxme
5164a82185 Routing: Fix regexp syntax support in UserMatcher (#3900) 2024-10-11 11:37:01 -04:00
dependabot[bot]
af7232d545 Bump github.com/pires/go-proxyproto from 0.7.0 to 0.8.0 (#3895)
Bumps [github.com/pires/go-proxyproto](https://github.com/pires/go-proxyproto) from 0.7.0 to 0.8.0.
- [Release notes](https://github.com/pires/go-proxyproto/releases)
- [Commits](https://github.com/pires/go-proxyproto/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: github.com/pires/go-proxyproto
  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>
2024-10-09 05:21:03 +00:00
dependabot[bot]
b3ab49f323 Bump google.golang.org/protobuf from 1.34.2 to 1.35.1 (#3893)
Bumps google.golang.org/protobuf from 1.34.2 to 1.35.1.

---
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>
2024-10-09 05:20:39 +00:00
dependabot[bot]
e2b9f71384 Bump golang.org/x/net from 0.29.0 to 0.30.0 (#3889)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.29.0 to 0.30.0.
- [Commits](https://github.com/golang/net/compare/v0.29.0...v0.30.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 05:20:18 +00:00
RPRX
c30f5d4796 Lint common/errors/feature_errors.go 2024-10-05 02:15:28 +00:00
RPRX
75729ce779 REALITY config: Add target as an alias of dest
https://t.me/projectXtls/364
2024-10-05 00:13:46 +00:00
Nikita Korotaev
c7534c4e36 README.md: Add Marzneshin to Web Panel (#3873) 2024-10-03 10:54:43 -04:00
dependabot[bot]
e45cef542e Bump google.golang.org/grpc from 1.67.0 to 1.67.1 (#3866)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.0 to 1.67.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.67.0...v1.67.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 04:16:29 +00:00
RPRX
3b06af882d v24.9.30 2024-09-30 15:20:13 +00:00
风扇滑翔翼
697156f6f6 SplitHTTP Config: Add capability to parse int in string format (#3855)
“100” → 100
“-1” → -1
“” → 0
2024-09-29 03:10:42 +08:00
RPRX
d8485bd5af Transport: Add RAW as an alias of TCP (#3852) 2024-09-28 05:25:59 +00:00
yuhan6665
3632e83faa Transport: Add HTTP3 to HTTP (#3819) 2024-09-26 01:29:41 +00:00
Kobe Arthur Scofield
7086d286be Remove legacy code (#3838)
* Add feature migration notice

* Remove legacy code of transport processing

* Clear legacy proto field

* Fix missing

* Unify protocolname

* Test remove

* Supressor

* Weird code

* Remove errorgen related comments
2024-09-23 11:28:19 -04:00
dependabot[bot]
d497de916f Bump google.golang.org/grpc from 1.66.2 to 1.67.0 (#3845)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.66.2 to 1.67.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.66.2...v1.67.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 05:37:54 +00:00
Lumière Élevé
acbf36e21b SplitHTTP server: Add global CORS headers for browser dialer (#3830) 2024-09-20 09:55:54 +02:00
mmmray
93cff1a576 Xmux: Value of 0 is treated the same as no value (#3835)
It turns out that some panels like to set `"xmux": {"maxConnections": 0,
"maxConcurrency": 0}`, and of course that fails now. To make their job
easier, let's treat `0` the same as not setting the parameter.

Again, I don't like that xray's defaults are hardcoded all over the
place. I would have liked a different default value for Xmux in a future
version, but it actually can't be done in practice because everybody
just copypastes the defaults from the docs into their own sourcecode
(and sometimes changes them silently to their own idea of a good
default)
2024-09-19 11:20:12 -04:00
Lumière Élevé
7677ac980d Browser Dialer: Change from ES5 to ES6+ for performance (#3832) 2024-09-19 10:57:43 +02:00
RPRX
bc28cad8f8 v24.9.19 2024-09-19 01:12:29 +00:00
Kobe Arthur Scofield
57a41f3b4b Config: Remove more legacy fields (#3817) 2024-09-19 01:05:59 +00:00
mmmray
f406b2dee0 SplitHTTP client: Fix xmux config deserialization (#3827) 2024-09-19 00:45:39 +00:00
RPRX
a35d5719f4 v24.9.16 2024-09-16 12:48:28 +00:00
dragonbreath2000
363e86c585 UDP noises: Add base64 and multi-packet support (#3794)
https://github.com/XTLS/Xray-core/pull/3794#issuecomment-2351329251

---------

Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-09-16 12:46:30 +00:00
ll11l1lIllIl1lll
b1c6471eeb SplitHTTP client: Add xmux (multiplex controller) for H3 & H2 (#3613)
https://github.com/XTLS/Xray-core/pull/3613#issuecomment-2351954957

Closes https://github.com/XTLS/Xray-core/issues/3560#issuecomment-2247495778

---------

Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-09-16 12:42:01 +00:00
Dmitry Anderson
a931507dd6 SplitHTTP: Read and validate HTTP/1.1 responses (#3797) 2024-09-16 12:33:03 +00:00
dependabot[bot]
67c2a29065 Bump github.com/sagernet/sing from 0.4.1 to 0.4.3 (#3818)
Bumps [github.com/sagernet/sing](https://github.com/sagernet/sing) from 0.4.1 to 0.4.3.
- [Commits](https://github.com/sagernet/sing/compare/v0.4.1...v0.4.3)

---
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>
2024-09-15 21:20:12 -04:00
Kobe Arthur Scofield
5f0642a671 Errors: Add PrintRemovedFeatureError & PrintDeprecatedFeatureWarning (#3804) 2024-09-15 04:55:54 +00:00
风扇滑翔翼
3fed0c773f DNS outbound: Add blockTypes (#3812) 2024-09-15 04:21:51 +00:00
Kuzmin Vladimir
d7c5a0fc5f Fix int overflow on x32 processors causing panic (#3810)
During the roll, "duration" is converted to int, causing overflow on x32 processors. The value may be very small or negative, causing a panic in rand.Intn.
2024-09-14 23:47:16 -04:00
风扇滑翔翼
781aaee21f QUIC sniffer: handle multiple initial packets (#3802)
* QUIC sniffer: handle multiple initial packets
Basically copied from Vigilans/v2ray-core@8f33db0

Co-Authored-By: Vigilans <vigilans@foxmail.com>

* Remove unnecessary file

---------

Co-authored-by: Vigilans <vigilans@foxmail.com>
2024-09-13 13:32:43 -04:00
风扇滑翔翼
7970f240de Log: show the matching rule tag (#3809) 2024-09-13 13:05:19 -04:00
风扇滑翔翼
88ae774cce Sniff: Routing “attrs” support non http inbound (#3808)
* Sniff: Support attrs route in non http inbound

* Add capability to sniff method and path

* Fix test

* Skip HTTP inbound PlainHTTP mode

* Fix test
again
2024-09-13 12:26:36 -04:00
Torikki
c259e4e4a6 Allow to inject custom validator in VLESS controller (#3453)
* Make Validator an interface

* Move validator creation away from VLESS inbound controller
2024-09-13 10:51:26 -04:00
vnxme
3a8c5f38e8 Routing: Add regexp syntax support to UserMatcher (#3799) 2024-09-12 10:48:41 -04:00
dependabot[bot]
12c3908e8c Bump google.golang.org/grpc from 1.66.1 to 1.66.2 (#3798)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.66.1 to 1.66.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.66.1...v1.66.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-12 10:38:51 -04:00
Kobe Arthur Scofield
1919a1e86f Log: Improve feature deprecation/removal logs (#3793)
* Improve feature deprecation/removal logs

* Add a note about the new feature

* When the feature has removed, this should be an error not a warning
2024-09-12 10:38:17 -04:00
风扇滑翔翼
1b607ff874 DNS: Do not hit cache if encounted err (#3784) 2024-09-12 10:34:45 -04:00
Kobe Arthur Scofield
7496413e5c Remove remnants of global transport (#3792)
* Remove remenants

* Generate pb.go

* Remove function
2024-09-11 14:06:11 -04:00
dependabot[bot]
297a9ae7bd Bump google.golang.org/grpc from 1.66.0 to 1.66.1 (#3786)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.66.0 to 1.66.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.66.0...v1.66.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 11:34:03 -04:00
风扇滑翔翼
a247997e38 Log: Add MaskAddress option to hide IP addresses (#3783)
* Log: Add maskAddress option

* Correct IPv6 subnet
2024-09-11 10:45:47 -04:00
Kobe Arthur Scofield
6b1bf312d7 Config: Remove legacy config fields again (#3782)
* Remove more lecacy fields

* Patch missing bracket

* Fix tests

* Fix missing comma

* Fix buried test bomb

* Cleanup test after removed legacy test content
2024-09-11 10:37:25 -04:00
yu
c90affe7db Fix: RPC call causes xray panic problem using wrong account type (#3744)
* fix:RPC call causes xray panic problem. Problem details: add a VMess protocol user in an inbound proxy. If inTag: "VMess-xxx", but the developer carelessly calls the add user method of vless or other protocols, such as xrayCtl.AddVlessUser(user), causing xray panic

* fix:use xray log system return error

---------

Co-authored-by: chengtao@snqu.com <chengtao@snqu.com>
2024-09-09 11:44:22 -04:00
风扇滑翔翼
3d0feae462 Transport: Add REALITY TLS1.3 support warning (#3774) 2024-09-09 11:37:39 -04:00
Kobe Arthur Scofield
f04cb0b288 Config: Remove some legacy fields from V2Ray 3.x era (#3776)
https://github.com/XTLS/Xray-core/pull/3776#issue-2512316726
2024-09-09 06:03:21 +00:00
mmmray
9438517130 README.md: Add SaeedDev94/Xray to Android clients
Closes https://github.com/XTLS/Xray-core/issues/3778
2024-09-09 05:59:12 +00:00
RPRX
3d9137cb6f v24.9.7 2024-09-07 00:30:27 +00:00
mmmray
6838a0ae55 Config: Remove legacy inbound/outbound/detours (#3769)
https://github.com/XTLS/Xray-core/pull/3769#issuecomment-2334915139
2024-09-06 23:43:58 +00:00
dependabot[bot]
3971532798 Bump golang.org/x/net from 0.28.0 to 0.29.0 (#3766)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.28.0 to 0.29.0.
- [Commits](https://github.com/golang/net/compare/v0.28.0...v0.29.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 01:52:47 +00:00
dependabot[bot]
d36e027a50 Bump golang.org/x/sys from 0.24.0 to 0.25.0 (#3762)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.24.0 to 0.25.0.
- [Commits](https://github.com/golang/sys/compare/v0.24.0...v0.25.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-06 01:47:43 +00:00
mmmray
f357245f93 Config: Remove global transport (#3751)
https://github.com/XTLS/Xray-core/pull/3751#issuecomment-2329564039

---------

Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
2024-09-04 18:09:16 -04:00
mmmray
c0a98f74fc Transport: Remove DomainSocket (#3757)
https://github.com/XTLS/Xray-core/pull/3755#issuecomment-2325533003
2024-09-03 11:36:11 +00:00
mmmray
9a953c070f Transport: Remove QUIC (#3754)
https://github.com/XTLS/Xray-core/pull/3554#issuecomment-2236171077
2024-09-03 02:39:44 +00:00
mmmray
ab3c00e96b SplitHTTP: Remove ok compatibility logic (#3753)
Remove some code that was added to maintain compatibility with older
Xray versions. This breaks compatibility with Xray-core v1.8.23 or older.
2024-09-03 02:25:15 +00:00
mmmray
f1c439c2aa Revert "Fix freedom PacketReader/PacketWriter type assertion (#3734)"
This reverts commit 815a959c96.
2024-09-01 10:59:31 -05:00
RPRX
6baad79f98 v1.8.24 2024-08-30 07:01:01 +00:00
dependabot[bot]
98e85b7f3c Bump google.golang.org/grpc from 1.65.0 to 1.66.0 (#3740)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.65.0 to 1.66.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.65.0...v1.66.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 11:32:36 -04:00
dragonbreath2000
002d08bf83 UDP noise (#3711)
* added udp noise

* adding protobuf settings

* freedom json parser and clean up

* resolve confict

* fix and clean up

* use net.conn instead of packetconnwrapper

* avoid constructing SequentialWriter directly

---------

Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-08-28 17:10:11 -04:00
xiaorouji
8674ed5a0d Support DNS queryStrategy config for UDP NameServer (#3728) 2024-08-27 10:19:33 -04:00
dyhkwong
815a959c96 Fix freedom PacketReader/PacketWriter type assertion (#3734) 2024-08-27 10:17:55 -04:00
RPRX
1cfed96aba README.md: Add Project VLESS to Telegram 2024-08-26 02:33:03 +00:00
yuhan6665
592c2daf58 Update go 1.23 (#3730) 2024-08-25 22:30:38 -04:00
dependabot[bot]
5d7dfbbcac Bump github.com/vishvananda/netlink from 1.2.1 to 1.3.0 (#3729)
Bumps [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink) from 1.2.1 to 1.3.0.
- [Release notes](https://github.com/vishvananda/netlink/releases)
- [Commits](https://github.com/vishvananda/netlink/compare/v1.2.1...v1.3.0)

---
updated-dependencies:
- dependency-name: github.com/vishvananda/netlink
  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>
2024-08-25 22:07:31 -04:00
mmmray
3dd3bf94d4 Fix data leak between mux.cool connections (#3718)
Fix #116
2024-08-25 21:02:01 +02:00
dependabot[bot]
c0c23fdfeb Bump github.com/vishvananda/netlink (#3719)
Bumps [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink) from 1.2.1-beta.2.0.20230316163032-ced5aaba43e3 to 1.2.1.
- [Release notes](https://github.com/vishvananda/netlink/releases)
- [Commits](https://github.com/vishvananda/netlink/commits/v1.2.1)

---
updated-dependencies:
- dependency-name: github.com/vishvananda/netlink
  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>
2024-08-23 08:41:35 +00:00
风扇滑翔翼
34e0a2fb41 Issues template: Add require for latest version 2024-08-23 06:48:25 +00:00
mmmray
83eef6bc1f SplitHTTP: Fix connection leaks and crashes (#3710) 2024-08-22 17:07:57 +02:00
mmmray
2be03c56cb Pin protobuf packages (#3715)
* Pin protobuf packages

It happened in the past that I ran with the wrong protobuf version
installed locally, and apparently there is even still some file wrong in
splithttp. Fix this issue once and for all.

* bump protobuf packages

* Revert "bump protobuf packages"

This reverts commit 7a3509346a.

* Revert "Revert "bump protobuf packages""

This reverts commit bb79707d15.

* fix deprecated grpc usage
2024-08-22 10:18:36 -04:00
curlwget
790f908f0b chore: fix some comment typos (#3716)
Signed-off-by: curlwget <curlwget@icloud.com>
2024-08-22 17:32:38 +08:00
dependabot[bot]
0df7fa23f8 Bump github.com/cloudflare/circl from 1.3.9 to 1.4.0 (#3712)
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.3.9 to 1.4.0.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.3.9...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  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>
2024-08-21 17:36:25 -04:00
チセ
41d03d1856 Wireguard inbound: Fix no route when bind to interface (#3698) 2024-08-20 08:20:01 +00:00
mmmray
160316d53c SplitHTTP: Do not produce too large upload (#3691) 2024-08-17 13:01:58 +02:00
HunterQ
1562e1ffb9 Config: Combine filename and format into a new struct (#3687) 2024-08-16 05:32:05 +00:00
RPRX
11b04807b9 Log: Add "from" before source address
https://github.com/XTLS/Xray-core/pull/3682#issuecomment-2292600144
2024-08-16 02:18:39 +00:00
风扇滑翔翼
b612da26eb Socks inbound: Support HTTP inbound by default (#3682)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-08-16 00:58:48 +00:00
HunterQ
030c9efc8c Commands: Comment some useless codes (#3681)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-08-15 08:04:09 +00:00
dependabot[bot]
08d1840344 Bump github.com/miekg/dns from 1.1.61 to 1.1.62 (#3680)
* Bump github.com/miekg/dns from 1.1.61 to 1.1.62

Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.61 to 1.1.62.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.61...v1.1.62)

---
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>

* Update go.mod

* Update go.sum

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-08-14 09:51:50 +00:00
yuhan6665
f0547bc04d Commands: Use creflect.MarshalToJson() as output (#3674) 2024-08-12 05:59:23 -05:00
mmmray
498d8eb3cc DialerProxy: Fix SplitHTTP H3 dialerProxy (#3570)
* wip

* wip

* formatting

* cnc connection no longer needs to be a Packetconn

* dialerProxy: do not cancel connection when Dial context is cancelled
2024-08-11 12:58:52 -04:00
Lumière Élevé
0c7303960a SplitHTTP server: Add "Cache-Control: no-store" to GET response (#3652)
https://github.com/XTLS/Xray-core/pull/3652#issuecomment-2282308407
2024-08-10 23:59:42 +00:00
mmmray
513182adf3 SplitHTTP server: Only "ok" to older clients (#3671)
https://github.com/XTLS/Xray-core/pull/3643#issuecomment-2282304185
2024-08-10 23:56:25 +00:00
mmmray
a3b306aaa4 SplitHTTP: Replace responseOkPadding with xPaddingBytes (#3643) 2024-08-10 21:47:42 +00:00
nobody
f650d87083 Commands: Add convert with two sub-commands (#3661)
* Add back convert-configs-to-protobuf command.

* Add convert-typedMessage-to-json command.

* Add -debug and -type arguments into convert.pb sub-command.

---------

Co-authored-by: nobody <nobody@nowhere.mars>
2024-08-10 12:09:07 -04:00
mmmray
85e2ebc6f7 SplitHTTP client: Raise idle timeout to 5 minutes, Add h*KeepalivePeriod (#3624) 2024-08-10 05:40:48 +00:00
风扇滑翔翼
9e93c19161 Freedom: Combine fragmented tlshello if interval is 0 (#3663)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Co-authored-by: Ahmadreza Dorkhah <djahmadfire@gmail.com>
2024-08-10 05:06:00 +00:00
dependabot[bot]
96e8b8b279 Bump golang.org/x/sys from 0.23.0 to 0.24.0 (#3662)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.23.0 to 0.24.0.
- [Commits](https://github.com/golang/sys/compare/v0.23.0...v0.24.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-09 02:25:33 +00:00
dependabot[bot]
1a95add8e3 Bump github.com/quic-go/quic-go from 0.45.2 to 0.46.0 (#3658)
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.45.2 to 0.46.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.45.2...v0.46.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 10:37:26 -04:00
nobody
ac628a9427 API: Improve MarshalToJson() in common/reflect/marshal.go (#3655)
* Serialize enum to string in MarshalToJson().

* MarshalToJson() respect json tags.

* Add insertTypeInfo parameter to MarshalToJson().

* Omit empty string in MarshalToJson().

* Serialize PortList to string in MarshalToJson().

---------

Co-authored-by: nobody <nobody@nowhere.mars>
2024-08-08 10:35:46 -04:00
RPRX
4a1c0d7124 README.md: Rename NFTs to Donation & NFTs 2024-08-07 13:15:25 +00:00
dependabot[bot]
661cb901de Bump golang.org/x/net from 0.27.0 to 0.28.0 (#3649)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.27.0 to 0.28.0.
- [Commits](https://github.com/golang/net/compare/v0.27.0...v0.28.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-07 00:28:06 +00:00
dependabot[bot]
c6d9d430bf Bump golang.org/x/sync from 0.7.0 to 0.8.0 (#3640)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.7.0 to 0.8.0.
- [Commits](https://github.com/golang/sync/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  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>
2024-08-05 22:24:16 -04:00
dependabot[bot]
1dfec5056d Bump golang.org/x/sys from 0.22.0 to 0.23.0 (#3639)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.22.0 to 0.23.0.
- [Commits](https://github.com/golang/sys/compare/v0.22.0...v0.23.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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 22:22:12 -04:00
definitio
2a5eb3db7d Docker: Fix permissions of geosite and geodat (#3634) 2024-08-05 00:21:22 +02:00
RPRX
4c9e4b9de7 README.md: Add NFTs 2024-08-03 14:56:05 +00:00
风扇滑翔翼
644901d1a5 Socks4a server: Check if the client sends an IP address as domain (#3628)
Fixes https://github.com/XTLS/Xray-core/issues/3622
2024-08-03 02:08:23 +00:00
dependabot[bot]
7e24239c9a Bump github.com/quic-go/quic-go from 0.45.1 to 0.45.2 (#3623)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-02 03:16:37 +02:00
mmmray
4b7947cca9 SplitHTTP server: add ok padding (#3614) 2024-08-02 03:16:19 +02:00
RPRX
4c82ef8a1b v1.8.23 2024-07-29 10:23:04 +00:00
mmmray
30af792777 SplitHTTP: Rename three options & Reduce server defaults (#3611)
* maxUploadSize -> scMaxEachPostBytes, default is 1MB on both sides (was 2MB on the server)
* minUploadIntervalMs -> scMinPostsIntervalMs, default is 30ms on the client (no server support for now)
* maxConcurrentUploads -> scMaxConcurrentPosts, default is 100 on both sides (was 200 on the server)
2024-07-29 10:10:29 +00:00
mmmray
33daa0c94b SplitHTTP: Fix wrong config deserialization (#3610)
Testing was conducted only using explicit parameters, and using
testsuite. However, when the parameters are not explicitly set in JSON
config, it seems that `c.MaxUploadSize` will contain `RandRangeConfig {
From: 0, To: 0 }` instead of `nil`, which breaks upload entirely.
2024-07-29 08:50:59 +00:00
RPRX
70383c50cc v1.8.22 2024-07-29 08:22:12 +00:00
mayampi01
521d8ef6a1 Docker: Add multi-arch builds and Loyalsoldier flavor (#3589)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2024-07-29 07:36:30 +00:00
lelemka0
4531a7e228 CertificateObject: Enable auto-reload for cacert & Add buildChain & Fixes (#3607) 2024-07-29 06:58:58 +00:00
yuhan6665
a342db3e28 Fix a nil pointer in Wireguard client logging (#3608) 2024-07-29 06:43:46 +00:00
RPRX
60553a6c26 SplitHTTP server: Add noSSEHeader
https://github.com/XTLS/Xray-core/pull/3603#issuecomment-2254968219
2024-07-29 06:32:04 +00:00
mmmray
59f6685774 SplitHTTP: More range options, change defaults, enforce maxUploadSize, fix querystring behavior (#3603)
* maxUploadSize and maxConcurrentUploads can now be ranges on the client
* maxUploadSize is now enforced on the server
* the default of maxUploadSize is 2MB on the server, and 1MB on the client
* the default of maxConcurrentUploads is 200 on the server, and 100 on the client
* ranges on the server are treated as a single number. if server is configured as `"1-2"`, server will enforce `2`
* querystrings in `path` are now handled correctly
2024-07-29 04:35:17 +00:00
yuhan6665
4cb2a128db Don't do raw/splice copy in case of MITM 2024-07-24 20:41:40 -04:00
mmmray
8a4217fdf5 SplitHTTP client: Add minUploadInterval (#3592) 2024-07-27 12:52:36 +00:00
mmmray
7cf5ee8afd WS, HU: Remove unnecessary sleep from test (#3600) 2024-07-27 12:38:54 +00:00
mmmray
2becdd6414 SplitHTTP server: Fix panic during concurrent Close and Push (#3593)
When Close and Push are called concurrently, it may happen that Push attempts to write to an already-closed channel, and trigger a panic.

From a user perspective, it results in logs like this:

    http: panic serving 172.19.0.6:50476: send on closed channel

It's probably triggered when download is closed at the same time an upload packet is submitted.

These panics don't crash the server and the inbound is still usable.
2024-07-26 04:36:55 +02:00
hellokindle
edae38c620 Fix SplitHTTP Unix domain socket (#3577)
Co-authored-by: mmmray <142015632+mmmray@users.noreply.github.com>
2024-07-22 22:19:31 +02:00
mayampi01
36f427f22b docker.yml: Set latest to auto to tag release version (#3581) 2024-07-22 16:16:25 +02:00
473 changed files with 14980 additions and 14669 deletions

View File

@@ -13,16 +13,14 @@ body:
required: true required: true
- label: I searched issues and did not find any similar issues. - label: I searched issues and did not find any similar issues.
required: true required: true
- type: input - label: The problem can be successfully reproduced in the latest Release
attributes: required: true
label: Version
description: Version of Xray-core
validations:
required: true
- type: textarea - type: textarea
attributes: attributes:
label: Description label: Description
description: Please provide a detailed description of the error. And the information you think valuable. description: |-
Please provide a detailed description of the error. And the information you think valuable.
If the problem occurs after the update, please provide the **specific** version
validations: validations:
required: true required: true
- type: textarea - type: textarea

View File

@@ -11,18 +11,16 @@ body:
required: true required: true
- label: 我提供了完整的配置文件和日志,而不是出于自己的判断只给出截取的部分。 - label: 我提供了完整的配置文件和日志,而不是出于自己的判断只给出截取的部分。
required: true required: true
- label: 我搜索了issues没有发现已提出的类似问题。 - label: 我搜索了 issues, 没有发现已提出的类似问题。
required: true
- label: 问题在 Release 最新的版本上可以成功复现
required: true required: true
- type: input
attributes:
label: 版本
description: 使用的Xray-core版本
validations:
required: true
- type: textarea - type: textarea
attributes: attributes:
label: 描述 label: 描述
description: 请提供错误的详细描述。以及你认为有价值的信息。 description: |-
请提供错误的详细描述。以及你认为有价值的信息。
如果问题在更新后出现,请提供**具体**出现问题的版本号。
validations: validations:
required: true required: true
- type: textarea - type: textarea

View File

@@ -1,22 +1,62 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:latest
FROM --platform=$BUILDPLATFORM golang:alpine AS build FROM --platform=$BUILDPLATFORM golang:latest AS build
# Build xray-core
WORKDIR /src WORKDIR /src
COPY . . COPY . .
ARG TARGETOS TARGETARCH ARG TARGETOS
ARG TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
FROM --platform=${TARGETPLATFORM} alpine:latest # Download geodat into a staging directory
WORKDIR /root ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat /tmp/geodat/geoip.dat
COPY .github/docker/files/config.json /etc/xray/config.json ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat /tmp/geodat/geosite.dat
COPY --from=build /src/xray /usr/bin/xray
RUN set -ex \
&& apk add --no-cache tzdata ca-certificates \
&& mkdir -p /var/log/xray /usr/share/xray \
&& chmod +x /usr/bin/xray \
&& wget -O /usr/share/xray/geosite.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat \
&& wget -O /usr/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
VOLUME /etc/xray RUN mkdir -p /tmp/empty
ENV TZ=Asia/Shanghai
ENTRYPOINT [ "/usr/bin/xray" ] # Create config files with empty JSON content
CMD [ "-config", "/etc/xray/config.json" ] RUN mkdir -p /tmp/usr/local/etc/xray
RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
{
"log": {
"error": "/var/log/xray/error.log",
"loglevel": "warning",
"access": "none",
"dnsLog": false
}
}
EOF
RUN echo '{}' >/tmp/usr/local/etc/xray/01_api.json
RUN echo '{}' >/tmp/usr/local/etc/xray/02_dns.json
RUN echo '{}' >/tmp/usr/local/etc/xray/03_routing.json
RUN echo '{}' >/tmp/usr/local/etc/xray/04_policy.json
RUN echo '{}' >/tmp/usr/local/etc/xray/05_inbounds.json
RUN echo '{}' >/tmp/usr/local/etc/xray/06_outbounds.json
RUN echo '{}' >/tmp/usr/local/etc/xray/07_transport.json
RUN echo '{}' >/tmp/usr/local/etc/xray/08_stats.json
RUN echo '{}' >/tmp/usr/local/etc/xray/09_reverse.json
# Create log files
RUN mkdir -p /tmp/var/log/xray && touch \
/tmp/var/log/xray/access.log \
/tmp/var/log/xray/error.log
# Build finally image
FROM gcr.io/distroless/static:nonroot
COPY --from=build --chown=0:0 --chmod=755 /src/xray /usr/local/bin/xray
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/share/xray
COPY --from=build --chown=0:0 --chmod=644 /tmp/geodat/*.dat /usr/local/share/xray/
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/etc/xray
COPY --from=build --chown=0:0 --chmod=644 /tmp/usr/local/etc/xray/*.json /usr/local/etc/xray/
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /var/log/xray
COPY --from=build --chown=65532:65532 --chmod=600 /tmp/var/log/xray/*.log /var/log/xray/
VOLUME /usr/local/etc/xray
VOLUME /var/log/xray
ARG TZ=Etc/UTC
ENV TZ=$TZ
ENTRYPOINT [ "/usr/local/bin/xray" ]
CMD [ "-confdir", "/usr/local/etc/xray/" ]

71
.github/docker/Dockerfile.usa vendored Normal file
View File

@@ -0,0 +1,71 @@
# syntax=docker/dockerfile:latest
FROM --platform=$BUILDPLATFORM golang:latest AS build
# Build xray-core
WORKDIR /src
COPY . .
ARG TARGETOS
ARG TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
# Download geodat into a staging directory
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat /tmp/geodat/geoip.dat
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat /tmp/geodat/geosite.dat
RUN mkdir -p /tmp/empty
# Create config files with empty JSON content
RUN mkdir -p /tmp/usr/local/etc/xray
RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
{
"log": {
"error": "/var/log/xray/error.log",
"loglevel": "warning",
"access": "none",
"dnsLog": false
}
}
EOF
RUN echo '{}' >/tmp/usr/local/etc/xray/01_api.json
RUN echo '{}' >/tmp/usr/local/etc/xray/02_dns.json
RUN echo '{}' >/tmp/usr/local/etc/xray/03_routing.json
RUN echo '{}' >/tmp/usr/local/etc/xray/04_policy.json
RUN echo '{}' >/tmp/usr/local/etc/xray/05_inbounds.json
RUN echo '{}' >/tmp/usr/local/etc/xray/06_outbounds.json
RUN echo '{}' >/tmp/usr/local/etc/xray/07_transport.json
RUN echo '{}' >/tmp/usr/local/etc/xray/08_stats.json
RUN echo '{}' >/tmp/usr/local/etc/xray/09_reverse.json
# Create log files
RUN mkdir -p /tmp/var/log/xray && touch \
/tmp/var/log/xray/access.log \
/tmp/var/log/xray/error.log
# Build finally image
# Note on Distroless Base Image and Architecture Support:
# - The official 'gcr.io/distroless/static' image provided by Google only supports a limited set of architectures for Linux:
# - linux/amd64
# - linux/arm/v7
# - linux/arm64/v8
# - linux/ppc64le
# - linux/s390x
# - Upon inspection, the blob contents of the Distroless images across these architectures are nearly identical, with only minor differences in metadata (e.g., 'Architecture' field in the manifest).
# - Due to this similarity in content, it is feasible to forcibly specify a single platform (e.g., '--platform=linux/amd64') for unsupported architectures, as the core image content remains compatible with statically compiled binaries like Go applications.
FROM --platform=linux/amd64 gcr.io/distroless/static:nonroot
COPY --from=build --chown=0:0 --chmod=755 /src/xray /usr/local/bin/xray
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/share/xray
COPY --from=build --chown=0:0 --chmod=644 /tmp/geodat/*.dat /usr/local/share/xray/
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/etc/xray
COPY --from=build --chown=0:0 --chmod=644 /tmp/usr/local/etc/xray/*.json /usr/local/etc/xray/
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /var/log/xray
COPY --from=build --chown=65532:65532 --chmod=600 /tmp/var/log/xray/*.log /var/log/xray/
VOLUME /usr/local/etc/xray
VOLUME /var/log/xray
ARG TZ=Etc/UTC
ENV TZ=$TZ
ENTRYPOINT [ "/usr/local/bin/xray" ]
CMD [ "-confdir", "/usr/local/etc/xray/" ]

View File

@@ -1,18 +0,0 @@
{
"inbounds": [{
"port": 9000,
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "1eb6e917-774b-4a84-aff6-b058577c60a5",
"level": 1
}
]
}
}],
"outbounds": [{
"protocol": "freedom",
"settings": {}
}]
}

View File

@@ -1,48 +1,133 @@
name: Build docker image name: Build and Push Docker Image
on: on:
release: release:
types: [published] types:
push: - published
branches: - released
- main
workflow_dispatch:
inputs:
tag:
description: "Docker image tag:"
required: true
latest:
description: "Set to latest"
type: boolean
default: false
jobs: jobs:
build-image: build-and-push:
if: (github.event.action != 'published') || (github.event.action == 'published' && github.event.release.prerelease == true)
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read
packages: write packages: write
steps: steps:
- uses: actions/checkout@v4 - name: Set repository and image name to lowercase
- name: Docker metadata env:
id: meta IMAGE_NAME: "${{ github.repository }}"
uses: docker/metadata-action@v5 run: |
with: echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
images: ghcr.io/${{ github.repository_owner }}/xray-core echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
flavor: latest=true
tags: | - name: Validate and extract tag
type=sha run: |
type=ref,event=branch SOURCE_TAG="${{ github.event.inputs.tag }}"
type=ref,event=pr if [[ -z "$SOURCE_TAG" ]]; then
type=semver,pattern={{version}} SOURCE_TAG="${{ github.ref_name }}"
fi
if [[ -z "$SOURCE_TAG" ]]; then
SOURCE_TAG="${{ github.event.release.tag_name }}"
fi
if [[ -z "$SOURCE_TAG" ]]; then
echo "Error: Could not determine a valid tag source. Input tag and context tag (github.ref_name) are both empty."
exit 1
fi
if [[ "$SOURCE_TAG" =~ ^v[0-9]+\.[0-9] ]]; then
IMAGE_TAG="${SOURCE_TAG#v}"
else
IMAGE_TAG="$SOURCE_TAG"
fi
echo "Docker image tag: '$IMAGE_TAG'."
echo "IMAGE_TAG=$IMAGE_TAG" >>${GITHUB_ENV}
LATEST=false
if [[ "${{ github.event_name }}" == "release" && "${{ github.event.release.prerelease }}" == "false" ]] || [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.latest }}" == "true" ]]; then
LATEST=true
fi
echo "Latest: '$LATEST'."
echo "LATEST=$LATEST" >>${GITHUB_ENV}
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- # Add support for more platforms with QEMU (optional)
# https://github.com/docker/setup-qemu-action - name: Build Docker image (main architectures)
name: Set up QEMU id: build_main_arches
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
platforms: linux/amd64,linux/arm64
file: .github/docker/Dockerfile file: .github/docker/Dockerfile
push: true platforms: |
tags: ${{ steps.meta.outputs.tags }} linux/amd64
labels: ${{ steps.meta.outputs.labels }} linux/arm/v7
linux/arm64/v8
linux/ppc64le
linux/s390x
provenance: false
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
- name: Build Docker image (additional architectures)
id: build_additional_arches
uses: docker/build-push-action@v6
with:
context: .
file: .github/docker/Dockerfile.usa
platforms: |
linux/386
linux/arm/v6
linux/riscv64
linux/loong64
provenance: false
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
- name: Create manifest list and push
run: |
echo "Creating multi-arch manifest with tag: '${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }}'."
docker buildx imagetools create \
--tag ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }} \
${{ env.FULL_IMAGE_NAME }}@${{ steps.build_main_arches.outputs.digest }} \
${{ env.FULL_IMAGE_NAME }}@${{ steps.build_additional_arches.outputs.digest }}
if [[ "${{ env.LATEST }}" == "true" ]]; then
echo "Adding 'latest' tag to manifest: '${{ env.FULL_IMAGE_NAME }}:latest'."
docker buildx imagetools create \
--tag ${{ env.FULL_IMAGE_NAME }}:latest \
${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }}
fi
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }}
if [[ "${{ env.LATEST }}" == "true" ]]; then
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:latest
fi

148
.github/workflows/release-win7.yml vendored Normal file
View File

@@ -0,0 +1,148 @@
name: Build and Release for Windows 7
on:
workflow_dispatch:
release:
types: [published]
push:
pull_request:
types: [opened, synchronize, reopened]
jobs:
check-assets:
runs-on: ubuntu-latest
steps:
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
- name: Check Assets Existence
id: check-assets
run: |
[ -d 'resources' ] || mkdir resources
LIST=('geoip.dat' 'geosite.dat')
for FILE_NAME in "${LIST[@]}"
do
echo -e "Checking ${FILE_NAME}..."
if [ -s "./resources/${FILE_NAME}" ]; then
echo -e "${FILE_NAME} exists."
else
echo -e "${FILE_NAME} does not exist."
echo "missing=true" >> $GITHUB_OUTPUT
break
fi
done
- name: Sleep for 90 seconds if Assets Missing
if: steps.check-assets.outputs.missing == 'true'
run: sleep 90
build:
needs: check-assets
permissions:
contents: write
strategy:
matrix:
include:
# BEGIN Windows 7
- goos: windows
goarch: amd64
assetname: win7-64
- goos: windows
goarch: 386
assetname: win7-32
# END Windows 7
fail-fast: false
runs-on: ubuntu-latest
env:
GOOS: ${{ matrix.goos}}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 0
steps:
- name: Checkout codebase
uses: actions/checkout@v4
- name: Show workflow information
run: |
_NAME=${{ matrix.assetname }}
echo "GOOS: ${{ matrix.goos }}, GOARCH: ${{ matrix.goarch }}, RELEASE_NAME: $_NAME"
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
check-latest: true
- name: Setup patched builder
run: |
GOSDK=$(go env GOROOT)
rm -r $GOSDK/*
cd $GOSDK
curl -O -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" https://github.com/XTLS/go-win7/releases/latest/download/go-for-win7-linux-amd64.zip
unzip ./go-for-win7-linux-amd64.zip -d $GOSDK
rm ./go-for-win7-linux-amd64.zip
- name: Get project dependencies
run: go mod download
- name: Build Xray
run: |
mkdir -p build_assets
COMMID=$(git describe --always --dirty)
echo 'Building Xray for Windows 7...'
go build -o build_assets/xray.exe -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
# The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
- name: Copy README.md & LICENSE
run: |
mv -f resources/* build_assets
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
- name: Create ZIP archive
if: github.event_name == 'release'
shell: bash
run: |
pushd build_assets || exit 1
touch -mt $(date +%Y01010000) *
zip -9vr ../Xray-${{ env.ASSET_NAME }}.zip .
popd || exit 1
FILE=./Xray-${{ env.ASSET_NAME }}.zip
DGST=$FILE.dgst
for METHOD in {"md5","sha1","sha256","sha512"}
do
openssl dgst -$METHOD $FILE | sed 's/([^)]*)//g' >>$DGST
done
- name: Change the name
run: |
mv build_assets Xray-${{ env.ASSET_NAME }}
- name: Upload files to Artifacts
uses: actions/upload-artifact@v4
with:
name: Xray-${{ env.ASSET_NAME }}
path: |
./Xray-${{ env.ASSET_NAME }}/*
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
if: github.event_name == 'release'
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./Xray-${{ env.ASSET_NAME }}.zip*
tag: ${{ github.ref }}
file_glob: true

View File

@@ -1,76 +1,61 @@
name: Build and Release name: Build and Release
# NOTE: This Github Actions file depends on the Makefile.
# Building the correct package requires the correct binaries generated by the Makefile. To
# ensure the correct output, the Makefile must accept the appropriate input and compile the
# correct file with the correct name. If you need to modify this file, please ensure it won't
# disrupt the Makefile.
on: on:
workflow_dispatch: workflow_dispatch:
release: release:
types: [published] types: [published]
push: push:
branches:
- main
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/release.yml"
pull_request: pull_request:
types: [opened, synchronize, reopened] types: [opened, synchronize, reopened]
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/release.yml"
jobs: jobs:
prepare: check-assets:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Restore Cache - name: Restore Geodat Cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
with: with:
path: resources path: resources
key: xray-geodat- key: xray-geodat-
- name: Update Geodat - name: Check Assets Existence
id: update id: check-assets
uses: nick-fields/retry@v3 run: |
with: [ -d 'resources' ] || mkdir resources
timeout_minutes: 60 LIST=('geoip.dat' 'geosite.dat')
retry_wait_seconds: 60 for FILE_NAME in "${LIST[@]}"
max_attempts: 60 do
command: | echo -e "Checking ${FILE_NAME}..."
[ -d 'resources' ] || mkdir resources if [ -s "./resources/${FILE_NAME}" ]; then
LIST=('geoip geoip geoip' 'domain-list-community dlc geosite') echo -e "${FILE_NAME} exists."
for i in "${LIST[@]}" else
do echo -e "${FILE_NAME} does not exist."
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3}')) echo "missing=true" >> $GITHUB_OUTPUT
FILE_NAME="${INFO[2]}.dat" break
echo -e "Verifying HASH key..." fi
HASH="$(curl -sL "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat.sha256sum" | awk -F ' ' '{print $1}')" done
if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
continue
else
echo -e "Downloading https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat..."
curl -L "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat" -o ./resources/${FILE_NAME}
echo -e "Verifying HASH key..."
[ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
echo "unhit=true" >> $GITHUB_OUTPUT
fi
done
- name: Save Cache - name: Trigger Asset Update Workflow if Assets Missing
uses: actions/cache/save@v4 if: steps.check-assets.outputs.missing == 'true'
if: ${{ steps.update.outputs.unhit }} uses: actions/github-script@v7
with: with:
path: resources github-token: ${{ secrets.GITHUB_TOKEN }}
key: xray-geodat-${{ github.sha }}-${{ github.run_number }} script: |
const { owner, repo } = context.repo;
await github.rest.actions.createWorkflowDispatch({
owner,
repo,
workflow_id: 'scheduled-assets-update.yml',
ref: context.ref
});
console.log('Triggered scheduled-assets-update.yml due to missing assets on branch:', context.ref);
- name: Sleep for 90 seconds if Assets Missing
if: steps.check-assets.outputs.missing == 'true'
run: sleep 90
build: build:
needs: prepare needs: check-assets
permissions: permissions:
contents: write contents: write
strategy: strategy:
@@ -78,9 +63,7 @@ jobs:
# Include amd64 on all platforms. # Include amd64 on all platforms.
goos: [windows, freebsd, openbsd, linux, darwin] goos: [windows, freebsd, openbsd, linux, darwin]
goarch: [amd64, 386] goarch: [amd64, 386]
gotoolchain: [""]
patch-assetname: [""] patch-assetname: [""]
exclude: exclude:
# Exclude i386 on darwin # Exclude i386 on darwin
- goarch: 386 - goarch: 386
@@ -105,6 +88,11 @@ jobs:
- goos: android - goos: android
goarch: arm64 goarch: arm64
# END Android ARM 8 # END Android ARM 8
# BEGIN Android AMD64
- goos: android
goarch: amd64
patch-assetname: android-amd64
# END Android AMD64
# Windows ARM # Windows ARM
- goos: windows - goos: windows
goarch: arm64 goarch: arm64
@@ -155,16 +143,6 @@ jobs:
goarch: arm goarch: arm
goarm: 7 goarm: 7
# END OPENBSD ARM # END OPENBSD ARM
# BEGIN Windows 7
- goos: windows
goarch: amd64
gotoolchain: 1.21.4
patch-assetname: win7-64
- goos: windows
goarch: 386
gotoolchain: 1.21.4
patch-assetname: win7-32
# END Windows 7
fail-fast: false fail-fast: false
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -177,6 +155,19 @@ jobs:
- name: Checkout codebase - name: Checkout codebase
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up NDK
if: matrix.goos == 'android'
run: |
wget -qO android-ndk.zip https://dl.google.com/android/repository/android-ndk-r28b-linux.zip
unzip android-ndk.zip
rm android-ndk.zip
declare -A arches=(
["amd64"]="x86_64-linux-android24-clang"
["arm64"]="aarch64-linux-android24-clang"
)
echo CC="$(realpath android-ndk-*/toolchains/llvm/prebuilt/linux-x86_64/bin)/${arches[${{ matrix.goarch }}]}" >> $GITHUB_ENV
echo CGO_ENABLED=1 >> $GITHUB_ENV
- name: Show workflow information - name: Show workflow information
run: | run: |
_NAME=${{ matrix.patch-assetname }} _NAME=${{ matrix.patch-assetname }}
@@ -187,19 +178,33 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: ${{ matrix.gotoolchain || '1.22' }} go-version-file: go.mod
check-latest: true check-latest: true
- name: Get project dependencies - name: Get project dependencies
run: go mod download run: go mod download
- name: Build Xray - name: Build Xray
run: | run: |
mkdir -p build_assets mkdir -p build_assets
make COMMID=$(git describe --always --dirty)
find . -maxdepth 1 -type f -regex './\(wxray\|xray\|xray_softfloat\)\(\|.exe\)' -exec mv {} ./build_assets/ \; if [[ ${GOOS} == 'windows' ]]; then
echo 'Building Xray for Windows...'
go build -o build_assets/xray.exe -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
# The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
else
echo 'Building Xray...'
go build -o build_assets/xray -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
if [[ ${GOARCH} == 'mips' || ${GOARCH} == 'mipsle' ]]; then
echo 'Building soft-float Xray for MIPS/MIPSLE 32-bit...'
GOMIPS=softfloat go build -o build_assets/xray_softfloat -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
fi
fi
- name: Restore Cache - name: Restore Geodat Cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
with: with:
path: resources path: resources

View File

@@ -0,0 +1,65 @@
name: Scheduled assets update
# NOTE: This Github Actions is required by other actions, for preparing other packaging assets in a
# routine manner, for example: GeoIP/GeoSite.
# Currently updating:
# - Geodat (GeoIP/Geosite)
on:
workflow_dispatch:
schedule:
# Update GeoData on every day (22:30 UTC)
- cron: "30 22 * * *"
push:
# Prevent triggering update request storm
paths:
- ".github/workflows/scheduled-assets-update.yml"
pull_request:
# Prevent triggering update request storm
paths:
- ".github/workflows/scheduled-assets-update.yml"
jobs:
geodat:
if: github.event.schedule == '30 22 * * *' || github.event_name == 'push'|| github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
- name: Update Geodat
id: update
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
retry_wait_seconds: 60
max_attempts: 60
command: |
[ -d 'resources' ] || mkdir resources
LIST=('Loyalsoldier v2ray-rules-dat geoip geoip' 'Loyalsoldier v2ray-rules-dat geosite geosite')
for i in "${LIST[@]}"
do
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3,$4}'))
FILE_NAME="${INFO[3]}.dat"
echo -e "Verifying HASH key..."
HASH="$(curl -sL -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
continue
else
echo -e "Downloading https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat..."
curl -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat" -o ./resources/${FILE_NAME}
echo -e "Verifying HASH key..."
[ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
echo "unhit=true" >> $GITHUB_OUTPUT
fi
done
- name: Save Geodat Cache
uses: actions/cache/save@v4
if: ${{ steps.update.outputs.unhit }}
with:
path: resources
key: xray-geodat-${{ github.sha }}-${{ github.run_number }}

View File

@@ -2,23 +2,40 @@ name: Test
on: on:
push: push:
branches:
- main
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/*.yml"
pull_request: pull_request:
types: [opened, synchronize, reopened] types: [opened, synchronize, reopened]
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/*.yml"
jobs: jobs:
check-assets:
runs-on: ubuntu-latest
steps:
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
- name: Check Assets Existence
id: check-assets
run: |
[ -d 'resources' ] || mkdir resources
LIST=('geoip.dat' 'geosite.dat')
for FILE_NAME in "${LIST[@]}"
do
echo -e "Checking ${FILE_NAME}..."
if [ -s "./resources/${FILE_NAME}" ]; then
echo -e "${FILE_NAME} exists."
else
echo -e "${FILE_NAME} does not exist."
echo "missing=true" >> $GITHUB_OUTPUT
break
fi
done
- name: Sleep for 90 seconds if Assets Missing
if: steps.check-assets.outputs.missing == 'true'
run: sleep 90
test: test:
needs: check-assets
permissions: permissions:
contents: read contents: read
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -32,9 +49,9 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.22' go-version-file: go.mod
check-latest: true check-latest: true
- name: Restore Cache - name: Restore Geodat Cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
with: with:
path: resources path: resources

20
.gitignore vendored
View File

@@ -14,10 +14,18 @@
# Dependency directories (remove the comment below to include it) # Dependency directories (remove the comment below to include it)
# vendor/ # vendor/
# macOS specific files
*.DS_Store *.DS_Store
.idea
# IDE specific files
.idea/
.vscode/
# Archive files
*.zip *.zip
*.tar.gz *.tar.gz
# Binaries
xray xray
xray_softfloat xray_softfloat
mockgen mockgen
@@ -26,5 +34,13 @@ vprotogen
errorgen errorgen
!common/errors/errorgen/ !common/errors/errorgen/
*.dat *.dat
.vscode
# Build assets
/build_assets /build_assets
# Output from dlv test
**/debug.*
# Certificates
*.crt
*.key

View File

@@ -1,37 +0,0 @@
NAME = xray
VERSION=$(shell git describe --always --dirty)
# NOTE: This MAKEFILE can be used to build Xray-core locally and in Automatic workflows. It is \
provided for convenience in automatic building and functions as a part of it.
# NOTE: If you need to modify this file, please be aware that:\
- This file is not the main Makefile; it only accepts environment variables and builds the \
binary.\
- Automatic building expects the correct binaries to be built by this Makefile. If you \
intend to propose a change to this Makefile, carefully review the file below and ensure \
that the change will not accidentally break the automatic building:\
.github/workflows/release.yml \
Otherwise it is recommended to contact the project maintainers.
LDFLAGS = -X github.com/xtls/xray-core/core.build=$(VERSION) -s -w -buildid=
PARAMS = -trimpath -ldflags "$(LDFLAGS)" -v
MAIN = ./main
PREFIX ?= $(shell go env GOPATH)
ifeq ($(GOOS),windows)
OUTPUT = $(NAME).exe
ADDITION = go build -o w$(NAME).exe -trimpath -ldflags "-H windowsgui $(LDFLAGS)" -v $(MAIN)
else
OUTPUT = $(NAME)
endif
ifeq ($(shell echo "$(GOARCH)" | grep -Eq "(mips|mipsle)" && echo true),true) #
ADDITION = GOMIPS=softfloat go build -o $(NAME)_softfloat -trimpath -ldflags "$(LDFLAGS)" -v $(MAIN)
endif
.PHONY: clean build
build:
go build -o $(OUTPUT) $(PARAMS) $(MAIN)
$(ADDITION)
clean:
go clean -v -i $(PWD)
rm -f xray xray.exe wxray.exe xray_softfloat

View File

@@ -1,9 +1,20 @@
# Project X # Project X
[![Project X NFT](https://raw2.seadn.io/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/7fa9ce900fb39b44226348db330e32/8b7fa9ce900fb39b44226348db330e32.svg)](https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1)
### [Collect a Project X NFT to support the development of Project X!](https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1)
[Project X](https://github.com/XTLS) originates from XTLS protocol, providing a set of network tools such as [Xray-core](https://github.com/XTLS/Xray-core) and [REALITY](https://github.com/XTLS/REALITY). [Project X](https://github.com/XTLS) originates from XTLS protocol, providing a set of network tools such as [Xray-core](https://github.com/XTLS/Xray-core) and [REALITY](https://github.com/XTLS/REALITY).
[README](https://github.com/XTLS/Xray-core#readme) is open, so feel free to submit your project [here](https://github.com/XTLS/Xray-core/pulls). [README](https://github.com/XTLS/Xray-core#readme) is open, so feel free to submit your project [here](https://github.com/XTLS/Xray-core/pulls).
## Donation & NFTs
- **ETH/USDT/USDC: `0xDc3Fe44F0f25D13CACb1C4896CD0D321df3146Ee`**
- **Project X NFT: https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1**
- **REALITY NFT: https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2**
- **Related links: https://opensea.io/collection/xtls, [Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633), [XHTTP: Beyond REALITY](https://github.com/XTLS/Xray-core/discussions/4113)**
## License ## License
[Mozilla Public License Version 2.0](https://github.com/XTLS/Xray-core/blob/main/LICENSE) [Mozilla Public License Version 2.0](https://github.com/XTLS/Xray-core/blob/main/LICENSE)
@@ -18,6 +29,10 @@
[Project X Channel](https://t.me/projectXtls) [Project X Channel](https://t.me/projectXtls)
[Project VLESS](https://t.me/projectVless) (Русский)
[Project XHTTP](https://t.me/projectXhttp) (Persian)
## Installation ## Installation
- Linux Script - Linux Script
@@ -26,14 +41,15 @@
- Docker - Docker
- [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core) (**Official**) - [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core) (**Official**)
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray) - [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
- Web Panel - [wulabing/xray_docker](https://github.com/wulabing/xray_docker)
- [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [Xray-UI](https://github.com/qist/xray-ui) - Web Panel - **WARNING: Please DO NOT USE plain HTTP panels like 3X-UI**, as they are believed to be bribed by Iran GFW for supporting plain HTTP by default and refused to change (https://github.com/XTLS/Xray-core/pull/3884#issuecomment-2439595331), which has already put many users' data security in danger in the past few years. **If you are already using 3X-UI, please switch to the following panels, which are verified to support HTTPS and SSH port forwarding only:**
- [Hiddify](https://github.com/hiddify/hiddify-config) - [Remnawave](https://github.com/remnawave/panel)
- [Marzban](https://github.com/Gozargah/Marzban) - [Marzban](https://github.com/Gozargah/Marzban)
- [Libertea](https://github.com/VZiChoushaDui/Libertea) - [Xray-UI](https://github.com/qist/xray-ui)
- [Hiddify](https://github.com/hiddify/Hiddify-Manager)
- One Click - One Click
- [Xray-REALITY](https://github.com/zxcvos/Xray-script), [xray-reality](https://github.com/sajjaddg/xray-reality), [reality-ezpz](https://github.com/aleskxyz/reality-ezpz) - [Xray-REALITY](https://github.com/zxcvos/Xray-script), [xray-reality](https://github.com/sajjaddg/xray-reality), [reality-ezpz](https://github.com/aleskxyz/reality-ezpz)
- [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool) - [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool), [VPainLess](https://github.com/vpainless/vpainless)
- [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU) - [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU)
- Magisk - Magisk
- [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk) - [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
@@ -64,33 +80,49 @@
- [PassWall](https://github.com/xiaorouji/openwrt-passwall), [PassWall 2](https://github.com/xiaorouji/openwrt-passwall2) - [PassWall](https://github.com/xiaorouji/openwrt-passwall), [PassWall 2](https://github.com/xiaorouji/openwrt-passwall2)
- [ShadowSocksR Plus+](https://github.com/fw876/helloworld) - [ShadowSocksR Plus+](https://github.com/fw876/helloworld)
- [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))
- Asuswrt-Merlin
- [XRAYUI](https://github.com/DanielLavrushin/asuswrt-merlin-xrayui)
- Windows - Windows
- [v2rayN](https://github.com/2dust/v2rayN) - [v2rayN](https://github.com/2dust/v2rayN)
- [Furious](https://github.com/LorenEteval/Furious) - [Furious](https://github.com/LorenEteval/Furious)
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient) - [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
- Android - Android
- [v2rayNG](https://github.com/2dust/v2rayNG) - [v2rayNG](https://github.com/2dust/v2rayNG)
- [X-flutter](https://github.com/XTLS/X-flutter) - [X-flutter](https://github.com/XTLS/X-flutter)
- iOS & macOS arm64 - [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
- [FoXray](https://apps.apple.com/app/foxray/id6448898396) - [SimpleXray](https://github.com/lhear/SimpleXray)
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
- iOS & macOS arm64 & tvOS
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) ([tvOS](https://apps.apple.com/us/app/happ-proxy-utility-for-tv/id6748297274))
- [Streisand](https://apps.apple.com/app/streisand/id6450534064) - [Streisand](https://apps.apple.com/app/streisand/id6450534064)
- [OneXray](https://github.com/OneXray/OneXray)
- macOS arm64 & x64 - macOS arm64 & x64
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215)
- [V2rayU](https://github.com/yanue/V2rayU) - [V2rayU](https://github.com/yanue/V2rayU)
- [V2RayXS](https://github.com/tzmax/V2RayXS) - [V2RayXS](https://github.com/tzmax/V2RayXS)
- [Furious](https://github.com/LorenEteval/Furious) - [Furious](https://github.com/LorenEteval/Furious)
- [FoXray](https://apps.apple.com/app/foxray/id6448898396) - [OneXray](https://github.com/OneXray/OneXray)
- [GoXRay](https://github.com/goxray/desktop)
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
- Linux - Linux
- [v2rayA](https://github.com/v2rayA/v2rayA) - [v2rayA](https://github.com/v2rayA/v2rayA)
- [Furious](https://github.com/LorenEteval/Furious) - [Furious](https://github.com/LorenEteval/Furious)
- [GorzRay](https://github.com/ketetefid/GorzRay)
- [GoXRay](https://github.com/goxray/desktop)
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX... ## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
- iOS & macOS arm64 - iOS & macOS arm64 & tvOS
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118) - [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
- [Loon](https://apps.apple.com/us/app/loon/id1373567447)
- Xray Tools - Xray Tools
- [xray-knife](https://github.com/lilendian0x00/xray-knife) - [xray-knife](https://github.com/lilendian0x00/xray-knife)
- [xray-checker](https://github.com/kutovoys/xray-checker)
- Xray Wrapper - Xray Wrapper
- [XTLS/libXray](https://github.com/XTLS/libXray) - [XTLS/libXray](https://github.com/XTLS/libXray)
- [xtls-sdk](https://github.com/remnawave/xtls-sdk)
- [xtlsapi](https://github.com/hiddify/xtlsapi) - [xtlsapi](https://github.com/hiddify/xtlsapi)
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite) - [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python) - [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
@@ -98,39 +130,43 @@
- [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)
- [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta) - Cores
- [clashN](https://github.com/2dust/clashN) - [Amnezia VPN](https://github.com/amnezia-vpn)
- [Clash Meta for Android](https://github.com/MetaCubeX/ClashMetaForAndroid) - [mihomo](https://github.com/MetaCubeX/mihomo)
- [sing-box](https://github.com/SagerNet/sing-box) - [sing-box](https://github.com/SagerNet/sing-box)
## Contributing ## Contributing
[Code of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md) [Code of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/XTLS/Xray-core)
## Credits ## Credits
- [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases). - [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases).
- For third-party projects used in [Xray-core](https://github.com/XTLS/Xray-core), check your local or [the latest go.mod](https://github.com/XTLS/Xray-core/blob/main/go.mod). - For third-party projects used in [Xray-core](https://github.com/XTLS/Xray-core), check your local or [the latest go.mod](https://github.com/XTLS/Xray-core/blob/main/go.mod).
## Compilation ## One-line Compilation
### Windows (PowerShell) ### Windows (PowerShell)
```powershell ```powershell
$env:CGO_ENABLED=0 $env:CGO_ENABLED=0
go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main go build -o xray.exe -trimpath -buildvcs=false -ldflags="-s -w -buildid=" -v ./main
``` ```
### Linux / macOS ### Linux / macOS
```bash ```bash
CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags="-s -w -buildid=" -v ./main
``` ```
### Reproducible Releases ### Reproducible Releases
Make sure that you are using the same Go version, and remember to set the git commit id (7 bytes):
```bash ```bash
make CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=REPLACE -s -w -buildid=" -v ./main
``` ```
## Stargazers over time ## Stargazers over time

View File

@@ -1,7 +1,5 @@
package commander package commander
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"
"net" "net"

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/commander/config.proto // source: app/commander/config.proto
package commander package commander
@@ -38,11 +38,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_commander_config_proto_msgTypes[0]
mi := &file_app_commander_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -53,7 +51,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_commander_config_proto_msgTypes[0] mi := &file_app_commander_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -98,11 +96,9 @@ type ReflectionConfig struct {
func (x *ReflectionConfig) Reset() { func (x *ReflectionConfig) Reset() {
*x = ReflectionConfig{} *x = ReflectionConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_commander_config_proto_msgTypes[1]
mi := &file_app_commander_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *ReflectionConfig) String() string { func (x *ReflectionConfig) String() string {
@@ -113,7 +109,7 @@ func (*ReflectionConfig) ProtoMessage() {}
func (x *ReflectionConfig) ProtoReflect() protoreflect.Message { func (x *ReflectionConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_commander_config_proto_msgTypes[1] mi := &file_app_commander_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -166,7 +162,7 @@ func file_app_commander_config_proto_rawDescGZIP() []byte {
} }
var file_app_commander_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_app_commander_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_app_commander_config_proto_goTypes = []interface{}{ var file_app_commander_config_proto_goTypes = []any{
(*Config)(nil), // 0: xray.app.commander.Config (*Config)(nil), // 0: xray.app.commander.Config
(*ReflectionConfig)(nil), // 1: xray.app.commander.ReflectionConfig (*ReflectionConfig)(nil), // 1: xray.app.commander.ReflectionConfig
(*serial.TypedMessage)(nil), // 2: xray.common.serial.TypedMessage (*serial.TypedMessage)(nil), // 2: xray.common.serial.TypedMessage
@@ -185,32 +181,6 @@ func file_app_commander_config_proto_init() {
if File_app_commander_config_proto != nil { if File_app_commander_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_commander_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_commander_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReflectionConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -8,6 +8,7 @@ import (
"github.com/xtls/xray-core/common/errors" "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/net/cnc" "github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
) )
@@ -108,3 +109,13 @@ func (co *Outbound) Close() error {
co.closed = true co.closed = true
return co.listener.Close() return co.listener.Close()
} }
// SenderSettings implements outbound.Handler.
func (co *Outbound) SenderSettings() *serial.TypedMessage {
return nil
}
// ProxySettings implements outbound.Handler.
func (co *Outbound) ProxySettings() *serial.TypedMessage {
return nil
}

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/dispatcher/config.proto // source: app/dispatcher/config.proto
package dispatcher package dispatcher
@@ -28,11 +28,9 @@ type SessionConfig struct {
func (x *SessionConfig) Reset() { func (x *SessionConfig) Reset() {
*x = SessionConfig{} *x = SessionConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_dispatcher_config_proto_msgTypes[0]
mi := &file_app_dispatcher_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *SessionConfig) String() string { func (x *SessionConfig) String() string {
@@ -43,7 +41,7 @@ func (*SessionConfig) ProtoMessage() {}
func (x *SessionConfig) ProtoReflect() protoreflect.Message { func (x *SessionConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_dispatcher_config_proto_msgTypes[0] mi := &file_app_dispatcher_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -68,11 +66,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_dispatcher_config_proto_msgTypes[1]
mi := &file_app_dispatcher_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -83,7 +79,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_dispatcher_config_proto_msgTypes[1] mi := &file_app_dispatcher_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -139,7 +135,7 @@ func file_app_dispatcher_config_proto_rawDescGZIP() []byte {
} }
var file_app_dispatcher_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_app_dispatcher_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_app_dispatcher_config_proto_goTypes = []interface{}{ var file_app_dispatcher_config_proto_goTypes = []any{
(*SessionConfig)(nil), // 0: xray.app.dispatcher.SessionConfig (*SessionConfig)(nil), // 0: xray.app.dispatcher.SessionConfig
(*Config)(nil), // 1: xray.app.dispatcher.Config (*Config)(nil), // 1: xray.app.dispatcher.Config
} }
@@ -157,32 +153,6 @@ func file_app_dispatcher_config_proto_init() {
if File_app_dispatcher_config_proto != nil { if File_app_dispatcher_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_dispatcher_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SessionConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_dispatcher_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -1,7 +1,5 @@
package dispatcher package dispatcher
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"
"regexp" "regexp"
@@ -10,8 +8,8 @@ import (
"time" "time"
"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/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"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"
@@ -35,17 +33,21 @@ type cachedReader struct {
cache buf.MultiBuffer cache buf.MultiBuffer
} }
func (r *cachedReader) Cache(b *buf.Buffer) { func (r *cachedReader) Cache(b *buf.Buffer, deadline time.Duration) error {
mb, _ := r.reader.ReadMultiBufferTimeout(time.Millisecond * 100) mb, err := r.reader.ReadMultiBufferTimeout(deadline)
if err != nil {
return err
}
r.Lock() r.Lock()
if !mb.IsEmpty() { if !mb.IsEmpty() {
r.cache, _ = buf.MergeMulti(r.cache, mb) r.cache, _ = buf.MergeMulti(r.cache, mb)
} }
b.Clear() b.Clear()
rawBytes := b.Extend(buf.Size) rawBytes := b.Extend(min(r.cache.Len(), b.Cap()))
n := r.cache.Copy(rawBytes) n := r.cache.Copy(rawBytes)
b.Resize(0, int32(n)) b.Resize(0, int32(n))
r.Unlock() r.Unlock()
return nil
} }
func (r *cachedReader) readInternal() buf.MultiBuffer { func (r *cachedReader) readInternal() buf.MultiBuffer {
@@ -94,7 +96,6 @@ type DefaultDispatcher struct {
router routing.Router router routing.Router
policy policy.Manager policy policy.Manager
stats stats.Manager stats stats.Manager
dns dns.Client
fdns dns.FakeDNSEngine fdns dns.FakeDNSEngine
} }
@@ -102,10 +103,10 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
d := new(DefaultDispatcher) d := new(DefaultDispatcher)
if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error { if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error {
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
d.fdns = fdns d.fdns = fdns
}) })
return d.Init(config.(*Config), om, router, pm, sm, dc) return d.Init(config.(*Config), om, router, pm, sm)
}); err != nil { }); err != nil {
return nil, err return nil, err
} }
@@ -114,12 +115,11 @@ func init() {
} }
// Init initializes DefaultDispatcher. // Init initializes DefaultDispatcher.
func (d *DefaultDispatcher) Init(config *Config, om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dns dns.Client) error { func (d *DefaultDispatcher) Init(config *Config, om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager) error {
d.ohm = om d.ohm = om
d.router = router d.router = router
d.policy = pm d.policy = pm
d.stats = sm d.stats = sm
d.dns = dns
return nil return nil
} }
@@ -177,6 +177,18 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
} }
} }
} }
if p.Stats.UserOnline {
name := "user>>>" + user.Email + ">>>online"
if om, _ := stats.GetOrRegisterOnlineMap(d.stats, name); om != nil {
sessionInbounds := session.InboundFromContext(ctx)
userIP := sessionInbounds.Source.Address.String()
om.AddIP(userIP)
// log Online user with ips
// errors.LogDebug(ctx, "user>>>" + user.Email + ">>>online", om.Count(), om.List())
}
}
} }
return inboundLink, outboundLink return inboundLink, outboundLink
@@ -339,7 +351,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
} }
func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, network net.Network) (SniffResult, error) { func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, network net.Network) (SniffResult, error) {
payload := buf.New() payload := buf.NewWithSize(32767)
defer payload.Release() defer payload.Release()
sniffer := NewSniffer(ctx) sniffer := NewSniffer(ctx)
@@ -351,26 +363,36 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
} }
contentResult, contentErr := func() (SniffResult, error) { contentResult, contentErr := func() (SniffResult, error) {
cacheDeadline := 200 * time.Millisecond
totalAttempt := 0 totalAttempt := 0
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() return nil, ctx.Err()
default: default:
totalAttempt++ cachingStartingTimeStamp := time.Now()
if totalAttempt > 2 { err := cReader.Cache(payload, cacheDeadline)
return nil, errSniffingTimeout if err != nil {
return nil, err
} }
cachingTimeElapsed := time.Since(cachingStartingTimeStamp)
cacheDeadline -= cachingTimeElapsed
cReader.Cache(payload)
if !payload.IsEmpty() { if !payload.IsEmpty() {
result, err := sniffer.Sniff(ctx, payload.Bytes(), network) result, err := sniffer.Sniff(ctx, payload.Bytes(), network)
if err != common.ErrNoClue { switch err {
case common.ErrNoClue: // No Clue: protocol not matches, and sniffer cannot determine whether there will be a match or not
totalAttempt++
case protocol.ErrProtoNeedMoreData: // Protocol Need More Data: protocol matches, but need more data to complete sniffing
// in this case, do not add totalAttempt(allow to read until timeout)
default:
return result, err return result, err
} }
} else {
totalAttempt++
} }
if payload.IsFull() { if totalAttempt >= 2 || cacheDeadline <= 0 {
return nil, errUnknownContent return nil, errSniffingTimeout
} }
} }
} }
@@ -386,18 +408,6 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) { func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1] ob := outbounds[len(outbounds)-1]
if hosts, ok := d.dns.(dns.HostsLookup); ok && destination.Address.Family().IsDomain() {
proxied := hosts.LookupHosts(ob.Target.String())
if proxied != nil {
ro := ob.RouteTarget == destination
destination.Address = *proxied
if ro {
ob.RouteTarget = destination
} else {
ob.Target = destination
}
}
}
var handler outbound.Handler var handler outbound.Handler
@@ -421,7 +431,11 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
outTag := route.GetOutboundTag() outTag := route.GetOutboundTag()
if h := d.ohm.GetHandler(outTag); h != nil { if h := d.ohm.GetHandler(outTag); h != nil {
isPickRoute = 2 isPickRoute = 2
errors.LogInfo(ctx, "taking detour [", outTag, "] for [", destination, "]") if route.GetRuleTag() == "" {
errors.LogInfo(ctx, "taking detour [", outTag, "] for [", destination, "]")
} else {
errors.LogInfo(ctx, "Hit route rule: [", route.GetRuleTag(), "] so taking detour [", outTag, "] for [", destination, "]")
}
handler = h handler = h
} else { } else {
errors.LogWarning(ctx, "non existing outTag: ", outTag) errors.LogWarning(ctx, "non existing outTag: ", outTag)

View File

@@ -1,3 +1 @@
package dispatcher package dispatcher
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen

View File

@@ -28,7 +28,7 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
} }
return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) { return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds) - 1] ob := outbounds[len(outbounds)-1]
if ob.Target.Network == net.Network_TCP || ob.Target.Network == net.Network_UDP { if ob.Target.Network == net.Network_TCP || ob.Target.Network == net.Network_UDP {
domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(ob.Target.Address) domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(ob.Target.Address)
if domainFromFakeDNS != "" { if domainFromFakeDNS != "" {

View File

@@ -6,6 +6,7 @@ import (
"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"
"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/bittorrent" "github.com/xtls/xray-core/common/protocol/bittorrent"
"github.com/xtls/xray-core/common/protocol/http" "github.com/xtls/xray-core/common/protocol/http"
"github.com/xtls/xray-core/common/protocol/quic" "github.com/xtls/xray-core/common/protocol/quic"
@@ -35,7 +36,7 @@ type Sniffer struct {
func NewSniffer(ctx context.Context) *Sniffer { func NewSniffer(ctx context.Context) *Sniffer {
ret := &Sniffer{ ret := &Sniffer{
sniffer: []protocolSnifferWithMetadata{ sniffer: []protocolSnifferWithMetadata{
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b) }, false, net.Network_TCP}, {func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b, c) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP}, {func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP}, {func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP}, {func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},
@@ -58,14 +59,17 @@ var errUnknownContent = errors.New("unknown content")
func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) { func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
var pendingSniffer []protocolSnifferWithMetadata var pendingSniffer []protocolSnifferWithMetadata
for _, si := range s.sniffer { for _, si := range s.sniffer {
s := si.protocolSniffer protocolSniffer := si.protocolSniffer
if si.metadataSniffer || si.network != network { if si.metadataSniffer || si.network != network {
continue continue
} }
result, err := s(c, payload) result, err := protocolSniffer(c, payload)
if err == common.ErrNoClue { if err == common.ErrNoClue {
pendingSniffer = append(pendingSniffer, si) pendingSniffer = append(pendingSniffer, si)
continue continue
} else if err == protocol.ErrProtoNeedMoreData { // Sniffer protocol matched, but need more data to complete sniffing
s.sniffer = []protocolSnifferWithMetadata{si}
return nil, err
} }
if err == nil && result != nil { if err == nil && result != nil {

188
app/dns/cache_controller.go Normal file
View File

@@ -0,0 +1,188 @@
package dns
import (
"context"
go_errors "errors"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/signal/pubsub"
"github.com/xtls/xray-core/common/task"
dns_feature "github.com/xtls/xray-core/features/dns"
"golang.org/x/net/dns/dnsmessage"
"sync"
"time"
)
type CacheController struct {
sync.RWMutex
ips map[string]*record
pub *pubsub.Service
cacheCleanup *task.Periodic
name string
disableCache bool
}
func NewCacheController(name string, disableCache bool) *CacheController {
c := &CacheController{
name: name,
disableCache: disableCache,
ips: make(map[string]*record),
pub: pubsub.NewService(),
}
c.cacheCleanup = &task.Periodic{
Interval: time.Minute,
Execute: c.CacheCleanup,
}
return c
}
// CacheCleanup clears expired items from cache
func (c *CacheController) CacheCleanup() error {
now := time.Now()
c.Lock()
defer c.Unlock()
if len(c.ips) == 0 {
return errors.New("nothing to do. stopping...")
}
for domain, record := range c.ips {
if record.A != nil && record.A.Expire.Before(now) {
record.A = nil
}
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
record.AAAA = nil
}
if record.A == nil && record.AAAA == nil {
errors.LogDebug(context.Background(), c.name, "cache cleanup ", domain)
delete(c.ips, domain)
} else {
c.ips[domain] = record
}
}
if len(c.ips) == 0 {
c.ips = make(map[string]*record)
}
return nil
}
func (c *CacheController) updateIP(req *dnsRequest, ipRec *IPRecord) {
elapsed := time.Since(req.start)
c.Lock()
rec, found := c.ips[req.domain]
if !found {
rec = &record{}
}
switch req.reqType {
case dnsmessage.TypeA:
rec.A = ipRec
case dnsmessage.TypeAAAA:
rec.AAAA = ipRec
}
errors.LogInfo(context.Background(), c.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
c.ips[req.domain] = rec
switch req.reqType {
case dnsmessage.TypeA:
c.pub.Publish(req.domain+"4", nil)
if !c.disableCache {
_, _, err := rec.AAAA.getIPs()
if !go_errors.Is(err, errRecordNotFound) {
c.pub.Publish(req.domain+"6", nil)
}
}
case dnsmessage.TypeAAAA:
c.pub.Publish(req.domain+"6", nil)
if !c.disableCache {
_, _, err := rec.A.getIPs()
if !go_errors.Is(err, errRecordNotFound) {
c.pub.Publish(req.domain+"4", nil)
}
}
}
c.Unlock()
common.Must(c.cacheCleanup.Start())
}
func (c *CacheController) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
c.RLock()
record, found := c.ips[domain]
c.RUnlock()
if !found {
return nil, 0, errRecordNotFound
}
var errs []error
var allIPs []net.IP
var rTTL uint32 = dns_feature.DefaultTTL
mergeReq := option.IPv4Enable && option.IPv6Enable
if option.IPv4Enable {
ips, ttl, err := record.A.getIPs()
if !mergeReq || go_errors.Is(err, errRecordNotFound) {
return ips, ttl, err
}
if ttl < rTTL {
rTTL = ttl
}
if len(ips) > 0 {
allIPs = append(allIPs, ips...)
} else {
errs = append(errs, err)
}
}
if option.IPv6Enable {
ips, ttl, err := record.AAAA.getIPs()
if !mergeReq || go_errors.Is(err, errRecordNotFound) {
return ips, ttl, err
}
if ttl < rTTL {
rTTL = ttl
}
if len(ips) > 0 {
allIPs = append(allIPs, ips...)
} else {
errs = append(errs, err)
}
}
if len(allIPs) > 0 {
return allIPs, rTTL, nil
}
if go_errors.Is(errs[0], errs[1]) {
return nil, rTTL, errs[0]
}
return nil, rTTL, errors.Combine(errs...)
}
func (c *CacheController) registerSubscribers(domain string, option dns_feature.IPOption) (sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
// ipv4 and ipv6 belong to different subscription groups
if option.IPv4Enable {
sub4 = c.pub.Subscribe(domain + "4")
}
if option.IPv6Enable {
sub6 = c.pub.Subscribe(domain + "6")
}
return
}
func closeSubscribers(sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
if sub4 != nil {
sub4.Close()
}
if sub6 != nil {
sub6.Close()
}
}

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/dns/config.proto // source: app/dns/config.proto
package dns package dns
@@ -80,6 +80,7 @@ const (
QueryStrategy_USE_IP QueryStrategy = 0 QueryStrategy_USE_IP QueryStrategy = 0
QueryStrategy_USE_IP4 QueryStrategy = 1 QueryStrategy_USE_IP4 QueryStrategy = 1
QueryStrategy_USE_IP6 QueryStrategy = 2 QueryStrategy_USE_IP6 QueryStrategy = 2
QueryStrategy_USE_SYS QueryStrategy = 3
) )
// Enum value maps for QueryStrategy. // Enum value maps for QueryStrategy.
@@ -88,11 +89,13 @@ var (
0: "USE_IP", 0: "USE_IP",
1: "USE_IP4", 1: "USE_IP4",
2: "USE_IP6", 2: "USE_IP6",
3: "USE_SYS",
} }
QueryStrategy_value = map[string]int32{ QueryStrategy_value = map[string]int32{
"USE_IP": 0, "USE_IP": 0,
"USE_IP4": 1, "USE_IP4": 1,
"USE_IP6": 2, "USE_IP6": 2,
"USE_SYS": 3,
} }
) )
@@ -132,18 +135,23 @@ type NameServer struct {
ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"` SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"` PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
Geoip []*router.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"` ExpectedGeoip []*router.GeoIP `protobuf:"bytes,3,rep,name=expected_geoip,json=expectedGeoip,proto3" json:"expected_geoip,omitempty"`
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"` OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"` QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
ActPrior bool `protobuf:"varint,8,opt,name=actPrior,proto3" json:"actPrior,omitempty"`
Tag string `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
TimeoutMs uint64 `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
DisableCache bool `protobuf:"varint,11,opt,name=disableCache,proto3" json:"disableCache,omitempty"`
FinalQuery bool `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
UnexpectedGeoip []*router.GeoIP `protobuf:"bytes,13,rep,name=unexpected_geoip,json=unexpectedGeoip,proto3" json:"unexpected_geoip,omitempty"`
ActUnprior bool `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
} }
func (x *NameServer) Reset() { func (x *NameServer) Reset() {
*x = NameServer{} *x = NameServer{}
if protoimpl.UnsafeEnabled { mi := &file_app_dns_config_proto_msgTypes[0]
mi := &file_app_dns_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *NameServer) String() string { func (x *NameServer) String() string {
@@ -154,7 +162,7 @@ func (*NameServer) ProtoMessage() {}
func (x *NameServer) ProtoReflect() protoreflect.Message { func (x *NameServer) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_config_proto_msgTypes[0] mi := &file_app_dns_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -197,9 +205,9 @@ func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
return nil return nil
} }
func (x *NameServer) GetGeoip() []*router.GeoIP { func (x *NameServer) GetExpectedGeoip() []*router.GeoIP {
if x != nil { if x != nil {
return x.Geoip return x.ExpectedGeoip
} }
return nil return nil
} }
@@ -218,24 +226,63 @@ func (x *NameServer) GetQueryStrategy() QueryStrategy {
return QueryStrategy_USE_IP return QueryStrategy_USE_IP
} }
func (x *NameServer) GetActPrior() bool {
if x != nil {
return x.ActPrior
}
return false
}
func (x *NameServer) GetTag() string {
if x != nil {
return x.Tag
}
return ""
}
func (x *NameServer) GetTimeoutMs() uint64 {
if x != nil {
return x.TimeoutMs
}
return 0
}
func (x *NameServer) GetDisableCache() bool {
if x != nil {
return x.DisableCache
}
return false
}
func (x *NameServer) GetFinalQuery() bool {
if x != nil {
return x.FinalQuery
}
return false
}
func (x *NameServer) GetUnexpectedGeoip() []*router.GeoIP {
if x != nil {
return x.UnexpectedGeoip
}
return nil
}
func (x *NameServer) GetActUnprior() bool {
if x != nil {
return x.ActUnprior
}
return false
}
type Config struct { type Config struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// Nameservers used by this DNS. Only traditional UDP servers are support at
// the moment. A special value 'localhost' as a domain address can be set to
// use DNS on local system.
//
// Deprecated: Marked as deprecated in app/dns/config.proto.
NameServers []*net.Endpoint `protobuf:"bytes,1,rep,name=NameServers,proto3" json:"NameServers,omitempty"`
// NameServer list used by this DNS client. // NameServer list used by this DNS client.
// A special value 'localhost' as a domain address can be set to use DNS on local system.
NameServer []*NameServer `protobuf:"bytes,5,rep,name=name_server,json=nameServer,proto3" json:"name_server,omitempty"` NameServer []*NameServer `protobuf:"bytes,5,rep,name=name_server,json=nameServer,proto3" json:"name_server,omitempty"`
// Static hosts. Domain to IP.
// Deprecated. Use static_hosts.
//
// Deprecated: Marked as deprecated in app/dns/config.proto.
Hosts map[string]*net.IPOrDomain `protobuf:"bytes,2,rep,name=Hosts,proto3" json:"Hosts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes // Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes
// (IPv6). // (IPv6).
ClientIp []byte `protobuf:"bytes,3,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"` ClientIp []byte `protobuf:"bytes,3,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
@@ -251,11 +298,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_dns_config_proto_msgTypes[1]
mi := &file_app_dns_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -266,7 +311,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_config_proto_msgTypes[1] mi := &file_app_dns_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -281,14 +326,6 @@ func (*Config) Descriptor() ([]byte, []int) {
return file_app_dns_config_proto_rawDescGZIP(), []int{1} return file_app_dns_config_proto_rawDescGZIP(), []int{1}
} }
// Deprecated: Marked as deprecated in app/dns/config.proto.
func (x *Config) GetNameServers() []*net.Endpoint {
if x != nil {
return x.NameServers
}
return nil
}
func (x *Config) GetNameServer() []*NameServer { func (x *Config) GetNameServer() []*NameServer {
if x != nil { if x != nil {
return x.NameServer return x.NameServer
@@ -296,14 +333,6 @@ func (x *Config) GetNameServer() []*NameServer {
return nil return nil
} }
// Deprecated: Marked as deprecated in app/dns/config.proto.
func (x *Config) GetHosts() map[string]*net.IPOrDomain {
if x != nil {
return x.Hosts
}
return nil
}
func (x *Config) GetClientIp() []byte { func (x *Config) GetClientIp() []byte {
if x != nil { if x != nil {
return x.ClientIp return x.ClientIp
@@ -364,11 +393,9 @@ type NameServer_PriorityDomain struct {
func (x *NameServer_PriorityDomain) Reset() { func (x *NameServer_PriorityDomain) Reset() {
*x = NameServer_PriorityDomain{} *x = NameServer_PriorityDomain{}
if protoimpl.UnsafeEnabled { mi := &file_app_dns_config_proto_msgTypes[2]
mi := &file_app_dns_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *NameServer_PriorityDomain) String() string { func (x *NameServer_PriorityDomain) String() string {
@@ -379,7 +406,7 @@ func (*NameServer_PriorityDomain) ProtoMessage() {}
func (x *NameServer_PriorityDomain) ProtoReflect() protoreflect.Message { func (x *NameServer_PriorityDomain) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_config_proto_msgTypes[2] mi := &file_app_dns_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -419,11 +446,9 @@ type NameServer_OriginalRule struct {
func (x *NameServer_OriginalRule) Reset() { func (x *NameServer_OriginalRule) Reset() {
*x = NameServer_OriginalRule{} *x = NameServer_OriginalRule{}
if protoimpl.UnsafeEnabled { mi := &file_app_dns_config_proto_msgTypes[3]
mi := &file_app_dns_config_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *NameServer_OriginalRule) String() string { func (x *NameServer_OriginalRule) String() string {
@@ -434,7 +459,7 @@ func (*NameServer_OriginalRule) ProtoMessage() {}
func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message { func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_config_proto_msgTypes[3] mi := &file_app_dns_config_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -478,11 +503,9 @@ type Config_HostMapping struct {
func (x *Config_HostMapping) Reset() { func (x *Config_HostMapping) Reset() {
*x = Config_HostMapping{} *x = Config_HostMapping{}
if protoimpl.UnsafeEnabled { mi := &file_app_dns_config_proto_msgTypes[4]
mi := &file_app_dns_config_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config_HostMapping) String() string { func (x *Config_HostMapping) String() string {
@@ -492,8 +515,8 @@ func (x *Config_HostMapping) String() string {
func (*Config_HostMapping) ProtoMessage() {} func (*Config_HostMapping) ProtoMessage() {}
func (x *Config_HostMapping) ProtoReflect() protoreflect.Message { func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_config_proto_msgTypes[5] mi := &file_app_dns_config_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -505,7 +528,7 @@ func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
// Deprecated: Use Config_HostMapping.ProtoReflect.Descriptor instead. // Deprecated: Use Config_HostMapping.ProtoReflect.Descriptor instead.
func (*Config_HostMapping) Descriptor() ([]byte, []int) { func (*Config_HostMapping) Descriptor() ([]byte, []int) {
return file_app_dns_config_proto_rawDescGZIP(), []int{1, 1} return file_app_dns_config_proto_rawDescGZIP(), []int{1, 0}
} }
func (x *Config_HostMapping) GetType() DomainMatchingType { func (x *Config_HostMapping) GetType() DomainMatchingType {
@@ -541,107 +564,109 @@ var File_app_dns_config_proto protoreflect.FileDescriptor
var file_app_dns_config_proto_rawDesc = []byte{ var file_app_dns_config_proto_rawDesc = []byte{
0x0a, 0x14, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x14, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb6, 0x06, 0x0a, 0x0a,
0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb2, 0x04, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72,
0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12,
0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01,
0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x22, 0x0a, 0x0c,
0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01,
0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x12, 0x56, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f,
0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x56, 0x0a, 0x12, 0x70, 0x72, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78,
0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44,
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a,
0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3d, 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x65,
0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69,
0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e,
0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73,
0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e,
0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65,
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72,
0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x74,
0x67, 0x79, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x63, 0x74,
0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x09, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f,
0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73,
0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6e,
0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66,
0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x69, 0x6e, 0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x41, 0x0a, 0x10, 0x75, 0x6e, 0x65,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0xef, 0x05, 0x0a, 0x06, 0x43, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0d, 0x20,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3f, 0x0a, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0f, 0x75, 0x6e, 0x65,
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a,
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08,
0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x1a, 0x5e, 0x0a, 0x0e,
0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78,
0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61,
0x72, 0x12, 0x39, 0x0a, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c,
0x79, 0x42, 0x02, 0x18, 0x01, 0x52, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65,
0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04,
0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x9c, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x67, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a,
0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c,
0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63,
0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69,
0x61, 0x63, 0x68, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e,
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e,
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52,
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22,
0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08,
0x08, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63,
0x63, 0x6b, 0x12, 0x36, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x68, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61,
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
0x28, 0x08, 0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x55, 0x0a, 0x0a, 0x48, 0x6f, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x12, 0x36, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62,
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08,
0x01, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63,
0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73,
0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16,
0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03,
0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65,
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x45, 0x0a, 0x12, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08,
0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x07, 0x10, 0x08, 0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74,
0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c,
0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x78, 0x10, 0x03, 0x2a, 0x35, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12,
0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x42, 0x0a, 0x0d, 0x51, 0x75,
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55,
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49,
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10,
0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x10, 0x03, 0x42, 0x46,
0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64,
0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f,
0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41,
0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@@ -657,39 +682,35 @@ func file_app_dns_config_proto_rawDescGZIP() []byte {
} }
var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_app_dns_config_proto_goTypes = []interface{}{ var file_app_dns_config_proto_goTypes = []any{
(DomainMatchingType)(0), // 0: xray.app.dns.DomainMatchingType (DomainMatchingType)(0), // 0: xray.app.dns.DomainMatchingType
(QueryStrategy)(0), // 1: xray.app.dns.QueryStrategy (QueryStrategy)(0), // 1: xray.app.dns.QueryStrategy
(*NameServer)(nil), // 2: xray.app.dns.NameServer (*NameServer)(nil), // 2: xray.app.dns.NameServer
(*Config)(nil), // 3: xray.app.dns.Config (*Config)(nil), // 3: xray.app.dns.Config
(*NameServer_PriorityDomain)(nil), // 4: xray.app.dns.NameServer.PriorityDomain (*NameServer_PriorityDomain)(nil), // 4: xray.app.dns.NameServer.PriorityDomain
(*NameServer_OriginalRule)(nil), // 5: xray.app.dns.NameServer.OriginalRule (*NameServer_OriginalRule)(nil), // 5: xray.app.dns.NameServer.OriginalRule
nil, // 6: xray.app.dns.Config.HostsEntry (*Config_HostMapping)(nil), // 6: xray.app.dns.Config.HostMapping
(*Config_HostMapping)(nil), // 7: xray.app.dns.Config.HostMapping (*net.Endpoint)(nil), // 7: xray.common.net.Endpoint
(*net.Endpoint)(nil), // 8: xray.common.net.Endpoint (*router.GeoIP)(nil), // 8: xray.app.router.GeoIP
(*router.GeoIP)(nil), // 9: xray.app.router.GeoIP
(*net.IPOrDomain)(nil), // 10: xray.common.net.IPOrDomain
} }
var file_app_dns_config_proto_depIdxs = []int32{ var file_app_dns_config_proto_depIdxs = []int32{
8, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint 7, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
4, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain 4, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain
9, // 2: xray.app.dns.NameServer.geoip:type_name -> xray.app.router.GeoIP 8, // 2: xray.app.dns.NameServer.expected_geoip:type_name -> xray.app.router.GeoIP
5, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule 5, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
1, // 4: xray.app.dns.NameServer.query_strategy:type_name -> xray.app.dns.QueryStrategy 1, // 4: xray.app.dns.NameServer.query_strategy:type_name -> xray.app.dns.QueryStrategy
8, // 5: xray.app.dns.Config.NameServers:type_name -> xray.common.net.Endpoint 8, // 5: xray.app.dns.NameServer.unexpected_geoip:type_name -> xray.app.router.GeoIP
2, // 6: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer 2, // 6: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
6, // 7: xray.app.dns.Config.Hosts:type_name -> xray.app.dns.Config.HostsEntry 6, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
7, // 8: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping 1, // 8: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
1, // 9: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy 0, // 9: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
0, // 10: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType 0, // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
10, // 11: xray.app.dns.Config.HostsEntry.value:type_name -> xray.common.net.IPOrDomain 11, // [11:11] is the sub-list for method output_type
0, // 12: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType 11, // [11:11] is the sub-list for method input_type
13, // [13:13] is the sub-list for method output_type 11, // [11:11] is the sub-list for extension type_name
13, // [13:13] is the sub-list for method input_type 11, // [11:11] is the sub-list for extension extendee
13, // [13:13] is the sub-list for extension type_name 0, // [0:11] is the sub-list for field type_name
13, // [13:13] is the sub-list for extension extendee
0, // [0:13] is the sub-list for field type_name
} }
func init() { file_app_dns_config_proto_init() } func init() { file_app_dns_config_proto_init() }
@@ -697,75 +718,13 @@ func file_app_dns_config_proto_init() {
if File_app_dns_config_proto != nil { if File_app_dns_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_dns_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NameServer); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_dns_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_dns_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NameServer_PriorityDomain); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_dns_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NameServer_OriginalRule); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_dns_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config_HostMapping); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_dns_config_proto_rawDesc, RawDescriptor: file_app_dns_config_proto_rawDesc,
NumEnums: 2, NumEnums: 2,
NumMessages: 6, NumMessages: 5,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View File

@@ -6,7 +6,6 @@ option go_package = "github.com/xtls/xray-core/app/dns";
option java_package = "com.xray.app.dns"; option java_package = "com.xray.app.dns";
option java_multiple_files = true; option java_multiple_files = true;
import "common/net/address.proto";
import "common/net/destination.proto"; import "common/net/destination.proto";
import "app/router/config.proto"; import "app/router/config.proto";
@@ -26,9 +25,16 @@ message NameServer {
} }
repeated PriorityDomain prioritized_domain = 2; repeated PriorityDomain prioritized_domain = 2;
repeated xray.app.router.GeoIP geoip = 3; repeated xray.app.router.GeoIP expected_geoip = 3;
repeated OriginalRule original_rules = 4; repeated OriginalRule original_rules = 4;
QueryStrategy query_strategy = 7; QueryStrategy query_strategy = 7;
bool actPrior = 8;
string tag = 9;
uint64 timeoutMs = 10;
bool disableCache = 11;
bool finalQuery = 12;
repeated xray.app.router.GeoIP unexpected_geoip = 13;
bool actUnprior = 14;
} }
enum DomainMatchingType { enum DomainMatchingType {
@@ -42,21 +48,14 @@ enum QueryStrategy {
USE_IP = 0; USE_IP = 0;
USE_IP4 = 1; USE_IP4 = 1;
USE_IP6 = 2; USE_IP6 = 2;
USE_SYS = 3;
} }
message Config { message Config {
// Nameservers used by this DNS. Only traditional UDP servers are support at
// the moment. A special value 'localhost' as a domain address can be set to
// use DNS on local system.
repeated xray.common.net.Endpoint NameServers = 1 [deprecated = true];
// NameServer list used by this DNS client. // NameServer list used by this DNS client.
// A special value 'localhost' as a domain address can be set to use DNS on local system.
repeated NameServer name_server = 5; repeated NameServer name_server = 5;
// Static hosts. Domain to IP.
// Deprecated. Use static_hosts.
map<string, xray.common.net.IPOrDomain> Hosts = 2 [deprecated = true];
// Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes // Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes
// (IPv6). // (IPv6).
bytes client_ip = 3; bytes client_ip = 3;

View File

@@ -1,29 +1,25 @@
// Package dns is an implementation of core.DNS feature. // Package dns is an implementation of core.DNS feature.
package dns package dns
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"
go_errors "errors"
"fmt" "fmt"
"sort"
"strings" "strings"
"sync" "sync"
"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"
"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"
"github.com/xtls/xray-core/common/strmatcher" "github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/features"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )
// DNS is a DNS rely server. // DNS is a DNS rely server.
type DNS struct { type DNS struct {
sync.Mutex sync.Mutex
tag string
disableCache bool
disableFallback bool disableFallback bool
disableFallbackIfMatch bool disableFallbackIfMatch bool
ipOption *dns.IPOption ipOption *dns.IPOption
@@ -32,6 +28,7 @@ type DNS struct {
ctx context.Context ctx context.Context
domainMatcher strmatcher.IndexMatcher domainMatcher strmatcher.IndexMatcher
matcherInfos []*DomainMatcherInfo matcherInfos []*DomainMatcherInfo
checkSystem bool
} }
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher // DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
@@ -42,13 +39,6 @@ type DomainMatcherInfo struct {
// New creates a new DNS server with given configuration. // New creates a new DNS server with given configuration.
func New(ctx context.Context, config *Config) (*DNS, error) { func New(ctx context.Context, config *Config) (*DNS, error) {
var tag string
if len(config.Tag) > 0 {
tag = config.Tag
} else {
tag = generateRandomTag()
}
var clientIP net.IP var clientIP net.IP
switch len(config.ClientIp) { switch len(config.ClientIp) {
case 0, net.IPv4len, net.IPv6len: case 0, net.IPv4len, net.IPv6len:
@@ -57,35 +47,51 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
return nil, errors.New("unexpected client IP length ", len(config.ClientIp)) return nil, errors.New("unexpected client IP length ", len(config.ClientIp))
} }
var ipOption *dns.IPOption var ipOption dns.IPOption
checkSystem := false
switch config.QueryStrategy { switch config.QueryStrategy {
case QueryStrategy_USE_IP: case QueryStrategy_USE_IP:
ipOption = &dns.IPOption{ ipOption = dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
} }
case QueryStrategy_USE_SYS:
ipOption = dns.IPOption{
IPv4Enable: true,
IPv6Enable: true,
FakeEnable: false,
}
checkSystem = true
case QueryStrategy_USE_IP4: case QueryStrategy_USE_IP4:
ipOption = &dns.IPOption{ ipOption = dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: false, IPv6Enable: false,
FakeEnable: false, FakeEnable: false,
} }
case QueryStrategy_USE_IP6: case QueryStrategy_USE_IP6:
ipOption = &dns.IPOption{ ipOption = dns.IPOption{
IPv4Enable: false, IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
} }
default:
return nil, errors.New("unexpected query strategy ", config.QueryStrategy)
} }
hosts, err := NewStaticHosts(config.StaticHosts, config.Hosts) hosts, err := NewStaticHosts(config.StaticHosts)
if err != nil { if err != nil {
return nil, errors.New("failed to create hosts").Base(err) return nil, errors.New("failed to create hosts").Base(err)
} }
clients := []*Client{} var clients []*Client
domainRuleCount := 0 domainRuleCount := 0
var defaultTag = config.Tag
if len(config.Tag) == 0 {
defaultTag = generateRandomTag()
}
for _, ns := range config.NameServer { for _, ns := range config.NameServer {
domainRuleCount += len(ns.PrioritizedDomain) domainRuleCount += len(ns.PrioritizedDomain)
} }
@@ -93,16 +99,6 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
// MatcherInfos is ensured to cover the maximum index domainMatcher could return, where matcher's index starts from 1 // MatcherInfos is ensured to cover the maximum index domainMatcher could return, where matcher's index starts from 1
matcherInfos := make([]*DomainMatcherInfo, domainRuleCount+1) matcherInfos := make([]*DomainMatcherInfo, domainRuleCount+1)
domainMatcher := &strmatcher.MatcherGroup{} domainMatcher := &strmatcher.MatcherGroup{}
geoipContainer := router.GeoIPMatcherContainer{}
for _, endpoint := range config.NameServers {
features.PrintDeprecatedFeatureWarning("simple DNS server")
client, err := NewSimpleClient(ctx, endpoint, clientIP)
if err != nil {
return nil, errors.New("failed to create client").Base(err)
}
clients = append(clients, client)
}
for _, ns := range config.NameServer { for _, ns := range config.NameServer {
clientIdx := len(clients) clientIdx := len(clients)
@@ -120,7 +116,19 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
case net.IPv4len, net.IPv6len: case net.IPv4len, net.IPv6len:
myClientIP = net.IP(ns.ClientIp) myClientIP = net.IP(ns.ClientIp)
} }
client, err := NewClient(ctx, ns, myClientIP, geoipContainer, &matcherInfos, updateDomain)
disableCache := config.DisableCache || ns.DisableCache
var tag = defaultTag
if len(ns.Tag) > 0 {
tag = ns.Tag
}
clientIPOption := ResolveIpOptionOverride(ns.QueryStrategy, ipOption)
if !clientIPOption.IPv4Enable && !clientIPOption.IPv6Enable {
return nil, errors.New("no QueryStrategy available for ", ns.Address)
}
client, err := NewClient(ctx, ns, myClientIP, disableCache, tag, clientIPOption, &matcherInfos, updateDomain)
if err != nil { if err != nil {
return nil, errors.New("failed to create client").Base(err) return nil, errors.New("failed to create client").Base(err)
} }
@@ -129,20 +137,19 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
// If there is no DNS client in config, add a `localhost` DNS client // If there is no DNS client in config, add a `localhost` DNS client
if len(clients) == 0 { if len(clients) == 0 {
clients = append(clients, NewLocalDNSClient()) clients = append(clients, NewLocalDNSClient(ipOption))
} }
return &DNS{ return &DNS{
tag: tag,
hosts: hosts, hosts: hosts,
ipOption: ipOption, ipOption: &ipOption,
clients: clients, clients: clients,
ctx: ctx, ctx: ctx,
domainMatcher: domainMatcher, domainMatcher: domainMatcher,
matcherInfos: matcherInfos, matcherInfos: matcherInfos,
disableCache: config.DisableCache,
disableFallback: config.DisableFallback, disableFallback: config.DisableFallback,
disableFallbackIfMatch: config.DisableFallbackIfMatch, disableFallbackIfMatch: config.DisableFallbackIfMatch,
checkSystem: checkSystem,
}, nil }, nil
} }
@@ -164,94 +171,101 @@ func (s *DNS) Close() error {
// IsOwnLink implements proxy.dns.ownLinkVerifier // IsOwnLink implements proxy.dns.ownLinkVerifier
func (s *DNS) IsOwnLink(ctx context.Context) bool { func (s *DNS) IsOwnLink(ctx context.Context) bool {
inbound := session.InboundFromContext(ctx) inbound := session.InboundFromContext(ctx)
return inbound != nil && inbound.Tag == s.tag if inbound == nil {
return false
}
for _, client := range s.clients {
if client.tag == inbound.Tag {
return true
}
}
return false
} }
// LookupIP implements dns.Client. // LookupIP implements dns.Client.
func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) { func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
if domain == "" {
return nil, errors.New("empty domain name")
}
option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable
option.IPv6Enable = option.IPv6Enable && s.ipOption.IPv6Enable
if !option.IPv4Enable && !option.IPv6Enable {
return nil, dns.ErrEmptyResponse
}
// Normalize the FQDN form query // Normalize the FQDN form query
domain = strings.TrimSuffix(domain, ".") domain = strings.TrimSuffix(domain, ".")
if domain == "" {
return nil, 0, errors.New("empty domain name")
}
if s.checkSystem {
supportIPv4, supportIPv6 := checkSystemNetwork()
option.IPv4Enable = option.IPv4Enable && supportIPv4
option.IPv6Enable = option.IPv6Enable && supportIPv6
} else {
option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable
option.IPv6Enable = option.IPv6Enable && s.ipOption.IPv6Enable
}
if !option.IPv4Enable && !option.IPv6Enable {
return nil, 0, dns.ErrEmptyResponse
}
// Static host lookup // Static host lookup
switch addrs := s.hosts.Lookup(domain, option); { switch addrs, err := s.hosts.Lookup(domain, option); {
case err != nil:
if go_errors.Is(err, dns.ErrEmptyResponse) {
return nil, 0, dns.ErrEmptyResponse
}
return nil, 0, errors.New("returning nil for domain ", domain).Base(err)
case addrs == nil: // Domain not recorded in static host case addrs == nil: // Domain not recorded in static host
break break
case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled) case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled)
return nil, dns.ErrEmptyResponse return nil, 0, dns.ErrEmptyResponse
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement
errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].Domain()) errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].Domain())
domain = addrs[0].Domain() domain = addrs[0].Domain()
default: // Successfully found ip records in static host default: // Successfully found ip records in static host
errors.LogInfo(s.ctx, "returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs) errors.LogInfo(s.ctx, "returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs)
return toNetIP(addrs) ips, err := toNetIP(addrs)
if err != nil {
return nil, 0, err
}
return ips, 10, nil // Hosts ttl is 10
} }
// Name servers lookup // Name servers lookup
errs := []error{} var errs []error
ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag})
for _, client := range s.sortClients(domain) { for _, client := range s.sortClients(domain) {
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") { if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name()) errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
continue continue
} }
ips, err := client.QueryIP(ctx, domain, option, s.disableCache)
ips, ttl, err := client.QueryIP(s.ctx, domain, option)
if len(ips) > 0 { if len(ips) > 0 {
return ips, nil if ttl == 0 {
ttl = 1
}
return ips, ttl, nil
} }
if err != nil {
errors.LogInfoInner(s.ctx, err, "failed to lookup ip for domain ", domain, " at server ", client.Name()) errors.LogInfoInner(s.ctx, err, "failed to lookup ip for domain ", domain, " at server ", client.Name())
errs = append(errs, err) if err == nil {
err = dns.ErrEmptyResponse
} }
// 5 for RcodeRefused in miekg/dns, hardcode to reduce binary size errs = append(errs, err)
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch && err != dns.ErrEmptyResponse && dns.RCodeFromError(err) != 5 {
return nil, err if client.IsFinalQuery() {
break
} }
} }
return nil, errors.New("returning nil for domain ", domain).Base(errors.Combine(errs...)) if len(errs) > 0 {
} allErrs := errors.Combine(errs...)
err0 := errs[0]
// LookupHosts implements dns.HostsLookup. if errors.AllEqual(err0, allErrs) {
func (s *DNS) LookupHosts(domain string) *net.Address { if go_errors.Is(err0, dns.ErrEmptyResponse) {
domain = strings.TrimSuffix(domain, ".") return nil, 0, dns.ErrEmptyResponse
if domain == "" { }
return nil return nil, 0, errors.New("returning nil for domain ", domain).Base(err0)
}
return nil, 0, errors.New("returning nil for domain ", domain).Base(allErrs)
} }
// Normalize the FQDN form query return nil, 0, dns.ErrEmptyResponse
addrs := s.hosts.Lookup(domain, *s.ipOption)
if len(addrs) > 0 {
errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].String())
return &addrs[0]
}
return nil
}
// GetIPOption implements ClientWithIPOption.
func (s *DNS) GetIPOption() *dns.IPOption {
return s.ipOption
}
// SetQueryOption implements ClientWithIPOption.
func (s *DNS) SetQueryOption(isIPv4Enable, isIPv6Enable bool) {
s.ipOption.IPv4Enable = isIPv4Enable
s.ipOption.IPv6Enable = isIPv6Enable
}
// SetFakeDNSOption implements ClientWithIPOption.
func (s *DNS) SetFakeDNSOption(isFakeEnable bool) {
s.ipOption.FakeEnable = isFakeEnable
} }
func (s *DNS) sortClients(domain string) []*Client { func (s *DNS) sortClients(domain string) []*Client {
@@ -262,7 +276,11 @@ func (s *DNS) sortClients(domain string) []*Client {
// Priority domain matching // Priority domain matching
hasMatch := false hasMatch := false
for _, match := range s.domainMatcher.Match(domain) { MatchSlice := s.domainMatcher.Match(domain)
sort.Slice(MatchSlice, func(i, j int) bool {
return MatchSlice[i] < MatchSlice[j]
})
for _, match := range MatchSlice {
info := s.matcherInfos[match] info := s.matcherInfos[match]
client := s.clients[info.clientIdx] client := s.clients[info.clientIdx]
domainRule := client.domains[info.domainRuleIdx] domainRule := client.domains[info.domainRuleIdx]
@@ -309,3 +327,22 @@ func init() {
return New(ctx, config.(*Config)) return New(ctx, config.(*Config))
})) }))
} }
func checkSystemNetwork() (supportIPv4 bool, supportIPv6 bool) {
conn4, err4 := net.Dial("udp4", "8.8.8.8:53")
if err4 != nil {
supportIPv4 = false
} else {
supportIPv4 = true
conn4.Close()
}
conn6, err6 := net.Dial("udp6", "[2001:4860:4860::8888]:53")
if err6 != nil {
supportIPv6 = false
} else {
supportIPv6 = true
conn6.Close()
}
return
}

View File

@@ -76,6 +76,9 @@ func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
case q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA: case q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA:
ans.MsgHdr.Rcode = dns.RcodeNameError ans.MsgHdr.Rcode = dns.RcodeNameError
case q.Name == "notexist.google.com." && q.Qtype == dns.TypeA:
ans.MsgHdr.Rcode = dns.RcodeNameError
case q.Name == "hostname." && q.Qtype == dns.TypeA: case q.Name == "hostname." && q.Qtype == dns.TypeA:
rr, _ := dns.NewRR("hostname. IN A 127.0.0.1") rr, _ := dns.NewRR("hostname. IN A 127.0.0.1")
ans.Answer = append(ans.Answer, rr) ans.Answer = append(ans.Answer, rr)
@@ -117,22 +120,23 @@ func TestUDPServerSubnet(t *testing.T) {
Handler: &staticHandler{}, Handler: &staticHandler{},
UDPSize: 1200, UDPSize: 1200,
} }
go dnsServer.ListenAndServe() go dnsServer.ListenAndServe()
time.Sleep(time.Second) time.Sleep(time.Second)
config := &core.Config{ config := &core.Config{
App: []*serial.TypedMessage{ App: []*serial.TypedMessage{
serial.ToTypedMessage(&Config{ serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{ NameServer: []*NameServer{
{ {
Network: net.Network_UDP, Address: &net.Endpoint{
Address: &net.IPOrDomain{ Network: net.Network_UDP,
Address: &net.IPOrDomain_Ip{ Address: &net.IPOrDomain{
Ip: []byte{127, 0, 0, 1}, Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
}, },
Port: uint32(port),
}, },
Port: uint32(port),
}, },
}, },
ClientIp: []byte{7, 8, 9, 10}, ClientIp: []byte{7, 8, 9, 10},
@@ -153,7 +157,7 @@ func TestUDPServerSubnet(t *testing.T) {
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
ips, err := client.LookupIP("google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -183,15 +187,17 @@ func TestUDPServer(t *testing.T) {
config := &core.Config{ config := &core.Config{
App: []*serial.TypedMessage{ App: []*serial.TypedMessage{
serial.ToTypedMessage(&Config{ serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{ NameServer: []*NameServer{
{ {
Network: net.Network_UDP, Address: &net.Endpoint{
Address: &net.IPOrDomain{ Network: net.Network_UDP,
Address: &net.IPOrDomain_Ip{ Address: &net.IPOrDomain{
Ip: []byte{127, 0, 0, 1}, Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
}, },
Port: uint32(port),
}, },
Port: uint32(port),
}, },
}, },
}), }),
@@ -212,7 +218,7 @@ func TestUDPServer(t *testing.T) {
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
{ {
ips, err := client.LookupIP("google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -227,7 +233,7 @@ func TestUDPServer(t *testing.T) {
} }
{ {
ips, err := client.LookupIP("facebook.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("facebook.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -242,7 +248,7 @@ func TestUDPServer(t *testing.T) {
} }
{ {
_, err := client.LookupIP("notexist.google.com", feature_dns.IPOption{ _, _, err := client.LookupIP("notexist.google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -256,7 +262,7 @@ func TestUDPServer(t *testing.T) {
} }
{ {
ips, err := client.LookupIP("ipv4only.google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("ipv4only.google.com", feature_dns.IPOption{
IPv4Enable: false, IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -272,7 +278,7 @@ func TestUDPServer(t *testing.T) {
dnsServer.Shutdown() dnsServer.Shutdown()
{ {
ips, err := client.LookupIP("google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -303,18 +309,18 @@ func TestPrioritizedDomain(t *testing.T) {
config := &core.Config{ config := &core.Config{
App: []*serial.TypedMessage{ App: []*serial.TypedMessage{
serial.ToTypedMessage(&Config{ serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
NameServer: []*NameServer{ NameServer: []*NameServer{
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
{ {
Address: &net.Endpoint{ Address: &net.Endpoint{
Network: net.Network_UDP, Network: net.Network_UDP,
@@ -353,7 +359,7 @@ func TestPrioritizedDomain(t *testing.T) {
startTime := time.Now() startTime := time.Now()
{ {
ips, err := client.LookupIP("google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -389,15 +395,17 @@ func TestUDPServerIPv6(t *testing.T) {
config := &core.Config{ config := &core.Config{
App: []*serial.TypedMessage{ App: []*serial.TypedMessage{
serial.ToTypedMessage(&Config{ serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{ NameServer: []*NameServer{
{ {
Network: net.Network_UDP, Address: &net.Endpoint{
Address: &net.IPOrDomain{ Network: net.Network_UDP,
Address: &net.IPOrDomain_Ip{ Address: &net.IPOrDomain{
Ip: []byte{127, 0, 0, 1}, Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
}, },
Port: uint32(port),
}, },
Port: uint32(port),
}, },
}, },
}), }),
@@ -417,7 +425,7 @@ func TestUDPServerIPv6(t *testing.T) {
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
{ {
ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
IPv4Enable: false, IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -448,15 +456,17 @@ func TestStaticHostDomain(t *testing.T) {
config := &core.Config{ config := &core.Config{
App: []*serial.TypedMessage{ App: []*serial.TypedMessage{
serial.ToTypedMessage(&Config{ serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{ NameServer: []*NameServer{
{ {
Network: net.Network_UDP, Address: &net.Endpoint{
Address: &net.IPOrDomain{ Network: net.Network_UDP,
Address: &net.IPOrDomain_Ip{ Address: &net.IPOrDomain{
Ip: []byte{127, 0, 0, 1}, Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
}, },
Port: uint32(port),
}, },
Port: uint32(port),
}, },
}, },
StaticHosts: []*Config_HostMapping{ StaticHosts: []*Config_HostMapping{
@@ -484,7 +494,7 @@ func TestStaticHostDomain(t *testing.T) {
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client) client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
{ {
ips, err := client.LookupIP("example.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("example.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -529,7 +539,7 @@ func TestIPMatch(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
Geoip: []*router.GeoIP{ ExpectedGeoip: []*router.GeoIP{
{ {
CountryCode: "local", CountryCode: "local",
Cidr: []*router.CIDR{ Cidr: []*router.CIDR{
@@ -553,7 +563,7 @@ func TestIPMatch(t *testing.T) {
}, },
Port: uint32(port), Port: uint32(port),
}, },
Geoip: []*router.GeoIP{ ExpectedGeoip: []*router.GeoIP{
{ {
CountryCode: "test", CountryCode: "test",
Cidr: []*router.CIDR{ Cidr: []*router.CIDR{
@@ -595,7 +605,7 @@ func TestIPMatch(t *testing.T) {
startTime := time.Now() startTime := time.Now()
{ {
ips, err := client.LookupIP("google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -631,18 +641,18 @@ func TestLocalDomain(t *testing.T) {
config := &core.Config{ config := &core.Config{
App: []*serial.TypedMessage{ App: []*serial.TypedMessage{
serial.ToTypedMessage(&Config{ serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
NameServer: []*NameServer{ NameServer: []*NameServer{
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
{ {
Address: &net.Endpoint{ Address: &net.Endpoint{
Network: net.Network_UDP, Network: net.Network_UDP,
@@ -657,7 +667,7 @@ func TestLocalDomain(t *testing.T) {
// Equivalent of dotless:localhost // Equivalent of dotless:localhost
{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"}, {Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
}, },
Geoip: []*router.GeoIP{ ExpectedGeoip: []*router.GeoIP{
{ // Will match localhost, localhost-a and localhost-b, { // Will match localhost, localhost-a and localhost-b,
CountryCode: "local", CountryCode: "local",
Cidr: []*router.CIDR{ Cidr: []*router.CIDR{
@@ -718,7 +728,7 @@ func TestLocalDomain(t *testing.T) {
startTime := time.Now() startTime := time.Now()
{ // Will match dotless: { // Will match dotless:
ips, err := client.LookupIP("hostname", feature_dns.IPOption{ ips, _, err := client.LookupIP("hostname", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -733,7 +743,7 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match domain:local { // Will match domain:local
ips, err := client.LookupIP("hostname.local", feature_dns.IPOption{ ips, _, err := client.LookupIP("hostname.local", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -748,7 +758,7 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match static ip { // Will match static ip
ips, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{ ips, _, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -763,7 +773,7 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match domain replacing { // Will match domain replacing
ips, err := client.LookupIP("hostnamealias", feature_dns.IPOption{ ips, _, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -777,8 +787,8 @@ func TestLocalDomain(t *testing.T) {
} }
} }
{ // Will match dotless:localhost, but not expectIPs: 127.0.0.2, 127.0.0.3, then matches at dotless: { // Will match dotless:localhost, but not expectedIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
ips, err := client.LookupIP("localhost", feature_dns.IPOption{ ips, _, err := client.LookupIP("localhost", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -792,8 +802,8 @@ func TestLocalDomain(t *testing.T) {
} }
} }
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3 { // Will match dotless:localhost, and expectedIPs: 127.0.0.2, 127.0.0.3
ips, err := client.LookupIP("localhost-a", feature_dns.IPOption{ ips, _, err := client.LookupIP("localhost-a", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -807,8 +817,8 @@ func TestLocalDomain(t *testing.T) {
} }
} }
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3 { // Will match dotless:localhost, and expectedIPs: 127.0.0.2, 127.0.0.3
ips, err := client.LookupIP("localhost-b", feature_dns.IPOption{ ips, _, err := client.LookupIP("localhost-b", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -823,7 +833,7 @@ func TestLocalDomain(t *testing.T) {
} }
{ // Will match dotless: { // Will match dotless:
ips, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{ ips, _, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -859,18 +869,18 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
config := &core.Config{ config := &core.Config{
App: []*serial.TypedMessage{ App: []*serial.TypedMessage{
serial.ToTypedMessage(&Config{ serial.ToTypedMessage(&Config{
NameServers: []*net.Endpoint{
{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
NameServer: []*NameServer{ NameServer: []*NameServer{
{
Address: &net.Endpoint{
Network: net.Network_UDP,
Address: &net.IPOrDomain{
Address: &net.IPOrDomain_Ip{
Ip: []byte{127, 0, 0, 1},
},
},
Port: 9999, /* unreachable */
},
},
{ {
Address: &net.Endpoint{ Address: &net.Endpoint{
Network: net.Network_UDP, Network: net.Network_UDP,
@@ -887,7 +897,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
Domain: "google.com", Domain: "google.com",
}, },
}, },
Geoip: []*router.GeoIP{ ExpectedGeoip: []*router.GeoIP{
{ // Will only match 8.8.8.8 and 8.8.4.4 { // Will only match 8.8.8.8 and 8.8.4.4
Cidr: []*router.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 8, 8}, Prefix: 32}, {Ip: []byte{8, 8, 8, 8}, Prefix: 32},
@@ -912,7 +922,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
Domain: "google.com", Domain: "google.com",
}, },
}, },
Geoip: []*router.GeoIP{ ExpectedGeoip: []*router.GeoIP{
{ // Will match 8.8.8.8 and 8.8.8.7, etc { // Will match 8.8.8.8 and 8.8.8.7, etc
Cidr: []*router.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 8, 7}, Prefix: 24}, {Ip: []byte{8, 8, 8, 7}, Prefix: 24},
@@ -936,7 +946,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
Domain: "api.google.com", Domain: "api.google.com",
}, },
}, },
Geoip: []*router.GeoIP{ ExpectedGeoip: []*router.GeoIP{
{ // Will only match 8.8.7.7 (api.google.com) { // Will only match 8.8.7.7 (api.google.com)
Cidr: []*router.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 7, 7}, Prefix: 32}, {Ip: []byte{8, 8, 7, 7}, Prefix: 32},
@@ -960,7 +970,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
Domain: "v2.api.google.com", Domain: "v2.api.google.com",
}, },
}, },
Geoip: []*router.GeoIP{ ExpectedGeoip: []*router.GeoIP{
{ // Will only match 8.8.7.8 (v2.api.google.com) { // Will only match 8.8.7.8 (v2.api.google.com)
Cidr: []*router.CIDR{ Cidr: []*router.CIDR{
{Ip: []byte{8, 8, 7, 8}, Prefix: 32}, {Ip: []byte{8, 8, 7, 8}, Prefix: 32},
@@ -989,7 +999,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
startTime := time.Now() startTime := time.Now()
{ // Will match server 1,2 and server 1 returns expected ip { // Will match server 1,2 and server 1 returns expected ip
ips, err := client.LookupIP("google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -1004,7 +1014,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
} }
{ // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one { // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: false, IPv6Enable: false,
FakeEnable: false, FakeEnable: false,
@@ -1019,7 +1029,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
} }
{ // Will match server 3,1,2 and server 3 returns expected one { // Will match server 3,1,2 and server 3 returns expected one
ips, err := client.LookupIP("api.google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("api.google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
@@ -1034,7 +1044,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
} }
{ // Will match server 4,3,1,2 and server 4 returns expected one { // Will match server 4,3,1,2 and server 4 returns expected one
ips, err := client.LookupIP("v2.api.google.com", feature_dns.IPOption{ ips, _, err := client.LookupIP("v2.api.google.com", feature_dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,

View File

@@ -31,30 +31,31 @@ type record struct {
// IPRecord is a cacheable item for a resolved domain // IPRecord is a cacheable item for a resolved domain
type IPRecord struct { type IPRecord struct {
ReqID uint16 ReqID uint16
IP []net.Address IP []net.IP
Expire time.Time Expire time.Time
RCode dnsmessage.RCode RCode dnsmessage.RCode
RawHeader *dnsmessage.Header
} }
func (r *IPRecord) getIPs() ([]net.Address, error) { func (r *IPRecord) getIPs() ([]net.IP, uint32, error) {
if r == nil || r.Expire.Before(time.Now()) { if r == nil {
return nil, errRecordNotFound return nil, 0, errRecordNotFound
} }
untilExpire := time.Until(r.Expire)
if untilExpire <= 0 {
return nil, 0, errRecordNotFound
}
ttl := uint32(untilExpire/time.Second) + uint32(1)
if r.RCode != dnsmessage.RCodeSuccess { if r.RCode != dnsmessage.RCodeSuccess {
return nil, dns_feature.RCodeError(r.RCode) return nil, ttl, dns_feature.RCodeError(r.RCode)
}
if len(r.IP) == 0 {
return nil, ttl, dns_feature.ErrEmptyResponse
} }
return r.IP, nil
}
func isNewer(baseRec *IPRecord, newRec *IPRecord) bool { return r.IP, ttl, nil
if newRec == nil {
return false
}
if baseRec == nil {
return true
}
return baseRec.Expire.Before(newRec.Expire)
} }
var errRecordNotFound = errors.New("record not found") var errRecordNotFound = errors.New("record not found")
@@ -67,49 +68,59 @@ type dnsRequest struct {
msg *dnsmessage.Message msg *dnsmessage.Message
} }
func genEDNS0Options(clientIP net.IP) *dnsmessage.Resource { func genEDNS0Options(clientIP net.IP, padding int) *dnsmessage.Resource {
if len(clientIP) == 0 { if len(clientIP) == 0 && padding == 0 {
return nil return nil
} }
var netmask int const EDNS0SUBNET = 0x8
var family uint16 const EDNS0PADDING = 0xc
if len(clientIP) == 4 {
family = 1
netmask = 24 // 24 for IPV4, 96 for IPv6
} else {
family = 2
netmask = 96
}
b := make([]byte, 4)
binary.BigEndian.PutUint16(b[0:], family)
b[2] = byte(netmask)
b[3] = 0
switch family {
case 1:
ip := clientIP.To4().Mask(net.CIDRMask(netmask, net.IPv4len*8))
needLength := (netmask + 8 - 1) / 8 // division rounding up
b = append(b, ip[:needLength]...)
case 2:
ip := clientIP.Mask(net.CIDRMask(netmask, net.IPv6len*8))
needLength := (netmask + 8 - 1) / 8 // division rounding up
b = append(b, ip[:needLength]...)
}
const EDNS0SUBNET = 0x08
opt := new(dnsmessage.Resource) opt := new(dnsmessage.Resource)
common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true)) common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true))
body := dnsmessage.OPTResource{}
opt.Body = &body
opt.Body = &dnsmessage.OPTResource{ if len(clientIP) != 0 {
Options: []dnsmessage.Option{ var netmask int
{ var family uint16
if len(clientIP) == 4 {
family = 1
netmask = 24 // 24 for IPV4, 96 for IPv6
} else {
family = 2
netmask = 96
}
b := make([]byte, 4)
binary.BigEndian.PutUint16(b[0:], family)
b[2] = byte(netmask)
b[3] = 0
switch family {
case 1:
ip := clientIP.To4().Mask(net.CIDRMask(netmask, net.IPv4len*8))
needLength := (netmask + 8 - 1) / 8 // division rounding up
b = append(b, ip[:needLength]...)
case 2:
ip := clientIP.Mask(net.CIDRMask(netmask, net.IPv6len*8))
needLength := (netmask + 8 - 1) / 8 // division rounding up
b = append(b, ip[:needLength]...)
}
body.Options = append(body.Options,
dnsmessage.Option{
Code: EDNS0SUBNET, Code: EDNS0SUBNET,
Data: b, Data: b,
}, })
}, }
if padding != 0 {
body.Options = append(body.Options,
dnsmessage.Option{
Code: EDNS0PADDING,
Data: make([]byte, padding),
})
} }
return opt return opt
@@ -179,9 +190,10 @@ func parseResponse(payload []byte) (*IPRecord, error) {
now := time.Now() now := time.Now()
ipRecord := &IPRecord{ ipRecord := &IPRecord{
ReqID: h.ID, ReqID: h.ID,
RCode: h.RCode, RCode: h.RCode,
Expire: now.Add(time.Second * 600), Expire: now.Add(time.Second * dns_feature.DefaultTTL),
RawHeader: &h,
} }
L: L:
@@ -196,7 +208,7 @@ L:
ttl := ah.TTL ttl := ah.TTL
if ttl == 0 { if ttl == 0 {
ttl = 600 ttl = 1
} }
expire := now.Add(time.Duration(ttl) * time.Second) expire := now.Add(time.Duration(ttl) * time.Second)
if ipRecord.Expire.After(expire) { if ipRecord.Expire.After(expire) {
@@ -210,14 +222,17 @@ L:
errors.LogInfoInner(context.Background(), err, "failed to parse A record for domain: ", ah.Name) errors.LogInfoInner(context.Background(), err, "failed to parse A record for domain: ", ah.Name)
break L break L
} }
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.A[:])) ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.A[:]).IP())
case dnsmessage.TypeAAAA: case dnsmessage.TypeAAAA:
ans, err := parser.AAAAResource() ans, err := parser.AAAAResource()
if err != nil { if err != nil {
errors.LogInfoInner(context.Background(), err, "failed to parse AAAA record for domain: ", ah.Name) errors.LogInfoInner(context.Background(), err, "failed to parse AAAA record for domain: ", ah.Name)
break L break L
} }
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.AAAA[:])) newIP := net.IPAddress(ans.AAAA[:]).IP()
if len(newIP) == net.IPv6len {
ipRecord.IP = append(ipRecord.IP, newIP)
}
default: default:
if err := parser.SkipAnswer(); err != nil { if err := parser.SkipAnswer(); err != nil {
errors.LogInfoInner(context.Background(), err, "failed to skip answer") errors.LogInfoInner(context.Background(), err, "failed to skip answer")

View File

@@ -51,7 +51,7 @@ func Test_parseResponse(t *testing.T) {
}{ }{
{ {
"empty", "empty",
&IPRecord{0, []net.Address(nil), time.Time{}, dnsmessage.RCodeSuccess}, &IPRecord{0, []net.IP(nil), time.Time{}, dnsmessage.RCodeSuccess, nil},
false, false,
}, },
{ {
@@ -63,15 +63,16 @@ func Test_parseResponse(t *testing.T) {
"a record", "a record",
&IPRecord{ &IPRecord{
1, 1,
[]net.Address{net.ParseAddress("8.8.8.8"), net.ParseAddress("8.8.4.4")}, []net.IP{net.ParseIP("8.8.8.8"), net.ParseIP("8.8.4.4")},
time.Time{}, time.Time{},
dnsmessage.RCodeSuccess, dnsmessage.RCodeSuccess,
nil,
}, },
false, false,
}, },
{ {
"aaaa record", "aaaa record",
&IPRecord{2, []net.Address{net.ParseAddress("2001::123:8888"), net.ParseAddress("2001::123:8844")}, time.Time{}, dnsmessage.RCodeSuccess}, &IPRecord{2, []net.IP{net.ParseIP("2001::123:8888"), net.ParseIP("2001::123:8844")}, time.Time{}, dnsmessage.RCodeSuccess, nil},
false, false,
}, },
} }
@@ -84,11 +85,12 @@ func Test_parseResponse(t *testing.T) {
} }
if got != nil { if got != nil {
// reset the time // reset the time and RawHeader
got.Expire = time.Time{} got.Expire = time.Time{}
got.RawHeader = nil
} }
if cmp.Diff(got, tt.want) != "" { if cmp.Diff(got, tt.want) != "" {
t.Errorf(cmp.Diff(got, tt.want)) t.Error(cmp.Diff(got, tt.want))
// t.Errorf("handleResponse() = %#v, want %#v", got, tt.want) // t.Errorf("handleResponse() = %#v, want %#v", got, tt.want)
} }
}) })
@@ -154,7 +156,7 @@ func Test_genEDNS0Options(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := genEDNS0Options(tt.args.clientIP); got == nil { if got := genEDNS0Options(tt.args.clientIP, 0); got == nil {
t.Errorf("genEDNS0Options() = %v, want %v", got, tt.want) t.Errorf("genEDNS0Options() = %v, want %v", got, tt.want)
} }
}) })

View File

@@ -1,3 +1 @@
package fakedns package fakedns
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/dns/fakedns/fakedns.proto // source: app/dns/fakedns/fakedns.proto
package fakedns package fakedns
@@ -31,11 +31,9 @@ type FakeDnsPool struct {
func (x *FakeDnsPool) Reset() { func (x *FakeDnsPool) Reset() {
*x = FakeDnsPool{} *x = FakeDnsPool{}
if protoimpl.UnsafeEnabled { mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[0]
mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *FakeDnsPool) String() string { func (x *FakeDnsPool) String() string {
@@ -46,7 +44,7 @@ func (*FakeDnsPool) ProtoMessage() {}
func (x *FakeDnsPool) ProtoReflect() protoreflect.Message { func (x *FakeDnsPool) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[0] mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -85,11 +83,9 @@ type FakeDnsPoolMulti struct {
func (x *FakeDnsPoolMulti) Reset() { func (x *FakeDnsPoolMulti) Reset() {
*x = FakeDnsPoolMulti{} *x = FakeDnsPoolMulti{}
if protoimpl.UnsafeEnabled { mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[1]
mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *FakeDnsPoolMulti) String() string { func (x *FakeDnsPoolMulti) String() string {
@@ -100,7 +96,7 @@ func (*FakeDnsPoolMulti) ProtoMessage() {}
func (x *FakeDnsPoolMulti) ProtoReflect() protoreflect.Message { func (x *FakeDnsPoolMulti) ProtoReflect() protoreflect.Message {
mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[1] mi := &file_app_dns_fakedns_fakedns_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -159,7 +155,7 @@ func file_app_dns_fakedns_fakedns_proto_rawDescGZIP() []byte {
} }
var file_app_dns_fakedns_fakedns_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_app_dns_fakedns_fakedns_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_app_dns_fakedns_fakedns_proto_goTypes = []interface{}{ var file_app_dns_fakedns_fakedns_proto_goTypes = []any{
(*FakeDnsPool)(nil), // 0: xray.app.dns.fakedns.FakeDnsPool (*FakeDnsPool)(nil), // 0: xray.app.dns.fakedns.FakeDnsPool
(*FakeDnsPoolMulti)(nil), // 1: xray.app.dns.fakedns.FakeDnsPoolMulti (*FakeDnsPoolMulti)(nil), // 1: xray.app.dns.fakedns.FakeDnsPoolMulti
} }
@@ -177,32 +173,6 @@ func file_app_dns_fakedns_fakedns_proto_init() {
if File_app_dns_fakedns_fakedns_proto != nil { if File_app_dns_fakedns_fakedns_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_dns_fakedns_fakedns_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*FakeDnsPool); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_dns_fakedns_fakedns_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*FakeDnsPoolMulti); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -2,12 +2,11 @@ package dns
import ( import (
"context" "context"
"strconv"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors" "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/strmatcher" "github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/features"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )
@@ -18,30 +17,13 @@ type StaticHosts struct {
} }
// NewStaticHosts creates a new StaticHosts instance. // NewStaticHosts creates a new StaticHosts instance.
func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDomain) (*StaticHosts, error) { func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
g := new(strmatcher.MatcherGroup) g := new(strmatcher.MatcherGroup)
sh := &StaticHosts{ sh := &StaticHosts{
ips: make([][]net.Address, len(hosts)+len(legacy)+16), ips: make([][]net.Address, len(hosts)+16),
matchers: g, matchers: g,
} }
if legacy != nil {
features.PrintDeprecatedFeatureWarning("simple host mapping")
for domain, ip := range legacy {
matcher, err := strmatcher.Full.New(domain)
common.Must(err)
id := g.Add(matcher)
address := ip.AsAddress()
if address.Family().IsDomain() {
return nil, errors.New("invalid domain address in static hosts: ", address.Domain()).AtWarning()
}
sh.ips[id] = []net.Address{address}
}
}
for _, mapping := range hosts { for _, mapping := range hosts {
matcher, err := toStrMatcher(mapping.Type, mapping.Domain) matcher, err := toStrMatcher(mapping.Type, mapping.Domain)
if err != nil { if err != nil {
@@ -51,7 +33,15 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
ips := make([]net.Address, 0, len(mapping.Ip)+1) ips := make([]net.Address, 0, len(mapping.Ip)+1)
switch { switch {
case len(mapping.ProxiedDomain) > 0: case len(mapping.ProxiedDomain) > 0:
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain)) if mapping.ProxiedDomain[0] == '#' {
rcode, err := strconv.Atoi(mapping.ProxiedDomain[1:])
if err != nil {
return nil, err
}
ips = append(ips, dns.RCodeError(rcode))
} else {
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
}
case len(mapping.Ip) > 0: case len(mapping.Ip) > 0:
for _, ip := range mapping.Ip { for _, ip := range mapping.Ip {
addr := net.IPAddress(ip) addr := net.IPAddress(ip)
@@ -60,8 +50,6 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
} }
ips = append(ips, addr) ips = append(ips, addr)
} }
default:
return nil, errors.New("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning()
} }
sh.ips[id] = ips sh.ips[id] = ips
@@ -80,33 +68,51 @@ func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
return filtered return filtered
} }
func (h *StaticHosts) lookupInternal(domain string) []net.Address { func (h *StaticHosts) lookupInternal(domain string) ([]net.Address, error) {
var ips []net.Address ips := make([]net.Address, 0)
found := false
for _, id := range h.matchers.Match(domain) { for _, id := range h.matchers.Match(domain) {
for _, v := range h.ips[id] {
if err, ok := v.(dns.RCodeError); ok {
if uint16(err) == 0 {
return nil, dns.ErrEmptyResponse
}
return nil, err
}
}
ips = append(ips, h.ips[id]...) ips = append(ips, h.ips[id]...)
found = true
} }
return ips if !found {
return nil, nil
}
return ips, nil
} }
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) []net.Address { func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) ([]net.Address, error) {
switch addrs := h.lookupInternal(domain); { switch addrs, err := h.lookupInternal(domain); {
case err != nil:
return nil, err
case len(addrs) == 0: // Not recorded in static hosts, return nil case len(addrs) == 0: // Not recorded in static hosts, return nil
return nil return addrs, nil
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain
errors.LogDebug(context.Background(), "found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it") errors.LogDebug(context.Background(), "found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it")
if maxDepth > 0 { if maxDepth > 0 {
unwrapped := h.lookup(addrs[0].Domain(), option, maxDepth-1) unwrapped, err := h.lookup(addrs[0].Domain(), option, maxDepth-1)
if err != nil {
return nil, err
}
if unwrapped != nil { if unwrapped != nil {
return unwrapped return unwrapped, nil
} }
} }
return addrs return addrs, nil
default: // IP record found, return a non-nil IP array default: // IP record found, return a non-nil IP array
return filterIP(addrs, option) return filterIP(addrs, option), nil
} }
} }
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts. // Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) []net.Address { func (h *StaticHosts) Lookup(domain string, option dns.IPOption) ([]net.Address, error) {
return h.lookup(domain, option, 5) return h.lookup(domain, option, 5)
} }

View File

@@ -12,6 +12,11 @@ import (
func TestStaticHosts(t *testing.T) { func TestStaticHosts(t *testing.T) {
pb := []*Config_HostMapping{ pb := []*Config_HostMapping{
{
Type: DomainMatchingType_Subdomain,
Domain: "lan",
ProxiedDomain: "#3",
},
{ {
Type: DomainMatchingType_Full, Type: DomainMatchingType_Full,
Domain: "example.com", Domain: "example.com",
@@ -50,11 +55,18 @@ func TestStaticHosts(t *testing.T) {
}, },
} }
hosts, err := NewStaticHosts(pb, nil) hosts, err := NewStaticHosts(pb)
common.Must(err) common.Must(err)
{ {
ips := hosts.Lookup("example.com", dns.IPOption{ _, err := hosts.Lookup("example.com.lan", dns.IPOption{})
if dns.RCodeFromError(err) != 3 {
t.Error(err)
}
}
{
ips, _ := hosts.Lookup("example.com", dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}) })
@@ -67,7 +79,7 @@ func TestStaticHosts(t *testing.T) {
} }
{ {
domain := hosts.Lookup("proxy.xray.com", dns.IPOption{ domain, _ := hosts.Lookup("proxy.xray.com", dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: false, IPv6Enable: false,
}) })
@@ -80,7 +92,7 @@ func TestStaticHosts(t *testing.T) {
} }
{ {
domain := hosts.Lookup("proxy2.xray.com", dns.IPOption{ domain, _ := hosts.Lookup("proxy2.xray.com", dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: false, IPv6Enable: false,
}) })
@@ -93,7 +105,7 @@ func TestStaticHosts(t *testing.T) {
} }
{ {
ips := hosts.Lookup("www.example.cn", dns.IPOption{ ips, _ := hosts.Lookup("www.example.cn", dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}) })
@@ -106,7 +118,7 @@ func TestStaticHosts(t *testing.T) {
} }
{ {
ips := hosts.Lookup("baidu.com", dns.IPOption{ ips, _ := hosts.Lookup("baidu.com", dns.IPOption{
IPv4Enable: false, IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
}) })

View File

@@ -9,6 +9,7 @@ import (
"github.com/xtls/xray-core/app/router" "github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common/errors" "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/session"
"github.com/xtls/xray-core/common/strmatcher" "github.com/xtls/xray-core/common/strmatcher"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
@@ -20,22 +21,27 @@ type Server interface {
// Name of the Client. // Name of the Client.
Name() string Name() string
// QueryIP sends IP queries to its configured server. // QueryIP sends IP queries to its configured server.
QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns.IPOption, disableCache bool) ([]net.IP, error) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error)
} }
// Client is the interface for DNS client. // Client is the interface for DNS client.
type Client struct { type Client struct {
server Server server Server
clientIP net.IP skipFallback bool
skipFallback bool domains []string
domains []string expectedIPs []*router.GeoIPMatcher
expectIPs []*router.GeoIPMatcher unexpectedIPs []*router.GeoIPMatcher
actPrior bool
actUnprior bool
tag string
timeoutMs time.Duration
finalQuery bool
ipOption *dns.IPOption
checkSystem bool
} }
var errExpectedIPNonMatch = errors.New("expectIPs not match")
// NewServer creates a name server object according to the network destination url. // NewServer creates a name server object according to the network destination url.
func NewServer(dest net.Destination, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (Server, error) { func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dispatcher, disableCache bool, clientIP net.IP) (Server, error) {
if address := dest.Address; address.Family().IsDomain() { if address := dest.Address; address.Family().IsDomain() {
u, err := url.Parse(address.Domain()) u, err := url.Parse(address.Domain())
if err != nil { if err != nil {
@@ -44,25 +50,36 @@ func NewServer(dest net.Destination, dispatcher routing.Dispatcher, queryStrateg
switch { switch {
case strings.EqualFold(u.String(), "localhost"): case strings.EqualFold(u.String(), "localhost"):
return NewLocalNameServer(), nil return NewLocalNameServer(), nil
case strings.EqualFold(u.Scheme, "https"): // DOH Remote mode case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode
return NewDoHNameServer(u, dispatcher, queryStrategy) return NewDoHNameServer(u, dispatcher, false, disableCache, clientIP), nil
case strings.EqualFold(u.Scheme, "https+local"): // DOH Local mode case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode
return NewDoHLocalNameServer(u, queryStrategy), nil return NewDoHNameServer(u, dispatcher, true, disableCache, clientIP), nil
case strings.EqualFold(u.Scheme, "https+local"): // DNS-over-HTTPS Local mode
return NewDoHNameServer(u, nil, false, disableCache, clientIP), nil
case strings.EqualFold(u.Scheme, "h2c+local"): // DNS-over-HTTPS h2c Local mode
return NewDoHNameServer(u, nil, true, disableCache, clientIP), nil
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
return NewQUICNameServer(u, queryStrategy) return NewQUICNameServer(u, disableCache, clientIP)
case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
return NewTCPNameServer(u, dispatcher, queryStrategy) return NewTCPNameServer(u, dispatcher, disableCache, clientIP)
case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
return NewTCPLocalNameServer(u, queryStrategy) return NewTCPLocalNameServer(u, disableCache, clientIP)
case strings.EqualFold(u.String(), "fakedns"): case strings.EqualFold(u.String(), "fakedns"):
return NewFakeDNSServer(), nil var fd dns.FakeDNSEngine
err = core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
fd = fdns
})
if err != nil {
return nil, err
}
return NewFakeDNSServer(fd), nil
} }
} }
if dest.Network == net.Network_Unknown { if dest.Network == net.Network_Unknown {
dest.Network = net.Network_UDP dest.Network = net.Network_UDP
} }
if dest.Network == net.Network_UDP { // UDP classic DNS mode if dest.Network == net.Network_UDP { // UDP classic DNS mode
return NewClassicNameServer(dest, dispatcher), nil return NewClassicNameServer(dest, dispatcher, disableCache, clientIP), nil
} }
return nil, errors.New("No available name server could be created from ", dest).AtWarning() return nil, errors.New("No available name server could be created from ", dest).AtWarning()
} }
@@ -72,7 +89,9 @@ func NewClient(
ctx context.Context, ctx context.Context,
ns *NameServer, ns *NameServer,
clientIP net.IP, clientIP net.IP,
container router.GeoIPMatcherContainer, disableCache bool,
tag string,
ipOption dns.IPOption,
matcherInfos *[]*DomainMatcherInfo, matcherInfos *[]*DomainMatcherInfo,
updateDomainRule func(strmatcher.Matcher, int, []*DomainMatcherInfo) error, updateDomainRule func(strmatcher.Matcher, int, []*DomainMatcherInfo) error,
) (*Client, error) { ) (*Client, error) {
@@ -80,7 +99,7 @@ func NewClient(
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
// Create a new server for each client for now // Create a new server for each client for now
server, err := NewServer(ns.Address.AsDestination(), dispatcher, ns.GetQueryStrategy()) server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, clientIP)
if err != nil { if err != nil {
return errors.New("failed to create nameserver").Base(err).AtWarning() return errors.New("failed to create nameserver").Base(err).AtWarning()
} }
@@ -90,7 +109,7 @@ func NewClient(
ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...) ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...)
ns.OriginalRules = append(ns.OriginalRules, localTLDsAndDotlessDomainsRule) ns.OriginalRules = append(ns.OriginalRules, localTLDsAndDotlessDomainsRule)
// The following lines is a solution to avoid core panicsrule index out of range when setting `localhost` DNS client in config. // The following lines is a solution to avoid core panicsrule index out of range when setting `localhost` DNS client in config.
// Because the `localhost` DNS client will apend len(localTLDsAndDotlessDomains) rules into matcherInfos to match `geosite:private` default rule. // Because the `localhost` DNS client will append len(localTLDsAndDotlessDomains) rules into matcherInfos to match `geosite:private` default rule.
// But `matcherInfos` has no enough length to add rules, which leads to core panics (rule index out of range). // But `matcherInfos` has no enough length to add rules, which leads to core panics (rule index out of range).
// To avoid this, the length of `matcherInfos` must be equal to the expected, so manually append it with Golang default zero value first for later modification. // To avoid this, the length of `matcherInfos` must be equal to the expected, so manually append it with Golang default zero value first for later modification.
// Related issues: // Related issues:
@@ -135,13 +154,23 @@ func NewClient(
} }
// Establish expected IPs // Establish expected IPs
var matchers []*router.GeoIPMatcher var expectedMatchers []*router.GeoIPMatcher
for _, geoip := range ns.Geoip { for _, geoip := range ns.ExpectedGeoip {
matcher, err := container.Add(geoip) matcher, err := router.GlobalGeoIPContainer.Add(geoip)
if err != nil { if err != nil {
return errors.New("failed to create ip matcher").Base(err).AtWarning() return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
} }
matchers = append(matchers, matcher) expectedMatchers = append(expectedMatchers, matcher)
}
// Establish unexpected IPs
var unexpectedMatchers []*router.GeoIPMatcher
for _, geoip := range ns.UnexpectedGeoip {
matcher, err := router.GlobalGeoIPContainer.Add(geoip)
if err != nil {
return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
}
unexpectedMatchers = append(unexpectedMatchers, matcher)
} }
if len(clientIP) > 0 { if len(clientIP) > 0 {
@@ -149,87 +178,112 @@ func NewClient(
case *net.IPOrDomain_Domain: case *net.IPOrDomain_Domain:
errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String()) errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String())
case *net.IPOrDomain_Ip: case *net.IPOrDomain_Ip:
errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetIp(), " uses clientIP ", clientIP.String()) errors.LogInfo(ctx, "DNS: client ", net.IP(ns.Address.Address.GetIp()), " uses clientIP ", clientIP.String())
} }
} }
var timeoutMs = 4000 * time.Millisecond
if ns.TimeoutMs > 0 {
timeoutMs = time.Duration(ns.TimeoutMs) * time.Millisecond
}
checkSystem := ns.QueryStrategy == QueryStrategy_USE_SYS
client.server = server client.server = server
client.clientIP = clientIP
client.skipFallback = ns.SkipFallback client.skipFallback = ns.SkipFallback
client.domains = rules client.domains = rules
client.expectIPs = matchers client.expectedIPs = expectedMatchers
client.unexpectedIPs = unexpectedMatchers
client.actPrior = ns.ActPrior
client.actUnprior = ns.ActUnprior
client.tag = tag
client.timeoutMs = timeoutMs
client.finalQuery = ns.FinalQuery
client.ipOption = &ipOption
client.checkSystem = checkSystem
return nil return nil
}) })
return client, err return client, err
} }
// NewSimpleClient creates a DNS client with a simple destination.
func NewSimpleClient(ctx context.Context, endpoint *net.Endpoint, clientIP net.IP) (*Client, error) {
client := &Client{}
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
server, err := NewServer(endpoint.AsDestination(), dispatcher, QueryStrategy_USE_IP)
if err != nil {
return errors.New("failed to create nameserver").Base(err).AtWarning()
}
client.server = server
client.clientIP = clientIP
return nil
})
if len(clientIP) > 0 {
switch endpoint.Address.GetAddress().(type) {
case *net.IPOrDomain_Domain:
errors.LogInfo(ctx, "DNS: client ", endpoint.Address.GetDomain(), " uses clientIP ", clientIP.String())
case *net.IPOrDomain_Ip:
errors.LogInfo(ctx, "DNS: client ", endpoint.Address.GetIp(), " uses clientIP ", clientIP.String())
}
}
return client, err
}
// Name returns the server name the client manages. // Name returns the server name the client manages.
func (c *Client) Name() string { func (c *Client) Name() string {
return c.server.Name() return c.server.Name()
} }
func (c *Client) IsFinalQuery() bool {
return c.finalQuery
}
// QueryIP sends DNS query to the name server with the client's IP. // QueryIP sends DNS query to the name server with the client's IP.
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, disableCache bool) ([]net.IP, error) { func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) {
ctx, cancel := context.WithTimeout(ctx, 4*time.Second) if c.checkSystem {
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, disableCache) supportIPv4, supportIPv6 := checkSystemNetwork()
option.IPv4Enable = option.IPv4Enable && supportIPv4
option.IPv6Enable = option.IPv6Enable && supportIPv6
} else {
option.IPv4Enable = option.IPv4Enable && c.ipOption.IPv4Enable
option.IPv6Enable = option.IPv6Enable && c.ipOption.IPv6Enable
}
if !option.IPv4Enable && !option.IPv6Enable {
return nil, 0, dns.ErrEmptyResponse
}
ctx, cancel := context.WithTimeout(ctx, c.timeoutMs)
ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: c.tag})
ips, ttl, err := c.server.QueryIP(ctx, domain, option)
cancel() cancel()
if err != nil { if err != nil {
return ips, err return nil, 0, err
} }
return c.MatchExpectedIPs(domain, ips)
}
// MatchExpectedIPs matches queried domain IPs with expected IPs and returns matched ones. if len(ips) == 0 {
func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) ([]net.IP, error) { return nil, 0, dns.ErrEmptyResponse
if len(c.expectIPs) == 0 {
return ips, nil
} }
newIps := []net.IP{}
for _, ip := range ips { if len(c.expectedIPs) > 0 && !c.actPrior {
for _, matcher := range c.expectIPs { ips = router.MatchIPs(c.expectedIPs, ips, false)
if matcher.Match(ip) { errors.LogDebug(context.Background(), "domain ", domain, " expectedIPs ", ips, " matched at server ", c.Name())
newIps = append(newIps, ip) if len(ips) == 0 {
break return nil, 0, dns.ErrEmptyResponse
}
} }
} }
if len(newIps) == 0 {
return nil, errExpectedIPNonMatch if len(c.unexpectedIPs) > 0 && !c.actUnprior {
ips = router.MatchIPs(c.unexpectedIPs, ips, true)
errors.LogDebug(context.Background(), "domain ", domain, " unexpectedIPs ", ips, " matched at server ", c.Name())
if len(ips) == 0 {
return nil, 0, dns.ErrEmptyResponse
}
} }
errors.LogDebug(context.Background(), "domain ", domain, " expectIPs ", newIps, " matched at server ", c.Name())
return newIps, nil if len(c.expectedIPs) > 0 && c.actPrior {
ipsNew := router.MatchIPs(c.expectedIPs, ips, false)
if len(ipsNew) > 0 {
ips = ipsNew
errors.LogDebug(context.Background(), "domain ", domain, " priorIPs ", ips, " matched at server ", c.Name())
}
}
if len(c.unexpectedIPs) > 0 && c.actUnprior {
ipsNew := router.MatchIPs(c.unexpectedIPs, ips, true)
if len(ipsNew) > 0 {
ips = ipsNew
errors.LogDebug(context.Background(), "domain ", domain, " unpriorIPs ", ips, " matched at server ", c.Name())
}
}
return ips, ttl, nil
} }
func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption) dns.IPOption { func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption) dns.IPOption {
switch queryStrategy { switch queryStrategy {
case QueryStrategy_USE_IP: case QueryStrategy_USE_IP:
return ipOption return ipOption
case QueryStrategy_USE_SYS:
return ipOption
case QueryStrategy_USE_IP4: case QueryStrategy_USE_IP4:
return dns.IPOption{ return dns.IPOption{
IPv4Enable: ipOption.IPv4Enable, IPv4Enable: ipOption.IPv4Enable,

View File

@@ -3,237 +3,136 @@ package dns
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/tls"
go_errors "errors"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
"sync" "strings"
"sync/atomic"
"time" "time"
utls "github.com/refraction-networking/utls"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"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"
"github.com/xtls/xray-core/common/protocol/dns" "github.com/xtls/xray-core/common/protocol/dns"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal/pubsub"
"github.com/xtls/xray-core/common/task"
dns_feature "github.com/xtls/xray-core/features/dns" dns_feature "github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"golang.org/x/net/dns/dnsmessage" "golang.org/x/net/http2"
) )
// DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format, // DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format,
// which is compatible with traditional dns over udp(RFC1035), // which is compatible with traditional dns over udp(RFC1035),
// thus most of the DOH implementation is copied from udpns.go // thus most of the DOH implementation is copied from udpns.go
type DoHNameServer struct { type DoHNameServer struct {
dispatcher routing.Dispatcher cacheController *CacheController
sync.RWMutex httpClient *http.Client
ips map[string]*record dohURL string
pub *pubsub.Service clientIP net.IP
cleanup *task.Periodic
reqID uint32
httpClient *http.Client
dohURL string
name string
queryStrategy QueryStrategy
} }
// NewDoHNameServer creates DOH server object for remote resolving. // NewDoHNameServer creates DOH/DOHL client object for remote/local resolving.
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (*DoHNameServer, error) { func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, disableCache bool, clientIP net.IP) *DoHNameServer {
errors.LogInfo(context.Background(), "DNS: created Remote DOH client for ", url.String())
s := baseDOHNameServer(url, "DOH", queryStrategy)
s.dispatcher = dispatcher
tr := &http.Transport{
MaxIdleConns: 30,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 30 * time.Second,
ForceAttemptHTTP2: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
link, err := s.dispatcher.Dispatch(toDnsContext(ctx, s.dohURL), dest)
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if err != nil {
return nil, err
}
cc := common.ChainedClosable{}
if cw, ok := link.Writer.(common.Closable); ok {
cc = append(cc, cw)
}
if cr, ok := link.Reader.(common.Closable); ok {
cc = append(cc, cr)
}
return cnc.NewConnection(
cnc.ConnectionInputMulti(link.Writer),
cnc.ConnectionOutputMulti(link.Reader),
cnc.ConnectionOnClose(cc),
), nil
},
}
s.httpClient = &http.Client{
Timeout: time.Second * 180,
Transport: tr,
}
return s, nil
}
// NewDoHLocalNameServer creates DOH client object for local resolving
func NewDoHLocalNameServer(url *url.URL, queryStrategy QueryStrategy) *DoHNameServer {
url.Scheme = "https" url.Scheme = "https"
s := baseDOHNameServer(url, "DOHL", queryStrategy) mode := "DOH"
tr := &http.Transport{ if dispatcher == nil {
IdleConnTimeout: 90 * time.Second, mode = "DOHL"
ForceAttemptHTTP2: true, }
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { errors.LogInfo(context.Background(), "DNS: created ", mode, " client for ", url.String(), ", with h2c ", h2c)
dest, err := net.ParseDestination(network + ":" + addr) s := &DoHNameServer{
if err != nil { cacheController: NewCacheController(mode+"//"+url.Host, disableCache),
return nil, err dohURL: url.String(),
} clientIP: clientIP,
conn, err := internet.DialSystem(ctx, dest, nil)
log.Record(&log.AccessMessage{
From: "DNS",
To: s.dohURL,
Status: log.AccessAccepted,
Detour: "local",
})
if err != nil {
return nil, err
}
return conn, nil
},
} }
s.httpClient = &http.Client{ s.httpClient = &http.Client{
Timeout: time.Second * 180, Transport: &http2.Transport{
Transport: tr, IdleConnTimeout: net.ConnIdleTimeout,
} ReadIdleTimeout: net.ChromeH2KeepAlivePeriod,
errors.LogInfo(context.Background(), "DNS: created Local DOH client for ", url.String()) DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
return s dest, err := net.ParseDestination(network + ":" + addr)
} if err != nil {
return nil, err
func baseDOHNameServer(url *url.URL, prefix string, queryStrategy QueryStrategy) *DoHNameServer { }
s := &DoHNameServer{ var conn net.Conn
ips: make(map[string]*record), if dispatcher != nil {
pub: pubsub.NewService(), dnsCtx := toDnsContext(ctx, s.dohURL)
name: prefix + "//" + url.Host, if h2c {
dohURL: url.String(), dnsCtx = session.ContextWithMitmAlpn11(dnsCtx, false) // for insurance
queryStrategy: queryStrategy, dnsCtx = session.ContextWithMitmServerName(dnsCtx, url.Hostname())
} }
s.cleanup = &task.Periodic{ link, err := dispatcher.Dispatch(dnsCtx, dest)
Interval: time.Minute, select {
Execute: s.Cleanup, case <-ctx.Done():
return nil, ctx.Err()
default:
}
if err != nil {
return nil, err
}
cc := common.ChainedClosable{}
if cw, ok := link.Writer.(common.Closable); ok {
cc = append(cc, cw)
}
if cr, ok := link.Reader.(common.Closable); ok {
cc = append(cc, cr)
}
conn = cnc.NewConnection(
cnc.ConnectionInputMulti(link.Writer),
cnc.ConnectionOutputMulti(link.Reader),
cnc.ConnectionOnClose(cc),
)
} else {
log.Record(&log.AccessMessage{
From: "DNS",
To: s.dohURL,
Status: log.AccessAccepted,
Detour: "local",
})
conn, err = internet.DialSystem(ctx, dest, nil)
if err != nil {
return nil, err
}
}
if !h2c {
conn = utls.UClient(conn, &utls.Config{ServerName: url.Hostname()}, utls.HelloChrome_Auto)
if err := conn.(*utls.UConn).HandshakeContext(ctx); err != nil {
return nil, err
}
}
return conn, nil
},
},
} }
return s return s
} }
// Name implements Server. // Name implements Server.
func (s *DoHNameServer) Name() string { func (s *DoHNameServer) Name() string {
return s.name return s.cacheController.name
}
// Cleanup clears expired items from cache
func (s *DoHNameServer) Cleanup() error {
now := time.Now()
s.Lock()
defer s.Unlock()
if len(s.ips) == 0 {
return errors.New("nothing to do. stopping...")
}
for domain, record := range s.ips {
if record.A != nil && record.A.Expire.Before(now) {
record.A = nil
}
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
record.AAAA = nil
}
if record.A == nil && record.AAAA == nil {
errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
delete(s.ips, domain)
} else {
s.ips[domain] = record
}
}
if len(s.ips) == 0 {
s.ips = make(map[string]*record)
}
return nil
}
func (s *DoHNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
elapsed := time.Since(req.start)
s.Lock()
rec, found := s.ips[req.domain]
if !found {
rec = &record{}
}
updated := false
switch req.reqType {
case dnsmessage.TypeA:
if isNewer(rec.A, ipRec) {
rec.A = ipRec
updated = true
}
case dnsmessage.TypeAAAA:
addr := make([]net.Address, 0, len(ipRec.IP))
for _, ip := range ipRec.IP {
if len(ip.IP()) == net.IPv6len {
addr = append(addr, ip)
}
}
ipRec.IP = addr
if isNewer(rec.AAAA, ipRec) {
rec.AAAA = ipRec
updated = true
}
}
errors.LogInfo(context.Background(), s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
if updated {
s.ips[req.domain] = rec
}
switch req.reqType {
case dnsmessage.TypeA:
s.pub.Publish(req.domain+"4", nil)
case dnsmessage.TypeAAAA:
s.pub.Publish(req.domain+"6", nil)
}
s.Unlock()
common.Must(s.cleanup.Start())
} }
func (s *DoHNameServer) newReqID() uint16 { func (s *DoHNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1)) return 0
} }
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
errors.LogInfo(ctx, s.name, " querying: ", domain) errors.LogInfo(ctx, s.Name(), " querying: ", domain)
if s.name+"." == "DOH//"+domain { if s.Name()+"." == "DOH//"+domain {
errors.LogError(ctx, s.name, " tries to resolve itself! Use IP or set \"hosts\" instead.") errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead.")
noResponseErrCh <- errors.New("tries to resolve itself!", s.Name())
return return
} }
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) // As we don't want our traffic pattern looks like DoH, we use Random-Length Padding instead of Block-Length Padding recommended in RFC 8467
// Although DoH server like 1.1.1.1 will pad the response to Block-Length 468, at least it is better than no padding for response at all
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, int(crypto.RandBetween(100, 300))))
var deadline time.Time var deadline time.Time
if d, ok := ctx.Deadline(); ok { if d, ok := ctx.Deadline(); ok {
@@ -268,19 +167,22 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP n
b, err := dns.PackMessage(r.msg) b, err := dns.PackMessage(r.msg)
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to pack dns query for ", domain) errors.LogErrorInner(ctx, err, "failed to pack dns query for ", domain)
noResponseErrCh <- err
return return
} }
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes()) resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to retrieve response for ", domain) errors.LogErrorInner(ctx, err, "failed to retrieve response for ", domain)
noResponseErrCh <- err
return return
} }
rec, err := parseResponse(resp) rec, err := parseResponse(resp)
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", domain) errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", domain)
noResponseErrCh <- err
return return
} }
s.updateIP(r, rec) s.cacheController.updateIP(r, rec)
}(req) }(req)
} }
} }
@@ -295,6 +197,8 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
req.Header.Add("Accept", "application/dns-message") req.Header.Add("Accept", "application/dns-message")
req.Header.Add("Content-Type", "application/dns-message") req.Header.Add("Content-Type", "application/dns-message")
req.Header.Set("X-Padding", strings.Repeat("X", int(crypto.RandBetween(100, 1000))))
hc := s.httpClient hc := s.httpClient
resp, err := hc.Do(req.WithContext(ctx)) resp, err := hc.Do(req.WithContext(ctx))
@@ -311,107 +215,50 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
return io.ReadAll(resp.Body) return io.ReadAll(resp.Body)
} }
func (s *DoHNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
s.RLock()
record, found := s.ips[domain]
s.RUnlock()
if !found {
return nil, errRecordNotFound
}
var err4 error
var err6 error
var ips []net.Address
var ip6 []net.Address
if option.IPv4Enable {
ips, err4 = record.A.getIPs()
}
if option.IPv6Enable {
ip6, err6 = record.AAAA.getIPs()
ips = append(ips, ip6...)
}
if len(ips) > 0 {
return toNetIP(ips)
}
if err4 != nil {
return nil, err4
}
if err6 != nil {
return nil, err6
}
if (option.IPv4Enable && record.A != nil) || (option.IPv6Enable && record.AAAA != nil) {
return nil, dns_feature.ErrEmptyResponse
}
return nil, errRecordNotFound
}
// QueryIP implements Server. // QueryIP implements Server.
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) { // nolint: dupl func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) { // nolint: dupl
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
option = ResolveIpOptionOverride(s.queryStrategy, option) sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
if !option.IPv4Enable && !option.IPv6Enable { defer closeSubscribers(sub4, sub6)
return nil, dns_feature.ErrEmptyResponse
}
if disableCache { if s.cacheController.disableCache {
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name) errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if !go_errors.Is(err, errRecordNotFound) {
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips) errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err}) log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
return ips, err return ips, ttl, err
} }
} }
// ipv4 and ipv6 belong to different subscription groups noResponseErrCh := make(chan error, 2)
var sub4, sub6 *pubsub.Subscriber s.sendQuery(ctx, noResponseErrCh, fqdn, option)
if option.IPv4Enable {
sub4 = s.pub.Subscribe(fqdn + "4")
defer sub4.Close()
}
if option.IPv6Enable {
sub6 = s.pub.Subscribe(fqdn + "6")
defer sub6.Close()
}
done := make(chan interface{})
go func() {
if sub4 != nil {
select {
case <-sub4.Wait():
case <-ctx.Done():
}
}
if sub6 != nil {
select {
case <-sub6.Wait():
case <-ctx.Done():
}
}
close(done)
}()
s.sendQuery(ctx, fqdn, clientIP, option)
start := time.Now() start := time.Now()
for { if sub4 != nil {
ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound {
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
return ips, err
}
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() return nil, 0, ctx.Err()
case <-done: case err := <-noResponseErrCh:
return nil, 0, err
case <-sub4.Wait():
sub4.Close()
} }
} }
if sub6 != nil {
select {
case <-ctx.Done():
return nil, 0, ctx.Err()
case err := <-noResponseErrCh:
return nil, 0, err
case <-sub6.Wait():
sub6.Close()
}
}
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
return ips, ttl, err
} }

View File

@@ -17,12 +17,12 @@ func TestDOHNameServer(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query") url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err) common.Must(err)
s := NewDoHLocalNameServer(url, QueryStrategy_USE_IP) s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@@ -34,12 +34,12 @@ func TestDOHNameServerWithCache(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query") url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err) common.Must(err)
s := NewDoHLocalNameServer(url, QueryStrategy_USE_IP) s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@@ -47,10 +47,10 @@ func TestDOHNameServerWithCache(t *testing.T) {
} }
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{ ips2, _, err := s.QueryIP(ctx2, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, true) })
cancel() cancel()
common.Must(err) common.Must(err)
if r := cmp.Diff(ips2, ips); r != "" { if r := cmp.Diff(ips2, ips); r != "" {
@@ -62,12 +62,12 @@ func TestDOHNameServerWithIPv4Override(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query") url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err) common.Must(err)
s := NewDoHLocalNameServer(url, QueryStrategy_USE_IP4) s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: false,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@@ -85,12 +85,12 @@ func TestDOHNameServerWithIPv6Override(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query") url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err) common.Must(err)
s := NewDoHLocalNameServer(url, QueryStrategy_USE_IP6) s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {

View File

@@ -5,7 +5,6 @@ import (
"github.com/xtls/xray-core/common/errors" "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/core"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )
@@ -13,22 +12,19 @@ type FakeDNSServer struct {
fakeDNSEngine dns.FakeDNSEngine fakeDNSEngine dns.FakeDNSEngine
} }
func NewFakeDNSServer() *FakeDNSServer { func NewFakeDNSServer(fd dns.FakeDNSEngine) *FakeDNSServer {
return &FakeDNSServer{} return &FakeDNSServer{fakeDNSEngine: fd}
} }
func (FakeDNSServer) Name() string { func (FakeDNSServer) Name() string {
return "FakeDNS" return "FakeDNS"
} }
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, opt dns.IPOption, _ bool) ([]net.IP, error) { func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOption) ([]net.IP, uint32, error) {
if f.fakeDNSEngine == nil { if f.fakeDNSEngine == nil {
if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) { return nil, 0, errors.New("Unable to locate a fake DNS Engine").AtError()
f.fakeDNSEngine = fd
}); err != nil {
return nil, errors.New("Unable to locate a fake DNS Engine").Base(err).AtError()
}
} }
var ips []net.Address var ips []net.Address
if fkr0, ok := f.fakeDNSEngine.(dns.FakeDNSEngineRev0); ok { if fkr0, ok := f.fakeDNSEngine.(dns.FakeDNSEngineRev0); ok {
ips = fkr0.GetFakeIPForDomain3(domain, opt.IPv4Enable, opt.IPv6Enable) ips = fkr0.GetFakeIPForDomain3(domain, opt.IPv4Enable, opt.IPv6Enable)
@@ -38,13 +34,13 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, op
netIP, err := toNetIP(ips) netIP, err := toNetIP(ips)
if err != nil { if err != nil {
return nil, errors.New("Unable to convert IP to net ip").Base(err).AtError() return nil, 0, errors.New("Unable to convert IP to net ip").Base(err).AtError()
} }
errors.LogInfo(ctx, f.Name(), " got answer: ", domain, " -> ", ips) errors.LogInfo(ctx, f.Name(), " got answer: ", domain, " -> ", ips)
if len(netIP) > 0 { if len(netIP) > 0 {
return netIP, nil return netIP, 1, nil // fakeIP ttl is 1
} }
return nil, dns.ErrEmptyResponse return nil, 0, dns.ErrEmptyResponse
} }

View File

@@ -2,7 +2,6 @@ package dns
import ( import (
"context" "context"
"strings"
"time" "time"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -17,16 +16,11 @@ type LocalNameServer struct {
client *localdns.Client client *localdns.Client
} }
const errEmptyResponse = "No address associated with hostname"
// QueryIP implements Server. // QueryIP implements Server.
func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) (ips []net.IP, err error) { func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, option dns.IPOption) (ips []net.IP, ttl uint32, err error) {
start := time.Now()
ips, err = s.client.LookupIP(domain, option)
if err != nil && strings.HasSuffix(err.Error(), errEmptyResponse) { start := time.Now()
err = dns.ErrEmptyResponse ips, ttl, err = s.client.LookupIP(domain, option)
}
if len(ips) > 0 { if len(ips) > 0 {
errors.LogInfo(ctx, "Localhost got answer: ", domain, " -> ", ips) errors.LogInfo(ctx, "Localhost got answer: ", domain, " -> ", ips)
@@ -50,6 +44,6 @@ func NewLocalNameServer() *LocalNameServer {
} }
// NewLocalDNSClient creates localdns client object for directly lookup in system DNS. // NewLocalDNSClient creates localdns client object for directly lookup in system DNS.
func NewLocalDNSClient() *Client { func NewLocalDNSClient(ipOption dns.IPOption) *Client {
return &Client{server: NewLocalNameServer()} return &Client{server: NewLocalNameServer(), ipOption: &ipOption}
} }

View File

@@ -7,18 +7,17 @@ import (
. "github.com/xtls/xray-core/app/dns" . "github.com/xtls/xray-core/app/dns"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )
func TestLocalNameServer(t *testing.T) { func TestLocalNameServer(t *testing.T) {
s := NewLocalNameServer() s := NewLocalNameServer()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
FakeEnable: false, FakeEnable: false,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {

View File

@@ -4,24 +4,20 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/binary" "encoding/binary"
go_errors "errors"
"net/url" "net/url"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/quic-go/quic-go" "github.com/quic-go/quic-go"
"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/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol/dns" "github.com/xtls/xray-core/common/protocol/dns"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal/pubsub"
"github.com/xtls/xray-core/common/task"
dns_feature "github.com/xtls/xray-core/features/dns" dns_feature "github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"golang.org/x/net/dns/dnsmessage"
"golang.org/x/net/http2" "golang.org/x/net/http2"
) )
@@ -34,18 +30,14 @@ const handshakeTimeout = time.Second * 8
// QUICNameServer implemented DNS over QUIC // QUICNameServer implemented DNS over QUIC
type QUICNameServer struct { type QUICNameServer struct {
sync.RWMutex sync.RWMutex
ips map[string]*record cacheController *CacheController
pub *pubsub.Service destination *net.Destination
cleanup *task.Periodic connection *quic.Conn
reqID uint32 clientIP net.IP
name string
destination *net.Destination
connection quic.Connection
queryStrategy QueryStrategy
} }
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving // NewQUICNameServer creates DNS-over-QUIC client object for local resolving
func NewQUICNameServer(url *url.URL, queryStrategy QueryStrategy) (*QUICNameServer, error) { func NewQUICNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*QUICNameServer, error) {
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String()) errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
var err error var err error
@@ -59,15 +51,9 @@ func NewQUICNameServer(url *url.URL, queryStrategy QueryStrategy) (*QUICNameServ
dest := net.UDPDestination(net.ParseAddress(url.Hostname()), port) dest := net.UDPDestination(net.ParseAddress(url.Hostname()), port)
s := &QUICNameServer{ s := &QUICNameServer{
ips: make(map[string]*record), cacheController: NewCacheController(url.String(), disableCache),
pub: pubsub.NewService(), destination: &dest,
name: url.String(), clientIP: clientIP,
destination: &dest,
queryStrategy: queryStrategy,
}
s.cleanup = &task.Periodic{
Interval: time.Minute,
Execute: s.Cleanup,
} }
return s, nil return s, nil
@@ -75,94 +61,17 @@ func NewQUICNameServer(url *url.URL, queryStrategy QueryStrategy) (*QUICNameServ
// Name returns client name // Name returns client name
func (s *QUICNameServer) Name() string { func (s *QUICNameServer) Name() string {
return s.name return s.cacheController.name
}
// Cleanup clears expired items from cache
func (s *QUICNameServer) Cleanup() error {
now := time.Now()
s.Lock()
defer s.Unlock()
if len(s.ips) == 0 {
return errors.New("nothing to do. stopping...")
}
for domain, record := range s.ips {
if record.A != nil && record.A.Expire.Before(now) {
record.A = nil
}
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
record.AAAA = nil
}
if record.A == nil && record.AAAA == nil {
errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
delete(s.ips, domain)
} else {
s.ips[domain] = record
}
}
if len(s.ips) == 0 {
s.ips = make(map[string]*record)
}
return nil
}
func (s *QUICNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
elapsed := time.Since(req.start)
s.Lock()
rec, found := s.ips[req.domain]
if !found {
rec = &record{}
}
updated := false
switch req.reqType {
case dnsmessage.TypeA:
if isNewer(rec.A, ipRec) {
rec.A = ipRec
updated = true
}
case dnsmessage.TypeAAAA:
addr := make([]net.Address, 0)
for _, ip := range ipRec.IP {
if len(ip.IP()) == net.IPv6len {
addr = append(addr, ip)
}
}
ipRec.IP = addr
if isNewer(rec.AAAA, ipRec) {
rec.AAAA = ipRec
updated = true
}
}
errors.LogInfo(context.Background(), s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
if updated {
s.ips[req.domain] = rec
}
switch req.reqType {
case dnsmessage.TypeA:
s.pub.Publish(req.domain+"4", nil)
case dnsmessage.TypeAAAA:
s.pub.Publish(req.domain+"6", nil)
}
s.Unlock()
common.Must(s.cleanup.Start())
} }
func (s *QUICNameServer) newReqID() uint16 { func (s *QUICNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1)) return 0
} }
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
errors.LogInfo(ctx, s.name, " querying: ", domain) errors.LogInfo(ctx, s.Name(), " querying: ", domain)
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
var deadline time.Time var deadline time.Time
if d, ok := ctx.Deadline(); ok { if d, ok := ctx.Deadline(); ok {
@@ -194,23 +103,36 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP
b, err := dns.PackMessage(r.msg) b, err := dns.PackMessage(r.msg)
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to pack dns query") errors.LogErrorInner(ctx, err, "failed to pack dns query")
noResponseErrCh <- err
return return
} }
dnsReqBuf := buf.New() dnsReqBuf := buf.New()
binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len())) err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
dnsReqBuf.Write(b.Bytes()) if err != nil {
errors.LogErrorInner(ctx, err, "binary write failed")
noResponseErrCh <- err
return
}
_, err = dnsReqBuf.Write(b.Bytes())
if err != nil {
errors.LogErrorInner(ctx, err, "buffer write failed")
noResponseErrCh <- err
return
}
b.Release() b.Release()
conn, err := s.openStream(dnsCtx) conn, err := s.openStream(dnsCtx)
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to open quic connection") errors.LogErrorInner(ctx, err, "failed to open quic connection")
noResponseErrCh <- err
return return
} }
_, err = conn.Write(dnsReqBuf.Bytes()) _, err = conn.Write(dnsReqBuf.Bytes())
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to send query") errors.LogErrorInner(ctx, err, "failed to send query")
noResponseErrCh <- err
return return
} }
@@ -221,137 +143,84 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP
n, err := respBuf.ReadFullFrom(conn, 2) n, err := respBuf.ReadFullFrom(conn, 2)
if err != nil && n == 0 { if err != nil && n == 0 {
errors.LogErrorInner(ctx, err, "failed to read response length") errors.LogErrorInner(ctx, err, "failed to read response length")
noResponseErrCh <- err
return return
} }
var length int16 var length int16
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length) err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to parse response length") errors.LogErrorInner(ctx, err, "failed to parse response length")
noResponseErrCh <- err
return return
} }
respBuf.Clear() respBuf.Clear()
n, err = respBuf.ReadFullFrom(conn, int32(length)) n, err = respBuf.ReadFullFrom(conn, int32(length))
if err != nil && n == 0 { if err != nil && n == 0 {
errors.LogErrorInner(ctx, err, "failed to read response length") errors.LogErrorInner(ctx, err, "failed to read response length")
noResponseErrCh <- err
return return
} }
rec, err := parseResponse(respBuf.Bytes()) rec, err := parseResponse(respBuf.Bytes())
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to handle response") errors.LogErrorInner(ctx, err, "failed to handle response")
noResponseErrCh <- err
return return
} }
s.updateIP(r, rec) s.cacheController.updateIP(r, rec)
}(req) }(req)
} }
} }
func (s *QUICNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
s.RLock()
record, found := s.ips[domain]
s.RUnlock()
if !found {
return nil, errRecordNotFound
}
var err4 error
var err6 error
var ips []net.Address
var ip6 []net.Address
if option.IPv4Enable {
ips, err4 = record.A.getIPs()
}
if option.IPv6Enable {
ip6, err6 = record.AAAA.getIPs()
ips = append(ips, ip6...)
}
if len(ips) > 0 {
return toNetIP(ips)
}
if err4 != nil {
return nil, err4
}
if err6 != nil {
return nil, err6
}
if (option.IPv4Enable && record.A != nil) || (option.IPv6Enable && record.AAAA != nil) {
return nil, dns_feature.ErrEmptyResponse
}
return nil, errRecordNotFound
}
// QueryIP is called from dns.Server->queryIPTimeout // QueryIP is called from dns.Server->queryIPTimeout
func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) { func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
option = ResolveIpOptionOverride(s.queryStrategy, option) sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
if !option.IPv4Enable && !option.IPv6Enable { defer closeSubscribers(sub4, sub6)
return nil, dns_feature.ErrEmptyResponse
}
if disableCache { if s.cacheController.disableCache {
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name) errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if !go_errors.Is(err, errRecordNotFound) {
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips) errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err}) log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
return ips, err return ips, ttl, err
} }
} }
// ipv4 and ipv6 belong to different subscription groups noResponseErrCh := make(chan error, 2)
var sub4, sub6 *pubsub.Subscriber s.sendQuery(ctx, noResponseErrCh, fqdn, option)
if option.IPv4Enable {
sub4 = s.pub.Subscribe(fqdn + "4")
defer sub4.Close()
}
if option.IPv6Enable {
sub6 = s.pub.Subscribe(fqdn + "6")
defer sub6.Close()
}
done := make(chan interface{})
go func() {
if sub4 != nil {
select {
case <-sub4.Wait():
case <-ctx.Done():
}
}
if sub6 != nil {
select {
case <-sub6.Wait():
case <-ctx.Done():
}
}
close(done)
}()
s.sendQuery(ctx, fqdn, clientIP, option)
start := time.Now() start := time.Now()
for { if sub4 != nil {
ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound {
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
return ips, err
}
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() return nil, 0, ctx.Err()
case <-done: case err := <-noResponseErrCh:
return nil, 0, err
case <-sub4.Wait():
sub4.Close()
} }
} }
if sub6 != nil {
select {
case <-ctx.Done():
return nil, 0, ctx.Err()
case err := <-noResponseErrCh:
return nil, 0, err
case <-sub6.Wait():
sub6.Close()
}
}
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
return ips, ttl, err
} }
func isActive(s quic.Connection) bool { func isActive(s *quic.Conn) bool {
select { select {
case <-s.Context().Done(): case <-s.Context().Done():
return false return false
@@ -360,8 +229,8 @@ func isActive(s quic.Connection) bool {
} }
} }
func (s *QUICNameServer) getConnection() (quic.Connection, error) { func (s *QUICNameServer) getConnection() (*quic.Conn, error) {
var conn quic.Connection var conn *quic.Conn
s.RLock() s.RLock()
conn = s.connection conn = s.connection
if conn != nil && isActive(conn) { if conn != nil && isActive(conn) {
@@ -394,7 +263,7 @@ func (s *QUICNameServer) getConnection() (quic.Connection, error) {
return conn, nil return conn, nil
} }
func (s *QUICNameServer) openConnection() (quic.Connection, error) { func (s *QUICNameServer) openConnection() (*quic.Conn, error) {
tlsConfig := tls.Config{} tlsConfig := tls.Config{}
quicConfig := &quic.Config{ quicConfig := &quic.Config{
HandshakeIdleTimeout: handshakeTimeout, HandshakeIdleTimeout: handshakeTimeout,
@@ -414,7 +283,7 @@ func (s *QUICNameServer) openConnection() (quic.Connection, error) {
return conn, nil return conn, nil
} }
func (s *QUICNameServer) openStream(ctx context.Context) (quic.Stream, error) { func (s *QUICNameServer) openStream(ctx context.Context) (*quic.Stream, error) {
conn, err := s.getConnection() conn, err := s.getConnection()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -14,26 +14,25 @@ import (
) )
func TestQUICNameServer(t *testing.T) { func TestQUICNameServer(t *testing.T) {
url, err := url.Parse("quic://dns.adguard.com") url, err := url.Parse("quic://dns.adguard-dns.com")
common.Must(err) common.Must(err)
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP) s, err := NewQUICNameServer(url, false, net.IP(nil))
common.Must(err) common.Must(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
t.Error("expect some ips, but got 0") t.Error("expect some ips, but got 0")
} }
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns.IPOption{ ips2, _, err := s.QueryIP(ctx2, "google.com", dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, true) })
cancel() cancel()
common.Must(err) common.Must(err)
if r := cmp.Diff(ips2, ips); r != "" { if r := cmp.Diff(ips2, ips); r != "" {
@@ -42,15 +41,15 @@ func TestQUICNameServer(t *testing.T) {
} }
func TestQUICNameServerWithIPv4Override(t *testing.T) { func TestQUICNameServerWithIPv4Override(t *testing.T) {
url, err := url.Parse("quic://dns.adguard.com") url, err := url.Parse("quic://dns.adguard-dns.com")
common.Must(err) common.Must(err)
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP4) s, err := NewQUICNameServer(url, false, net.IP(nil))
common.Must(err) common.Must(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: false,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@@ -65,15 +64,15 @@ func TestQUICNameServerWithIPv4Override(t *testing.T) {
} }
func TestQUICNameServerWithIPv6Override(t *testing.T) { func TestQUICNameServerWithIPv6Override(t *testing.T) {
url, err := url.Parse("quic://dns.adguard.com") url, err := url.Parse("quic://dns.adguard-dns.com")
common.Must(err) common.Must(err)
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP6) s, err := NewQUICNameServer(url, false, net.IP(nil))
common.Must(err) common.Must(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
IPv4Enable: true, IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {

View File

@@ -4,12 +4,11 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/binary" "encoding/binary"
go_errors "errors"
"net/url" "net/url"
"sync"
"sync/atomic" "sync/atomic"
"time" "time"
"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/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
@@ -17,34 +16,28 @@ import (
"github.com/xtls/xray-core/common/net/cnc" "github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/protocol/dns" "github.com/xtls/xray-core/common/protocol/dns"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal/pubsub"
"github.com/xtls/xray-core/common/task"
dns_feature "github.com/xtls/xray-core/features/dns" dns_feature "github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"golang.org/x/net/dns/dnsmessage"
) )
// TCPNameServer implemented DNS over TCP (RFC7766). // TCPNameServer implemented DNS over TCP (RFC7766).
type TCPNameServer struct { type TCPNameServer struct {
sync.RWMutex cacheController *CacheController
name string destination *net.Destination
destination *net.Destination reqID uint32
ips map[string]*record dial func(context.Context) (net.Conn, error)
pub *pubsub.Service clientIP net.IP
cleanup *task.Periodic
reqID uint32
dial func(context.Context) (net.Conn, error)
queryStrategy QueryStrategy
} }
// NewTCPNameServer creates DNS over TCP server object for remote resolving. // NewTCPNameServer creates DNS over TCP server object for remote resolving.
func NewTCPNameServer( func NewTCPNameServer(
url *url.URL, url *url.URL,
dispatcher routing.Dispatcher, dispatcher routing.Dispatcher,
queryStrategy QueryStrategy, disableCache bool,
clientIP net.IP,
) (*TCPNameServer, error) { ) (*TCPNameServer, error) {
s, err := baseTCPNameServer(url, "TCP", queryStrategy) s, err := baseTCPNameServer(url, "TCP", disableCache, clientIP)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -65,8 +58,8 @@ func NewTCPNameServer(
} }
// NewTCPLocalNameServer creates DNS over TCP client object for local resolving // NewTCPLocalNameServer creates DNS over TCP client object for local resolving
func NewTCPLocalNameServer(url *url.URL, queryStrategy QueryStrategy) (*TCPNameServer, error) { func NewTCPLocalNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*TCPNameServer, error) {
s, err := baseTCPNameServer(url, "TCPL", queryStrategy) s, err := baseTCPNameServer(url, "TCPL", disableCache, clientIP)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -78,7 +71,7 @@ func NewTCPLocalNameServer(url *url.URL, queryStrategy QueryStrategy) (*TCPNameS
return s, nil return s, nil
} }
func baseTCPNameServer(url *url.URL, prefix string, queryStrategy QueryStrategy) (*TCPNameServer, error) { func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, clientIP net.IP) (*TCPNameServer, error) {
port := net.Port(53) port := net.Port(53)
if url.Port() != "" { if url.Port() != "" {
var err error var err error
@@ -89,15 +82,9 @@ func baseTCPNameServer(url *url.URL, prefix string, queryStrategy QueryStrategy)
dest := net.TCPDestination(net.ParseAddress(url.Hostname()), port) dest := net.TCPDestination(net.ParseAddress(url.Hostname()), port)
s := &TCPNameServer{ s := &TCPNameServer{
destination: &dest, cacheController: NewCacheController(prefix+"//"+dest.NetAddr(), disableCache),
ips: make(map[string]*record), destination: &dest,
pub: pubsub.NewService(), clientIP: clientIP,
name: prefix + "//" + dest.NetAddr(),
queryStrategy: queryStrategy,
}
s.cleanup = &task.Periodic{
Interval: time.Minute,
Execute: s.Cleanup,
} }
return s, nil return s, nil
@@ -105,94 +92,17 @@ func baseTCPNameServer(url *url.URL, prefix string, queryStrategy QueryStrategy)
// Name implements Server. // Name implements Server.
func (s *TCPNameServer) Name() string { func (s *TCPNameServer) Name() string {
return s.name return s.cacheController.name
}
// Cleanup clears expired items from cache
func (s *TCPNameServer) Cleanup() error {
now := time.Now()
s.Lock()
defer s.Unlock()
if len(s.ips) == 0 {
return errors.New("nothing to do. stopping...")
}
for domain, record := range s.ips {
if record.A != nil && record.A.Expire.Before(now) {
record.A = nil
}
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
record.AAAA = nil
}
if record.A == nil && record.AAAA == nil {
errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
delete(s.ips, domain)
} else {
s.ips[domain] = record
}
}
if len(s.ips) == 0 {
s.ips = make(map[string]*record)
}
return nil
}
func (s *TCPNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
elapsed := time.Since(req.start)
s.Lock()
rec, found := s.ips[req.domain]
if !found {
rec = &record{}
}
updated := false
switch req.reqType {
case dnsmessage.TypeA:
if isNewer(rec.A, ipRec) {
rec.A = ipRec
updated = true
}
case dnsmessage.TypeAAAA:
addr := make([]net.Address, 0)
for _, ip := range ipRec.IP {
if len(ip.IP()) == net.IPv6len {
addr = append(addr, ip)
}
}
ipRec.IP = addr
if isNewer(rec.AAAA, ipRec) {
rec.AAAA = ipRec
updated = true
}
}
errors.LogInfo(context.Background(), s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
if updated {
s.ips[req.domain] = rec
}
switch req.reqType {
case dnsmessage.TypeA:
s.pub.Publish(req.domain+"4", nil)
case dnsmessage.TypeAAAA:
s.pub.Publish(req.domain+"6", nil)
}
s.Unlock()
common.Must(s.cleanup.Start())
} }
func (s *TCPNameServer) newReqID() uint16 { func (s *TCPNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1)) return uint16(atomic.AddUint32(&s.reqID, 1))
} }
func (s *TCPNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
errors.LogDebug(ctx, s.name, " querying DNS for: ", domain) errors.LogDebug(ctx, s.Name(), " querying DNS for: ", domain)
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
var deadline time.Time var deadline time.Time
if d, ok := ctx.Deadline(); ok { if d, ok := ctx.Deadline(); ok {
@@ -221,23 +131,36 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, domain string, clientIP n
b, err := dns.PackMessage(r.msg) b, err := dns.PackMessage(r.msg)
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to pack dns query") errors.LogErrorInner(ctx, err, "failed to pack dns query")
noResponseErrCh <- err
return return
} }
conn, err := s.dial(dnsCtx) conn, err := s.dial(dnsCtx)
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to dial namesever") errors.LogErrorInner(ctx, err, "failed to dial namesever")
noResponseErrCh <- err
return return
} }
defer conn.Close() defer conn.Close()
dnsReqBuf := buf.New() dnsReqBuf := buf.New()
binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len())) err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
dnsReqBuf.Write(b.Bytes()) if err != nil {
errors.LogErrorInner(ctx, err, "binary write failed")
noResponseErrCh <- err
return
}
_, err = dnsReqBuf.Write(b.Bytes())
if err != nil {
errors.LogErrorInner(ctx, err, "buffer write failed")
noResponseErrCh <- err
return
}
b.Release() b.Release()
_, err = conn.Write(dnsReqBuf.Bytes()) _, err = conn.Write(dnsReqBuf.Bytes())
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to send query") errors.LogErrorInner(ctx, err, "failed to send query")
noResponseErrCh <- err
return return
} }
dnsReqBuf.Release() dnsReqBuf.Release()
@@ -247,129 +170,80 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, domain string, clientIP n
n, err := respBuf.ReadFullFrom(conn, 2) n, err := respBuf.ReadFullFrom(conn, 2)
if err != nil && n == 0 { if err != nil && n == 0 {
errors.LogErrorInner(ctx, err, "failed to read response length") errors.LogErrorInner(ctx, err, "failed to read response length")
noResponseErrCh <- err
return return
} }
var length int16 var length int16
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length) err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to parse response length") errors.LogErrorInner(ctx, err, "failed to parse response length")
noResponseErrCh <- err
return return
} }
respBuf.Clear() respBuf.Clear()
n, err = respBuf.ReadFullFrom(conn, int32(length)) n, err = respBuf.ReadFullFrom(conn, int32(length))
if err != nil && n == 0 { if err != nil && n == 0 {
errors.LogErrorInner(ctx, err, "failed to read response length") errors.LogErrorInner(ctx, err, "failed to read response length")
noResponseErrCh <- err
return return
} }
rec, err := parseResponse(respBuf.Bytes()) rec, err := parseResponse(respBuf.Bytes())
if err != nil { if err != nil {
errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response") errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response")
noResponseErrCh <- err
return return
} }
s.updateIP(r, rec) s.cacheController.updateIP(r, rec)
}(req) }(req)
} }
} }
func (s *TCPNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
s.RLock()
record, found := s.ips[domain]
s.RUnlock()
if !found {
return nil, errRecordNotFound
}
var err4 error
var err6 error
var ips []net.Address
var ip6 []net.Address
if option.IPv4Enable {
ips, err4 = record.A.getIPs()
}
if option.IPv6Enable {
ip6, err6 = record.AAAA.getIPs()
ips = append(ips, ip6...)
}
if len(ips) > 0 {
return toNetIP(ips)
}
if err4 != nil {
return nil, err4
}
if err6 != nil {
return nil, err6
}
return nil, dns_feature.ErrEmptyResponse
}
// QueryIP implements Server. // QueryIP implements Server.
func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) { func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
option = ResolveIpOptionOverride(s.queryStrategy, option) sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
if !option.IPv4Enable && !option.IPv6Enable { defer closeSubscribers(sub4, sub6)
return nil, dns_feature.ErrEmptyResponse
}
if disableCache { if s.cacheController.disableCache {
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name) errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if !go_errors.Is(err, errRecordNotFound) {
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips) errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err}) log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
return ips, err return ips, ttl, err
} }
} }
// ipv4 and ipv6 belong to different subscription groups noResponseErrCh := make(chan error, 2)
var sub4, sub6 *pubsub.Subscriber s.sendQuery(ctx, noResponseErrCh, fqdn, option)
if option.IPv4Enable {
sub4 = s.pub.Subscribe(fqdn + "4")
defer sub4.Close()
}
if option.IPv6Enable {
sub6 = s.pub.Subscribe(fqdn + "6")
defer sub6.Close()
}
done := make(chan interface{})
go func() {
if sub4 != nil {
select {
case <-sub4.Wait():
case <-ctx.Done():
}
}
if sub6 != nil {
select {
case <-sub6.Wait():
case <-ctx.Done():
}
}
close(done)
}()
s.sendQuery(ctx, fqdn, clientIP, option)
start := time.Now() start := time.Now()
for { if sub4 != nil {
ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound {
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
return ips, err
}
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() return nil, 0, ctx.Err()
case <-done: case err := <-noResponseErrCh:
return nil, 0, err
case <-sub4.Wait():
sub4.Close()
} }
} }
if sub6 != nil {
select {
case <-ctx.Done():
return nil, 0, ctx.Err()
case err := <-noResponseErrCh:
return nil, 0, err
case <-sub6.Wait():
sub6.Close()
}
}
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
return ips, ttl, err
} }

View File

@@ -16,13 +16,13 @@ import (
func TestTCPLocalNameServer(t *testing.T) { func TestTCPLocalNameServer(t *testing.T) {
url, err := url.Parse("tcp+local://8.8.8.8") url, err := url.Parse("tcp+local://8.8.8.8")
common.Must(err) common.Must(err)
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP) s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
common.Must(err) common.Must(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@@ -33,13 +33,13 @@ func TestTCPLocalNameServer(t *testing.T) {
func TestTCPLocalNameServerWithCache(t *testing.T) { func TestTCPLocalNameServerWithCache(t *testing.T) {
url, err := url.Parse("tcp+local://8.8.8.8") url, err := url.Parse("tcp+local://8.8.8.8")
common.Must(err) common.Must(err)
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP) s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
common.Must(err) common.Must(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
if len(ips) == 0 { if len(ips) == 0 {
@@ -47,10 +47,10 @@ func TestTCPLocalNameServerWithCache(t *testing.T) {
} }
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{ ips2, _, err := s.QueryIP(ctx2, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: true,
}, true) })
cancel() cancel()
common.Must(err) common.Must(err)
if r := cmp.Diff(ips2, ips); r != "" { if r := cmp.Diff(ips2, ips); r != "" {
@@ -61,13 +61,13 @@ func TestTCPLocalNameServerWithCache(t *testing.T) {
func TestTCPLocalNameServerWithIPv4Override(t *testing.T) { func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
url, err := url.Parse("tcp+local://8.8.8.8") url, err := url.Parse("tcp+local://8.8.8.8")
common.Must(err) common.Must(err)
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP4) s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
common.Must(err) common.Must(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
IPv6Enable: true, IPv6Enable: false,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)
@@ -85,13 +85,13 @@ func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
func TestTCPLocalNameServerWithIPv6Override(t *testing.T) { func TestTCPLocalNameServerWithIPv6Override(t *testing.T) {
url, err := url.Parse("tcp+local://8.8.8.8") url, err := url.Parse("tcp+local://8.8.8.8")
common.Must(err) common.Must(err)
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP6) s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
common.Must(err) common.Must(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: false,
IPv6Enable: true, IPv6Enable: true,
}, false) })
cancel() cancel()
common.Must(err) common.Must(err)

View File

@@ -2,6 +2,7 @@ package dns
import ( import (
"context" "context"
go_errors "errors"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
@@ -13,7 +14,6 @@ import (
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol/dns" "github.com/xtls/xray-core/common/protocol/dns"
udp_proto "github.com/xtls/xray-core/common/protocol/udp" udp_proto "github.com/xtls/xray-core/common/protocol/udp"
"github.com/xtls/xray-core/common/signal/pubsub"
"github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/common/task"
dns_feature "github.com/xtls/xray-core/features/dns" dns_feature "github.com/xtls/xray-core/features/dns"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
@@ -24,33 +24,36 @@ import (
// ClassicNameServer implemented traditional UDP DNS. // ClassicNameServer implemented traditional UDP DNS.
type ClassicNameServer struct { type ClassicNameServer struct {
sync.RWMutex sync.RWMutex
name string cacheController *CacheController
address *net.Destination address *net.Destination
ips map[string]*record requests map[uint16]*udpDnsRequest
requests map[uint16]*dnsRequest udpServer *udp.Dispatcher
pub *pubsub.Service requestsCleanup *task.Periodic
udpServer *udp.Dispatcher reqID uint32
cleanup *task.Periodic clientIP net.IP
reqID uint32 }
type udpDnsRequest struct {
dnsRequest
ctx context.Context
} }
// NewClassicNameServer creates udp server object for remote resolving. // NewClassicNameServer creates udp server object for remote resolving.
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher) *ClassicNameServer { func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, disableCache bool, clientIP net.IP) *ClassicNameServer {
// default to 53 if unspecific // default to 53 if unspecific
if address.Port == 0 { if address.Port == 0 {
address.Port = net.Port(53) address.Port = net.Port(53)
} }
s := &ClassicNameServer{ s := &ClassicNameServer{
address: &address, cacheController: NewCacheController(strings.ToUpper(address.String()), disableCache),
ips: make(map[string]*record), address: &address,
requests: make(map[uint16]*dnsRequest), requests: make(map[uint16]*udpDnsRequest),
pub: pubsub.NewService(), clientIP: clientIP,
name: strings.ToUpper(address.String()),
} }
s.cleanup = &task.Periodic{ s.requestsCleanup = &task.Periodic{
Interval: time.Minute, Interval: time.Minute,
Execute: s.Cleanup, Execute: s.RequestsCleanup,
} }
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse) s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr()) errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr())
@@ -59,37 +62,17 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
// Name implements Server. // Name implements Server.
func (s *ClassicNameServer) Name() string { func (s *ClassicNameServer) Name() string {
return s.name return s.cacheController.name
} }
// Cleanup clears expired items from cache // RequestsCleanup clears expired items from cache
func (s *ClassicNameServer) Cleanup() error { func (s *ClassicNameServer) RequestsCleanup() error {
now := time.Now() now := time.Now()
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
if len(s.ips) == 0 && len(s.requests) == 0 { if len(s.requests) == 0 {
return errors.New(s.name, " nothing to do. stopping...") return errors.New(s.Name(), " nothing to do. stopping...")
}
for domain, record := range s.ips {
if record.A != nil && record.A.Expire.Before(now) {
record.A = nil
}
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
record.AAAA = nil
}
if record.A == nil && record.AAAA == nil {
errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
delete(s.ips, domain)
} else {
s.ips[domain] = record
}
}
if len(s.ips) == 0 {
s.ips = make(map[string]*record)
} }
for id, req := range s.requests { for id, req := range s.requests {
@@ -99,7 +82,7 @@ func (s *ClassicNameServer) Cleanup() error {
} }
if len(s.requests) == 0 { if len(s.requests) == 0 {
s.requests = make(map[uint16]*dnsRequest) s.requests = make(map[uint16]*udpDnsRequest)
} }
return nil return nil
@@ -109,7 +92,7 @@ func (s *ClassicNameServer) Cleanup() error {
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) { func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
ipRec, err := parseResponse(packet.Payload.Bytes()) ipRec, err := parseResponse(packet.Payload.Bytes())
if err != nil { if err != nil {
errors.LogError(ctx, s.name, " fail to parse responded DNS udp") errors.LogError(ctx, s.Name(), " fail to parse responded DNS udp")
return return
} }
@@ -122,175 +105,107 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
} }
s.Unlock() s.Unlock()
if !ok { if !ok {
errors.LogError(ctx, s.name, " cannot find the pending request") errors.LogError(ctx, s.Name(), " cannot find the pending request")
return return
} }
var rec record // if truncated, retry with EDNS0 option(udp payload size: 1350)
switch req.reqType { if ipRec.RawHeader.Truncated {
case dnsmessage.TypeA: // if already has EDNS0 option, no need to retry
rec.A = ipRec if len(req.msg.Additionals) == 0 {
case dnsmessage.TypeAAAA: // copy necessary meta data from original request
rec.AAAA = ipRec // and add EDNS0 option
opt := new(dnsmessage.Resource)
common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true))
opt.Body = &dnsmessage.OPTResource{}
newMsg := *req.msg
newReq := *req
newMsg.Additionals = append(newMsg.Additionals, *opt)
newMsg.ID = s.newReqID()
newReq.msg = &newMsg
s.addPendingRequest(&newReq)
b, _ := dns.PackMessage(newReq.msg)
s.udpServer.Dispatch(toDnsContext(newReq.ctx, s.address.String()), *s.address, b)
return
}
} }
elapsed := time.Since(req.start) s.cacheController.updateIP(&req.dnsRequest, ipRec)
errors.LogInfo(ctx, s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
if len(req.domain) > 0 && (rec.A != nil || rec.AAAA != nil) {
s.updateIP(req.domain, &rec)
}
}
func (s *ClassicNameServer) updateIP(domain string, newRec *record) {
s.Lock()
rec, found := s.ips[domain]
if !found {
rec = &record{}
}
updated := false
if isNewer(rec.A, newRec.A) {
rec.A = newRec.A
updated = true
}
if isNewer(rec.AAAA, newRec.AAAA) {
rec.AAAA = newRec.AAAA
updated = true
}
if updated {
errors.LogDebug(context.Background(), s.name, " updating IP records for domain:", domain)
s.ips[domain] = rec
}
if newRec.A != nil {
s.pub.Publish(domain+"4", nil)
}
if newRec.AAAA != nil {
s.pub.Publish(domain+"6", nil)
}
s.Unlock()
common.Must(s.cleanup.Start())
} }
func (s *ClassicNameServer) newReqID() uint16 { func (s *ClassicNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1)) return uint16(atomic.AddUint32(&s.reqID, 1))
} }
func (s *ClassicNameServer) addPendingRequest(req *dnsRequest) { func (s *ClassicNameServer) addPendingRequest(req *udpDnsRequest) {
s.Lock() s.Lock()
defer s.Unlock()
id := req.msg.ID id := req.msg.ID
req.expire = time.Now().Add(time.Second * 8) req.expire = time.Now().Add(time.Second * 8)
s.requests[id] = req s.requests[id] = req
s.Unlock()
common.Must(s.requestsCleanup.Start())
} }
func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, domain string, option dns_feature.IPOption) {
errors.LogDebug(ctx, s.name, " querying DNS for: ", domain) errors.LogDebug(ctx, s.Name(), " querying DNS for: ", domain)
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP)) reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
for _, req := range reqs { for _, req := range reqs {
s.addPendingRequest(req) udpReq := &udpDnsRequest{
dnsRequest: *req,
ctx: ctx,
}
s.addPendingRequest(udpReq)
b, _ := dns.PackMessage(req.msg) b, _ := dns.PackMessage(req.msg)
s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b) s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b)
} }
} }
func (s *ClassicNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
s.RLock()
record, found := s.ips[domain]
s.RUnlock()
if !found {
return nil, errRecordNotFound
}
var err4 error
var err6 error
var ips []net.Address
var ip6 []net.Address
if option.IPv4Enable {
ips, err4 = record.A.getIPs()
}
if option.IPv6Enable {
ip6, err6 = record.AAAA.getIPs()
ips = append(ips, ip6...)
}
if len(ips) > 0 {
return toNetIP(ips)
}
if err4 != nil {
return nil, err4
}
if err6 != nil {
return nil, err6
}
return nil, dns_feature.ErrEmptyResponse
}
// QueryIP implements Server. // QueryIP implements Server.
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) { func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
fqdn := Fqdn(domain) fqdn := Fqdn(domain)
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
defer closeSubscribers(sub4, sub6)
if disableCache { if s.cacheController.disableCache {
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name) errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
} else { } else {
ips, err := s.findIPsForDomain(fqdn, option) ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
if err != errRecordNotFound { if !go_errors.Is(err, errRecordNotFound) {
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips) errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err}) log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
return ips, err return ips, ttl, err
} }
} }
// ipv4 and ipv6 belong to different subscription groups noResponseErrCh := make(chan error, 2)
var sub4, sub6 *pubsub.Subscriber s.sendQuery(ctx, noResponseErrCh, fqdn, option)
if option.IPv4Enable {
sub4 = s.pub.Subscribe(fqdn + "4")
defer sub4.Close()
}
if option.IPv6Enable {
sub6 = s.pub.Subscribe(fqdn + "6")
defer sub6.Close()
}
done := make(chan interface{})
go func() {
if sub4 != nil {
select {
case <-sub4.Wait():
case <-ctx.Done():
}
}
if sub6 != nil {
select {
case <-sub6.Wait():
case <-ctx.Done():
}
}
close(done)
}()
s.sendQuery(ctx, fqdn, clientIP, option)
start := time.Now() start := time.Now()
for { if sub4 != nil {
ips, err := s.findIPsForDomain(fqdn, option)
if err != errRecordNotFound {
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
return ips, err
}
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() return nil, 0, ctx.Err()
case <-done: case err := <-noResponseErrCh:
return nil, 0, err
case <-sub4.Wait():
sub4.Close()
} }
} }
if sub6 != nil {
select {
case <-ctx.Done():
return nil, 0, ctx.Err()
case err := <-noResponseErrCh:
return nil, 0, err
case <-sub6.Wait():
sub6.Close()
}
}
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
return ips, ttl, err
} }

View File

@@ -1,7 +1,5 @@
package command package command
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/log/command/config.proto // source: app/log/command/config.proto
package command package command
@@ -28,11 +28,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_log_command_config_proto_msgTypes[0]
mi := &file_app_log_command_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -43,7 +41,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_log_command_config_proto_msgTypes[0] mi := &file_app_log_command_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -66,11 +64,9 @@ type RestartLoggerRequest struct {
func (x *RestartLoggerRequest) Reset() { func (x *RestartLoggerRequest) Reset() {
*x = RestartLoggerRequest{} *x = RestartLoggerRequest{}
if protoimpl.UnsafeEnabled { mi := &file_app_log_command_config_proto_msgTypes[1]
mi := &file_app_log_command_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *RestartLoggerRequest) String() string { func (x *RestartLoggerRequest) String() string {
@@ -81,7 +77,7 @@ func (*RestartLoggerRequest) ProtoMessage() {}
func (x *RestartLoggerRequest) ProtoReflect() protoreflect.Message { func (x *RestartLoggerRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_log_command_config_proto_msgTypes[1] mi := &file_app_log_command_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -104,11 +100,9 @@ type RestartLoggerResponse struct {
func (x *RestartLoggerResponse) Reset() { func (x *RestartLoggerResponse) Reset() {
*x = RestartLoggerResponse{} *x = RestartLoggerResponse{}
if protoimpl.UnsafeEnabled { mi := &file_app_log_command_config_proto_msgTypes[2]
mi := &file_app_log_command_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *RestartLoggerResponse) String() string { func (x *RestartLoggerResponse) String() string {
@@ -119,7 +113,7 @@ func (*RestartLoggerResponse) ProtoMessage() {}
func (x *RestartLoggerResponse) ProtoReflect() protoreflect.Message { func (x *RestartLoggerResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_log_command_config_proto_msgTypes[2] mi := &file_app_log_command_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -174,7 +168,7 @@ func file_app_log_command_config_proto_rawDescGZIP() []byte {
} }
var file_app_log_command_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_app_log_command_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_app_log_command_config_proto_goTypes = []interface{}{ var file_app_log_command_config_proto_goTypes = []any{
(*Config)(nil), // 0: xray.app.log.command.Config (*Config)(nil), // 0: xray.app.log.command.Config
(*RestartLoggerRequest)(nil), // 1: xray.app.log.command.RestartLoggerRequest (*RestartLoggerRequest)(nil), // 1: xray.app.log.command.RestartLoggerRequest
(*RestartLoggerResponse)(nil), // 2: xray.app.log.command.RestartLoggerResponse (*RestartLoggerResponse)(nil), // 2: xray.app.log.command.RestartLoggerResponse
@@ -194,44 +188,6 @@ func file_app_log_command_config_proto_init() {
if File_app_log_command_config_proto != nil { if File_app_log_command_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_log_command_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_log_command_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RestartLoggerRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_log_command_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RestartLoggerResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.3.0 // - protoc-gen-go-grpc v1.5.1
// - protoc v5.27.0 // - protoc v5.28.2
// source: app/log/command/config.proto // source: app/log/command/config.proto
package command package command
@@ -15,8 +15,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later. // Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion7 const _ = grpc.SupportPackageIsVersion9
const ( const (
LoggerService_RestartLogger_FullMethodName = "/xray.app.log.command.LoggerService/RestartLogger" LoggerService_RestartLogger_FullMethodName = "/xray.app.log.command.LoggerService/RestartLogger"
@@ -38,8 +38,9 @@ func NewLoggerServiceClient(cc grpc.ClientConnInterface) LoggerServiceClient {
} }
func (c *loggerServiceClient) RestartLogger(ctx context.Context, in *RestartLoggerRequest, opts ...grpc.CallOption) (*RestartLoggerResponse, error) { func (c *loggerServiceClient) RestartLogger(ctx context.Context, in *RestartLoggerRequest, opts ...grpc.CallOption) (*RestartLoggerResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RestartLoggerResponse) out := new(RestartLoggerResponse)
err := c.cc.Invoke(ctx, LoggerService_RestartLogger_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, LoggerService_RestartLogger_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -48,20 +49,24 @@ func (c *loggerServiceClient) RestartLogger(ctx context.Context, in *RestartLogg
// LoggerServiceServer is the server API for LoggerService service. // LoggerServiceServer is the server API for LoggerService service.
// All implementations must embed UnimplementedLoggerServiceServer // All implementations must embed UnimplementedLoggerServiceServer
// for forward compatibility // for forward compatibility.
type LoggerServiceServer interface { type LoggerServiceServer interface {
RestartLogger(context.Context, *RestartLoggerRequest) (*RestartLoggerResponse, error) RestartLogger(context.Context, *RestartLoggerRequest) (*RestartLoggerResponse, error)
mustEmbedUnimplementedLoggerServiceServer() mustEmbedUnimplementedLoggerServiceServer()
} }
// UnimplementedLoggerServiceServer must be embedded to have forward compatible implementations. // UnimplementedLoggerServiceServer must be embedded to have
type UnimplementedLoggerServiceServer struct { // forward compatible implementations.
} //
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedLoggerServiceServer struct{}
func (UnimplementedLoggerServiceServer) RestartLogger(context.Context, *RestartLoggerRequest) (*RestartLoggerResponse, error) { func (UnimplementedLoggerServiceServer) RestartLogger(context.Context, *RestartLoggerRequest) (*RestartLoggerResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RestartLogger not implemented") return nil, status.Errorf(codes.Unimplemented, "method RestartLogger not implemented")
} }
func (UnimplementedLoggerServiceServer) mustEmbedUnimplementedLoggerServiceServer() {} func (UnimplementedLoggerServiceServer) mustEmbedUnimplementedLoggerServiceServer() {}
func (UnimplementedLoggerServiceServer) testEmbeddedByValue() {}
// UnsafeLoggerServiceServer may be embedded to opt out of forward compatibility for this service. // UnsafeLoggerServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to LoggerServiceServer will // Use of this interface is not recommended, as added methods to LoggerServiceServer will
@@ -71,6 +76,13 @@ type UnsafeLoggerServiceServer interface {
} }
func RegisterLoggerServiceServer(s grpc.ServiceRegistrar, srv LoggerServiceServer) { func RegisterLoggerServiceServer(s grpc.ServiceRegistrar, srv LoggerServiceServer) {
// If the following call pancis, it indicates UnimplementedLoggerServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&LoggerService_ServiceDesc, srv) s.RegisterService(&LoggerService_ServiceDesc, srv)
} }

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/log/config.proto // source: app/log/config.proto
package log package log
@@ -84,15 +84,14 @@ type Config struct {
AccessLogType LogType `protobuf:"varint,4,opt,name=access_log_type,json=accessLogType,proto3,enum=xray.app.log.LogType" json:"access_log_type,omitempty"` AccessLogType LogType `protobuf:"varint,4,opt,name=access_log_type,json=accessLogType,proto3,enum=xray.app.log.LogType" json:"access_log_type,omitempty"`
AccessLogPath string `protobuf:"bytes,5,opt,name=access_log_path,json=accessLogPath,proto3" json:"access_log_path,omitempty"` AccessLogPath string `protobuf:"bytes,5,opt,name=access_log_path,json=accessLogPath,proto3" json:"access_log_path,omitempty"`
EnableDnsLog bool `protobuf:"varint,6,opt,name=enable_dns_log,json=enableDnsLog,proto3" json:"enable_dns_log,omitempty"` EnableDnsLog bool `protobuf:"varint,6,opt,name=enable_dns_log,json=enableDnsLog,proto3" json:"enable_dns_log,omitempty"`
MaskAddress string `protobuf:"bytes,7,opt,name=mask_address,json=maskAddress,proto3" json:"mask_address,omitempty"`
} }
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_log_config_proto_msgTypes[0]
mi := &file_app_log_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -103,7 +102,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_log_config_proto_msgTypes[0] mi := &file_app_log_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -160,13 +159,20 @@ func (x *Config) GetEnableDnsLog() bool {
return false return false
} }
func (x *Config) GetMaskAddress() string {
if x != nil {
return x.MaskAddress
}
return ""
}
var File_app_log_config_proto protoreflect.FileDescriptor var File_app_log_config_proto protoreflect.FileDescriptor
var file_app_log_config_proto_rawDesc = []byte{ var file_app_log_config_proto_rawDesc = []byte{
0x0a, 0x14, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x14, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x6c, 0x6f, 0x67, 0x1a, 0x14, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6c, 0x6f, 0x67, 0x2e, 0x6c, 0x6f, 0x67, 0x1a, 0x14, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6c, 0x6f, 0x67,
0x2f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x02, 0x0a, 0x06, 0x43, 0x2f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xde, 0x02, 0x0a, 0x06, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6c, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6c,
0x6f, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x6f, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x4c, 0x6f, 0x67, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x4c, 0x6f, 0x67,
@@ -186,15 +192,18 @@ var file_app_log_config_proto_rawDesc = []byte{
0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x50, 0x61, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x50, 0x61,
0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x6e, 0x73, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x6e, 0x73,
0x5f, 0x6c, 0x6f, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x65, 0x6e, 0x61, 0x62, 0x5f, 0x6c, 0x6f, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x65, 0x6e, 0x61, 0x62,
0x6c, 0x65, 0x44, 0x6e, 0x73, 0x4c, 0x6f, 0x67, 0x2a, 0x35, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x54, 0x6c, 0x65, 0x44, 0x6e, 0x73, 0x4c, 0x6f, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x73, 0x6b,
0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
0x07, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x69, 0x6d, 0x61, 0x73, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2a, 0x35, 0x0a, 0x07, 0x4c,
0x6c, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x10, 0x03, 0x42, 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00,
0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a,
0x6c, 0x6f, 0x67, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x10, 0x03, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x41, 0x70, 0x70, 0x2e, 0x4c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63,
0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0xaa, 0x02, 0x0c, 0x58, 0x72,
0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
} }
var ( var (
@@ -211,7 +220,7 @@ func file_app_log_config_proto_rawDescGZIP() []byte {
var file_app_log_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_app_log_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_app_log_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_app_log_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_app_log_config_proto_goTypes = []interface{}{ var file_app_log_config_proto_goTypes = []any{
(LogType)(0), // 0: xray.app.log.LogType (LogType)(0), // 0: xray.app.log.LogType
(*Config)(nil), // 1: xray.app.log.Config (*Config)(nil), // 1: xray.app.log.Config
(log.Severity)(0), // 2: xray.common.log.Severity (log.Severity)(0), // 2: xray.common.log.Severity
@@ -232,20 +241,6 @@ func file_app_log_config_proto_init() {
if File_app_log_config_proto != nil { if File_app_log_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_log_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -23,4 +23,5 @@ message Config {
LogType access_log_type = 4; LogType access_log_type = 4;
string access_log_path = 5; string access_log_path = 5;
bool enable_dns_log = 6; bool enable_dns_log = 6;
string mask_address= 7;
} }

View File

@@ -1,9 +1,10 @@
package log package log
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"
"fmt"
"regexp"
"strings"
"sync" "sync"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -30,8 +31,8 @@ func New(ctx context.Context, config *Config) (*Instance, error) {
} }
log.RegisterHandler(g) log.RegisterHandler(g)
// Start logger instantly on initialization // start logger now,
// Other modules would log during initialization // then other modules will be able to log during initialization
if err := g.startInternal(); err != nil { if err := g.startInternal(); err != nil {
return nil, err return nil, err
} }
@@ -101,18 +102,25 @@ func (g *Instance) Handle(msg log.Message) {
return return
} }
var Msg log.Message
if g.config.MaskAddress != "" {
Msg = &MaskedMsgWrapper{Message: msg, config: g.config}
} else {
Msg = msg
}
switch msg := msg.(type) { switch msg := msg.(type) {
case *log.AccessMessage: case *log.AccessMessage:
if g.accessLogger != nil { if g.accessLogger != nil {
g.accessLogger.Handle(msg) g.accessLogger.Handle(Msg)
} }
case *log.DNSLog: case *log.DNSLog:
if g.dns && g.accessLogger != nil { if g.dns && g.accessLogger != nil {
g.accessLogger.Handle(msg) g.accessLogger.Handle(Msg)
} }
case *log.GeneralMessage: case *log.GeneralMessage:
if g.errorLogger != nil && msg.Severity <= g.config.ErrorLogLevel { if g.errorLogger != nil && msg.Severity <= g.config.ErrorLogLevel {
g.errorLogger.Handle(msg) g.errorLogger.Handle(Msg)
} }
default: default:
// Swallow // Swallow
@@ -141,6 +149,56 @@ func (g *Instance) Close() error {
return nil return nil
} }
// MaskedMsgWrapper is to wrap the string() method to mask IP addresses in the log.
type MaskedMsgWrapper struct {
log.Message
config *Config
}
func (m *MaskedMsgWrapper) String() string {
str := m.Message.String()
ipv4Regex := regexp.MustCompile(`(\d{1,3}\.){3}\d{1,3}`)
ipv6Regex := regexp.MustCompile(`((?:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}){2,7})(?:[\/\\%](\d{1,3}))?`)
// Process ipv4
maskedMsg := ipv4Regex.ReplaceAllStringFunc(str, func(ip string) string {
parts := strings.Split(ip, ".")
switch m.config.MaskAddress {
case "half":
return fmt.Sprintf("%s.%s.*.*", parts[0], parts[1])
case "quarter":
return fmt.Sprintf("%s.*.*.*", parts[0])
case "full":
return "[Masked IPv4]"
default:
return ip
}
})
// process ipv6
maskedMsg = ipv6Regex.ReplaceAllStringFunc(maskedMsg, func(ip string) string {
parts := strings.Split(ip, ":")
switch m.config.MaskAddress {
case "half":
if len(parts) >= 2 {
return fmt.Sprintf("%s:%s::/32", parts[0], parts[1])
}
case "quarter":
if len(parts) >= 1 {
return fmt.Sprintf("%s::/16", parts[0])
}
case "full":
return "Masked IPv6" // Do not use [Masked IPv6] like ipv4, or you will get "[[Masked IPv6]]" (v6 address already has [])
default:
return ip
}
return ip
})
return maskedMsg
}
func init() { func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return New(ctx, config.(*Config)) return New(ctx, config.(*Config))

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/metrics/config.proto // source: app/metrics/config.proto
package metrics package metrics
@@ -27,16 +27,15 @@ type Config struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// Tag of the outbound handler that handles metrics http connections. // Tag of the outbound handler that handles metrics http connections.
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
Listen string `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
} }
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_metrics_config_proto_msgTypes[0]
mi := &file_app_metrics_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -47,7 +46,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_metrics_config_proto_msgTypes[0] mi := &file_app_metrics_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -69,20 +68,28 @@ func (x *Config) GetTag() string {
return "" return ""
} }
func (x *Config) GetListen() string {
if x != nil {
return x.Listen
}
return ""
}
var File_app_metrics_config_proto protoreflect.FileDescriptor var File_app_metrics_config_proto protoreflect.FileDescriptor
var file_app_metrics_config_proto_rawDesc = []byte{ var file_app_metrics_config_proto_rawDesc = []byte{
0x0a, 0x18, 0x61, 0x70, 0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x63, 0x6f, 0x0a, 0x18, 0x61, 0x70, 0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61, 0x79, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x1a, 0x0a, 0x06, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x32, 0x0a, 0x06,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x42, 0x52, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e,
0x50, 0x01, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x42, 0x52, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x50, 0x01, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68,
0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0xaa, 0x02, 0x10, 0x58, 0x72, 0x61, 0x79, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
0x6f, 0x74, 0x6f, 0x33, 0x73, 0xaa, 0x02, 0x10, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4d, 0x65, 0x74,
0x72, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@@ -98,7 +105,7 @@ func file_app_metrics_config_proto_rawDescGZIP() []byte {
} }
var file_app_metrics_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_app_metrics_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_app_metrics_config_proto_goTypes = []interface{}{ var file_app_metrics_config_proto_goTypes = []any{
(*Config)(nil), // 0: xray.app.metrics.Config (*Config)(nil), // 0: xray.app.metrics.Config
} }
var file_app_metrics_config_proto_depIdxs = []int32{ var file_app_metrics_config_proto_depIdxs = []int32{
@@ -114,20 +121,6 @@ func file_app_metrics_config_proto_init() {
if File_app_metrics_config_proto != nil { if File_app_metrics_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_metrics_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -10,4 +10,5 @@ option java_multiple_files = true;
message Config { message Config {
// Tag of the outbound handler that handles metrics http connections. // Tag of the outbound handler that handles metrics http connections.
string tag = 1; string tag = 1;
string listen = 2;
} }

View File

@@ -24,12 +24,15 @@ type MetricsHandler struct {
statsManager feature_stats.Manager statsManager feature_stats.Manager
observatory extension.Observatory observatory extension.Observatory
tag string tag string
listen string
tcpListener net.Listener
} }
// NewMetricsHandler creates a new MetricsHandler based on the given config. // NewMetricsHandler creates a new MetricsHandler based on the given config.
func NewMetricsHandler(ctx context.Context, config *Config) (*MetricsHandler, error) { func NewMetricsHandler(ctx context.Context, config *Config) (*MetricsHandler, error) {
c := &MetricsHandler{ c := &MetricsHandler{
tag: config.Tag, tag: config.Tag,
listen: config.Listen,
} }
common.Must(core.RequireFeatures(ctx, func(om outbound.Manager, sm feature_stats.Manager) { common.Must(core.RequireFeatures(ctx, func(om outbound.Manager, sm feature_stats.Manager) {
c.statsManager = sm c.statsManager = sm
@@ -87,6 +90,23 @@ func (p *MetricsHandler) Type() interface{} {
} }
func (p *MetricsHandler) Start() error { func (p *MetricsHandler) Start() error {
// direct listen a port if listen is set
if p.listen != "" {
TCPlistener, err := net.Listen("tcp", p.listen)
if err != nil {
return err
}
p.tcpListener = TCPlistener
errors.LogInfo(context.Background(), "Metrics server listening on ", p.listen)
go func() {
if err := http.Serve(TCPlistener, http.DefaultServeMux); err != nil {
errors.LogErrorInner(context.Background(), err, "failed to start metrics server")
}
}()
}
listener := &OutboundListener{ listener := &OutboundListener{
buffer: make(chan net.Conn, 4), buffer: make(chan net.Conn, 4),
done: done.New(), done: done.New(),

View File

@@ -8,6 +8,7 @@ import (
"github.com/xtls/xray-core/common/errors" "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/net/cnc" "github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/signal/done" "github.com/xtls/xray-core/common/signal/done"
"github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport"
) )
@@ -108,3 +109,13 @@ func (co *Outbound) Close() error {
co.closed = true co.closed = true
return co.listener.Close() return co.listener.Close()
} }
// SenderSettings implements outbound.Handler.
func (co *Outbound) SenderSettings() *serial.TypedMessage {
return nil
}
// ProxySettings implements outbound.Handler.
func (co *Outbound) ProxySettings() *serial.TypedMessage {
return nil
}

View File

@@ -5,8 +5,6 @@ import (
"time" "time"
) )
//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
const ( const (
rttFailed = time.Duration(math.MaxInt64 - iota) rttFailed = time.Duration(math.MaxInt64 - iota)
rttUntested rttUntested

View File

@@ -12,6 +12,7 @@ import (
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"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/features/routing"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@@ -88,13 +89,15 @@ func (o *Observer) Close() error {
func New(ctx context.Context, config *Config) (*Observer, error) { func New(ctx context.Context, config *Config) (*Observer, error) {
var outboundManager outbound.Manager var outboundManager outbound.Manager
err := core.RequireFeatures(ctx, func(om outbound.Manager) { var dispatcher routing.Dispatcher
err := core.RequireFeatures(ctx, func(om outbound.Manager, rd routing.Dispatcher) {
outboundManager = om outboundManager = om
dispatcher = rd
}) })
if err != nil { if err != nil {
return nil, errors.New("Cannot get depended features").Base(err) return nil, errors.New("Cannot get depended features").Base(err)
} }
hp := NewHealthPing(ctx, config.PingConfig) hp := NewHealthPing(ctx, dispatcher, config.PingConfig)
return &Observer{ return &Observer{
config: config, config: config,
ctx: ctx, ctx: ctx,

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/observatory/burst/config.proto // source: app/observatory/burst/config.proto
package burst package burst
@@ -32,11 +32,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_burst_config_proto_msgTypes[0]
mi := &file_app_observatory_burst_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -47,7 +45,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_burst_config_proto_msgTypes[0] mi := &file_app_observatory_burst_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -92,15 +90,15 @@ type HealthPingConfig struct {
SamplingCount int32 `protobuf:"varint,4,opt,name=samplingCount,proto3" json:"samplingCount,omitempty"` SamplingCount int32 `protobuf:"varint,4,opt,name=samplingCount,proto3" json:"samplingCount,omitempty"`
// ping timeout, int64 values of time.Duration // ping timeout, int64 values of time.Duration
Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"` Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"`
// http method to make request
HttpMethod string `protobuf:"bytes,6,opt,name=httpMethod,proto3" json:"httpMethod,omitempty"`
} }
func (x *HealthPingConfig) Reset() { func (x *HealthPingConfig) Reset() {
*x = HealthPingConfig{} *x = HealthPingConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_burst_config_proto_msgTypes[1]
mi := &file_app_observatory_burst_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *HealthPingConfig) String() string { func (x *HealthPingConfig) String() string {
@@ -111,7 +109,7 @@ func (*HealthPingConfig) ProtoMessage() {}
func (x *HealthPingConfig) ProtoReflect() protoreflect.Message { func (x *HealthPingConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_burst_config_proto_msgTypes[1] mi := &file_app_observatory_burst_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -161,6 +159,13 @@ func (x *HealthPingConfig) GetTimeout() int64 {
return 0 return 0
} }
func (x *HealthPingConfig) GetHttpMethod() string {
if x != nil {
return x.HttpMethod
}
return ""
}
var File_app_observatory_burst_config_proto protoreflect.FileDescriptor var File_app_observatory_burst_config_proto protoreflect.FileDescriptor
var file_app_observatory_burst_config_proto_rawDesc = []byte{ var file_app_observatory_burst_config_proto_rawDesc = []byte{
@@ -177,7 +182,7 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{
0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72,
0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
0xb4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0xd4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69,
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
@@ -188,7 +193,9 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{
0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73,
0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07,
0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74,
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x4d, 0x65,
0x74, 0x68, 0x6f, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x74, 0x74, 0x70,
0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
@@ -211,7 +218,7 @@ func file_app_observatory_burst_config_proto_rawDescGZIP() []byte {
} }
var file_app_observatory_burst_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_app_observatory_burst_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_app_observatory_burst_config_proto_goTypes = []interface{}{ var file_app_observatory_burst_config_proto_goTypes = []any{
(*Config)(nil), // 0: xray.core.app.observatory.burst.Config (*Config)(nil), // 0: xray.core.app.observatory.burst.Config
(*HealthPingConfig)(nil), // 1: xray.core.app.observatory.burst.HealthPingConfig (*HealthPingConfig)(nil), // 1: xray.core.app.observatory.burst.HealthPingConfig
} }
@@ -229,32 +236,6 @@ func file_app_observatory_burst_config_proto_init() {
if File_app_observatory_burst_config_proto != nil { if File_app_observatory_burst_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_observatory_burst_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_burst_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HealthPingConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -26,4 +26,7 @@ message HealthPingConfig {
int32 samplingCount = 4; int32 samplingCount = 4;
// ping timeout, int64 values of time.Duration // ping timeout, int64 values of time.Duration
int64 timeout = 5; int64 timeout = 5;
// http method to make request
string httpMethod = 6;
} }

View File

@@ -9,6 +9,7 @@ import (
"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/errors"
"github.com/xtls/xray-core/features/routing"
) )
// HealthPingSettings holds settings for health Checker // HealthPingSettings holds settings for health Checker
@@ -18,11 +19,13 @@ type HealthPingSettings struct {
Interval time.Duration `json:"interval"` Interval time.Duration `json:"interval"`
SamplingCount int `json:"sampling"` SamplingCount int `json:"sampling"`
Timeout time.Duration `json:"timeout"` Timeout time.Duration `json:"timeout"`
HttpMethod string `json:"httpMethod"`
} }
// HealthPing is the health checker for balancers // HealthPing is the health checker for balancers
type HealthPing struct { type HealthPing struct {
ctx context.Context ctx context.Context
dispatcher routing.Dispatcher
access sync.Mutex access sync.Mutex
ticker *time.Ticker ticker *time.Ticker
tickerClose chan struct{} tickerClose chan struct{}
@@ -32,15 +35,24 @@ type HealthPing struct {
} }
// NewHealthPing creates a new HealthPing with settings // NewHealthPing creates a new HealthPing with settings
func NewHealthPing(ctx context.Context, config *HealthPingConfig) *HealthPing { func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *HealthPingConfig) *HealthPing {
settings := &HealthPingSettings{} settings := &HealthPingSettings{}
if config != nil { if config != nil {
var httpMethod string
if config.HttpMethod == "" {
httpMethod = "HEAD"
} else {
httpMethod = strings.TrimSpace(config.HttpMethod)
}
settings = &HealthPingSettings{ settings = &HealthPingSettings{
Connectivity: strings.TrimSpace(config.Connectivity), Connectivity: strings.TrimSpace(config.Connectivity),
Destination: strings.TrimSpace(config.Destination), Destination: strings.TrimSpace(config.Destination),
Interval: time.Duration(config.Interval), Interval: time.Duration(config.Interval),
SamplingCount: int(config.SamplingCount), SamplingCount: int(config.SamplingCount),
Timeout: time.Duration(config.Timeout), Timeout: time.Duration(config.Timeout),
HttpMethod: httpMethod,
} }
} }
if settings.Destination == "" { if settings.Destination == "" {
@@ -64,9 +76,10 @@ func NewHealthPing(ctx context.Context, config *HealthPingConfig) *HealthPing {
settings.Timeout = time.Duration(5) * time.Second settings.Timeout = time.Duration(5) * time.Second
} }
return &HealthPing{ return &HealthPing{
ctx: ctx, ctx: ctx,
Settings: settings, dispatcher: dispatcher,
Results: nil, Settings: settings,
Results: nil,
} }
} }
@@ -149,6 +162,7 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
handler := tag handler := tag
client := newPingClient( client := newPingClient(
h.ctx, h.ctx,
h.dispatcher,
h.Settings.Destination, h.Settings.Destination,
h.Settings.Timeout, h.Settings.Timeout,
handler, handler,
@@ -156,11 +170,11 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
for i := 0; i < rounds; i++ { for i := 0; i < rounds; i++ {
delay := time.Duration(0) delay := time.Duration(0)
if duration > 0 { if duration > 0 {
delay = time.Duration(dice.Roll(int(duration))) delay = time.Duration(dice.RollInt63n(int64(duration)))
} }
time.AfterFunc(delay, func() { time.AfterFunc(delay, func() {
errors.LogDebug(h.ctx, "checking ", handler) errors.LogDebug(h.ctx, "checking ", handler)
delay, err := client.MeasureDelay() delay, err := client.MeasureDelay(h.Settings.HttpMethod)
if err == nil { if err == nil {
ch <- &rtt{ ch <- &rtt{
handler: handler, handler: handler,
@@ -247,7 +261,7 @@ func (h *HealthPing) checkConnectivity() bool {
h.Settings.Connectivity, h.Settings.Connectivity,
h.Settings.Timeout, h.Settings.Timeout,
) )
if _, err := tester.MeasureDelay(); err != nil { if _, err := tester.MeasureDelay(h.Settings.HttpMethod); err != nil {
return false return false
} }
return true return true

View File

@@ -2,10 +2,12 @@ package burst
import ( import (
"context" "context"
"io"
"net/http" "net/http"
"time" "time"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/tagged" "github.com/xtls/xray-core/transport/internet/tagged"
) )
@@ -14,10 +16,10 @@ type pingClient struct {
httpClient *http.Client httpClient *http.Client
} }
func newPingClient(ctx context.Context, destination string, timeout time.Duration, handler string) *pingClient { func newPingClient(ctx context.Context, dispatcher routing.Dispatcher, destination string, timeout time.Duration, handler string) *pingClient {
return &pingClient{ return &pingClient{
destination: destination, destination: destination,
httpClient: newHTTPClient(ctx, handler, timeout), httpClient: newHTTPClient(ctx, dispatcher, handler, timeout),
} }
} }
@@ -28,7 +30,7 @@ func newDirectPingClient(destination string, timeout time.Duration) *pingClient
} }
} }
func newHTTPClient(ctxv context.Context, handler string, timeout time.Duration) *http.Client { func newHTTPClient(ctxv context.Context, dispatcher routing.Dispatcher, handler string, timeout time.Duration) *http.Client {
tr := &http.Transport{ tr := &http.Transport{
DisableKeepAlives: true, DisableKeepAlives: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
@@ -36,7 +38,7 @@ func newHTTPClient(ctxv context.Context, handler string, timeout time.Duration)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return tagged.Dialer(ctxv, dest, handler) return tagged.Dialer(ctxv, dispatcher, dest, handler)
}, },
} }
return &http.Client{ return &http.Client{
@@ -50,20 +52,28 @@ func newHTTPClient(ctxv context.Context, handler string, timeout time.Duration)
} }
// MeasureDelay returns the delay time of the request to dest // MeasureDelay returns the delay time of the request to dest
func (s *pingClient) MeasureDelay() (time.Duration, error) { func (s *pingClient) MeasureDelay(httpMethod string) (time.Duration, error) {
if s.httpClient == nil { if s.httpClient == nil {
panic("pingClient no initialized") panic("pingClient not initialized")
} }
req, err := http.NewRequest(http.MethodHead, s.destination, nil)
req, err := http.NewRequest(httpMethod, s.destination, nil)
if err != nil { if err != nil {
return rttFailed, err return rttFailed, err
} }
start := time.Now() start := time.Now()
resp, err := s.httpClient.Do(req) resp, err := s.httpClient.Do(req)
if err != nil { if err != nil {
return rttFailed, err return rttFailed, err
} }
// don't wait for body if httpMethod == http.MethodGet {
_, err = io.Copy(io.Discard, resp.Body)
if err != nil {
return rttFailed, err
}
}
resp.Body.Close() resp.Body.Close()
return time.Since(start), nil return time.Since(start), nil
} }

View File

@@ -38,7 +38,7 @@ func init() {
sv := &service{v: s} sv := &service{v: s}
err := s.RequireFeatures(func(Observatory extension.Observatory) { err := s.RequireFeatures(func(Observatory extension.Observatory) {
sv.observatory = Observatory sv.observatory = Observatory
}) }, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/observatory/command/command.proto // source: app/observatory/command/command.proto
package command package command
@@ -29,11 +29,9 @@ type GetOutboundStatusRequest struct {
func (x *GetOutboundStatusRequest) Reset() { func (x *GetOutboundStatusRequest) Reset() {
*x = GetOutboundStatusRequest{} *x = GetOutboundStatusRequest{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_command_command_proto_msgTypes[0]
mi := &file_app_observatory_command_command_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *GetOutboundStatusRequest) String() string { func (x *GetOutboundStatusRequest) String() string {
@@ -44,7 +42,7 @@ func (*GetOutboundStatusRequest) ProtoMessage() {}
func (x *GetOutboundStatusRequest) ProtoReflect() protoreflect.Message { func (x *GetOutboundStatusRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_command_command_proto_msgTypes[0] mi := &file_app_observatory_command_command_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -69,11 +67,9 @@ type GetOutboundStatusResponse struct {
func (x *GetOutboundStatusResponse) Reset() { func (x *GetOutboundStatusResponse) Reset() {
*x = GetOutboundStatusResponse{} *x = GetOutboundStatusResponse{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_command_command_proto_msgTypes[1]
mi := &file_app_observatory_command_command_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *GetOutboundStatusResponse) String() string { func (x *GetOutboundStatusResponse) String() string {
@@ -84,7 +80,7 @@ func (*GetOutboundStatusResponse) ProtoMessage() {}
func (x *GetOutboundStatusResponse) ProtoReflect() protoreflect.Message { func (x *GetOutboundStatusResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_command_command_proto_msgTypes[1] mi := &file_app_observatory_command_command_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -114,11 +110,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_command_command_proto_msgTypes[2]
mi := &file_app_observatory_command_command_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -129,7 +123,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_command_command_proto_msgTypes[2] mi := &file_app_observatory_command_command_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -197,7 +191,7 @@ func file_app_observatory_command_command_proto_rawDescGZIP() []byte {
} }
var file_app_observatory_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_app_observatory_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_app_observatory_command_command_proto_goTypes = []interface{}{ var file_app_observatory_command_command_proto_goTypes = []any{
(*GetOutboundStatusRequest)(nil), // 0: xray.core.app.observatory.command.GetOutboundStatusRequest (*GetOutboundStatusRequest)(nil), // 0: xray.core.app.observatory.command.GetOutboundStatusRequest
(*GetOutboundStatusResponse)(nil), // 1: xray.core.app.observatory.command.GetOutboundStatusResponse (*GetOutboundStatusResponse)(nil), // 1: xray.core.app.observatory.command.GetOutboundStatusResponse
(*Config)(nil), // 2: xray.core.app.observatory.command.Config (*Config)(nil), // 2: xray.core.app.observatory.command.Config
@@ -219,44 +213,6 @@ func file_app_observatory_command_command_proto_init() {
if File_app_observatory_command_command_proto != nil { if File_app_observatory_command_command_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_observatory_command_command_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetOutboundStatusRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_command_command_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetOutboundStatusResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_command_command_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.3.0 // - protoc-gen-go-grpc v1.5.1
// - protoc v5.27.0 // - protoc v5.28.2
// source: app/observatory/command/command.proto // source: app/observatory/command/command.proto
package command package command
@@ -15,8 +15,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later. // Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion7 const _ = grpc.SupportPackageIsVersion9
const ( const (
ObservatoryService_GetOutboundStatus_FullMethodName = "/xray.core.app.observatory.command.ObservatoryService/GetOutboundStatus" ObservatoryService_GetOutboundStatus_FullMethodName = "/xray.core.app.observatory.command.ObservatoryService/GetOutboundStatus"
@@ -38,8 +38,9 @@ func NewObservatoryServiceClient(cc grpc.ClientConnInterface) ObservatoryService
} }
func (c *observatoryServiceClient) GetOutboundStatus(ctx context.Context, in *GetOutboundStatusRequest, opts ...grpc.CallOption) (*GetOutboundStatusResponse, error) { func (c *observatoryServiceClient) GetOutboundStatus(ctx context.Context, in *GetOutboundStatusRequest, opts ...grpc.CallOption) (*GetOutboundStatusResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetOutboundStatusResponse) out := new(GetOutboundStatusResponse)
err := c.cc.Invoke(ctx, ObservatoryService_GetOutboundStatus_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, ObservatoryService_GetOutboundStatus_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -48,20 +49,24 @@ func (c *observatoryServiceClient) GetOutboundStatus(ctx context.Context, in *Ge
// ObservatoryServiceServer is the server API for ObservatoryService service. // ObservatoryServiceServer is the server API for ObservatoryService service.
// All implementations must embed UnimplementedObservatoryServiceServer // All implementations must embed UnimplementedObservatoryServiceServer
// for forward compatibility // for forward compatibility.
type ObservatoryServiceServer interface { type ObservatoryServiceServer interface {
GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error) GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error)
mustEmbedUnimplementedObservatoryServiceServer() mustEmbedUnimplementedObservatoryServiceServer()
} }
// UnimplementedObservatoryServiceServer must be embedded to have forward compatible implementations. // UnimplementedObservatoryServiceServer must be embedded to have
type UnimplementedObservatoryServiceServer struct { // forward compatible implementations.
} //
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedObservatoryServiceServer struct{}
func (UnimplementedObservatoryServiceServer) GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error) { func (UnimplementedObservatoryServiceServer) GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetOutboundStatus not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetOutboundStatus not implemented")
} }
func (UnimplementedObservatoryServiceServer) mustEmbedUnimplementedObservatoryServiceServer() {} func (UnimplementedObservatoryServiceServer) mustEmbedUnimplementedObservatoryServiceServer() {}
func (UnimplementedObservatoryServiceServer) testEmbeddedByValue() {}
// UnsafeObservatoryServiceServer may be embedded to opt out of forward compatibility for this service. // UnsafeObservatoryServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ObservatoryServiceServer will // Use of this interface is not recommended, as added methods to ObservatoryServiceServer will
@@ -71,6 +76,13 @@ type UnsafeObservatoryServiceServer interface {
} }
func RegisterObservatoryServiceServer(s grpc.ServiceRegistrar, srv ObservatoryServiceServer) { func RegisterObservatoryServiceServer(s grpc.ServiceRegistrar, srv ObservatoryServiceServer) {
// If the following call pancis, it indicates UnimplementedObservatoryServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&ObservatoryService_ServiceDesc, srv) s.RegisterService(&ObservatoryService_ServiceDesc, srv)
} }

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/observatory/config.proto // source: app/observatory/config.proto
package observatory package observatory
@@ -30,11 +30,9 @@ type ObservationResult struct {
func (x *ObservationResult) Reset() { func (x *ObservationResult) Reset() {
*x = ObservationResult{} *x = ObservationResult{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_config_proto_msgTypes[0]
mi := &file_app_observatory_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *ObservationResult) String() string { func (x *ObservationResult) String() string {
@@ -45,7 +43,7 @@ func (*ObservationResult) ProtoMessage() {}
func (x *ObservationResult) ProtoReflect() protoreflect.Message { func (x *ObservationResult) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[0] mi := &file_app_observatory_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -82,11 +80,9 @@ type HealthPingMeasurementResult struct {
func (x *HealthPingMeasurementResult) Reset() { func (x *HealthPingMeasurementResult) Reset() {
*x = HealthPingMeasurementResult{} *x = HealthPingMeasurementResult{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_config_proto_msgTypes[1]
mi := &file_app_observatory_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *HealthPingMeasurementResult) String() string { func (x *HealthPingMeasurementResult) String() string {
@@ -97,7 +93,7 @@ func (*HealthPingMeasurementResult) ProtoMessage() {}
func (x *HealthPingMeasurementResult) ProtoReflect() protoreflect.Message { func (x *HealthPingMeasurementResult) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[1] mi := &file_app_observatory_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -183,11 +179,9 @@ type OutboundStatus struct {
func (x *OutboundStatus) Reset() { func (x *OutboundStatus) Reset() {
*x = OutboundStatus{} *x = OutboundStatus{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_config_proto_msgTypes[2]
mi := &file_app_observatory_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *OutboundStatus) String() string { func (x *OutboundStatus) String() string {
@@ -198,7 +192,7 @@ func (*OutboundStatus) ProtoMessage() {}
func (x *OutboundStatus) ProtoReflect() protoreflect.Message { func (x *OutboundStatus) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[2] mi := &file_app_observatory_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -281,11 +275,9 @@ type ProbeResult struct {
func (x *ProbeResult) Reset() { func (x *ProbeResult) Reset() {
*x = ProbeResult{} *x = ProbeResult{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_config_proto_msgTypes[3]
mi := &file_app_observatory_config_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *ProbeResult) String() string { func (x *ProbeResult) String() string {
@@ -296,7 +288,7 @@ func (*ProbeResult) ProtoMessage() {}
func (x *ProbeResult) ProtoReflect() protoreflect.Message { func (x *ProbeResult) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[3] mi := &file_app_observatory_config_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -344,11 +336,9 @@ type Intensity struct {
func (x *Intensity) Reset() { func (x *Intensity) Reset() {
*x = Intensity{} *x = Intensity{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_config_proto_msgTypes[4]
mi := &file_app_observatory_config_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Intensity) String() string { func (x *Intensity) String() string {
@@ -359,7 +349,7 @@ func (*Intensity) ProtoMessage() {}
func (x *Intensity) ProtoReflect() protoreflect.Message { func (x *Intensity) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[4] mi := &file_app_observatory_config_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -395,11 +385,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_observatory_config_proto_msgTypes[5]
mi := &file_app_observatory_config_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -410,7 +398,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_observatory_config_proto_msgTypes[5] mi := &file_app_observatory_config_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -536,7 +524,7 @@ func file_app_observatory_config_proto_rawDescGZIP() []byte {
} }
var file_app_observatory_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_app_observatory_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_app_observatory_config_proto_goTypes = []interface{}{ var file_app_observatory_config_proto_goTypes = []any{
(*ObservationResult)(nil), // 0: xray.core.app.observatory.ObservationResult (*ObservationResult)(nil), // 0: xray.core.app.observatory.ObservationResult
(*HealthPingMeasurementResult)(nil), // 1: xray.core.app.observatory.HealthPingMeasurementResult (*HealthPingMeasurementResult)(nil), // 1: xray.core.app.observatory.HealthPingMeasurementResult
(*OutboundStatus)(nil), // 2: xray.core.app.observatory.OutboundStatus (*OutboundStatus)(nil), // 2: xray.core.app.observatory.OutboundStatus
@@ -559,80 +547,6 @@ func file_app_observatory_config_proto_init() {
if File_app_observatory_config_proto != nil { if File_app_observatory_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_observatory_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ObservationResult); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HealthPingMeasurementResult); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OutboundStatus); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ProbeResult); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Intensity); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_observatory_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -1,3 +1 @@
package observatory package observatory
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen

View File

@@ -18,6 +18,7 @@ import (
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"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/features/routing"
"github.com/xtls/xray-core/transport/internet/tagged" "github.com/xtls/xray-core/transport/internet/tagged"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@@ -31,7 +32,8 @@ type Observer struct {
finished *done.Instance finished *done.Instance
ohm outbound.Manager ohm outbound.Manager
dispatcher routing.Dispatcher
} }
func (o *Observer) GetObservation(ctx context.Context) (proto.Message, error) { func (o *Observer) GetObservation(ctx context.Context) (proto.Message, error) {
@@ -131,7 +133,7 @@ func (o *Observer) probe(outbound string) ProbeResult {
return errors.New("cannot understand address").Base(err) return errors.New("cannot understand address").Base(err)
} }
trackedCtx := session.TrackedConnectionError(o.ctx, errorCollectorForRequest) trackedCtx := session.TrackedConnectionError(o.ctx, errorCollectorForRequest)
conn, err := tagged.Dialer(trackedCtx, dest, outbound) conn, err := tagged.Dialer(trackedCtx, o.dispatcher, dest, outbound)
if err != nil { if err != nil {
return errors.New("cannot dial remote address ", dest).Base(err) return errors.New("cannot dial remote address ", dest).Base(err)
} }
@@ -215,16 +217,19 @@ func (o *Observer) findStatusLocationLockHolderOnly(outbound string) int {
func New(ctx context.Context, config *Config) (*Observer, error) { func New(ctx context.Context, config *Config) (*Observer, error) {
var outboundManager outbound.Manager var outboundManager outbound.Manager
err := core.RequireFeatures(ctx, func(om outbound.Manager) { var dispatcher routing.Dispatcher
err := core.RequireFeatures(ctx, func(om outbound.Manager, rd routing.Dispatcher) {
outboundManager = om outboundManager = om
dispatcher = rd
}) })
if err != nil { if err != nil {
return nil, errors.New("Cannot get depended features").Base(err) return nil, errors.New("Cannot get depended features").Base(err)
} }
return &Observer{ return &Observer{
config: config, config: config,
ctx: ctx, ctx: ctx,
ohm: outboundManager, ohm: outboundManager,
dispatcher: dispatcher,
}, nil }, nil
} }

View File

@@ -73,6 +73,7 @@ func (p *Policy) ToCorePolicy() policy.Session {
if p.Stats != nil { if p.Stats != nil {
cp.Stats.UserUplink = p.Stats.UserUplink cp.Stats.UserUplink = p.Stats.UserUplink
cp.Stats.UserDownlink = p.Stats.UserDownlink cp.Stats.UserDownlink = p.Stats.UserDownlink
cp.Stats.UserOnline = p.Stats.UserOnline
} }
if p.Buffer != nil { if p.Buffer != nil {
cp.Buffer.PerConnection = p.Buffer.Connection cp.Buffer.PerConnection = p.Buffer.Connection

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/policy/config.proto // source: app/policy/config.proto
package policy package policy
@@ -30,11 +30,9 @@ type Second struct {
func (x *Second) Reset() { func (x *Second) Reset() {
*x = Second{} *x = Second{}
if protoimpl.UnsafeEnabled { mi := &file_app_policy_config_proto_msgTypes[0]
mi := &file_app_policy_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Second) String() string { func (x *Second) String() string {
@@ -45,7 +43,7 @@ func (*Second) ProtoMessage() {}
func (x *Second) ProtoReflect() protoreflect.Message { func (x *Second) ProtoReflect() protoreflect.Message {
mi := &file_app_policy_config_proto_msgTypes[0] mi := &file_app_policy_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -79,11 +77,9 @@ type Policy struct {
func (x *Policy) Reset() { func (x *Policy) Reset() {
*x = Policy{} *x = Policy{}
if protoimpl.UnsafeEnabled { mi := &file_app_policy_config_proto_msgTypes[1]
mi := &file_app_policy_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Policy) String() string { func (x *Policy) String() string {
@@ -94,7 +90,7 @@ func (*Policy) ProtoMessage() {}
func (x *Policy) ProtoReflect() protoreflect.Message { func (x *Policy) ProtoReflect() protoreflect.Message {
mi := &file_app_policy_config_proto_msgTypes[1] mi := &file_app_policy_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -140,11 +136,9 @@ type SystemPolicy struct {
func (x *SystemPolicy) Reset() { func (x *SystemPolicy) Reset() {
*x = SystemPolicy{} *x = SystemPolicy{}
if protoimpl.UnsafeEnabled { mi := &file_app_policy_config_proto_msgTypes[2]
mi := &file_app_policy_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *SystemPolicy) String() string { func (x *SystemPolicy) String() string {
@@ -155,7 +149,7 @@ func (*SystemPolicy) ProtoMessage() {}
func (x *SystemPolicy) ProtoReflect() protoreflect.Message { func (x *SystemPolicy) ProtoReflect() protoreflect.Message {
mi := &file_app_policy_config_proto_msgTypes[2] mi := &file_app_policy_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -188,11 +182,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_policy_config_proto_msgTypes[3]
mi := &file_app_policy_config_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -203,7 +195,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_policy_config_proto_msgTypes[3] mi := &file_app_policy_config_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -246,11 +238,9 @@ type Policy_Timeout struct {
func (x *Policy_Timeout) Reset() { func (x *Policy_Timeout) Reset() {
*x = Policy_Timeout{} *x = Policy_Timeout{}
if protoimpl.UnsafeEnabled { mi := &file_app_policy_config_proto_msgTypes[4]
mi := &file_app_policy_config_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Policy_Timeout) String() string { func (x *Policy_Timeout) String() string {
@@ -261,7 +251,7 @@ func (*Policy_Timeout) ProtoMessage() {}
func (x *Policy_Timeout) ProtoReflect() protoreflect.Message { func (x *Policy_Timeout) ProtoReflect() protoreflect.Message {
mi := &file_app_policy_config_proto_msgTypes[4] mi := &file_app_policy_config_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -311,15 +301,14 @@ type Policy_Stats struct {
UserUplink bool `protobuf:"varint,1,opt,name=user_uplink,json=userUplink,proto3" json:"user_uplink,omitempty"` UserUplink bool `protobuf:"varint,1,opt,name=user_uplink,json=userUplink,proto3" json:"user_uplink,omitempty"`
UserDownlink bool `protobuf:"varint,2,opt,name=user_downlink,json=userDownlink,proto3" json:"user_downlink,omitempty"` UserDownlink bool `protobuf:"varint,2,opt,name=user_downlink,json=userDownlink,proto3" json:"user_downlink,omitempty"`
UserOnline bool `protobuf:"varint,3,opt,name=user_online,json=userOnline,proto3" json:"user_online,omitempty"`
} }
func (x *Policy_Stats) Reset() { func (x *Policy_Stats) Reset() {
*x = Policy_Stats{} *x = Policy_Stats{}
if protoimpl.UnsafeEnabled { mi := &file_app_policy_config_proto_msgTypes[5]
mi := &file_app_policy_config_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Policy_Stats) String() string { func (x *Policy_Stats) String() string {
@@ -330,7 +319,7 @@ func (*Policy_Stats) ProtoMessage() {}
func (x *Policy_Stats) ProtoReflect() protoreflect.Message { func (x *Policy_Stats) ProtoReflect() protoreflect.Message {
mi := &file_app_policy_config_proto_msgTypes[5] mi := &file_app_policy_config_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -359,6 +348,13 @@ func (x *Policy_Stats) GetUserDownlink() bool {
return false return false
} }
func (x *Policy_Stats) GetUserOnline() bool {
if x != nil {
return x.UserOnline
}
return false
}
type Policy_Buffer struct { type Policy_Buffer struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -370,11 +366,9 @@ type Policy_Buffer struct {
func (x *Policy_Buffer) Reset() { func (x *Policy_Buffer) Reset() {
*x = Policy_Buffer{} *x = Policy_Buffer{}
if protoimpl.UnsafeEnabled { mi := &file_app_policy_config_proto_msgTypes[6]
mi := &file_app_policy_config_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Policy_Buffer) String() string { func (x *Policy_Buffer) String() string {
@@ -385,7 +379,7 @@ func (*Policy_Buffer) ProtoMessage() {}
func (x *Policy_Buffer) ProtoReflect() protoreflect.Message { func (x *Policy_Buffer) ProtoReflect() protoreflect.Message {
mi := &file_app_policy_config_proto_msgTypes[6] mi := &file_app_policy_config_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -420,11 +414,9 @@ type SystemPolicy_Stats struct {
func (x *SystemPolicy_Stats) Reset() { func (x *SystemPolicy_Stats) Reset() {
*x = SystemPolicy_Stats{} *x = SystemPolicy_Stats{}
if protoimpl.UnsafeEnabled { mi := &file_app_policy_config_proto_msgTypes[7]
mi := &file_app_policy_config_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *SystemPolicy_Stats) String() string { func (x *SystemPolicy_Stats) String() string {
@@ -435,7 +427,7 @@ func (*SystemPolicy_Stats) ProtoMessage() {}
func (x *SystemPolicy_Stats) ProtoReflect() protoreflect.Message { func (x *SystemPolicy_Stats) ProtoReflect() protoreflect.Message {
mi := &file_app_policy_config_proto_msgTypes[7] mi := &file_app_policy_config_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -485,7 +477,7 @@ var file_app_policy_config_proto_rawDesc = []byte{
0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x1e, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x1e, 0x0a, 0x06, 0x53, 0x65,
0x63, 0x6f, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa6, 0x04, 0x0a, 0x06, 0x50, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc7, 0x04, 0x0a, 0x06, 0x50,
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
@@ -512,49 +504,51 @@ var file_app_policy_config_proto_rawDesc = []byte{
0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x0c, 0x64, 0x6f, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x0c, 0x64, 0x6f,
0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x4f, 0x6e, 0x6c, 0x79, 0x1a, 0x4d, 0x0a, 0x05, 0x53, 0x74, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x4f, 0x6e, 0x6c, 0x79, 0x1a, 0x6e, 0x0a, 0x05, 0x53, 0x74,
0x61, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x61, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x6c, 0x69,
0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x55, 0x70, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x55, 0x70,
0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x6f, 0x77, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x6f, 0x77,
0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65,
0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x1a, 0x28, 0x0a, 0x06, 0x42, 0x75, 0x66, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x73, 0x65,
0x66, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x72, 0x5f, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a,
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x75, 0x73, 0x65, 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x1a, 0x28, 0x0a, 0x06, 0x42, 0x75,
0x69, 0x6f, 0x6e, 0x22, 0xfb, 0x01, 0x0a, 0x0c, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69,
0x6c, 0x69, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xfb, 0x01, 0x0a, 0x0c, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50,
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6f, 0x6c, 0x69, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01,
0x63, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0xaf, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x62, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6f, 0x6c,
0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73,
0x08, 0x52, 0x0d, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x1a, 0xaf, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e,
0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01,
0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e, 0x62, 0x6f, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x70, 0x6c, 0x69, 0x6e,
0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x6b, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x64, 0x6f, 0x77,
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e, 0x62,
0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x27, 0x0a, 0x0f,
0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18,
0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55,
0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e,
0x6b, 0x22, 0xcc, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a, 0x05, 0x64, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x6b, 0x22, 0xcc, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a,
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78,
0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65,
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x1a, 0x51, 0x0a, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x0a, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x1a, 0x51,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x0a, 0x0a, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d,
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x01, 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xaa, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68,
0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79,
0xaa, 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x69,
0x63, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@@ -570,7 +564,7 @@ func file_app_policy_config_proto_rawDescGZIP() []byte {
} }
var file_app_policy_config_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_app_policy_config_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_app_policy_config_proto_goTypes = []interface{}{ var file_app_policy_config_proto_goTypes = []any{
(*Second)(nil), // 0: xray.app.policy.Second (*Second)(nil), // 0: xray.app.policy.Second
(*Policy)(nil), // 1: xray.app.policy.Policy (*Policy)(nil), // 1: xray.app.policy.Policy
(*SystemPolicy)(nil), // 2: xray.app.policy.SystemPolicy (*SystemPolicy)(nil), // 2: xray.app.policy.SystemPolicy
@@ -605,104 +599,6 @@ func file_app_policy_config_proto_init() {
if File_app_policy_config_proto != nil { if File_app_policy_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_policy_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Second); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Policy); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SystemPolicy); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Policy_Timeout); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Policy_Stats); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Policy_Buffer); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_policy_config_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SystemPolicy_Stats); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -22,6 +22,7 @@ message Policy {
message Stats { message Stats {
bool user_uplink = 1; bool user_uplink = 1;
bool user_downlink = 2; bool user_downlink = 2;
bool user_online = 3;
} }
message Buffer { message Buffer {

View File

@@ -1,4 +1,2 @@
// Package policy is an implementation of policy.Manager feature. // Package policy is an implementation of policy.Manager feature.
package policy package policy
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen

View File

@@ -3,8 +3,10 @@ package command
import ( import (
"context" "context"
"github.com/xtls/xray-core/app/commander"
"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"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/inbound" "github.com/xtls/xray-core/features/inbound"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
@@ -98,6 +100,68 @@ func (s *handlerServer) AlterInbound(ctx context.Context, request *AlterInboundR
return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler) return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler)
} }
func (s *handlerServer) ListInbounds(ctx context.Context, request *ListInboundsRequest) (*ListInboundsResponse, error) {
handlers := s.ihm.ListHandlers(ctx)
response := &ListInboundsResponse{}
if request.GetIsOnlyTags() {
for _, handler := range handlers {
response.Inbounds = append(response.Inbounds, &core.InboundHandlerConfig{
Tag: handler.Tag(),
})
}
} else {
for _, handler := range handlers {
response.Inbounds = append(response.Inbounds, &core.InboundHandlerConfig{
Tag: handler.Tag(),
ReceiverSettings: handler.ReceiverSettings(),
ProxySettings: handler.ProxySettings(),
})
}
}
return response, nil
}
func (s *handlerServer) GetInboundUsers(ctx context.Context, request *GetInboundUserRequest) (*GetInboundUserResponse, error) {
handler, err := s.ihm.GetHandler(ctx, request.Tag)
if err != nil {
return nil, errors.New("failed to get handler: ", request.Tag).Base(err)
}
p, err := getInbound(handler)
if err != nil {
return nil, err
}
um, ok := p.(proxy.UserManager)
if !ok {
return nil, errors.New("proxy is not a UserManager")
}
if len(request.Email) > 0 {
return &GetInboundUserResponse{Users: []*protocol.User{protocol.ToProtoUser(um.GetUser(ctx, request.Email))}}, nil
}
var result = make([]*protocol.User, 0, 100)
users := um.GetUsers(ctx)
for _, u := range users {
result = append(result, protocol.ToProtoUser(u))
}
return &GetInboundUserResponse{Users: result}, nil
}
func (s *handlerServer) GetInboundUsersCount(ctx context.Context, request *GetInboundUserRequest) (*GetInboundUsersCountResponse, error) {
handler, err := s.ihm.GetHandler(ctx, request.Tag)
if err != nil {
return nil, errors.New("failed to get handler: ", request.Tag).Base(err)
}
p, err := getInbound(handler)
if err != nil {
return nil, err
}
um, ok := p.(proxy.UserManager)
if !ok {
return nil, errors.New("proxy is not a UserManager")
}
return &GetInboundUsersCountResponse{Count: um.GetUsersCount(ctx)}, nil
}
func (s *handlerServer) AddOutbound(ctx context.Context, request *AddOutboundRequest) (*AddOutboundResponse, error) { func (s *handlerServer) AddOutbound(ctx context.Context, request *AddOutboundRequest) (*AddOutboundResponse, error) {
if err := core.AddOutboundHandler(s.s, request.Outbound); err != nil { if err := core.AddOutboundHandler(s.s, request.Outbound); err != nil {
return nil, err return nil, err
@@ -123,6 +187,23 @@ func (s *handlerServer) AlterOutbound(ctx context.Context, request *AlterOutboun
return &AlterOutboundResponse{}, operation.ApplyOutbound(ctx, handler) return &AlterOutboundResponse{}, operation.ApplyOutbound(ctx, handler)
} }
func (s *handlerServer) ListOutbounds(ctx context.Context, request *ListOutboundsRequest) (*ListOutboundsResponse, error) {
handlers := s.ohm.ListHandlers(ctx)
response := &ListOutboundsResponse{}
for _, handler := range handlers {
// Ignore gRPC outbound
if _, ok := handler.(*commander.Outbound); ok {
continue
}
response.Outbounds = append(response.Outbounds, &core.OutboundHandlerConfig{
Tag: handler.Tag(),
SenderSettings: handler.SenderSettings(),
ProxySettings: handler.ProxySettings(),
})
}
return response, nil
}
func (s *handlerServer) mustEmbedUnimplementedHandlerServiceServer() {} func (s *handlerServer) mustEmbedUnimplementedHandlerServiceServer() {}
type service struct { type service struct {
@@ -136,7 +217,7 @@ func (s *service) Register(server *grpc.Server) {
common.Must(s.v.RequireFeatures(func(im inbound.Manager, om outbound.Manager) { common.Must(s.v.RequireFeatures(func(im inbound.Manager, om outbound.Manager) {
hs.ihm = im hs.ihm = im
hs.ohm = om hs.ohm = om
})) }, false))
RegisterHandlerServiceServer(server, hs) RegisterHandlerServiceServer(server, hs)
// For compatibility purposes // For compatibility purposes

File diff suppressed because it is too large Load Diff

View File

@@ -37,6 +37,27 @@ message AlterInboundRequest {
message AlterInboundResponse {} message AlterInboundResponse {}
message ListInboundsRequest {
bool isOnlyTags = 1;
}
message ListInboundsResponse {
repeated core.InboundHandlerConfig inbounds = 1;
}
message GetInboundUserRequest {
string tag = 1;
string email = 2;
}
message GetInboundUserResponse {
repeated xray.common.protocol.User users = 1;
}
message GetInboundUsersCountResponse {
int64 count = 1;
}
message AddOutboundRequest { message AddOutboundRequest {
core.OutboundHandlerConfig outbound = 1; core.OutboundHandlerConfig outbound = 1;
} }
@@ -56,6 +77,12 @@ message AlterOutboundRequest {
message AlterOutboundResponse {} message AlterOutboundResponse {}
message ListOutboundsRequest {}
message ListOutboundsResponse {
repeated core.OutboundHandlerConfig outbounds = 1;
}
service HandlerService { service HandlerService {
rpc AddInbound(AddInboundRequest) returns (AddInboundResponse) {} rpc AddInbound(AddInboundRequest) returns (AddInboundResponse) {}
@@ -63,11 +90,19 @@ service HandlerService {
rpc AlterInbound(AlterInboundRequest) returns (AlterInboundResponse) {} rpc AlterInbound(AlterInboundRequest) returns (AlterInboundResponse) {}
rpc ListInbounds(ListInboundsRequest) returns (ListInboundsResponse) {}
rpc GetInboundUsers(GetInboundUserRequest) returns (GetInboundUserResponse) {}
rpc GetInboundUsersCount(GetInboundUserRequest) returns (GetInboundUsersCountResponse) {}
rpc AddOutbound(AddOutboundRequest) returns (AddOutboundResponse) {} rpc AddOutbound(AddOutboundRequest) returns (AddOutboundResponse) {}
rpc RemoveOutbound(RemoveOutboundRequest) returns (RemoveOutboundResponse) {} rpc RemoveOutbound(RemoveOutboundRequest) returns (RemoveOutboundResponse) {}
rpc AlterOutbound(AlterOutboundRequest) returns (AlterOutboundResponse) {} rpc AlterOutbound(AlterOutboundRequest) returns (AlterOutboundResponse) {}
rpc ListOutbounds(ListOutboundsRequest) returns (ListOutboundsResponse) {}
} }
message Config {} message Config {}

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.3.0 // - protoc-gen-go-grpc v1.5.1
// - protoc v5.27.0 // - protoc v5.28.2
// source: app/proxyman/command/command.proto // source: app/proxyman/command/command.proto
package command package command
@@ -15,16 +15,20 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later. // Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion7 const _ = grpc.SupportPackageIsVersion9
const ( const (
HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound" HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound"
HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound" HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound"
HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound" HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound"
HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound" HandlerService_ListInbounds_FullMethodName = "/xray.app.proxyman.command.HandlerService/ListInbounds"
HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound" HandlerService_GetInboundUsers_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsers"
HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound" HandlerService_GetInboundUsersCount_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsersCount"
HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound"
HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound"
HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound"
HandlerService_ListOutbounds_FullMethodName = "/xray.app.proxyman.command.HandlerService/ListOutbounds"
) )
// HandlerServiceClient is the client API for HandlerService service. // HandlerServiceClient is the client API for HandlerService service.
@@ -34,9 +38,13 @@ type HandlerServiceClient interface {
AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error) AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error)
RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error) RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error)
AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error) AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error)
ListInbounds(ctx context.Context, in *ListInboundsRequest, opts ...grpc.CallOption) (*ListInboundsResponse, error)
GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error)
GetInboundUsersCount(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUsersCountResponse, error)
AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error) AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error)
RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error) RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error)
AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error) AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error)
ListOutbounds(ctx context.Context, in *ListOutboundsRequest, opts ...grpc.CallOption) (*ListOutboundsResponse, error)
} }
type handlerServiceClient struct { type handlerServiceClient struct {
@@ -48,8 +56,9 @@ func NewHandlerServiceClient(cc grpc.ClientConnInterface) HandlerServiceClient {
} }
func (c *handlerServiceClient) AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error) { func (c *handlerServiceClient) AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AddInboundResponse) out := new(AddInboundResponse)
err := c.cc.Invoke(ctx, HandlerService_AddInbound_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, HandlerService_AddInbound_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -57,8 +66,9 @@ func (c *handlerServiceClient) AddInbound(ctx context.Context, in *AddInboundReq
} }
func (c *handlerServiceClient) RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error) { func (c *handlerServiceClient) RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RemoveInboundResponse) out := new(RemoveInboundResponse)
err := c.cc.Invoke(ctx, HandlerService_RemoveInbound_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, HandlerService_RemoveInbound_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -66,8 +76,39 @@ func (c *handlerServiceClient) RemoveInbound(ctx context.Context, in *RemoveInbo
} }
func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error) { func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AlterInboundResponse) out := new(AlterInboundResponse)
err := c.cc.Invoke(ctx, HandlerService_AlterInbound_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, HandlerService_AlterInbound_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *handlerServiceClient) ListInbounds(ctx context.Context, in *ListInboundsRequest, opts ...grpc.CallOption) (*ListInboundsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListInboundsResponse)
err := c.cc.Invoke(ctx, HandlerService_ListInbounds_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *handlerServiceClient) GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetInboundUserResponse)
err := c.cc.Invoke(ctx, HandlerService_GetInboundUsers_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *handlerServiceClient) GetInboundUsersCount(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUsersCountResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetInboundUsersCountResponse)
err := c.cc.Invoke(ctx, HandlerService_GetInboundUsersCount_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -75,8 +116,9 @@ func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboun
} }
func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error) { func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AddOutboundResponse) out := new(AddOutboundResponse)
err := c.cc.Invoke(ctx, HandlerService_AddOutbound_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, HandlerService_AddOutbound_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -84,8 +126,9 @@ func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *AddOutboundR
} }
func (c *handlerServiceClient) RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error) { func (c *handlerServiceClient) RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RemoveOutboundResponse) out := new(RemoveOutboundResponse)
err := c.cc.Invoke(ctx, HandlerService_RemoveOutbound_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, HandlerService_RemoveOutbound_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -93,8 +136,19 @@ func (c *handlerServiceClient) RemoveOutbound(ctx context.Context, in *RemoveOut
} }
func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error) { func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AlterOutboundResponse) out := new(AlterOutboundResponse)
err := c.cc.Invoke(ctx, HandlerService_AlterOutbound_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, HandlerService_AlterOutbound_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *handlerServiceClient) ListOutbounds(ctx context.Context, in *ListOutboundsRequest, opts ...grpc.CallOption) (*ListOutboundsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListOutboundsResponse)
err := c.cc.Invoke(ctx, HandlerService_ListOutbounds_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -103,20 +157,27 @@ func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *AlterOutbo
// HandlerServiceServer is the server API for HandlerService service. // HandlerServiceServer is the server API for HandlerService service.
// All implementations must embed UnimplementedHandlerServiceServer // All implementations must embed UnimplementedHandlerServiceServer
// for forward compatibility // for forward compatibility.
type HandlerServiceServer interface { type HandlerServiceServer interface {
AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error) AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error)
RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error) RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error)
AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error)
ListInbounds(context.Context, *ListInboundsRequest) (*ListInboundsResponse, error)
GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error)
GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error)
AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error) AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error)
RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error) RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error)
AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error) AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error)
ListOutbounds(context.Context, *ListOutboundsRequest) (*ListOutboundsResponse, error)
mustEmbedUnimplementedHandlerServiceServer() mustEmbedUnimplementedHandlerServiceServer()
} }
// UnimplementedHandlerServiceServer must be embedded to have forward compatible implementations. // UnimplementedHandlerServiceServer must be embedded to have
type UnimplementedHandlerServiceServer struct { // forward compatible implementations.
} //
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedHandlerServiceServer struct{}
func (UnimplementedHandlerServiceServer) AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error) { func (UnimplementedHandlerServiceServer) AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddInbound not implemented") return nil, status.Errorf(codes.Unimplemented, "method AddInbound not implemented")
@@ -127,6 +188,15 @@ func (UnimplementedHandlerServiceServer) RemoveInbound(context.Context, *RemoveI
func (UnimplementedHandlerServiceServer) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) { func (UnimplementedHandlerServiceServer) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AlterInbound not implemented") return nil, status.Errorf(codes.Unimplemented, "method AlterInbound not implemented")
} }
func (UnimplementedHandlerServiceServer) ListInbounds(context.Context, *ListInboundsRequest) (*ListInboundsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListInbounds not implemented")
}
func (UnimplementedHandlerServiceServer) GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetInboundUsers not implemented")
}
func (UnimplementedHandlerServiceServer) GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetInboundUsersCount not implemented")
}
func (UnimplementedHandlerServiceServer) AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error) { func (UnimplementedHandlerServiceServer) AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddOutbound not implemented") return nil, status.Errorf(codes.Unimplemented, "method AddOutbound not implemented")
} }
@@ -136,7 +206,11 @@ func (UnimplementedHandlerServiceServer) RemoveOutbound(context.Context, *Remove
func (UnimplementedHandlerServiceServer) AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error) { func (UnimplementedHandlerServiceServer) AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AlterOutbound not implemented") return nil, status.Errorf(codes.Unimplemented, "method AlterOutbound not implemented")
} }
func (UnimplementedHandlerServiceServer) ListOutbounds(context.Context, *ListOutboundsRequest) (*ListOutboundsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListOutbounds not implemented")
}
func (UnimplementedHandlerServiceServer) mustEmbedUnimplementedHandlerServiceServer() {} func (UnimplementedHandlerServiceServer) mustEmbedUnimplementedHandlerServiceServer() {}
func (UnimplementedHandlerServiceServer) testEmbeddedByValue() {}
// UnsafeHandlerServiceServer may be embedded to opt out of forward compatibility for this service. // UnsafeHandlerServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to HandlerServiceServer will // Use of this interface is not recommended, as added methods to HandlerServiceServer will
@@ -146,6 +220,13 @@ type UnsafeHandlerServiceServer interface {
} }
func RegisterHandlerServiceServer(s grpc.ServiceRegistrar, srv HandlerServiceServer) { func RegisterHandlerServiceServer(s grpc.ServiceRegistrar, srv HandlerServiceServer) {
// If the following call pancis, it indicates UnimplementedHandlerServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&HandlerService_ServiceDesc, srv) s.RegisterService(&HandlerService_ServiceDesc, srv)
} }
@@ -203,6 +284,60 @@ func _HandlerService_AlterInbound_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _HandlerService_ListInbounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListInboundsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HandlerServiceServer).ListInbounds(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: HandlerService_ListInbounds_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HandlerServiceServer).ListInbounds(ctx, req.(*ListInboundsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HandlerService_GetInboundUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetInboundUserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HandlerServiceServer).GetInboundUsers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: HandlerService_GetInboundUsers_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HandlerServiceServer).GetInboundUsers(ctx, req.(*GetInboundUserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HandlerService_GetInboundUsersCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetInboundUserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HandlerServiceServer).GetInboundUsersCount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: HandlerService_GetInboundUsersCount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HandlerServiceServer).GetInboundUsersCount(ctx, req.(*GetInboundUserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _HandlerService_AddOutbound_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _HandlerService_AddOutbound_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddOutboundRequest) in := new(AddOutboundRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@@ -257,6 +392,24 @@ func _HandlerService_AlterOutbound_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _HandlerService_ListOutbounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListOutboundsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(HandlerServiceServer).ListOutbounds(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: HandlerService_ListOutbounds_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(HandlerServiceServer).ListOutbounds(ctx, req.(*ListOutboundsRequest))
}
return interceptor(ctx, in, info, handler)
}
// HandlerService_ServiceDesc is the grpc.ServiceDesc for HandlerService service. // HandlerService_ServiceDesc is the grpc.ServiceDesc for HandlerService service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
@@ -276,6 +429,18 @@ var HandlerService_ServiceDesc = grpc.ServiceDesc{
MethodName: "AlterInbound", MethodName: "AlterInbound",
Handler: _HandlerService_AlterInbound_Handler, Handler: _HandlerService_AlterInbound_Handler,
}, },
{
MethodName: "ListInbounds",
Handler: _HandlerService_ListInbounds_Handler,
},
{
MethodName: "GetInboundUsers",
Handler: _HandlerService_GetInboundUsers_Handler,
},
{
MethodName: "GetInboundUsersCount",
Handler: _HandlerService_GetInboundUsersCount_Handler,
},
{ {
MethodName: "AddOutbound", MethodName: "AddOutbound",
Handler: _HandlerService_AddOutbound_Handler, Handler: _HandlerService_AddOutbound_Handler,
@@ -288,6 +453,10 @@ var HandlerService_ServiceDesc = grpc.ServiceDesc{
MethodName: "AlterOutbound", MethodName: "AlterOutbound",
Handler: _HandlerService_AlterOutbound_Handler, Handler: _HandlerService_AlterOutbound_Handler,
}, },
{
MethodName: "ListOutbounds",
Handler: _HandlerService_ListOutbounds_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "app/proxyman/command/command.proto", Metadata: "app/proxyman/command/command.proto",

View File

@@ -1,3 +1 @@
package command package command
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen

View File

@@ -19,21 +19,5 @@ func (c *ReceiverConfig) GetEffectiveSniffingSettings() *SniffingConfig {
return c.SniffingSettings return c.SniffingSettings
} }
if len(c.DomainOverride) > 0 {
var p []string
for _, kd := range c.DomainOverride {
switch kd {
case KnownProtocols_HTTP:
p = append(p, "http")
case KnownProtocols_TLS:
p = append(p, "tls")
}
}
return &SniffingConfig{
Enabled: true,
DestinationOverride: p,
}
}
return nil return nil
} }

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/proxyman/config.proto // source: app/proxyman/config.proto
package proxyman package proxyman
@@ -23,52 +23,6 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
type KnownProtocols int32
const (
KnownProtocols_HTTP KnownProtocols = 0
KnownProtocols_TLS KnownProtocols = 1
)
// Enum value maps for KnownProtocols.
var (
KnownProtocols_name = map[int32]string{
0: "HTTP",
1: "TLS",
}
KnownProtocols_value = map[string]int32{
"HTTP": 0,
"TLS": 1,
}
)
func (x KnownProtocols) Enum() *KnownProtocols {
p := new(KnownProtocols)
*p = x
return p
}
func (x KnownProtocols) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (KnownProtocols) Descriptor() protoreflect.EnumDescriptor {
return file_app_proxyman_config_proto_enumTypes[0].Descriptor()
}
func (KnownProtocols) Type() protoreflect.EnumType {
return &file_app_proxyman_config_proto_enumTypes[0]
}
func (x KnownProtocols) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use KnownProtocols.Descriptor instead.
func (KnownProtocols) EnumDescriptor() ([]byte, []int) {
return file_app_proxyman_config_proto_rawDescGZIP(), []int{0}
}
type AllocationStrategy_Type int32 type AllocationStrategy_Type int32
const ( const (
@@ -105,11 +59,11 @@ func (x AllocationStrategy_Type) String() string {
} }
func (AllocationStrategy_Type) Descriptor() protoreflect.EnumDescriptor { func (AllocationStrategy_Type) Descriptor() protoreflect.EnumDescriptor {
return file_app_proxyman_config_proto_enumTypes[1].Descriptor() return file_app_proxyman_config_proto_enumTypes[0].Descriptor()
} }
func (AllocationStrategy_Type) Type() protoreflect.EnumType { func (AllocationStrategy_Type) Type() protoreflect.EnumType {
return &file_app_proxyman_config_proto_enumTypes[1] return &file_app_proxyman_config_proto_enumTypes[0]
} }
func (x AllocationStrategy_Type) Number() protoreflect.EnumNumber { func (x AllocationStrategy_Type) Number() protoreflect.EnumNumber {
@@ -129,11 +83,9 @@ type InboundConfig struct {
func (x *InboundConfig) Reset() { func (x *InboundConfig) Reset() {
*x = InboundConfig{} *x = InboundConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[0]
mi := &file_app_proxyman_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *InboundConfig) String() string { func (x *InboundConfig) String() string {
@@ -144,7 +96,7 @@ func (*InboundConfig) ProtoMessage() {}
func (x *InboundConfig) ProtoReflect() protoreflect.Message { func (x *InboundConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[0] mi := &file_app_proxyman_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -175,11 +127,9 @@ type AllocationStrategy struct {
func (x *AllocationStrategy) Reset() { func (x *AllocationStrategy) Reset() {
*x = AllocationStrategy{} *x = AllocationStrategy{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[1]
mi := &file_app_proxyman_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *AllocationStrategy) String() string { func (x *AllocationStrategy) String() string {
@@ -190,7 +140,7 @@ func (*AllocationStrategy) ProtoMessage() {}
func (x *AllocationStrategy) ProtoReflect() protoreflect.Message { func (x *AllocationStrategy) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[1] mi := &file_app_proxyman_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -246,11 +196,9 @@ type SniffingConfig struct {
func (x *SniffingConfig) Reset() { func (x *SniffingConfig) Reset() {
*x = SniffingConfig{} *x = SniffingConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[2]
mi := &file_app_proxyman_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *SniffingConfig) String() string { func (x *SniffingConfig) String() string {
@@ -261,7 +209,7 @@ func (*SniffingConfig) ProtoMessage() {}
func (x *SniffingConfig) ProtoReflect() protoreflect.Message { func (x *SniffingConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[2] mi := &file_app_proxyman_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -323,21 +271,14 @@ type ReceiverConfig struct {
AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"` AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"`
StreamSettings *internet.StreamConfig `protobuf:"bytes,4,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"` StreamSettings *internet.StreamConfig `protobuf:"bytes,4,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
ReceiveOriginalDestination bool `protobuf:"varint,5,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"` ReceiveOriginalDestination bool `protobuf:"varint,5,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"`
// Override domains for the given protocol. SniffingSettings *SniffingConfig `protobuf:"bytes,7,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
// Deprecated. Use sniffing_settings.
//
// Deprecated: Marked as deprecated in app/proxyman/config.proto.
DomainOverride []KnownProtocols `protobuf:"varint,7,rep,packed,name=domain_override,json=domainOverride,proto3,enum=xray.app.proxyman.KnownProtocols" json:"domain_override,omitempty"`
SniffingSettings *SniffingConfig `protobuf:"bytes,8,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
} }
func (x *ReceiverConfig) Reset() { func (x *ReceiverConfig) Reset() {
*x = ReceiverConfig{} *x = ReceiverConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[3]
mi := &file_app_proxyman_config_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *ReceiverConfig) String() string { func (x *ReceiverConfig) String() string {
@@ -348,7 +289,7 @@ func (*ReceiverConfig) ProtoMessage() {}
func (x *ReceiverConfig) ProtoReflect() protoreflect.Message { func (x *ReceiverConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[3] mi := &file_app_proxyman_config_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -398,14 +339,6 @@ func (x *ReceiverConfig) GetReceiveOriginalDestination() bool {
return false return false
} }
// Deprecated: Marked as deprecated in app/proxyman/config.proto.
func (x *ReceiverConfig) GetDomainOverride() []KnownProtocols {
if x != nil {
return x.DomainOverride
}
return nil
}
func (x *ReceiverConfig) GetSniffingSettings() *SniffingConfig { func (x *ReceiverConfig) GetSniffingSettings() *SniffingConfig {
if x != nil { if x != nil {
return x.SniffingSettings return x.SniffingSettings
@@ -425,11 +358,9 @@ type InboundHandlerConfig struct {
func (x *InboundHandlerConfig) Reset() { func (x *InboundHandlerConfig) Reset() {
*x = InboundHandlerConfig{} *x = InboundHandlerConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[4]
mi := &file_app_proxyman_config_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *InboundHandlerConfig) String() string { func (x *InboundHandlerConfig) String() string {
@@ -440,7 +371,7 @@ func (*InboundHandlerConfig) ProtoMessage() {}
func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message { func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[4] mi := &file_app_proxyman_config_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -484,11 +415,9 @@ type OutboundConfig struct {
func (x *OutboundConfig) Reset() { func (x *OutboundConfig) Reset() {
*x = OutboundConfig{} *x = OutboundConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[5]
mi := &file_app_proxyman_config_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *OutboundConfig) String() string { func (x *OutboundConfig) String() string {
@@ -499,7 +428,7 @@ func (*OutboundConfig) ProtoMessage() {}
func (x *OutboundConfig) ProtoReflect() protoreflect.Message { func (x *OutboundConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[5] mi := &file_app_proxyman_config_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -529,11 +458,9 @@ type SenderConfig struct {
func (x *SenderConfig) Reset() { func (x *SenderConfig) Reset() {
*x = SenderConfig{} *x = SenderConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[6]
mi := &file_app_proxyman_config_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *SenderConfig) String() string { func (x *SenderConfig) String() string {
@@ -544,7 +471,7 @@ func (*SenderConfig) ProtoMessage() {}
func (x *SenderConfig) ProtoReflect() protoreflect.Message { func (x *SenderConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[6] mi := &file_app_proxyman_config_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -611,11 +538,9 @@ type MultiplexingConfig struct {
func (x *MultiplexingConfig) Reset() { func (x *MultiplexingConfig) Reset() {
*x = MultiplexingConfig{} *x = MultiplexingConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[7]
mi := &file_app_proxyman_config_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *MultiplexingConfig) String() string { func (x *MultiplexingConfig) String() string {
@@ -626,7 +551,7 @@ func (*MultiplexingConfig) ProtoMessage() {}
func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message { func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[7] mi := &file_app_proxyman_config_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -679,11 +604,9 @@ type AllocationStrategy_AllocationStrategyConcurrency struct {
func (x *AllocationStrategy_AllocationStrategyConcurrency) Reset() { func (x *AllocationStrategy_AllocationStrategyConcurrency) Reset() {
*x = AllocationStrategy_AllocationStrategyConcurrency{} *x = AllocationStrategy_AllocationStrategyConcurrency{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[8]
mi := &file_app_proxyman_config_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *AllocationStrategy_AllocationStrategyConcurrency) String() string { func (x *AllocationStrategy_AllocationStrategyConcurrency) String() string {
@@ -694,7 +617,7 @@ func (*AllocationStrategy_AllocationStrategyConcurrency) ProtoMessage() {}
func (x *AllocationStrategy_AllocationStrategyConcurrency) ProtoReflect() protoreflect.Message { func (x *AllocationStrategy_AllocationStrategyConcurrency) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[8] mi := &file_app_proxyman_config_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -726,11 +649,9 @@ type AllocationStrategy_AllocationStrategyRefresh struct {
func (x *AllocationStrategy_AllocationStrategyRefresh) Reset() { func (x *AllocationStrategy_AllocationStrategyRefresh) Reset() {
*x = AllocationStrategy_AllocationStrategyRefresh{} *x = AllocationStrategy_AllocationStrategyRefresh{}
if protoimpl.UnsafeEnabled { mi := &file_app_proxyman_config_proto_msgTypes[9]
mi := &file_app_proxyman_config_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *AllocationStrategy_AllocationStrategyRefresh) String() string { func (x *AllocationStrategy_AllocationStrategyRefresh) String() string {
@@ -741,7 +662,7 @@ func (*AllocationStrategy_AllocationStrategyRefresh) ProtoMessage() {}
func (x *AllocationStrategy_AllocationStrategyRefresh) ProtoReflect() protoreflect.Message { func (x *AllocationStrategy_AllocationStrategyRefresh) ProtoReflect() protoreflect.Message {
mi := &file_app_proxyman_config_proto_msgTypes[9] mi := &file_app_proxyman_config_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -817,7 +738,7 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f, 0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f,
0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65,
0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x8d, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0xbd, 0x03, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f,
0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72,
@@ -840,13 +761,8 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69,
0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e,
0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b, 0x6e, 0x6f, 0x77,
0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e,
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x4e,
0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e,
0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e,
0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04,
@@ -894,16 +810,13 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72,
0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78,
0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x78,
0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x2a, 0x23, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x42, 0x55,
0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x4c, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75,
0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f,
0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70,
0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
} }
var ( var (
@@ -918,48 +831,46 @@ func file_app_proxyman_config_proto_rawDescGZIP() []byte {
return file_app_proxyman_config_proto_rawDescData return file_app_proxyman_config_proto_rawDescData
} }
var file_app_proxyman_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_app_proxyman_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_app_proxyman_config_proto_goTypes = []interface{}{ var file_app_proxyman_config_proto_goTypes = []any{
(KnownProtocols)(0), // 0: xray.app.proxyman.KnownProtocols (AllocationStrategy_Type)(0), // 0: xray.app.proxyman.AllocationStrategy.Type
(AllocationStrategy_Type)(0), // 1: xray.app.proxyman.AllocationStrategy.Type (*InboundConfig)(nil), // 1: xray.app.proxyman.InboundConfig
(*InboundConfig)(nil), // 2: xray.app.proxyman.InboundConfig (*AllocationStrategy)(nil), // 2: xray.app.proxyman.AllocationStrategy
(*AllocationStrategy)(nil), // 3: xray.app.proxyman.AllocationStrategy (*SniffingConfig)(nil), // 3: xray.app.proxyman.SniffingConfig
(*SniffingConfig)(nil), // 4: xray.app.proxyman.SniffingConfig (*ReceiverConfig)(nil), // 4: xray.app.proxyman.ReceiverConfig
(*ReceiverConfig)(nil), // 5: xray.app.proxyman.ReceiverConfig (*InboundHandlerConfig)(nil), // 5: xray.app.proxyman.InboundHandlerConfig
(*InboundHandlerConfig)(nil), // 6: xray.app.proxyman.InboundHandlerConfig (*OutboundConfig)(nil), // 6: xray.app.proxyman.OutboundConfig
(*OutboundConfig)(nil), // 7: xray.app.proxyman.OutboundConfig (*SenderConfig)(nil), // 7: xray.app.proxyman.SenderConfig
(*SenderConfig)(nil), // 8: xray.app.proxyman.SenderConfig (*MultiplexingConfig)(nil), // 8: xray.app.proxyman.MultiplexingConfig
(*MultiplexingConfig)(nil), // 9: xray.app.proxyman.MultiplexingConfig (*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 9: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency (*AllocationStrategy_AllocationStrategyRefresh)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh (*net.PortList)(nil), // 11: xray.common.net.PortList
(*net.PortList)(nil), // 12: xray.common.net.PortList (*net.IPOrDomain)(nil), // 12: xray.common.net.IPOrDomain
(*net.IPOrDomain)(nil), // 13: xray.common.net.IPOrDomain (*internet.StreamConfig)(nil), // 13: xray.transport.internet.StreamConfig
(*internet.StreamConfig)(nil), // 14: xray.transport.internet.StreamConfig (*serial.TypedMessage)(nil), // 14: xray.common.serial.TypedMessage
(*serial.TypedMessage)(nil), // 15: xray.common.serial.TypedMessage (*internet.ProxyConfig)(nil), // 15: xray.transport.internet.ProxyConfig
(*internet.ProxyConfig)(nil), // 16: xray.transport.internet.ProxyConfig
} }
var file_app_proxyman_config_proto_depIdxs = []int32{ var file_app_proxyman_config_proto_depIdxs = []int32{
1, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type 0, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency 9, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh 10, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
12, // 3: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList 11, // 3: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain 12, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
3, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy 2, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
14, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig 13, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
0, // 7: xray.app.proxyman.ReceiverConfig.domain_override:type_name -> xray.app.proxyman.KnownProtocols 3, // 7: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
4, // 8: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig 14, // 8: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
15, // 9: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage 14, // 9: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
15, // 10: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage 12, // 10: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
13, // 11: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain 13, // 11: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
14, // 12: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig 15, // 12: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
16, // 13: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig 8, // 13: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
9, // 14: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig 14, // [14:14] is the sub-list for method output_type
15, // [15:15] is the sub-list for method output_type 14, // [14:14] is the sub-list for method input_type
15, // [15:15] is the sub-list for method input_type 14, // [14:14] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension type_name 14, // [14:14] is the sub-list for extension extendee
15, // [15:15] is the sub-list for extension extendee 0, // [0:14] is the sub-list for field type_name
0, // [0:15] is the sub-list for field type_name
} }
func init() { file_app_proxyman_config_proto_init() } func init() { file_app_proxyman_config_proto_init() }
@@ -967,134 +878,12 @@ func file_app_proxyman_config_proto_init() {
if File_app_proxyman_config_proto != nil { if File_app_proxyman_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_proxyman_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*InboundConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AllocationStrategy); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SniffingConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReceiverConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*InboundHandlerConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OutboundConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SenderConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MultiplexingConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AllocationStrategy_AllocationStrategyConcurrency); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_proxyman_config_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AllocationStrategy_AllocationStrategyRefresh); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_proxyman_config_proto_rawDesc, RawDescriptor: file_app_proxyman_config_proto_rawDesc,
NumEnums: 2, NumEnums: 1,
NumMessages: 10, NumMessages: 10,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,

View File

@@ -40,11 +40,6 @@ message AllocationStrategy {
AllocationStrategyRefresh refresh = 3; AllocationStrategyRefresh refresh = 3;
} }
enum KnownProtocols {
HTTP = 0;
TLS = 1;
}
message SniffingConfig { message SniffingConfig {
// Whether or not to enable content sniffing on an inbound connection. // Whether or not to enable content sniffing on an inbound connection.
bool enabled = 1; bool enabled = 1;
@@ -71,10 +66,7 @@ message ReceiverConfig {
xray.transport.internet.StreamConfig stream_settings = 4; xray.transport.internet.StreamConfig stream_settings = 4;
bool receive_original_destination = 5; bool receive_original_destination = 5;
reserved 6; reserved 6;
// Override domains for the given protocol. SniffingConfig sniffing_settings = 7;
// Deprecated. Use sniffing_settings.
repeated KnownProtocols domain_override = 7 [ deprecated = true ];
SniffingConfig sniffing_settings = 8;
} }
message InboundHandlerConfig { message InboundHandlerConfig {

View File

@@ -9,11 +9,13 @@ import (
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"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/serial"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/features/stats"
"github.com/xtls/xray-core/proxy" "github.com/xtls/xray-core/proxy"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"google.golang.org/protobuf/proto"
) )
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) { func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
@@ -42,10 +44,12 @@ func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter)
} }
type AlwaysOnInboundHandler struct { type AlwaysOnInboundHandler struct {
proxy proxy.Inbound proxyConfig interface{}
workers []worker receiverConfig *proxyman.ReceiverConfig
mux *mux.Server proxy proxy.Inbound
tag string workers []worker
mux *mux.Server
tag string
} }
func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) { func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) {
@@ -59,9 +63,11 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
} }
h := &AlwaysOnInboundHandler{ h := &AlwaysOnInboundHandler{
proxy: p, receiverConfig: receiverConfig,
mux: mux.NewServer(ctx), proxyConfig: proxyConfig,
tag: tag, proxy: p,
mux: mux.NewServer(ctx),
tag: tag,
} }
uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag) uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag)
@@ -187,3 +193,16 @@ func (h *AlwaysOnInboundHandler) Tag() string {
func (h *AlwaysOnInboundHandler) GetInbound() proxy.Inbound { func (h *AlwaysOnInboundHandler) GetInbound() proxy.Inbound {
return h.proxy return h.proxy
} }
// ReceiverSettings implements inbound.Handler.
func (h *AlwaysOnInboundHandler) ReceiverSettings() *serial.TypedMessage {
return serial.ToTypedMessage(h.receiverConfig)
}
// ProxySettings implements inbound.Handler.
func (h *AlwaysOnInboundHandler) ProxySettings() *serial.TypedMessage {
if v, ok := h.proxyConfig.(proto.Message); ok {
return serial.ToTypedMessage(v)
}
return nil
}

View File

@@ -10,10 +10,12 @@ import (
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"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/serial"
"github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/common/task"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/proxy" "github.com/xtls/xray-core/proxy"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"google.golang.org/protobuf/proto"
) )
type DynamicInboundHandler struct { type DynamicInboundHandler struct {
@@ -23,7 +25,7 @@ type DynamicInboundHandler struct {
receiverConfig *proxyman.ReceiverConfig receiverConfig *proxyman.ReceiverConfig
streamSettings *internet.MemoryStreamConfig streamSettings *internet.MemoryStreamConfig
portMutex sync.Mutex portMutex sync.Mutex
portsInUse map[net.Port]bool portsInUse map[net.Port]struct{}
workerMutex sync.RWMutex workerMutex sync.RWMutex
worker []worker worker []worker
lastRefresh time.Time lastRefresh time.Time
@@ -39,7 +41,7 @@ func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *p
tag: tag, tag: tag,
proxyConfig: proxyConfig, proxyConfig: proxyConfig,
receiverConfig: receiverConfig, receiverConfig: receiverConfig,
portsInUse: make(map[net.Port]bool), portsInUse: make(map[net.Port]struct{}),
mux: mux.NewServer(ctx), mux: mux.NewServer(ctx),
v: v, v: v,
ctx: ctx, ctx: ctx,
@@ -84,7 +86,7 @@ func (h *DynamicInboundHandler) allocatePort() net.Port {
port := net.Port(allPorts[r]) port := net.Port(allPorts[r])
_, used := h.portsInUse[port] _, used := h.portsInUse[port]
if !used { if !used {
h.portsInUse[port] = true h.portsInUse[port] = struct{}{}
return port return port
} }
} }
@@ -205,3 +207,16 @@ func (h *DynamicInboundHandler) GetRandomInboundProxy() (interface{}, net.Port,
func (h *DynamicInboundHandler) Tag() string { func (h *DynamicInboundHandler) Tag() string {
return h.tag return h.tag
} }
// ReceiverSettings implements inbound.Handler.
func (h *DynamicInboundHandler) ReceiverSettings() *serial.TypedMessage {
return serial.ToTypedMessage(h.receiverConfig)
}
// ProxySettings implements inbound.Handler.
func (h *DynamicInboundHandler) ProxySettings() *serial.TypedMessage {
if v, ok := h.proxyConfig.(proto.Message); ok {
return serial.ToTypedMessage(v)
}
return nil
}

View File

@@ -1,7 +1,5 @@
package inbound package inbound
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"
"sync" "sync"
@@ -9,13 +7,14 @@ 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/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/inbound" "github.com/xtls/xray-core/features/inbound"
) )
// Manager is to manage all inbound handlers. // Manager manages all inbound handlers.
type Manager struct { type Manager struct {
access sync.RWMutex access sync.RWMutex
untaggedHandler []inbound.Handler untaggedHandler []inbound.Handler
@@ -90,6 +89,21 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
return common.ErrNoClue return common.ErrNoClue
} }
// ListHandlers implements inbound.Manager.
func (m *Manager) ListHandlers(ctx context.Context) []inbound.Handler {
m.access.RLock()
defer m.access.RUnlock()
var response []inbound.Handler
copy(m.untaggedHandler, response)
for _, v := range m.taggedHandlers {
response = append(response, v)
}
return response
}
// Start implements common.Runnable. // Start implements common.Runnable.
func (m *Manager) Start() error { func (m *Manager) Start() error {
m.access.Lock() m.access.Lock()
@@ -160,6 +174,9 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound
Mark: streamSettings.SocketSettings.Mark, Mark: streamSettings.SocketSettings.Mark,
}) })
} }
if streamSettings != nil && streamSettings.ProtocolName == "splithttp" {
ctx = session.ContextWithAllowedNetwork(ctx, net.Network_UDP)
}
allocStrategy := receiverSettings.AllocationStrategy allocStrategy := receiverSettings.AllocationStrategy
if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always { if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always {

View File

@@ -161,6 +161,7 @@ type udpConn struct {
uplink stats.Counter uplink stats.Counter
downlink stats.Counter downlink stats.Counter
inactive bool inactive bool
cancel context.CancelFunc
} }
func (c *udpConn) setInactive() { func (c *udpConn) setInactive() {
@@ -203,6 +204,9 @@ func (c *udpConn) Write(buf []byte) (int, error) {
} }
func (c *udpConn) Close() error { func (c *udpConn) Close() error {
if c.cancel != nil {
c.cancel()
}
common.Must(c.done.Close()) common.Must(c.done.Close())
common.Must(common.Close(c.writer)) common.Must(common.Close(c.writer))
return nil return nil
@@ -259,6 +263,7 @@ func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
defer w.Unlock() defer w.Unlock()
if conn, found := w.activeConn[id]; found && !conn.done.Done() { if conn, found := w.activeConn[id]; found && !conn.done.Done() {
conn.updateActivity()
return conn, true return conn, true
} }
@@ -306,7 +311,8 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
common.Must(w.checker.Start()) common.Must(w.checker.Start())
go func() { go func() {
ctx := w.ctx ctx, cancel := context.WithCancel(w.ctx)
conn.cancel = cancel
sid := session.NewID() sid := session.NewID()
ctx = c.ContextWithID(ctx, sid) ctx = c.ContextWithID(ctx, sid)
@@ -324,6 +330,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
if w.sniffingConfig != nil { if w.sniffingConfig != nil {
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
} }

View File

@@ -11,11 +11,12 @@ 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/errors"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"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"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
@@ -27,6 +28,7 @@ import (
"github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
"github.com/xtls/xray-core/transport/pipe" "github.com/xtls/xray-core/transport/pipe"
"google.golang.org/protobuf/proto"
) )
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) { func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
@@ -54,11 +56,12 @@ func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter)
return uplinkCounter, downlinkCounter return uplinkCounter, downlinkCounter
} }
// Handler is an implements of outbound.Handler. // Handler implements outbound.Handler.
type Handler struct { type Handler struct {
tag string tag string
senderSettings *proxyman.SenderConfig senderSettings *proxyman.SenderConfig
streamSettings *internet.MemoryStreamConfig streamSettings *internet.MemoryStreamConfig
proxyConfig proto.Message
proxy proxy.Outbound proxy proxy.Outbound
outboundManager outbound.Manager outboundManager outbound.Manager
mux *mux.ClientManager mux *mux.ClientManager
@@ -101,6 +104,7 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
if err != nil { if err != nil {
return nil, err return nil, err
} }
h.proxyConfig = proxyConfig
rawProxyHandler, err := common.CreateObject(ctx, proxyConfig) rawProxyHandler, err := common.CreateObject(ctx, proxyConfig)
if err != nil { if err != nil {
@@ -241,7 +245,9 @@ func (h *Handler) DestIpAddress() net.IP {
// Dial implements internet.Dialer. // Dial implements internet.Dialer.
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) { func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) {
if h.senderSettings != nil { if h.senderSettings != nil {
if h.senderSettings.ProxySettings.HasTag() { if h.senderSettings.ProxySettings.HasTag() {
tag := h.senderSettings.ProxySettings.Tag tag := h.senderSettings.ProxySettings.Tag
handler := h.outboundManager.GetHandler(tag) handler := h.outboundManager.GetHandler(tag)
if handler != nil { if handler != nil {
@@ -270,13 +276,44 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
} }
if h.senderSettings.Via != nil { if h.senderSettings.Via != nil {
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1] ob := outbounds[len(outbounds)-1]
if h.senderSettings.ViaCidr == "" { var domain string
ob.Gateway = h.senderSettings.Via.AsAddress() addr := h.senderSettings.Via.AsAddress()
} else { //Get a random address. domain = h.senderSettings.Via.GetDomain()
ob.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr) switch {
case h.senderSettings.ViaCidr != "":
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
case domain == "origin":
if inbound := session.InboundFromContext(ctx); inbound != nil {
if inbound.Conn != nil {
origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String())
if err == nil {
ob.Gateway = net.ParseAddress(origin)
errors.LogDebug(ctx, "use receive package ip as snedthrough: ", origin)
}
}
}
case domain == "srcip":
if inbound := session.InboundFromContext(ctx); inbound != nil {
if inbound.Conn != nil {
clientaddr, _, err := net.SplitHostPort(inbound.Conn.RemoteAddr().String())
if err == nil {
ob.Gateway = net.ParseAddress(clientaddr)
errors.LogDebug(ctx, "use client src ip as snedthrough: ", clientaddr)
}
}
}
//case addr.Family().IsDomain():
default:
ob.Gateway = addr
} }
} }
} }
@@ -316,23 +353,35 @@ func (h *Handler) Start() error {
// Close implements common.Closable. // Close implements common.Closable.
func (h *Handler) Close() error { func (h *Handler) Close() error {
common.Close(h.mux) common.Close(h.mux)
common.Close(h.proxy)
return nil return nil
} }
func ParseRandomIPv6(address net.Address, prefix string) net.Address { // SenderSettings implements outbound.Handler.
_, network, _ := gonet.ParseCIDR(address.IP().String() + "/" + prefix) func (h *Handler) SenderSettings() *serial.TypedMessage {
return serial.ToTypedMessage(h.senderSettings)
maskSize, totalBits := network.Mask.Size() }
subnetSize := big.NewInt(1).Lsh(big.NewInt(1), uint(totalBits-maskSize))
// ProxySettings implements outbound.Handler.
// random func (h *Handler) ProxySettings() *serial.TypedMessage {
randomBigInt, _ := rand.Int(rand.Reader, subnetSize) return serial.ToTypedMessage(h.proxyConfig)
}
startIPBigInt := big.NewInt(0).SetBytes(network.IP.To16())
randomIPBigInt := big.NewInt(0).Add(startIPBigInt, randomBigInt) func ParseRandomIP(addr net.Address, prefix string) net.Address {
randomIPBytes := randomIPBigInt.Bytes() _, ipnet, _ := gonet.ParseCIDR(addr.IP().String() + "/" + prefix)
randomIPBytes = append(make([]byte, 16-len(randomIPBytes)), randomIPBytes...)
ones, bits := ipnet.Mask.Size()
return net.ParseAddress(gonet.IP(randomIPBytes).String()) subnetSize := new(big.Int).Lsh(big.NewInt(1), uint(bits-ones))
rnd, _ := rand.Int(rand.Reader, subnetSize)
startInt := new(big.Int).SetBytes(ipnet.IP)
rndInt := new(big.Int).Add(startInt, rnd)
rndBytes := rndInt.Bytes()
padded := make([]byte, len(ipnet.IP))
copy(padded[len(padded)-len(rndBytes):], rndBytes)
return net.ParseAddress(gonet.IP(padded).String())
} }

View File

@@ -1,7 +1,5 @@
package outbound package outbound
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"
"sort" "sort"
@@ -147,6 +145,21 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
return nil return nil
} }
// ListHandlers implements outbound.Manager.
func (m *Manager) ListHandlers(ctx context.Context) []outbound.Handler {
m.access.RLock()
defer m.access.RUnlock()
var response []outbound.Handler
copy(m.untaggedHandlers, response)
for _, v := range m.taggedHandler {
response = append(response, v)
}
return response
}
// Select implements outbound.HandlerSelector. // Select implements outbound.HandlerSelector.
func (m *Manager) Select(selectors []string) []string { func (m *Manager) Select(selectors []string) []string {

View File

@@ -9,6 +9,7 @@ import (
func (c *Control) FillInRandom() { func (c *Control) FillInRandom() {
randomLength := dice.Roll(64) randomLength := dice.Roll(64)
randomLength++
c.Random = make([]byte, randomLength) c.Random = make([]byte, randomLength)
io.ReadFull(rand.Reader, c.Random) io.ReadFull(rand.Reader, c.Random)
} }

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/reverse/config.proto // source: app/reverse/config.proto
package reverse package reverse
@@ -77,11 +77,9 @@ type Control struct {
func (x *Control) Reset() { func (x *Control) Reset() {
*x = Control{} *x = Control{}
if protoimpl.UnsafeEnabled { mi := &file_app_reverse_config_proto_msgTypes[0]
mi := &file_app_reverse_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Control) String() string { func (x *Control) String() string {
@@ -92,7 +90,7 @@ func (*Control) ProtoMessage() {}
func (x *Control) ProtoReflect() protoreflect.Message { func (x *Control) ProtoReflect() protoreflect.Message {
mi := &file_app_reverse_config_proto_msgTypes[0] mi := &file_app_reverse_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -132,11 +130,9 @@ type BridgeConfig struct {
func (x *BridgeConfig) Reset() { func (x *BridgeConfig) Reset() {
*x = BridgeConfig{} *x = BridgeConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_reverse_config_proto_msgTypes[1]
mi := &file_app_reverse_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *BridgeConfig) String() string { func (x *BridgeConfig) String() string {
@@ -147,7 +143,7 @@ func (*BridgeConfig) ProtoMessage() {}
func (x *BridgeConfig) ProtoReflect() protoreflect.Message { func (x *BridgeConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_reverse_config_proto_msgTypes[1] mi := &file_app_reverse_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -187,11 +183,9 @@ type PortalConfig struct {
func (x *PortalConfig) Reset() { func (x *PortalConfig) Reset() {
*x = PortalConfig{} *x = PortalConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_reverse_config_proto_msgTypes[2]
mi := &file_app_reverse_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *PortalConfig) String() string { func (x *PortalConfig) String() string {
@@ -202,7 +196,7 @@ func (*PortalConfig) ProtoMessage() {}
func (x *PortalConfig) ProtoReflect() protoreflect.Message { func (x *PortalConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_reverse_config_proto_msgTypes[2] mi := &file_app_reverse_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -242,11 +236,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_reverse_config_proto_msgTypes[3]
mi := &file_app_reverse_config_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -257,7 +249,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_reverse_config_proto_msgTypes[3] mi := &file_app_reverse_config_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -338,7 +330,7 @@ func file_app_reverse_config_proto_rawDescGZIP() []byte {
var file_app_reverse_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_app_reverse_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_app_reverse_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_app_reverse_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_app_reverse_config_proto_goTypes = []interface{}{ var file_app_reverse_config_proto_goTypes = []any{
(Control_State)(0), // 0: xray.app.reverse.Control.State (Control_State)(0), // 0: xray.app.reverse.Control.State
(*Control)(nil), // 1: xray.app.reverse.Control (*Control)(nil), // 1: xray.app.reverse.Control
(*BridgeConfig)(nil), // 2: xray.app.reverse.BridgeConfig (*BridgeConfig)(nil), // 2: xray.app.reverse.BridgeConfig
@@ -361,56 +353,6 @@ func file_app_reverse_config_proto_init() {
if File_app_reverse_config_proto != nil { if File_app_reverse_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_reverse_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Control); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_reverse_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BridgeConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_reverse_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PortalConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_reverse_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -10,6 +10,7 @@ import (
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"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/serial"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/task" "github.com/xtls/xray-core/common/task"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
@@ -111,6 +112,16 @@ func (o *Outbound) Close() error {
return nil return nil
} }
// SenderSettings implements outbound.Handler.
func (o *Outbound) SenderSettings() *serial.TypedMessage {
return nil
}
// ProxySettings implements outbound.Handler.
func (o *Outbound) ProxySettings() *serial.TypedMessage {
return nil
}
type StaticMuxPicker struct { type StaticMuxPicker struct {
access sync.Mutex access sync.Mutex
workers []*PortalWorker workers []*PortalWorker
@@ -159,7 +170,7 @@ func (p *StaticMuxPicker) PickAvailable() (*mux.ClientWorker, error) {
if w.draining { if w.draining {
continue continue
} }
if w.client.Closed() { if w.IsFull() {
continue continue
} }
if w.client.ActiveConnections() < minConn { if w.client.ActiveConnections() < minConn {
@@ -200,6 +211,7 @@ type PortalWorker struct {
writer buf.Writer writer buf.Writer
reader buf.Reader reader buf.Reader
draining bool draining bool
counter uint32
} }
func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) { func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
@@ -233,7 +245,7 @@ func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
} }
func (w *PortalWorker) heartbeat() error { func (w *PortalWorker) heartbeat() error {
if w.client.Closed() { if w.Closed() {
return errors.New("client worker stopped") return errors.New("client worker stopped")
} }
@@ -249,16 +261,21 @@ func (w *PortalWorker) heartbeat() error {
msg.State = Control_DRAIN msg.State = Control_DRAIN
defer func() { defer func() {
w.client.GetTimer().Reset(time.Second * 16)
common.Close(w.writer) common.Close(w.writer)
common.Interrupt(w.reader) common.Interrupt(w.reader)
w.writer = nil w.writer = nil
}() }()
} }
b, err := proto.Marshal(msg) w.counter = (w.counter + 1) % 5
common.Must(err) if w.draining || w.counter == 1 {
mb := buf.MergeBytes(nil, b) b, err := proto.Marshal(msg)
return w.writer.WriteMultiBuffer(mb) common.Must(err)
mb := buf.MergeBytes(nil, b)
return w.writer.WriteMultiBuffer(mb)
}
return nil
} }
func (w *PortalWorker) IsFull() bool { func (w *PortalWorker) IsFull() bool {

View File

@@ -1,7 +1,5 @@
package reverse package reverse
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"

View File

@@ -31,6 +31,12 @@ type RoundRobinStrategy struct {
func (s *RoundRobinStrategy) InjectContext(ctx context.Context) { func (s *RoundRobinStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx s.ctx = ctx
if len(s.FallbackTag) > 0 {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
} }
func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string { func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string {
@@ -38,12 +44,6 @@ func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string {
} }
func (s *RoundRobinStrategy) PickOutbound(tags []string) string { func (s *RoundRobinStrategy) PickOutbound(tags []string) string {
if len(s.FallbackTag) > 0 && s.observatory == nil {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
if s.observatory != nil { if s.observatory != nil {
observeReport, err := s.observatory.GetObservation(s.ctx) observeReport, err := s.observatory.GetObservation(s.ctx)
if err == nil { if err == nil {

View File

@@ -1,7 +1,5 @@
package command package command
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"
"time" "time"
@@ -137,7 +135,7 @@ func (s *service) Register(server *grpc.Server) {
vCoreDesc := RoutingService_ServiceDesc vCoreDesc := RoutingService_ServiceDesc
vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService" vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService"
server.RegisterService(&vCoreDesc, rs) server.RegisterService(&vCoreDesc, rs)
})) }, false))
} }
func init() { func init() {

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/router/command/command.proto // source: app/router/command/command.proto
package command package command
@@ -46,11 +46,9 @@ type RoutingContext struct {
func (x *RoutingContext) Reset() { func (x *RoutingContext) Reset() {
*x = RoutingContext{} *x = RoutingContext{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[0]
mi := &file_app_router_command_command_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *RoutingContext) String() string { func (x *RoutingContext) String() string {
@@ -61,7 +59,7 @@ func (*RoutingContext) ProtoMessage() {}
func (x *RoutingContext) ProtoReflect() protoreflect.Message { func (x *RoutingContext) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[0] mi := &file_app_router_command_command_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -188,11 +186,9 @@ type SubscribeRoutingStatsRequest struct {
func (x *SubscribeRoutingStatsRequest) Reset() { func (x *SubscribeRoutingStatsRequest) Reset() {
*x = SubscribeRoutingStatsRequest{} *x = SubscribeRoutingStatsRequest{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[1]
mi := &file_app_router_command_command_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *SubscribeRoutingStatsRequest) String() string { func (x *SubscribeRoutingStatsRequest) String() string {
@@ -203,7 +199,7 @@ func (*SubscribeRoutingStatsRequest) ProtoMessage() {}
func (x *SubscribeRoutingStatsRequest) ProtoReflect() protoreflect.Message { func (x *SubscribeRoutingStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[1] mi := &file_app_router_command_command_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -244,11 +240,9 @@ type TestRouteRequest struct {
func (x *TestRouteRequest) Reset() { func (x *TestRouteRequest) Reset() {
*x = TestRouteRequest{} *x = TestRouteRequest{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[2]
mi := &file_app_router_command_command_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *TestRouteRequest) String() string { func (x *TestRouteRequest) String() string {
@@ -259,7 +253,7 @@ func (*TestRouteRequest) ProtoMessage() {}
func (x *TestRouteRequest) ProtoReflect() protoreflect.Message { func (x *TestRouteRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[2] mi := &file_app_router_command_command_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -305,11 +299,9 @@ type PrincipleTargetInfo struct {
func (x *PrincipleTargetInfo) Reset() { func (x *PrincipleTargetInfo) Reset() {
*x = PrincipleTargetInfo{} *x = PrincipleTargetInfo{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[3]
mi := &file_app_router_command_command_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *PrincipleTargetInfo) String() string { func (x *PrincipleTargetInfo) String() string {
@@ -320,7 +312,7 @@ func (*PrincipleTargetInfo) ProtoMessage() {}
func (x *PrincipleTargetInfo) ProtoReflect() protoreflect.Message { func (x *PrincipleTargetInfo) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[3] mi := &file_app_router_command_command_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -352,11 +344,9 @@ type OverrideInfo struct {
func (x *OverrideInfo) Reset() { func (x *OverrideInfo) Reset() {
*x = OverrideInfo{} *x = OverrideInfo{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[4]
mi := &file_app_router_command_command_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *OverrideInfo) String() string { func (x *OverrideInfo) String() string {
@@ -367,7 +357,7 @@ func (*OverrideInfo) ProtoMessage() {}
func (x *OverrideInfo) ProtoReflect() protoreflect.Message { func (x *OverrideInfo) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[4] mi := &file_app_router_command_command_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -400,11 +390,9 @@ type BalancerMsg struct {
func (x *BalancerMsg) Reset() { func (x *BalancerMsg) Reset() {
*x = BalancerMsg{} *x = BalancerMsg{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[5]
mi := &file_app_router_command_command_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *BalancerMsg) String() string { func (x *BalancerMsg) String() string {
@@ -415,7 +403,7 @@ func (*BalancerMsg) ProtoMessage() {}
func (x *BalancerMsg) ProtoReflect() protoreflect.Message { func (x *BalancerMsg) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[5] mi := &file_app_router_command_command_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -454,11 +442,9 @@ type GetBalancerInfoRequest struct {
func (x *GetBalancerInfoRequest) Reset() { func (x *GetBalancerInfoRequest) Reset() {
*x = GetBalancerInfoRequest{} *x = GetBalancerInfoRequest{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[6]
mi := &file_app_router_command_command_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *GetBalancerInfoRequest) String() string { func (x *GetBalancerInfoRequest) String() string {
@@ -469,7 +455,7 @@ func (*GetBalancerInfoRequest) ProtoMessage() {}
func (x *GetBalancerInfoRequest) ProtoReflect() protoreflect.Message { func (x *GetBalancerInfoRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[6] mi := &file_app_router_command_command_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -501,11 +487,9 @@ type GetBalancerInfoResponse struct {
func (x *GetBalancerInfoResponse) Reset() { func (x *GetBalancerInfoResponse) Reset() {
*x = GetBalancerInfoResponse{} *x = GetBalancerInfoResponse{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[7]
mi := &file_app_router_command_command_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *GetBalancerInfoResponse) String() string { func (x *GetBalancerInfoResponse) String() string {
@@ -516,7 +500,7 @@ func (*GetBalancerInfoResponse) ProtoMessage() {}
func (x *GetBalancerInfoResponse) ProtoReflect() protoreflect.Message { func (x *GetBalancerInfoResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[7] mi := &file_app_router_command_command_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -549,11 +533,9 @@ type OverrideBalancerTargetRequest struct {
func (x *OverrideBalancerTargetRequest) Reset() { func (x *OverrideBalancerTargetRequest) Reset() {
*x = OverrideBalancerTargetRequest{} *x = OverrideBalancerTargetRequest{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[8]
mi := &file_app_router_command_command_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *OverrideBalancerTargetRequest) String() string { func (x *OverrideBalancerTargetRequest) String() string {
@@ -564,7 +546,7 @@ func (*OverrideBalancerTargetRequest) ProtoMessage() {}
func (x *OverrideBalancerTargetRequest) ProtoReflect() protoreflect.Message { func (x *OverrideBalancerTargetRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[8] mi := &file_app_router_command_command_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -601,11 +583,9 @@ type OverrideBalancerTargetResponse struct {
func (x *OverrideBalancerTargetResponse) Reset() { func (x *OverrideBalancerTargetResponse) Reset() {
*x = OverrideBalancerTargetResponse{} *x = OverrideBalancerTargetResponse{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[9]
mi := &file_app_router_command_command_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *OverrideBalancerTargetResponse) String() string { func (x *OverrideBalancerTargetResponse) String() string {
@@ -616,7 +596,7 @@ func (*OverrideBalancerTargetResponse) ProtoMessage() {}
func (x *OverrideBalancerTargetResponse) ProtoReflect() protoreflect.Message { func (x *OverrideBalancerTargetResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[9] mi := &file_app_router_command_command_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -642,11 +622,9 @@ type AddRuleRequest struct {
func (x *AddRuleRequest) Reset() { func (x *AddRuleRequest) Reset() {
*x = AddRuleRequest{} *x = AddRuleRequest{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[10]
mi := &file_app_router_command_command_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *AddRuleRequest) String() string { func (x *AddRuleRequest) String() string {
@@ -657,7 +635,7 @@ func (*AddRuleRequest) ProtoMessage() {}
func (x *AddRuleRequest) ProtoReflect() protoreflect.Message { func (x *AddRuleRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[10] mi := &file_app_router_command_command_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -694,11 +672,9 @@ type AddRuleResponse struct {
func (x *AddRuleResponse) Reset() { func (x *AddRuleResponse) Reset() {
*x = AddRuleResponse{} *x = AddRuleResponse{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[11]
mi := &file_app_router_command_command_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *AddRuleResponse) String() string { func (x *AddRuleResponse) String() string {
@@ -709,7 +685,7 @@ func (*AddRuleResponse) ProtoMessage() {}
func (x *AddRuleResponse) ProtoReflect() protoreflect.Message { func (x *AddRuleResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[11] mi := &file_app_router_command_command_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -734,11 +710,9 @@ type RemoveRuleRequest struct {
func (x *RemoveRuleRequest) Reset() { func (x *RemoveRuleRequest) Reset() {
*x = RemoveRuleRequest{} *x = RemoveRuleRequest{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[12]
mi := &file_app_router_command_command_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *RemoveRuleRequest) String() string { func (x *RemoveRuleRequest) String() string {
@@ -749,7 +723,7 @@ func (*RemoveRuleRequest) ProtoMessage() {}
func (x *RemoveRuleRequest) ProtoReflect() protoreflect.Message { func (x *RemoveRuleRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[12] mi := &file_app_router_command_command_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -779,11 +753,9 @@ type RemoveRuleResponse struct {
func (x *RemoveRuleResponse) Reset() { func (x *RemoveRuleResponse) Reset() {
*x = RemoveRuleResponse{} *x = RemoveRuleResponse{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[13]
mi := &file_app_router_command_command_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *RemoveRuleResponse) String() string { func (x *RemoveRuleResponse) String() string {
@@ -794,7 +766,7 @@ func (*RemoveRuleResponse) ProtoMessage() {}
func (x *RemoveRuleResponse) ProtoReflect() protoreflect.Message { func (x *RemoveRuleResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[13] mi := &file_app_router_command_command_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -817,11 +789,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_command_command_proto_msgTypes[14]
mi := &file_app_router_command_command_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -832,7 +802,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[14] mi := &file_app_router_command_command_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -1019,7 +989,7 @@ func file_app_router_command_command_proto_rawDescGZIP() []byte {
} }
var file_app_router_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_app_router_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
var file_app_router_command_command_proto_goTypes = []interface{}{ var file_app_router_command_command_proto_goTypes = []any{
(*RoutingContext)(nil), // 0: xray.app.router.command.RoutingContext (*RoutingContext)(nil), // 0: xray.app.router.command.RoutingContext
(*SubscribeRoutingStatsRequest)(nil), // 1: xray.app.router.command.SubscribeRoutingStatsRequest (*SubscribeRoutingStatsRequest)(nil), // 1: xray.app.router.command.SubscribeRoutingStatsRequest
(*TestRouteRequest)(nil), // 2: xray.app.router.command.TestRouteRequest (*TestRouteRequest)(nil), // 2: xray.app.router.command.TestRouteRequest
@@ -1071,188 +1041,6 @@ func file_app_router_command_command_proto_init() {
if File_app_router_command_command_proto != nil { if File_app_router_command_command_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled {
file_app_router_command_command_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RoutingContext); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SubscribeRoutingStatsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TestRouteRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PrincipleTargetInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OverrideInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BalancerMsg); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetBalancerInfoRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetBalancerInfoResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OverrideBalancerTargetRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OverrideBalancerTargetResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AddRuleRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AddRuleResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RemoveRuleRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RemoveRuleResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_command_command_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.3.0 // - protoc-gen-go-grpc v1.5.1
// - protoc v5.27.0 // - protoc v5.28.2
// source: app/router/command/command.proto // source: app/router/command/command.proto
package command package command
@@ -15,8 +15,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later. // Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion7 const _ = grpc.SupportPackageIsVersion9
const ( const (
RoutingService_SubscribeRoutingStats_FullMethodName = "/xray.app.router.command.RoutingService/SubscribeRoutingStats" RoutingService_SubscribeRoutingStats_FullMethodName = "/xray.app.router.command.RoutingService/SubscribeRoutingStats"
@@ -31,7 +31,7 @@ const (
// //
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type RoutingServiceClient interface { type RoutingServiceClient interface {
SubscribeRoutingStats(ctx context.Context, in *SubscribeRoutingStatsRequest, opts ...grpc.CallOption) (RoutingService_SubscribeRoutingStatsClient, error) SubscribeRoutingStats(ctx context.Context, in *SubscribeRoutingStatsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[RoutingContext], error)
TestRoute(ctx context.Context, in *TestRouteRequest, opts ...grpc.CallOption) (*RoutingContext, error) TestRoute(ctx context.Context, in *TestRouteRequest, opts ...grpc.CallOption) (*RoutingContext, error)
GetBalancerInfo(ctx context.Context, in *GetBalancerInfoRequest, opts ...grpc.CallOption) (*GetBalancerInfoResponse, error) GetBalancerInfo(ctx context.Context, in *GetBalancerInfoRequest, opts ...grpc.CallOption) (*GetBalancerInfoResponse, error)
OverrideBalancerTarget(ctx context.Context, in *OverrideBalancerTargetRequest, opts ...grpc.CallOption) (*OverrideBalancerTargetResponse, error) OverrideBalancerTarget(ctx context.Context, in *OverrideBalancerTargetRequest, opts ...grpc.CallOption) (*OverrideBalancerTargetResponse, error)
@@ -47,12 +47,13 @@ func NewRoutingServiceClient(cc grpc.ClientConnInterface) RoutingServiceClient {
return &routingServiceClient{cc} return &routingServiceClient{cc}
} }
func (c *routingServiceClient) SubscribeRoutingStats(ctx context.Context, in *SubscribeRoutingStatsRequest, opts ...grpc.CallOption) (RoutingService_SubscribeRoutingStatsClient, error) { func (c *routingServiceClient) SubscribeRoutingStats(ctx context.Context, in *SubscribeRoutingStatsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[RoutingContext], error) {
stream, err := c.cc.NewStream(ctx, &RoutingService_ServiceDesc.Streams[0], RoutingService_SubscribeRoutingStats_FullMethodName, opts...) cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &RoutingService_ServiceDesc.Streams[0], RoutingService_SubscribeRoutingStats_FullMethodName, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
x := &routingServiceSubscribeRoutingStatsClient{stream} x := &grpc.GenericClientStream[SubscribeRoutingStatsRequest, RoutingContext]{ClientStream: stream}
if err := x.ClientStream.SendMsg(in); err != nil { if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err return nil, err
} }
@@ -62,26 +63,13 @@ func (c *routingServiceClient) SubscribeRoutingStats(ctx context.Context, in *Su
return x, nil return x, nil
} }
type RoutingService_SubscribeRoutingStatsClient interface { // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
Recv() (*RoutingContext, error) type RoutingService_SubscribeRoutingStatsClient = grpc.ServerStreamingClient[RoutingContext]
grpc.ClientStream
}
type routingServiceSubscribeRoutingStatsClient struct {
grpc.ClientStream
}
func (x *routingServiceSubscribeRoutingStatsClient) Recv() (*RoutingContext, error) {
m := new(RoutingContext)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *routingServiceClient) TestRoute(ctx context.Context, in *TestRouteRequest, opts ...grpc.CallOption) (*RoutingContext, error) { func (c *routingServiceClient) TestRoute(ctx context.Context, in *TestRouteRequest, opts ...grpc.CallOption) (*RoutingContext, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RoutingContext) out := new(RoutingContext)
err := c.cc.Invoke(ctx, RoutingService_TestRoute_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, RoutingService_TestRoute_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -89,8 +77,9 @@ func (c *routingServiceClient) TestRoute(ctx context.Context, in *TestRouteReque
} }
func (c *routingServiceClient) GetBalancerInfo(ctx context.Context, in *GetBalancerInfoRequest, opts ...grpc.CallOption) (*GetBalancerInfoResponse, error) { func (c *routingServiceClient) GetBalancerInfo(ctx context.Context, in *GetBalancerInfoRequest, opts ...grpc.CallOption) (*GetBalancerInfoResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetBalancerInfoResponse) out := new(GetBalancerInfoResponse)
err := c.cc.Invoke(ctx, RoutingService_GetBalancerInfo_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, RoutingService_GetBalancerInfo_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -98,8 +87,9 @@ func (c *routingServiceClient) GetBalancerInfo(ctx context.Context, in *GetBalan
} }
func (c *routingServiceClient) OverrideBalancerTarget(ctx context.Context, in *OverrideBalancerTargetRequest, opts ...grpc.CallOption) (*OverrideBalancerTargetResponse, error) { func (c *routingServiceClient) OverrideBalancerTarget(ctx context.Context, in *OverrideBalancerTargetRequest, opts ...grpc.CallOption) (*OverrideBalancerTargetResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(OverrideBalancerTargetResponse) out := new(OverrideBalancerTargetResponse)
err := c.cc.Invoke(ctx, RoutingService_OverrideBalancerTarget_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, RoutingService_OverrideBalancerTarget_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -107,8 +97,9 @@ func (c *routingServiceClient) OverrideBalancerTarget(ctx context.Context, in *O
} }
func (c *routingServiceClient) AddRule(ctx context.Context, in *AddRuleRequest, opts ...grpc.CallOption) (*AddRuleResponse, error) { func (c *routingServiceClient) AddRule(ctx context.Context, in *AddRuleRequest, opts ...grpc.CallOption) (*AddRuleResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AddRuleResponse) out := new(AddRuleResponse)
err := c.cc.Invoke(ctx, RoutingService_AddRule_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, RoutingService_AddRule_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -116,8 +107,9 @@ func (c *routingServiceClient) AddRule(ctx context.Context, in *AddRuleRequest,
} }
func (c *routingServiceClient) RemoveRule(ctx context.Context, in *RemoveRuleRequest, opts ...grpc.CallOption) (*RemoveRuleResponse, error) { func (c *routingServiceClient) RemoveRule(ctx context.Context, in *RemoveRuleRequest, opts ...grpc.CallOption) (*RemoveRuleResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RemoveRuleResponse) out := new(RemoveRuleResponse)
err := c.cc.Invoke(ctx, RoutingService_RemoveRule_FullMethodName, in, out, opts...) err := c.cc.Invoke(ctx, RoutingService_RemoveRule_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -126,9 +118,9 @@ func (c *routingServiceClient) RemoveRule(ctx context.Context, in *RemoveRuleReq
// RoutingServiceServer is the server API for RoutingService service. // RoutingServiceServer is the server API for RoutingService service.
// All implementations must embed UnimplementedRoutingServiceServer // All implementations must embed UnimplementedRoutingServiceServer
// for forward compatibility // for forward compatibility.
type RoutingServiceServer interface { type RoutingServiceServer interface {
SubscribeRoutingStats(*SubscribeRoutingStatsRequest, RoutingService_SubscribeRoutingStatsServer) error SubscribeRoutingStats(*SubscribeRoutingStatsRequest, grpc.ServerStreamingServer[RoutingContext]) error
TestRoute(context.Context, *TestRouteRequest) (*RoutingContext, error) TestRoute(context.Context, *TestRouteRequest) (*RoutingContext, error)
GetBalancerInfo(context.Context, *GetBalancerInfoRequest) (*GetBalancerInfoResponse, error) GetBalancerInfo(context.Context, *GetBalancerInfoRequest) (*GetBalancerInfoResponse, error)
OverrideBalancerTarget(context.Context, *OverrideBalancerTargetRequest) (*OverrideBalancerTargetResponse, error) OverrideBalancerTarget(context.Context, *OverrideBalancerTargetRequest) (*OverrideBalancerTargetResponse, error)
@@ -137,11 +129,14 @@ type RoutingServiceServer interface {
mustEmbedUnimplementedRoutingServiceServer() mustEmbedUnimplementedRoutingServiceServer()
} }
// UnimplementedRoutingServiceServer must be embedded to have forward compatible implementations. // UnimplementedRoutingServiceServer must be embedded to have
type UnimplementedRoutingServiceServer struct { // forward compatible implementations.
} //
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedRoutingServiceServer struct{}
func (UnimplementedRoutingServiceServer) SubscribeRoutingStats(*SubscribeRoutingStatsRequest, RoutingService_SubscribeRoutingStatsServer) error { func (UnimplementedRoutingServiceServer) SubscribeRoutingStats(*SubscribeRoutingStatsRequest, grpc.ServerStreamingServer[RoutingContext]) error {
return status.Errorf(codes.Unimplemented, "method SubscribeRoutingStats not implemented") return status.Errorf(codes.Unimplemented, "method SubscribeRoutingStats not implemented")
} }
func (UnimplementedRoutingServiceServer) TestRoute(context.Context, *TestRouteRequest) (*RoutingContext, error) { func (UnimplementedRoutingServiceServer) TestRoute(context.Context, *TestRouteRequest) (*RoutingContext, error) {
@@ -160,6 +155,7 @@ func (UnimplementedRoutingServiceServer) RemoveRule(context.Context, *RemoveRule
return nil, status.Errorf(codes.Unimplemented, "method RemoveRule not implemented") return nil, status.Errorf(codes.Unimplemented, "method RemoveRule not implemented")
} }
func (UnimplementedRoutingServiceServer) mustEmbedUnimplementedRoutingServiceServer() {} func (UnimplementedRoutingServiceServer) mustEmbedUnimplementedRoutingServiceServer() {}
func (UnimplementedRoutingServiceServer) testEmbeddedByValue() {}
// UnsafeRoutingServiceServer may be embedded to opt out of forward compatibility for this service. // UnsafeRoutingServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to RoutingServiceServer will // Use of this interface is not recommended, as added methods to RoutingServiceServer will
@@ -169,6 +165,13 @@ type UnsafeRoutingServiceServer interface {
} }
func RegisterRoutingServiceServer(s grpc.ServiceRegistrar, srv RoutingServiceServer) { func RegisterRoutingServiceServer(s grpc.ServiceRegistrar, srv RoutingServiceServer) {
// If the following call pancis, it indicates UnimplementedRoutingServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&RoutingService_ServiceDesc, srv) s.RegisterService(&RoutingService_ServiceDesc, srv)
} }
@@ -177,21 +180,11 @@ func _RoutingService_SubscribeRoutingStats_Handler(srv interface{}, stream grpc.
if err := stream.RecvMsg(m); err != nil { if err := stream.RecvMsg(m); err != nil {
return err return err
} }
return srv.(RoutingServiceServer).SubscribeRoutingStats(m, &routingServiceSubscribeRoutingStatsServer{stream}) return srv.(RoutingServiceServer).SubscribeRoutingStats(m, &grpc.GenericServerStream[SubscribeRoutingStatsRequest, RoutingContext]{ServerStream: stream})
} }
type RoutingService_SubscribeRoutingStatsServer interface { // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
Send(*RoutingContext) error type RoutingService_SubscribeRoutingStatsServer = grpc.ServerStreamingServer[RoutingContext]
grpc.ServerStream
}
type routingServiceSubscribeRoutingStatsServer struct {
grpc.ServerStream
}
func (x *routingServiceSubscribeRoutingStatsServer) Send(m *RoutingContext) error {
return x.ServerStream.SendMsg(m)
}
func _RoutingService_TestRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _RoutingService_TestRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TestRouteRequest) in := new(TestRouteRequest)

View File

@@ -28,6 +28,10 @@ func (c routingContext) GetTargetPort() net.Port {
return net.Port(c.RoutingContext.GetTargetPort()) return net.Port(c.RoutingContext.GetTargetPort())
} }
func (c routingContext) GetRuleTag() string {
return ""
}
// GetSkipDNSResolve is a mock implementation here to match the interface, // GetSkipDNSResolve is a mock implementation here to match the interface,
// SkipDNSResolve is set from dns module, no use if coming from a protobuf object? // SkipDNSResolve is set from dns module, no use if coming from a protobuf object?
// TODO: please confirm @Vigilans // TODO: please confirm @Vigilans

View File

@@ -119,7 +119,7 @@ type MultiGeoIPMatcher struct {
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) { func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
var matchers []*GeoIPMatcher var matchers []*GeoIPMatcher
for _, geoip := range geoips { for _, geoip := range geoips {
matcher, err := globalGeoIPContainer.Add(geoip) matcher, err := GlobalGeoIPContainer.Add(geoip)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -192,18 +192,28 @@ func (v NetworkMatcher) Apply(ctx routing.Context) bool {
} }
type UserMatcher struct { type UserMatcher struct {
user []string user []string
pattern []*regexp.Regexp
} }
func NewUserMatcher(users []string) *UserMatcher { func NewUserMatcher(users []string) *UserMatcher {
usersCopy := make([]string, 0, len(users)) usersCopy := make([]string, 0, len(users))
patternsCopy := make([]*regexp.Regexp, 0, len(users))
for _, user := range users { for _, user := range users {
if len(user) > 0 { if len(user) > 0 {
if len(user) > 7 && strings.HasPrefix(user, "regexp:") {
if re, err := regexp.Compile(user[7:]); err == nil {
patternsCopy = append(patternsCopy, re)
}
// Items of users slice with an invalid regexp syntax are ignored.
continue
}
usersCopy = append(usersCopy, user) usersCopy = append(usersCopy, user)
} }
} }
return &UserMatcher{ return &UserMatcher{
user: usersCopy, user: usersCopy,
pattern: patternsCopy,
} }
} }
@@ -218,6 +228,11 @@ func (v *UserMatcher) Apply(ctx routing.Context) bool {
return true return true
} }
} }
for _, re := range v.pattern {
if re.MatchString(user) {
return true
}
}
return false return false
} }

View File

@@ -115,4 +115,30 @@ func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
return m, nil return m, nil
} }
var globalGeoIPContainer GeoIPMatcherContainer var GlobalGeoIPContainer GeoIPMatcherContainer
func MatchIPs(matchers []*GeoIPMatcher, ips []net.IP, reverse bool) []net.IP {
if len(matchers) == 0 {
panic("GeoIP matchers should not be empty to avoid ambiguity")
}
newIPs := make([]net.IP, 0, len(ips))
var isFound bool
for _, ip := range ips {
isFound = false
for _, matcher := range matchers {
if matcher.Match(ip) {
isFound = true
break
}
}
if isFound && !reverse {
newIPs = append(newIPs, ip)
continue
}
if !isFound && reverse {
newIPs = append(newIPs, ip)
continue
}
}
return newIPs
}

View File

@@ -1,6 +1,7 @@
package router_test package router_test
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@@ -13,16 +14,25 @@ import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
func init() { func getAssetPath(file string) (string, error) {
wd, err := os.Getwd() path := platform.GetAssetLocation(file)
common.Must(err) _, err := os.Stat(path)
if os.IsNotExist(err) {
path := filepath.Join("..", "..", "resources", file)
_, err := os.Stat(path)
if os.IsNotExist(err) {
return "", fmt.Errorf("can't find %s in standard asset locations or {project_root}/resources", file)
}
if err != nil {
return "", fmt.Errorf("can't stat %s: %v", path, err)
}
return path, nil
}
if err != nil {
return "", fmt.Errorf("can't stat %s: %v", path, err)
}
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) { return path, nil
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
}
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat")))
}
} }
func TestGeoIPMatcherContainer(t *testing.T) { func TestGeoIPMatcherContainer(t *testing.T) {
@@ -217,10 +227,15 @@ func TestGeoIPMatcher6US(t *testing.T) {
} }
func loadGeoIP(country string) ([]*router.CIDR, error) { func loadGeoIP(country string) ([]*router.CIDR, error) {
geoipBytes, err := filesystem.ReadAsset("geoip.dat") path, err := getAssetPath("geoip.dat")
if err != nil { if err != nil {
return nil, err return nil, err
} }
geoipBytes, err := filesystem.ReadFile(path)
if err != nil {
return nil, err
}
var geoipList router.GeoIPList var geoipList router.GeoIPList
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil { if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
return nil, err return nil, err

View File

@@ -1,8 +1,6 @@
package router_test package router_test
import ( import (
"os"
"path/filepath"
"strconv" "strconv"
"testing" "testing"
@@ -10,7 +8,6 @@ import (
"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"
"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/filesystem" "github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/protocol/http" "github.com/xtls/xray-core/common/protocol/http"
@@ -20,18 +17,6 @@ import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
func init() {
wd, err := os.Getwd()
common.Must(err)
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "release", "config", "geoip.dat")))
}
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "release", "config", "geosite.dat")))
}
}
func withBackground() routing.Context { func withBackground() routing.Context {
return &routing_session.Context{} return &routing_session.Context{}
} }
@@ -106,42 +91,6 @@ func TestRoutingRule(t *testing.T) {
}, },
}, },
}, },
{
rule: &RoutingRule{
Cidr: []*CIDR{
{
Ip: []byte{8, 8, 8, 8},
Prefix: 32,
},
{
Ip: []byte{8, 8, 8, 8},
Prefix: 32,
},
{
Ip: net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334").IP(),
Prefix: 128,
},
},
},
test: []ruleTest{
{
input: withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)}),
output: true,
},
{
input: withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.4.4"), 80)}),
output: false,
},
{
input: withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), 80)}),
output: true,
},
{
input: withBackground(),
output: false,
},
},
},
{ {
rule: &RoutingRule{ rule: &RoutingRule{
Geoip: []*GeoIP{ Geoip: []*GeoIP{
@@ -184,10 +133,14 @@ func TestRoutingRule(t *testing.T) {
}, },
{ {
rule: &RoutingRule{ rule: &RoutingRule{
SourceCidr: []*CIDR{ SourceGeoip: []*GeoIP{
{ {
Ip: []byte{192, 168, 0, 0}, Cidr: []*CIDR{
Prefix: 16, {
Ip: []byte{192, 168, 0, 0},
Prefix: 16,
},
},
}, },
}, },
}, },
@@ -348,10 +301,15 @@ func TestRoutingRule(t *testing.T) {
} }
func loadGeoSite(country string) ([]*Domain, error) { func loadGeoSite(country string) ([]*Domain, error) {
geositeBytes, err := filesystem.ReadAsset("geosite.dat") path, err := getAssetPath("geosite.dat")
if err != nil { if err != nil {
return nil, err return nil, err
} }
geositeBytes, err := filesystem.ReadFile(path)
if err != nil {
return nil, err
}
var geositeList GeoSiteList var geositeList GeoSiteList
if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil { if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
return nil, err return nil, err

View File

@@ -6,7 +6,6 @@ import (
"strings" "strings"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
) )
@@ -63,8 +62,6 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
if rr.PortList != nil { if rr.PortList != nil {
conds.Add(NewPortMatcher(rr.PortList, false)) conds.Add(NewPortMatcher(rr.PortList, false))
} else if rr.PortRange != nil {
conds.Add(NewPortMatcher(&net.PortList{Range: []*net.PortRange{rr.PortRange}}, false))
} }
if rr.SourcePortList != nil { if rr.SourcePortList != nil {
@@ -73,8 +70,6 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
if len(rr.Networks) > 0 { if len(rr.Networks) > 0 {
conds.Add(NewNetworkMatcher(rr.Networks)) conds.Add(NewNetworkMatcher(rr.Networks))
} else if rr.NetworkList != nil {
conds.Add(NewNetworkMatcher(rr.NetworkList.Network))
} }
if len(rr.Geoip) > 0 { if len(rr.Geoip) > 0 {
@@ -83,12 +78,6 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
return nil, err return nil, err
} }
conds.Add(cond) conds.Add(cond)
} else if len(rr.Cidr) > 0 {
cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.Cidr}}, false)
if err != nil {
return nil, err
}
conds.Add(cond)
} }
if len(rr.SourceGeoip) > 0 { if len(rr.SourceGeoip) > 0 {
@@ -97,12 +86,6 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
return nil, err return nil, err
} }
conds.Add(cond) conds.Add(cond)
} else if len(rr.SourceCidr) > 0 {
cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.SourceCidr}}, true)
if err != nil {
return nil, err
}
conds.Add(cond)
} }
if len(rr.Protocol) > 0 { if len(rr.Protocol) > 0 {

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.34.1 // protoc-gen-go v1.35.1
// protoc v5.27.0 // protoc v5.28.2
// source: app/router/config.proto // source: app/router/config.proto
package router package router
@@ -151,11 +151,9 @@ type Domain struct {
func (x *Domain) Reset() { func (x *Domain) Reset() {
*x = Domain{} *x = Domain{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[0]
mi := &file_app_router_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Domain) String() string { func (x *Domain) String() string {
@@ -166,7 +164,7 @@ func (*Domain) ProtoMessage() {}
func (x *Domain) ProtoReflect() protoreflect.Message { func (x *Domain) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[0] mi := &file_app_router_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -216,11 +214,9 @@ type CIDR struct {
func (x *CIDR) Reset() { func (x *CIDR) Reset() {
*x = CIDR{} *x = CIDR{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[1]
mi := &file_app_router_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *CIDR) String() string { func (x *CIDR) String() string {
@@ -231,7 +227,7 @@ func (*CIDR) ProtoMessage() {}
func (x *CIDR) ProtoReflect() protoreflect.Message { func (x *CIDR) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[1] mi := &file_app_router_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -272,11 +268,9 @@ type GeoIP struct {
func (x *GeoIP) Reset() { func (x *GeoIP) Reset() {
*x = GeoIP{} *x = GeoIP{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[2]
mi := &file_app_router_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *GeoIP) String() string { func (x *GeoIP) String() string {
@@ -287,7 +281,7 @@ func (*GeoIP) ProtoMessage() {}
func (x *GeoIP) ProtoReflect() protoreflect.Message { func (x *GeoIP) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[2] mi := &file_app_router_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -333,11 +327,9 @@ type GeoIPList struct {
func (x *GeoIPList) Reset() { func (x *GeoIPList) Reset() {
*x = GeoIPList{} *x = GeoIPList{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[3]
mi := &file_app_router_config_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *GeoIPList) String() string { func (x *GeoIPList) String() string {
@@ -348,7 +340,7 @@ func (*GeoIPList) ProtoMessage() {}
func (x *GeoIPList) ProtoReflect() protoreflect.Message { func (x *GeoIPList) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[3] mi := &file_app_router_config_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -381,11 +373,9 @@ type GeoSite struct {
func (x *GeoSite) Reset() { func (x *GeoSite) Reset() {
*x = GeoSite{} *x = GeoSite{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[4]
mi := &file_app_router_config_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *GeoSite) String() string { func (x *GeoSite) String() string {
@@ -396,7 +386,7 @@ func (*GeoSite) ProtoMessage() {}
func (x *GeoSite) ProtoReflect() protoreflect.Message { func (x *GeoSite) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[4] mi := &file_app_router_config_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -435,11 +425,9 @@ type GeoSiteList struct {
func (x *GeoSiteList) Reset() { func (x *GeoSiteList) Reset() {
*x = GeoSiteList{} *x = GeoSiteList{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[5]
mi := &file_app_router_config_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *GeoSiteList) String() string { func (x *GeoSiteList) String() string {
@@ -450,7 +438,7 @@ func (*GeoSiteList) ProtoMessage() {}
func (x *GeoSiteList) ProtoReflect() protoreflect.Message { func (x *GeoSiteList) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[5] mi := &file_app_router_config_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -485,33 +473,15 @@ type RoutingRule struct {
RuleTag string `protobuf:"bytes,18,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"` RuleTag string `protobuf:"bytes,18,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"`
// List of domains for target domain matching. // List of domains for target domain matching.
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"` Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
// List of CIDRs for target IP address matching.
// Deprecated. Use geoip below.
//
// Deprecated: Marked as deprecated in app/router/config.proto.
Cidr []*CIDR `protobuf:"bytes,3,rep,name=cidr,proto3" json:"cidr,omitempty"`
// List of GeoIPs for target IP address matching. If this entry exists, the // List of GeoIPs for target IP address matching. If this entry exists, the
// cidr above will have no effect. GeoIP fields with the same country code are // cidr above will have no effect. GeoIP fields with the same country code are
// supposed to contain exactly same content. They will be merged during // supposed to contain exactly same content. They will be merged during
// runtime. For customized GeoIPs, please leave country code empty. // runtime. For customized GeoIPs, please leave country code empty.
Geoip []*GeoIP `protobuf:"bytes,10,rep,name=geoip,proto3" json:"geoip,omitempty"` Geoip []*GeoIP `protobuf:"bytes,10,rep,name=geoip,proto3" json:"geoip,omitempty"`
// A range of port [from, to]. If the destination port is in this range, this
// rule takes effect. Deprecated. Use port_list.
//
// Deprecated: Marked as deprecated in app/router/config.proto.
PortRange *net.PortRange `protobuf:"bytes,4,opt,name=port_range,json=portRange,proto3" json:"port_range,omitempty"`
// List of ports. // List of ports.
PortList *net.PortList `protobuf:"bytes,14,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"` PortList *net.PortList `protobuf:"bytes,14,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
// List of networks. Deprecated. Use networks.
//
// Deprecated: Marked as deprecated in app/router/config.proto.
NetworkList *net.NetworkList `protobuf:"bytes,5,opt,name=network_list,json=networkList,proto3" json:"network_list,omitempty"`
// List of networks for matching. // List of networks for matching.
Networks []net.Network `protobuf:"varint,13,rep,packed,name=networks,proto3,enum=xray.common.net.Network" json:"networks,omitempty"` Networks []net.Network `protobuf:"varint,13,rep,packed,name=networks,proto3,enum=xray.common.net.Network" json:"networks,omitempty"`
// List of CIDRs for source IP address matching.
//
// Deprecated: Marked as deprecated in app/router/config.proto.
SourceCidr []*CIDR `protobuf:"bytes,6,rep,name=source_cidr,json=sourceCidr,proto3" json:"source_cidr,omitempty"`
// List of GeoIPs for source IP address matching. If this entry exists, the // List of GeoIPs for source IP address matching. If this entry exists, the
// source_cidr above will have no effect. // source_cidr above will have no effect.
SourceGeoip []*GeoIP `protobuf:"bytes,11,rep,name=source_geoip,json=sourceGeoip,proto3" json:"source_geoip,omitempty"` SourceGeoip []*GeoIP `protobuf:"bytes,11,rep,name=source_geoip,json=sourceGeoip,proto3" json:"source_geoip,omitempty"`
@@ -526,11 +496,9 @@ type RoutingRule struct {
func (x *RoutingRule) Reset() { func (x *RoutingRule) Reset() {
*x = RoutingRule{} *x = RoutingRule{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[6]
mi := &file_app_router_config_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *RoutingRule) String() string { func (x *RoutingRule) String() string {
@@ -541,7 +509,7 @@ func (*RoutingRule) ProtoMessage() {}
func (x *RoutingRule) ProtoReflect() protoreflect.Message { func (x *RoutingRule) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[6] mi := &file_app_router_config_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -591,14 +559,6 @@ func (x *RoutingRule) GetDomain() []*Domain {
return nil return nil
} }
// Deprecated: Marked as deprecated in app/router/config.proto.
func (x *RoutingRule) GetCidr() []*CIDR {
if x != nil {
return x.Cidr
}
return nil
}
func (x *RoutingRule) GetGeoip() []*GeoIP { func (x *RoutingRule) GetGeoip() []*GeoIP {
if x != nil { if x != nil {
return x.Geoip return x.Geoip
@@ -606,14 +566,6 @@ func (x *RoutingRule) GetGeoip() []*GeoIP {
return nil return nil
} }
// Deprecated: Marked as deprecated in app/router/config.proto.
func (x *RoutingRule) GetPortRange() *net.PortRange {
if x != nil {
return x.PortRange
}
return nil
}
func (x *RoutingRule) GetPortList() *net.PortList { func (x *RoutingRule) GetPortList() *net.PortList {
if x != nil { if x != nil {
return x.PortList return x.PortList
@@ -621,14 +573,6 @@ func (x *RoutingRule) GetPortList() *net.PortList {
return nil return nil
} }
// Deprecated: Marked as deprecated in app/router/config.proto.
func (x *RoutingRule) GetNetworkList() *net.NetworkList {
if x != nil {
return x.NetworkList
}
return nil
}
func (x *RoutingRule) GetNetworks() []net.Network { func (x *RoutingRule) GetNetworks() []net.Network {
if x != nil { if x != nil {
return x.Networks return x.Networks
@@ -636,14 +580,6 @@ func (x *RoutingRule) GetNetworks() []net.Network {
return nil return nil
} }
// Deprecated: Marked as deprecated in app/router/config.proto.
func (x *RoutingRule) GetSourceCidr() []*CIDR {
if x != nil {
return x.SourceCidr
}
return nil
}
func (x *RoutingRule) GetSourceGeoip() []*GeoIP { func (x *RoutingRule) GetSourceGeoip() []*GeoIP {
if x != nil { if x != nil {
return x.SourceGeoip return x.SourceGeoip
@@ -725,11 +661,9 @@ type BalancingRule struct {
func (x *BalancingRule) Reset() { func (x *BalancingRule) Reset() {
*x = BalancingRule{} *x = BalancingRule{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[7]
mi := &file_app_router_config_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *BalancingRule) String() string { func (x *BalancingRule) String() string {
@@ -740,7 +674,7 @@ func (*BalancingRule) ProtoMessage() {}
func (x *BalancingRule) ProtoReflect() protoreflect.Message { func (x *BalancingRule) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[7] mi := &file_app_router_config_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -802,11 +736,9 @@ type StrategyWeight struct {
func (x *StrategyWeight) Reset() { func (x *StrategyWeight) Reset() {
*x = StrategyWeight{} *x = StrategyWeight{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[8]
mi := &file_app_router_config_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *StrategyWeight) String() string { func (x *StrategyWeight) String() string {
@@ -817,7 +749,7 @@ func (*StrategyWeight) ProtoMessage() {}
func (x *StrategyWeight) ProtoReflect() protoreflect.Message { func (x *StrategyWeight) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[8] mi := &file_app_router_config_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -872,11 +804,9 @@ type StrategyLeastLoadConfig struct {
func (x *StrategyLeastLoadConfig) Reset() { func (x *StrategyLeastLoadConfig) Reset() {
*x = StrategyLeastLoadConfig{} *x = StrategyLeastLoadConfig{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[9]
mi := &file_app_router_config_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *StrategyLeastLoadConfig) String() string { func (x *StrategyLeastLoadConfig) String() string {
@@ -887,7 +817,7 @@ func (*StrategyLeastLoadConfig) ProtoMessage() {}
func (x *StrategyLeastLoadConfig) ProtoReflect() protoreflect.Message { func (x *StrategyLeastLoadConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[9] mi := &file_app_router_config_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -949,11 +879,9 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[10]
mi := &file_app_router_config_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Config) String() string { func (x *Config) String() string {
@@ -964,7 +892,7 @@ func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[10] mi := &file_app_router_config_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -1015,11 +943,9 @@ type Domain_Attribute struct {
func (x *Domain_Attribute) Reset() { func (x *Domain_Attribute) Reset() {
*x = Domain_Attribute{} *x = Domain_Attribute{}
if protoimpl.UnsafeEnabled { mi := &file_app_router_config_proto_msgTypes[11]
mi := &file_app_router_config_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Domain_Attribute) String() string { func (x *Domain_Attribute) String() string {
@@ -1030,7 +956,7 @@ func (*Domain_Attribute) ProtoMessage() {}
func (x *Domain_Attribute) ProtoReflect() protoreflect.Message { func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
mi := &file_app_router_config_proto_msgTypes[11] mi := &file_app_router_config_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -1143,7 +1069,7 @@ var file_app_router_config_proto_rawDesc = []byte{
0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6e, 0x74,
0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69,
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xbd, 0x07, 0x0a, 0x0b, 0x52, 0x6f, 0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xce, 0x05, 0x0a, 0x0b, 0x52, 0x6f,
0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a,
0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c,
@@ -1153,112 +1079,97 @@ var file_app_router_config_proto_rawDesc = []byte{
0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x12, 0x2d, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
0x2e, 0x43, 0x49, 0x44, 0x52, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x36,
0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x3d, 0x0a, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f,
0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6b, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x02, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f,
0x01, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x09, 0x72, 0x6b, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x39, 0x0a, 0x0c,
0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0b, 0x20, 0x03,
0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72,
0x4c, 0x69, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x63, 0x65, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x43, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28,
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x6e, 0x65, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x73, 0x6f,
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x08, 0x6e, 0x65, 0x74, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a,
0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09,
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x69,
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09,
0x3a, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x06, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49, 0x44, 0x52, 0x42, 0x02, 0x18, 0x01, 0x52, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x4c, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72,
0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x69, 0x64, 0x72, 0x12, 0x39, 0x0a, 0x0c, 0x73, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52,
0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69,
0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72,
0x65, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x43, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x1a, 0x3d, 0x0a,
0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a,
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42,
0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03,
0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b,
0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x4c, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73,
0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74,
0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x65, 0x67, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01,
0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x1a, 0x3d, 0x0a, 0x0f, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73,
0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65,
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61,
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72,
0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72,
0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x65, 0x67, 0x65, 0x78, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67,
0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b, 0x0a, 0x65, 0x78, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01,
0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
0x6e, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0xc0, 0x01, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73,
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63,
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61,
0x67, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72,
0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73,
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18,
0x61, 0x67, 0x65, 0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65, 0x74, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73,
0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01,
0x6b, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61, 0x6c, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06,
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x61, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61,
0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63,
0x67, 0x65, 0x78, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67, 0x65, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e,
0x78, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x63, 0x65, 0x22, 0x9b, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a,
0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc0, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x01, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63, 0x6f, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e,
0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78,
0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52,
0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65,
0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75,
0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e,
0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63,
0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49,
0x65, 0x22, 0x9b, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10,
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02,
0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03,
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75,
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30, 0x0a, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65,
0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x45, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c,
0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69,
0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49, 0x73,
0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10, 0x0a,
0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02, 0x12,
0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03, 0x42,
0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63,
0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa, 0x02,
0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@@ -1275,7 +1186,7 @@ func file_app_router_config_proto_rawDescGZIP() []byte {
var file_app_router_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_app_router_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_app_router_config_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_app_router_config_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_app_router_config_proto_goTypes = []interface{}{ var file_app_router_config_proto_goTypes = []any{
(Domain_Type)(0), // 0: xray.app.router.Domain.Type (Domain_Type)(0), // 0: xray.app.router.Domain.Type
(Config_DomainStrategy)(0), // 1: xray.app.router.Config.DomainStrategy (Config_DomainStrategy)(0), // 1: xray.app.router.Config.DomainStrategy
(*Domain)(nil), // 2: xray.app.router.Domain (*Domain)(nil), // 2: xray.app.router.Domain
@@ -1291,11 +1202,9 @@ var file_app_router_config_proto_goTypes = []interface{}{
(*Config)(nil), // 12: xray.app.router.Config (*Config)(nil), // 12: xray.app.router.Config
(*Domain_Attribute)(nil), // 13: xray.app.router.Domain.Attribute (*Domain_Attribute)(nil), // 13: xray.app.router.Domain.Attribute
nil, // 14: xray.app.router.RoutingRule.AttributesEntry nil, // 14: xray.app.router.RoutingRule.AttributesEntry
(*net.PortRange)(nil), // 15: xray.common.net.PortRange (*net.PortList)(nil), // 15: xray.common.net.PortList
(*net.PortList)(nil), // 16: xray.common.net.PortList (net.Network)(0), // 16: xray.common.net.Network
(*net.NetworkList)(nil), // 17: xray.common.net.NetworkList (*serial.TypedMessage)(nil), // 17: xray.common.serial.TypedMessage
(net.Network)(0), // 18: xray.common.net.Network
(*serial.TypedMessage)(nil), // 19: xray.common.serial.TypedMessage
} }
var file_app_router_config_proto_depIdxs = []int32{ var file_app_router_config_proto_depIdxs = []int32{
0, // 0: xray.app.router.Domain.type:type_name -> xray.app.router.Domain.Type 0, // 0: xray.app.router.Domain.type:type_name -> xray.app.router.Domain.Type
@@ -1305,26 +1214,22 @@ var file_app_router_config_proto_depIdxs = []int32{
2, // 4: xray.app.router.GeoSite.domain:type_name -> xray.app.router.Domain 2, // 4: xray.app.router.GeoSite.domain:type_name -> xray.app.router.Domain
6, // 5: xray.app.router.GeoSiteList.entry:type_name -> xray.app.router.GeoSite 6, // 5: xray.app.router.GeoSiteList.entry:type_name -> xray.app.router.GeoSite
2, // 6: xray.app.router.RoutingRule.domain:type_name -> xray.app.router.Domain 2, // 6: xray.app.router.RoutingRule.domain:type_name -> xray.app.router.Domain
3, // 7: xray.app.router.RoutingRule.cidr:type_name -> xray.app.router.CIDR 4, // 7: xray.app.router.RoutingRule.geoip:type_name -> xray.app.router.GeoIP
4, // 8: xray.app.router.RoutingRule.geoip:type_name -> xray.app.router.GeoIP 15, // 8: xray.app.router.RoutingRule.port_list:type_name -> xray.common.net.PortList
15, // 9: xray.app.router.RoutingRule.port_range:type_name -> xray.common.net.PortRange 16, // 9: xray.app.router.RoutingRule.networks:type_name -> xray.common.net.Network
16, // 10: xray.app.router.RoutingRule.port_list:type_name -> xray.common.net.PortList 4, // 10: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP
17, // 11: xray.app.router.RoutingRule.network_list:type_name -> xray.common.net.NetworkList 15, // 11: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
18, // 12: xray.app.router.RoutingRule.networks:type_name -> xray.common.net.Network 14, // 12: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
3, // 13: xray.app.router.RoutingRule.source_cidr:type_name -> xray.app.router.CIDR 17, // 13: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
4, // 14: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP 10, // 14: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
16, // 15: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList 1, // 15: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
14, // 16: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry 8, // 16: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
19, // 17: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage 9, // 17: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
10, // 18: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight 18, // [18:18] is the sub-list for method output_type
1, // 19: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy 18, // [18:18] is the sub-list for method input_type
8, // 20: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule 18, // [18:18] is the sub-list for extension type_name
9, // 21: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule 18, // [18:18] is the sub-list for extension extendee
22, // [22:22] is the sub-list for method output_type 0, // [0:18] is the sub-list for field type_name
22, // [22:22] is the sub-list for method input_type
22, // [22:22] is the sub-list for extension type_name
22, // [22:22] is the sub-list for extension extendee
0, // [0:22] is the sub-list for field type_name
} }
func init() { file_app_router_config_proto_init() } func init() { file_app_router_config_proto_init() }
@@ -1332,157 +1237,11 @@ func file_app_router_config_proto_init() {
if File_app_router_config_proto != nil { if File_app_router_config_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled { file_app_router_config_proto_msgTypes[6].OneofWrappers = []any{
file_app_router_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Domain); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CIDR); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GeoIP); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GeoIPList); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GeoSite); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GeoSiteList); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RoutingRule); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BalancingRule); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StrategyWeight); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StrategyLeastLoadConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_router_config_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Domain_Attribute); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_app_router_config_proto_msgTypes[6].OneofWrappers = []interface{}{
(*RoutingRule_Tag)(nil), (*RoutingRule_Tag)(nil),
(*RoutingRule_BalancingTag)(nil), (*RoutingRule_BalancingTag)(nil),
} }
file_app_router_config_proto_msgTypes[11].OneofWrappers = []interface{}{ file_app_router_config_proto_msgTypes[11].OneofWrappers = []any{
(*Domain_Attribute_BoolValue)(nil), (*Domain_Attribute_BoolValue)(nil),
(*Domain_Attribute_IntValue)(nil), (*Domain_Attribute_IntValue)(nil),
} }

View File

@@ -84,32 +84,18 @@ message RoutingRule {
// List of domains for target domain matching. // List of domains for target domain matching.
repeated Domain domain = 2; repeated Domain domain = 2;
// List of CIDRs for target IP address matching.
// Deprecated. Use geoip below.
repeated CIDR cidr = 3 [deprecated = true];
// List of GeoIPs for target IP address matching. If this entry exists, the // List of GeoIPs for target IP address matching. If this entry exists, the
// cidr above will have no effect. GeoIP fields with the same country code are // cidr above will have no effect. GeoIP fields with the same country code are
// supposed to contain exactly same content. They will be merged during // supposed to contain exactly same content. They will be merged during
// runtime. For customized GeoIPs, please leave country code empty. // runtime. For customized GeoIPs, please leave country code empty.
repeated GeoIP geoip = 10; repeated GeoIP geoip = 10;
// A range of port [from, to]. If the destination port is in this range, this
// rule takes effect. Deprecated. Use port_list.
xray.common.net.PortRange port_range = 4 [deprecated = true];
// List of ports. // List of ports.
xray.common.net.PortList port_list = 14; xray.common.net.PortList port_list = 14;
// List of networks. Deprecated. Use networks.
xray.common.net.NetworkList network_list = 5 [deprecated = true];
// List of networks for matching. // List of networks for matching.
repeated xray.common.net.Network networks = 13; repeated xray.common.net.Network networks = 13;
// List of CIDRs for source IP address matching.
repeated CIDR source_cidr = 6 [deprecated = true];
// List of GeoIPs for source IP address matching. If this entry exists, the // List of GeoIPs for source IP address matching. If this entry exists, the
// source_cidr above will have no effect. // source_cidr above will have no effect.
repeated GeoIP source_geoip = 11; repeated GeoIP source_geoip = 11;

View File

@@ -1,7 +1,5 @@
package router package router
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
import ( import (
"context" "context"
sync "sync" sync "sync"
@@ -34,6 +32,7 @@ type Route struct {
routing.Context routing.Context
outboundGroupTags []string outboundGroupTags []string
outboundTag string outboundTag string
ruleTag string
} }
// Init initializes the Router. // Init initializes the Router.
@@ -89,7 +88,7 @@ func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Route{Context: ctx, outboundTag: tag}, nil return &Route{Context: ctx, outboundTag: tag, ruleTag: rule.RuleTag}, nil
} }
// AddRule implements routing.Router. // AddRule implements routing.Router.
@@ -239,6 +238,10 @@ func (r *Route) GetOutboundTag() string {
return r.outboundTag return r.outboundTag
} }
func (r *Route) GetRuleTag() string {
return r.ruleTag
}
func init() { func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
r := new(Router) r := new(Router)

Some files were not shown because too many files have changed in this diff Show More