Compare commits

..
Author SHA1 Message Date
Fangliding e9a2d26c07 Exp: Make eveything listable 2026-02-02 01:26:01 +08:00
Fangliding 37efc4237a Add listable 2026-01-31 20:18:26 +08:00
RPRX 2c92339f95 TLS config: allowInsecure->pinnedPeerCertSha256; verifyPeerCertInNames->verifyPeerCertByName
And use `,` as the separator instead of `~`/array

https://github.com/XTLS/Xray-core/pull/5567#issuecomment-3766081805
https://t.me/projectXtls/1464
https://t.me/projectXtls/1465
https://t.me/projectXtls/1466
https://github.com/XTLS/Xray-core/pull/5625#issuecomment-3824855736
2026-01-31 09:32:51 +00:00
RPRXandGitHub 9c46a2d55a Upgrade gVisor to latest version v0.0.0-20260122175437-89a5d21be8f0
https://github.com/XTLS/Xray-core/issues/5561#issuecomment-3767618362
2026-01-30 21:39:13 +00:00
nasaboyandGitHub 19186edfa1 README.md: Add Egern & Quantumult X to Others (#5624) 2026-01-30 14:06:17 +00:00
风扇滑翔翼andGitHub f6a7e93923 VMess inbound: Optimize replay filter (#5562)
And https://github.com/XTLS/Xray-core/pull/5562#issuecomment-3765387903
2026-01-27 18:34:46 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
077070dbe0 Bump github.com/pires/go-proxyproto from 0.9.1 to 0.9.2 (#5614)
Bumps [github.com/pires/go-proxyproto](https://github.com/pires/go-proxyproto) from 0.9.1 to 0.9.2.
- [Release notes](https://github.com/pires/go-proxyproto/releases)
- [Commits](https://github.com/pires/go-proxyproto/compare/v0.9.1...v0.9.2)

---
updated-dependencies:
- dependency-name: github.com/pires/go-proxyproto
  dependency-version: 0.9.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>
2026-01-27 10:11:28 +00:00
Evozi TeamandGitHub c3af657c0e TUN inbound: Add iOS support (#5612)
And https://github.com/XTLS/Xray-core/pull/5612#issuecomment-3799070838
2026-01-26 12:43:10 +00:00
MeowandGitHub 9a04eecaf9 Geodat: Reduce peak memory usage (#5581)
Fixes https://github.com/XTLS/Xray-core/commit/5f7474120f523ad1e36174481e0b16c3446cc29c
2026-01-26 10:45:25 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1951a278ac Bump github.com/pires/go-proxyproto from 0.9.0 to 0.9.1 (#5608)
Bumps [github.com/pires/go-proxyproto](https://github.com/pires/go-proxyproto) from 0.9.0 to 0.9.1.
- [Release notes](https://github.com/pires/go-proxyproto/releases)
- [Commits](https://github.com/pires/go-proxyproto/compare/v0.9.0...v0.9.1)

---
updated-dependencies:
- dependency-name: github.com/pires/go-proxyproto
  dependency-version: 0.9.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>
2026-01-26 10:31:34 +00:00
LjhAUMEMandGitHub f1aee0b7c5 Hysteria transport: Support range & random for interval in udphop as well (#5603)
https://github.com/XTLS/Xray-core/pull/5560#issuecomment-3794621260
2026-01-25 18:28:51 +00:00
OwersunandGitHub 5173e5c15d TUN inbound: Enhance Darwin interface support (#5598)
* Proxy: TUN: Enhance Darwin interface support.
- reduce number of actions done to create/configure the interface in the system
- assign synthetic static link-local ipv4/ipv6 addresses to the interface, that are required by the OS for the routing to work
- make tun_darwin_endpoint be implemented significantly more similar to tun_windows_enpoint, preparing them for potential unification

* Proxy: TUN: Unify Darwin/Windows endpoint, which are now extremely similar, into one GVisorEndpoint.
Making darwin/windows tun implement GVisorDevice with simple readpacket/writepacket methods that GVisorEndpoint untilise
2026-01-25 18:19:05 +00:00
风扇滑翔翼andRPRX daf9cba29f XUDP client: Initialize Global ID's BaseKey correctly (#5602)
https://t.me/projectXray/4624679
2026-01-24 15:11:44 +00:00
kiandGitHub 445c0d456c TUN inbound: Disable RACK/TLP recovery to fix connection stalls (#5600)
https://github.com/XTLS/Xray-core/issues/5599#issuecomment-3794495254

Fixes https://github.com/XTLS/Xray-core/issues/5599
2026-01-24 12:39:07 +00:00
RPRXandGitHub 0a42dba13e v26.1.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

VLESS Post-Quantum Encryption: https://github.com/XTLS/Xray-core/pull/5067
VLESS NFT: https://opensea.io/collection/vless

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2026-01-23 15:48:16 +00:00
cd8aab9544 common/errors/feature_errors.go: Add PrintNonRemovalDeprecatedFeatureWarning() (#5567)
And https://github.com/XTLS/Xray-core/pull/5567#issuecomment-3765466219

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2026-01-23 15:45:20 +00:00
MouMengandGitHub 59dc2cee2e API: Add ListRule() for routing (#5569)
https://github.com/XTLS/Xray-core/pull/5569#issuecomment-3766310407
2026-01-23 15:44:16 +00:00
风扇滑翔翼andGitHub 5846f94784 Log config: More flexible maskAddress (#5570)
https://github.com/XTLS/Xray-core/pull/5566#issuecomment-3765429984
2026-01-23 13:49:08 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e0ee2350fc Bump github.com/miekg/dns from 1.1.70 to 1.1.72 (#5590)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.70 to 1.1.72.
- [Commits](https://github.com/miekg/dns/compare/v1.1.70...v1.1.72)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-version: 1.1.72
  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>
2026-01-23 13:11:41 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
48164c8267 Bump github.com/cloudflare/circl from 1.6.2 to 1.6.3 (#5589)
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.6.2 to 1.6.3.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.6.2...v1.6.3)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  dependency-version: 1.6.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>
2026-01-23 13:11:20 +00:00
LjhAUMEMandGitHub 2d2102f654 Hysteria transport: Fix speedtest issue (#5587)
Fixes https://github.com/XTLS/Xray-core/issues/5546
2026-01-22 13:37:27 +00:00
RPRXandGitHub 262770564f README.md: Add fancyss to Asuswrt-Merlin Clients 2026-01-22 03:08:46 +00:00
风扇滑翔翼andGitHub 777e31302c Router: Fix panic in ProcessNameMatcher when source IPs are empty (#5574)
Fixes https://github.com/XTLS/Xray-core/issues/5573
2026-01-21 13:24:51 +00:00
gamekiller0010andGitHub 30d6a5221b README.md: Update links for PassWall & PassWall 2 (#5572) 2026-01-21 13:16:27 +00:00
风扇滑翔翼andGitHub a778d3d273 Tests: Reduce RAM usage (#5577)
https://github.com/XTLS/Xray-core/pull/5577#issuecomment-3768963110
2026-01-21 13:02:04 +00:00
e813a3744f TUN inbound: Cancel ctx when handling is done (#5565)
https://github.com/XTLS/Xray-core/pull/5565#issuecomment-3777939907

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2026-01-21 12:58:30 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
66628943d8 Bump github.com/pires/go-proxyproto from 0.8.1 to 0.9.0 (#5582)
Bumps [github.com/pires/go-proxyproto](https://github.com/pires/go-proxyproto) from 0.8.1 to 0.9.0.
- [Release notes](https://github.com/pires/go-proxyproto/releases)
- [Commits](https://github.com/pires/go-proxyproto/compare/v0.8.1...v0.9.0)

---
updated-dependencies:
- dependency-name: github.com/pires/go-proxyproto
  dependency-version: 0.9.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>
2026-01-21 12:23:59 +00:00
RPRXandGitHub 7ff06f65ec v26.1.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

VLESS Post-Quantum Encryption: https://github.com/XTLS/Xray-core/pull/5067
VLESS NFT: https://opensea.io/collection/vless

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2026-01-18 05:43:07 +00:00
RPRXandGitHub 1cf5662949 Create SECURITY.md
All for the FREE Internet!
2026-01-18 05:11:51 +00:00
LjhAUMEMandGitHub a6aca101d6 Hysteria outbound: Fix ContextWithRequireDatagram() (#5558)
Fixes https://github.com/XTLS/Xray-core/pull/5549
2026-01-18 04:25:36 +00:00
RPRXandGitHub 5836f36f69 Config: Add Warning for deprecated features (allowInsecure, Shadowsocks, VMess, Trojan, VLESS without flow)
Accelerate!
2026-01-18 04:17:25 +00:00
osypaiandGitHub 6d6c045a5a TUN inbound: Add macOS support (#5559) 2026-01-18 03:39:39 +00:00
LjhAUMEMandGitHub cfc78b3ac1 Hysteria transport: Add congestion config (""/"reno"/"bbr"/"brutal"/"force-brutal") (#5549)
Closes https://github.com/XTLS/Xray-core/issues/5546
2026-01-17 13:29:50 +00:00
风扇滑翔翼andRPRX 5f7474120f Geofiles: Revert related changes for now, waiting for better changes (#5557)
Reverts https://github.com/XTLS/Xray-core/commit/5d94a62a83073bc4aa378fb7e2198e15878e90da https://github.com/XTLS/Xray-core/commit/c715154309e41e759f544edd3667889e257fb3af https://github.com/XTLS/Xray-core/commit/961c352127f32c04034a88d021a683e6a80eac20 https://github.com/XTLS/Xray-core/commit/36425d2a6e53c755c96d25ef2323b7fffd1fab3f

Fixes https://github.com/XTLS/Xray-core/issues/5538 https://github.com/XTLS/Xray-core/issues/5536
2026-01-17 12:40:53 +00:00
风扇滑翔翼andGitHub 09f619d67c TLS client: Add pin_test.go for leaf and CA (#5553)
https://github.com/XTLS/Xray-core/pull/5532#issuecomment-3760231005
2026-01-17 09:42:06 +00:00
RPRXandGitHub 760223ad70 TLS client: Skip TLS' built-in verification when using pinnedPeerCertSha256; Fixes
https://github.com/XTLS/Xray-core/pull/5532#issuecomment-3745598515
https://github.com/XTLS/Xray-core/pull/5532#issuecomment-3759930283
https://github.com/XTLS/Xray-core/pull/5532#issuecomment-3760057266
https://github.com/XTLS/Xray-core/pull/5532#issuecomment-3760540231
2026-01-16 15:23:39 +00:00
nobodyandGitHub d75b33a3a3 Commands: "xray run -dump" supports reading JSON from STDIN (#5550)
Fixes https://github.com/XTLS/Xray-core/issues/5534
2026-01-16 10:55:43 +00:00
Happ-devandGitHub 7c418486c8 README.md: Add Happ RU to iOS & macOS Clients (#5551) 2026-01-16 10:44:44 +00:00
风扇滑翔翼andGitHub a384be0f84 SS2022 outbound: Fix UDP leak (#5544)
Fixes https://github.com/XTLS/Xray-core/issues/5541
2026-01-14 13:31:43 +00:00
LjhAUMEMandGitHub 649e989fa2 Hysteria: Fix transport's "udphop without salamander" dialing issue; Require "version": 2 in outbound's settings as well (#5537)
Updated example: https://github.com/XTLS/Xray-core/pull/5508#issue-3795798712
2026-01-14 10:42:07 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0443de7798 Bump github.com/refraction-networking/utls from 1.8.1 to 1.8.2 (#5535)
Bumps [github.com/refraction-networking/utls](https://github.com/refraction-networking/utls) from 1.8.1 to 1.8.2.
- [Release notes](https://github.com/refraction-networking/utls/releases)
- [Commits](https://github.com/refraction-networking/utls/compare/v1.8.1...v1.8.2)

---
updated-dependencies:
- dependency-name: github.com/refraction-networking/utls
  dependency-version: 1.8.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>
2026-01-14 08:24:12 +00:00
RPRXandGitHub 9a121a489b v26.1.13
Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

VLESS Post-Quantum Encryption: https://github.com/XTLS/Xray-core/pull/5067
VLESS NFT: https://opensea.io/collection/vless

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2026-01-13 15:32:01 +00:00
风扇滑翔翼andGitHub 4bdf6e5c92 TLS client: Verify leaf cert (name, time) when pinning self-signed CA (#5532)
https://github.com/XTLS/Xray-core/pull/5154#issuecomment-3732159602
2026-01-13 14:35:24 +00:00
OwersunandRPRX ef2a967f12 TUN inbound: Close connection when handling is done (#5531)
https://github.com/XTLS/Xray-core/pull/5531#issuecomment-3744446015
2026-01-13 14:25:42 +00:00
LjhAUMEMandGitHub 92ada2dd1d Proxy: Add Hysteria outbound & transport (version 2, udphop) and Salamander udpmask (#5508)
https://github.com/XTLS/Xray-core/issues/3547#issuecomment-3549896520
https://github.com/XTLS/Xray-core/issues/2635#issuecomment-3570871754
2026-01-13 13:31:51 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8a9dbd407f Bump github.com/miekg/dns from 1.1.69 to 1.1.70 (#5528)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.69 to 1.1.70.
- [Commits](https://github.com/miekg/dns/compare/v1.1.69...v1.1.70)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-version: 1.1.70
  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>
2026-01-13 09:55:42 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
de6be7c5a9 Bump golang.org/x/net from 0.48.0 to 0.49.0 (#5530)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.48.0 to 0.49.0.
- [Commits](https://github.com/golang/net/compare/v0.48.0...v0.49.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.49.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>
2026-01-13 09:49:58 +00:00
OwersunandGitHub e742e84ded Upgrade gVisor to latest version v0.0.0-20260109181451-4be7c433dae2 (#5527)
https://github.com/XTLS/Xray-core/pull/5526#issuecomment-3738638586
2026-01-12 18:18:02 +00:00
7726fbece0 TUN inbound: Make udp_fullcone pure side effect free udp connection (#5526)
https://github.com/XTLS/Xray-core/pull/5526#issue-3804306341

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2026-01-12 15:34:09 +00:00
0c09f4342b TUN inbound: Fix log, CanSpliceCopy, tag, sniffing, and port config issues (#5522)
Fixes https://github.com/XTLS/Xray-core/pull/5509#issuecomment-3732488294 & https://github.com/XTLS/Xray-core/pull/5509#issuecomment-3732740897

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2026-01-12 10:01:27 +00:00
14e171ac8e TUN inbound: Implement UDP FullCone NAT (#5509)
https://github.com/XTLS/Xray-core/pull/5509#issuecomment-3732898130

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
Co-authored-by: Fangliding <45535409+Fangliding@users.noreply.github.com>
Co-authored-by: Owersun <4807375+Owersun@users.noreply.github.com>
2026-01-11 14:26:45 +00:00
风扇滑翔翼andGitHub 07a0dafa41 DNS: Check err for UDP dns.PackMessage(req.msg) (#5512)
Fixes https://github.com/XTLS/Xray-core/issues/5506
2026-01-09 14:22:07 +00:00
0ca13452b8 TLS config: Add pinnedPeerCertSha256; Remove pinnedPeerCertificateChainSha256 and pinnedPeerCertificatePublicKeySha256 (#5154)
Usage: https://github.com/XTLS/Xray-core/pull/5507

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2026-01-09 00:11:24 +00:00
Hossin AsaadiandGitHub 36425d2a6e Tests: Improve geosite & geoip tests (#5502)
https://github.com/XTLS/Xray-core/pull/5488#issuecomment-3711843548
2026-01-08 08:00:49 +00:00
39ba1f7952 Proxy: Add TUN inbound for Windows & Linux, including Android (#5464)
* Proxy: Implement tun raw network interface inbound support for Linux

* Proxy: Tun. Include "android" as build condition for build of tun_default implementation

* Proxy: Tun. Add .Close() cleanup calls to Handler.Init() where needed

* Proxy: Add Tun for Android

* Proxy: Tun. Implement Windows support

---------

Co-authored-by: yuhan6665 <1588741+yuhan6665@users.noreply.github.com>
2026-01-07 22:05:08 +00:00
𐲓𐳛𐳪𐳂𐳐 𐲀𐳢𐳦𐳫𐳢 𐲥𐳔𐳛𐳪𐳌𐳑𐳖𐳇andGitHub 394e117998 GitHub Actions: Add wintun.dll into Windows zips; Workflow refinement (#5501)
For https://github.com/XTLS/Xray-core/pull/5464
2026-01-07 12:59:23 +00:00
风扇滑翔翼andRPRX 446df149bd Routing config: Replace processName with process (full-name/abs-path/abs-folder) (#5496)
About `self/` & `xray/`: https://github.com/XTLS/Xray-core/pull/5496#issuecomment-3714620380

Replaces https://github.com/XTLS/Xray-core/pull/5489
2026-01-06 14:03:21 +00:00
风扇滑翔翼andGitHub d9025857fe transport/pipe/impl.go: Remove runtime.Gosched() in WriteMultiBuffer() (#5467) 2026-01-06 12:43:08 +00:00
Alireza AhmandandGitHub ced3e75bf3 README.md: Add TX-UI to Web Panels (#4981) 2026-01-06 12:24:32 +00:00
Hossin AsaadiandGitHub 961c352127 DNS: Fix parse domain and geoip (#5499)
Fixes https://github.com/XTLS/Xray-core/pull/5488#issuecomment-3712856715
2026-01-06 12:21:50 +00:00
Hossin AsaadiandGitHub c715154309 Routing: Reduce peak memory usage (#5488)
https://github.com/XTLS/Xray-core/pull/5488#issuecomment-3711430369

For https://github.com/XTLS/Xray-core/issues/4422
2026-01-05 23:02:40 +00:00
RPRXandGitHub b38a41249f README.md: Re-add 3X-UI to Web Panels
https://github.com/XTLS/Xray-core/pull/3884#issuecomment-3678495173

https://github.com/XTLS/Xray-core/issues/5478#issuecomment-3700567911
2026-01-05 08:42:35 +00:00
风扇滑翔翼andGitHub 7265b5ac3f Routing config: Add processName (#5489) 2026-01-05 01:12:13 +00:00
fanymagnetandRPRX e7c72c011f XHTTP server: Fix ScStreamUpServerSecs' non-default value (#5486) 2026-01-05 01:07:00 +00:00
yuhan6665andGitHub a54e1f2be4 Remove redundant stats in mux and bridge dispatcher (#5466)
Fixes https://github.com/XTLS/Xray-core/issues/5446
2025-12-31 11:00:45 +00:00
Hossin AsaadiandGitHub 5d94a62a83 Geofiles: Implement mmap in filesystem to reduce ram usage (#5480)
For https://github.com/XTLS/Xray-core/issues/4422
2025-12-31 08:50:30 +00:00
Maxim PlotnikovandGitHub ad468e462d API: Add GetAllOnlineUsers RPC to StatsService for retrieving online users (#5080) 2025-12-26 16:07:06 -05:00
ari-ahmandGitHub 6738ecf68e common/uuid: fix panic when parsing 32-len invalid UUID string. (#5468)
* common/uuid: fix panic when parsing 32-len invalid UUID string.

* fix: removed typo
2025-12-26 15:17:24 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
36968909a1 Bump google.golang.org/grpc from 1.77.0 to 1.78.0 (#5469)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.77.0 to 1.78.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.77.0...v1.78.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.78.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-12-24 20:45:54 -05:00
MeowandGitHub 7f6ceb39f7 DomainMatcher: Prevent illegal domain rules from causing core startup failures (#5430)
Closes https://github.com/XTLS/Xray-core/issues/5429
2025-12-23 10:14:42 +00:00
风扇滑翔翼andGitHub fa64775f07 Tunnel/Dokodemo: Fix stats conn unwrap (#5440)
Fixes https://github.com/XTLS/Xray-core/issues/5439
2025-12-23 09:44:54 +00:00
a6792dda69 TLS ECH: Increase DOH timeout (#5455)
Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
2025-12-23 09:41:01 +00:00
3572209cbd REALITY client: Clearer log when receiving real certificate (#5427)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-12-23 08:58:43 +00:00
dd757ca27c VLESS inbound: Print invalid UUID string (#5426)
Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-12-23 08:27:40 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
04b433dd97 Bump github.com/cloudflare/circl from 1.6.1 to 1.6.2 (#5465)
Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.6.1 to 1.6.2.
- [Release notes](https://github.com/cloudflare/circl/releases)
- [Commits](https://github.com/cloudflare/circl/compare/v1.6.1...v1.6.2)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/circl
  dependency-version: 1.6.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-12-23 08:13:09 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6bf0376773 Bump github.com/quic-go/quic-go from 0.57.1 to 0.58.0 (#5459)
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.57.1 to 0.58.0.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.57.1...v0.58.0)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-version: 0.58.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-12-21 22:28:33 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
74df63add2 Bump actions/upload-artifact from 5 to 6 (#5425)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  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-12-14 22:01:02 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c40326dfd7 Bump google.golang.org/protobuf from 1.36.10 to 1.36.11 (#5424)
Bumps google.golang.org/protobuf from 1.36.10 to 1.36.11.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-version: 1.36.11
  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-12-14 22:00:53 -05:00
MeowandGitHub a3ba3eefb6 Wireguard: Decouple server endpoint DNS from address option (#5417)
* Wireguard: Decouple server endpoint DNS from address option

Previously, Wireguard server endpoint's domain resolution was incorrectly constrained by the local `address` option. For example, `ForceIPv6v4` might fail to resolve AAAA records for the server domain if no IPv6 was explicitly configured in the `address` option.

This commit decouples the server endpoint's domain resolution from the local `address` configuration. It ensures the Wireguard server address is resolved independently, allowing its `domainStrategy` to function correctly without being limited by the client's local network or `address` settings.

* Delete code instead of commenting it out
2025-12-14 10:13:47 -05:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9cf22114a1 Bump github.com/miekg/dns from 1.1.68 to 1.1.69 (#5410)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.68 to 1.1.69.
- [Commits](https://github.com/miekg/dns/compare/v1.1.68...v1.1.69)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-version: 1.1.69
  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-12-12 06:01:44 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a903e80356 Bump actions/cache from 4 to 5 (#5411)
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  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-12-12 06:01:24 +00:00
179 changed files with 11042 additions and 2233 deletions
+48 -16
View File
@@ -13,11 +13,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: resources
key: xray-geodat-
- name: Restore Wintun Cache
uses: actions/cache/restore@v5
with:
path: resources
key: xray-wintun-
- name: Check Assets Existence
id: check-assets
run: |
@@ -34,6 +40,18 @@ jobs:
break
fi
done
LIST=('amd64' 'x86')
for ARCHITECTURE in "${LIST[@]}"
do
echo -e "Checking wintun.dll for ${ARCHITECTURE}..."
if [ -s "./resources/wintun/bin/${ARCHITECTURE}/wintun.dll" ]; then
echo -e "wintun.dll for ${ARCHITECTURE} exists."
else
echo -e "wintun.dll for ${ARCHITECTURE} is missing."
echo "missing=true" >> $GITHUB_OUTPUT
break
fi
done
- name: Sleep for 90 seconds if Assets Missing
if: steps.check-assets.outputs.missing == 'true'
@@ -95,20 +113,38 @@ jobs:
COMMID=$(git describe --always --dirty)
echo 'Building Xray for Windows 7...'
go build -o build_assets/xray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -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 -gcflags="all=-l=4" -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
uses: actions/cache/restore@v5
with:
path: resources
key: xray-geodat-
- name: Restore Wintun Cache
uses: actions/cache/restore@v5
with:
path: resources
key: xray-wintun-
- name: Add additional assets into package
run: |
mv -f resources/geo* build_assets/
if [[ ${GOOS} == 'windows' ]]; then
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
if [[ ${GOARCH} == 'amd64' ]]; then
mv resources/wintun/bin/amd64/wintun.dll build_assets/
fi
if [[ ${GOARCH} == '386' ]]; then
mv resources/wintun/bin/x86/wintun.dll build_assets/
fi
mv resources/wintun/LICENSE.txt build_assets/LICENSE-wintun.txt
fi
- 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
@@ -127,17 +163,6 @@ jobs:
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@v5
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'
@@ -146,3 +171,10 @@ jobs:
file: ./Xray-${{ env.ASSET_NAME }}.zip*
tag: ${{ github.ref }}
file_glob: true
- name: Upload files to Artifacts
uses: actions/upload-artifact@v6
with:
name: Xray-${{ env.ASSET_NAME }}
path: |
./build_assets/*
+55 -16
View File
@@ -13,11 +13,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: resources
key: xray-geodat-
- name: Restore Wintun Cache
uses: actions/cache/restore@v5
with:
path: resources
key: xray-wintun-
- name: Check Assets Existence
id: check-assets
run: |
@@ -34,6 +40,18 @@ jobs:
break
fi
done
LIST=('amd64' 'x86' 'arm64' 'arm')
for ARCHITECTURE in "${LIST[@]}"
do
echo -e "Checking wintun.dll for ${ARCHITECTURE}..."
if [ -s "./resources/wintun/bin/${ARCHITECTURE}/wintun.dll" ]; then
echo -e "wintun.dll for ${ARCHITECTURE} exists."
else
echo -e "wintun.dll for ${ARCHITECTURE} is missing."
echo "missing=true" >> $GITHUB_OUTPUT
break
fi
done
- name: Trigger Asset Update Workflow if Assets Missing
if: steps.check-assets.outputs.missing == 'true'
@@ -191,8 +209,6 @@ jobs:
if [[ ${GOOS} == 'windows' ]]; then
echo 'Building Xray for Windows...'
go build -o build_assets/xray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -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 -gcflags="all=-l=4" -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
else
@@ -207,14 +223,41 @@ jobs:
fi
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: resources
key: xray-geodat-
- name: Restore Wintun Cache
if: matrix.goos == 'windows'
uses: actions/cache/restore@v5
with:
path: resources
key: xray-wintun-
- name: Add additional assets into package
run: |
mv -f resources/geo* build_assets/
if [[ ${GOOS} == 'windows' ]]; then
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
if [[ ${GOARCH} == 'amd64' ]]; then
mv resources/wintun/bin/amd64/wintun.dll build_assets/
fi
if [[ ${GOARCH} == '386' ]]; then
mv resources/wintun/bin/x86/wintun.dll build_assets/
fi
if [[ ${GOARCH} == 'arm64' ]]; then
mv resources/wintun/bin/arm64/wintun.dll build_assets/
fi
if [[ ${GOARCH} == 'arm' ]]; then
mv resources/wintun/bin/arm/wintun.dll build_assets/
fi
mv resources/wintun/LICENSE.txt build_assets/LICENSE-wintun.txt
fi
- 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
@@ -233,17 +276,6 @@ jobs:
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@v5
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'
@@ -252,3 +284,10 @@ jobs:
file: ./Xray-${{ env.ASSET_NAME }}.zip*
tag: ${{ github.ref }}
file_glob: true
- name: Upload files to Artifacts
uses: actions/upload-artifact@v6
with:
name: Xray-${{ env.ASSET_NAME }}
path: |
./build_assets/*
+67 -3
View File
@@ -4,6 +4,7 @@ name: Scheduled assets update
# routine manner, for example: GeoIP/GeoSite.
# Currently updating:
# - Geodat (GeoIP/Geosite)
# - Wintun (wintun.dll)
on:
workflow_dispatch:
@@ -21,11 +22,11 @@ on:
jobs:
geodat:
if: github.event.schedule == '30 22 * * *' || github.event_name == 'push'|| github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
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
uses: actions/cache/restore@v5
with:
path: resources
key: xray-geodat-
@@ -58,8 +59,71 @@ jobs:
done
- name: Save Geodat Cache
uses: actions/cache/save@v4
uses: actions/cache/save@v5
if: ${{ steps.update.outputs.unhit }}
with:
path: resources
key: xray-geodat-${{ github.sha }}-${{ github.run_number }}
wintun:
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 Wintun Cache
uses: actions/cache/restore@v5
with:
path: resources
key: xray-wintun-
- name: Force downloading if run manually or on file update
if: github.event_name == 'workflow_dispatch' || github.event_name == 'push'
run: |
echo "FORCE_UPDATE=true" >> $GITHUB_ENV
- name: Update Wintun
id: update
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
retry_wait_seconds: 60
max_attempts: 60
command: |
[ -d 'resources' ] || mkdir resources
LIST=('amd64' 'x86' 'arm64' 'arm')
for ARCHITECTURE in "${LIST[@]}"
do
FILE_PATH="resources/wintun/bin/${ARCHITECTURE}/wintun.dll"
echo -e "Checking if wintun.dll for ${ARCHITECTURE} exists..."
if [ -s "./resources/wintun/bin/${ARCHITECTURE}/wintun.dll" ]; then
echo -e "wintun.dll for ${ARCHITECTURE} exists"
continue
else
echo -e "wintun.dll for ${ARCHITECTURE} is missing"
missing=true
fi
done
if [ -s "./resources/wintun/LICENSE.txt" ]; then
echo -e "LICENSE for Wintun exists"
else
echo -e "LICENSE for Wintun is missing"
missing=true
fi
if [[ -v FORCE_UPDATE ]]; then
missing=true
fi
if [[ "$missing" == true ]]; then
FILENAME=wintun.zip
DOWNLOAD_FILE=wintun-0.14.1.zip
echo -e "Downloading https://www.wintun.net/builds/${DOWNLOAD_FILE}..."
curl -L "https://www.wintun.net/builds/${DOWNLOAD_FILE}" -o "${FILENAME}"
echo -e "Unpacking wintun..."
unzip -u ${FILENAME} -d resources/
echo "unhit=true" >> $GITHUB_OUTPUT
fi
- name: Save Wintun Cache
uses: actions/cache/save@v5
if: ${{ steps.update.outputs.unhit }}
with:
path: resources
key: xray-wintun-${{ github.sha }}-${{ github.run_number }}
+2 -2
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: resources
key: xray-geodat-
@@ -52,7 +52,7 @@ jobs:
go-version-file: go.mod
check-latest: true
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
uses: actions/cache/restore@v5
with:
path: resources
key: xray-geodat-
+11 -6
View File
@@ -56,13 +56,15 @@
- [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core) (**Official**)
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
- [wulabing/xray_docker](https://github.com/wulabing/xray_docker)
- 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:**
- Web Panel
- [Remnawave](https://github.com/remnawave/panel)
- [X-Panel](https://github.com/xeefei/X-Panel)
- [3X-UI](https://github.com/MHSanaei/3x-ui)
- [PasarGuard](https://github.com/PasarGuard/panel)
- [Marzban](https://github.com/Gozargah/Marzban)
- [Xray-UI](https://github.com/qist/xray-ui)
- [X-Panel](https://github.com/xeefei/X-Panel)
- [Marzban](https://github.com/Gozargah/Marzban)
- [Hiddify](https://github.com/hiddify/Hiddify-Manager)
- [TX-UI](https://github.com/AghayeCoder/tx-ui)
- 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_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool), [VPainLess](https://github.com/vpainless/vpainless)
@@ -93,11 +95,12 @@
## GUI Clients
- OpenWrt
- [PassWall](https://github.com/xiaorouji/openwrt-passwall), [PassWall 2](https://github.com/xiaorouji/openwrt-passwall2)
- [PassWall](https://github.com/Openwrt-Passwall/openwrt-passwall), [PassWall 2](https://github.com/Openwrt-Passwall/openwrt-passwall2)
- [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))
- Asuswrt-Merlin
- [XRAYUI](https://github.com/DanielLavrushin/asuswrt-merlin-xrayui)
- [fancyss](https://github.com/hq450/fancyss)
- Windows
- [v2rayN](https://github.com/2dust/v2rayN)
- [Furious](https://github.com/LorenEteval/Furious)
@@ -110,11 +113,11 @@
- [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))
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973) | [Happ tvOS](https://apps.apple.com/us/app/happ-proxy-utility-for-tv/id6748297274)
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
- [OneXray](https://github.com/OneXray/OneXray)
- macOS arm64 & x64
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215)
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973)
- [V2rayU](https://github.com/yanue/V2rayU)
- [V2RayXS](https://github.com/tzmax/V2RayXS)
- [Furious](https://github.com/LorenEteval/Furious)
@@ -135,6 +138,8 @@
- iOS & macOS arm64 & tvOS
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
- [Loon](https://apps.apple.com/us/app/loon/id1373567447)
- [Egern](https://apps.apple.com/us/app/egern/id1616105820)
- [Quantumult X](https://apps.apple.com/us/app/quantumult-x/id1443988620)
- Xray Tools
- [xray-knife](https://github.com/lilendian0x00/xray-knife)
- [xray-checker](https://github.com/kutovoys/xray-checker)
+5
View File
@@ -0,0 +1,5 @@
# Security Policy
If you found an issue related to security vulnerability or protocol-identification problem, please report it to us via "[Report a vulnerability](https://github.com/XTLS/Xray-core/security/advisories/new)" privately, instead of publish it publicly before we release the fixed version.
Thanks for your contribution to the FREE Internet!
+7 -6
View File
@@ -196,7 +196,7 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
return inboundLink, outboundLink
}
func (d *DefaultDispatcher) WrapLink(ctx context.Context, link *transport.Link) *transport.Link {
func WrapLink(ctx context.Context, policyManager policy.Manager, statsManager stats.Manager, link *transport.Link) *transport.Link {
sessionInbound := session.InboundFromContext(ctx)
var user *protocol.MemoryUser
if sessionInbound != nil {
@@ -206,16 +206,16 @@ func (d *DefaultDispatcher) WrapLink(ctx context.Context, link *transport.Link)
link.Reader = &buf.TimeoutWrapperReader{Reader: link.Reader}
if user != nil && len(user.Email) > 0 {
p := d.policy.ForLevel(user.Level)
p := policyManager.ForLevel(user.Level)
if p.Stats.UserUplink {
name := "user>>>" + user.Email + ">>>traffic>>>uplink"
if c, _ := stats.GetOrRegisterCounter(d.stats, name); c != nil {
if c, _ := stats.GetOrRegisterCounter(statsManager, name); c != nil {
link.Reader.(*buf.TimeoutWrapperReader).Counter = c
}
}
if p.Stats.UserDownlink {
name := "user>>>" + user.Email + ">>>traffic>>>downlink"
if c, _ := stats.GetOrRegisterCounter(d.stats, name); c != nil {
if c, _ := stats.GetOrRegisterCounter(statsManager, name); c != nil {
link.Writer = &SizeStatWriter{
Counter: c,
Writer: link.Writer,
@@ -224,7 +224,7 @@ func (d *DefaultDispatcher) WrapLink(ctx context.Context, link *transport.Link)
}
if p.Stats.UserOnline {
name := "user>>>" + user.Email + ">>>online"
if om, _ := stats.GetOrRegisterOnlineMap(d.stats, name); om != nil {
if om, _ := stats.GetOrRegisterOnlineMap(statsManager, name); om != nil {
sessionInbounds := session.InboundFromContext(ctx)
userIP := sessionInbounds.Source.Address.String()
om.AddIP(userIP)
@@ -357,7 +357,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
content = new(session.Content)
ctx = session.ContextWithContent(ctx, content)
}
outbound = d.WrapLink(ctx, outbound)
outbound = WrapLink(ctx, d.policy, d.stats, outbound)
sniffingRequest := content.SniffingRequest
if !sniffingRequest.Enabled {
d.routedDispatch(ctx, outbound, destination)
@@ -449,6 +449,7 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
}
return contentResult, contentErr
}
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
+1 -2
View File
@@ -106,13 +106,12 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
for _, ns := range config.NameServer {
clientIdx := len(clients)
updateDomain := func(domainRule strmatcher.Matcher, originalRuleIdx int, matcherInfos []*DomainMatcherInfo) error {
updateDomain := func(domainRule strmatcher.Matcher, originalRuleIdx int, matcherInfos []*DomainMatcherInfo) {
midx := domainMatcher.Add(domainRule)
matcherInfos[midx] = &DomainMatcherInfo{
clientIdx: uint16(clientIdx),
domainRuleIdx: uint16(originalRuleIdx),
}
return nil
}
myClientIP := clientIP
+11 -3
View File
@@ -2,6 +2,7 @@ package dns
import (
"context"
"runtime"
"strconv"
"github.com/xtls/xray-core/common/errors"
@@ -24,10 +25,13 @@ func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
matchers: g,
}
for _, mapping := range hosts {
defer runtime.GC()
for i, mapping := range hosts {
hosts[i] = nil
matcher, err := toStrMatcher(mapping.Type, mapping.Domain)
if err != nil {
return nil, errors.New("failed to create domain matcher").Base(err)
errors.LogErrorInner(context.Background(), err, "failed to create domain matcher, ignore domain rule [type: ", mapping.Type, ", domain: ", mapping.Domain, "]")
continue
}
id := g.Add(matcher)
ips := make([]net.Address, 0, len(mapping.Ip)+1)
@@ -46,10 +50,14 @@ func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
for _, ip := range mapping.Ip {
addr := net.IPAddress(ip)
if addr == nil {
return nil, errors.New("invalid IP address in static hosts: ", ip).AtWarning()
errors.LogError(context.Background(), "invalid IP address in static hosts: ", ip, ", ignore this ip for rule [type: ", mapping.Type, ", domain: ", mapping.Domain, "]")
continue
}
ips = append(ips, addr)
}
if len(ips) == 0 {
continue
}
}
sh.ips[id] = ips
+13 -7
View File
@@ -3,6 +3,7 @@ package dns
import (
"context"
"net/url"
"runtime"
"strings"
"time"
@@ -97,7 +98,7 @@ func NewClient(
tag string,
ipOption dns.IPOption,
matcherInfos *[]*DomainMatcherInfo,
updateDomainRule func(strmatcher.Matcher, int, []*DomainMatcherInfo) error,
updateDomainRule func(strmatcher.Matcher, int, []*DomainMatcherInfo),
) (*Client, error) {
client := &Client{}
@@ -131,10 +132,12 @@ func NewClient(
var rules []string
ruleCurr := 0
ruleIter := 0
for _, domain := range ns.PrioritizedDomain {
for i, domain := range ns.PrioritizedDomain {
ns.PrioritizedDomain[i] = nil
domainRule, err := toStrMatcher(domain.Type, domain.Domain)
if err != nil {
return errors.New("failed to create prioritized domain").Base(err).AtWarning()
errors.LogErrorInner(ctx, err, "failed to create domain matcher, ignore domain rule [type: ", domain.Type, ", domain: ", domain.Domain, "]")
domainRule, _ = toStrMatcher(DomainMatchingType_Full, "hack.fix.index.for.illegal.domain.rule")
}
originalRuleIdx := ruleCurr
if ruleCurr < len(ns.OriginalRules) {
@@ -151,11 +154,10 @@ func NewClient(
rules = append(rules, domainRule.String())
ruleCurr++
}
err = updateDomainRule(domainRule, originalRuleIdx, *matcherInfos)
if err != nil {
return errors.New("failed to create prioritized domain").Base(err).AtWarning()
}
updateDomainRule(domainRule, originalRuleIdx, *matcherInfos)
}
ns.PrioritizedDomain = nil
runtime.GC()
// Establish expected IPs
var expectedMatcher router.GeoIPMatcher
@@ -164,6 +166,8 @@ func NewClient(
if err != nil {
return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
}
ns.ExpectedGeoip = nil
runtime.GC()
}
// Establish unexpected IPs
@@ -173,6 +177,8 @@ func NewClient(
if err != nil {
return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
}
ns.UnexpectedGeoip = nil
runtime.GC()
}
if len(clientIP) > 0 {
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"sync"
"time"
"github.com/quic-go/quic-go"
"github.com/apernet/quic-go"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log"
+9 -2
View File
@@ -160,7 +160,7 @@ func (s *ClassicNameServer) getCacheController() *CacheController {
}
// sendQuery implements CachedNameserver.
func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, fqdn string, option dns_feature.IPOption) {
func (s *ClassicNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, fqdn string, option dns_feature.IPOption) {
errors.LogInfo(ctx, s.Name(), " querying DNS for: ", fqdn)
reqs := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
@@ -171,7 +171,14 @@ func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, fqdn
ctx: ctx,
}
s.addPendingRequest(udpReq)
b, _ := dns.PackMessage(req.msg)
b, err := dns.PackMessage(req.msg)
if err != nil {
errors.LogErrorInner(ctx, err, "failed to pack dns query")
if noResponseErrCh != nil {
noResponseErrCh <- err
}
return
}
copyDest := net.UDPDestination(s.address.Address, s.address.Port)
b.UDP = &copyDest
s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b)
+83 -33
View File
@@ -2,8 +2,9 @@ package log
import (
"context"
"fmt"
"net"
"regexp"
"strconv"
"strings"
"sync"
@@ -20,14 +21,23 @@ type Instance struct {
errorLogger log.Handler
active bool
dns bool
mask4 int
mask6 int
}
// New creates a new log.Instance based on the given config.
func New(ctx context.Context, config *Config) (*Instance, error) {
m4, m6, err := ParseMaskAddress(config.MaskAddress)
if err != nil {
return nil, err
}
g := &Instance{
config: config,
active: false,
dns: config.EnableDnsLog,
mask4: m4,
mask6: m6,
}
log.RegisterHandler(g)
@@ -104,7 +114,11 @@ func (g *Instance) Handle(msg log.Message) {
var Msg log.Message
if g.config.MaskAddress != "" {
Msg = &MaskedMsgWrapper{Message: msg, config: g.config}
Msg = &MaskedMsgWrapper{
Message: msg,
Mask4: g.mask4,
Mask6: g.mask6,
}
} else {
Msg = msg
}
@@ -149,51 +163,87 @@ func (g *Instance) Close() error {
return nil
}
func ParseMaskAddress(c string) (int, int, error) {
var m4, m6 int
switch c {
case "half":
m4, m6 = 16, 32
case "quarter":
m4, m6 = 8, 16
case "full":
m4, m6 = 0, 0
case "":
// do nothing
default:
if parts := strings.Split(c, "+"); len(parts) > 0 {
if len(parts) >= 1 && parts[0] != "" {
i, err := strconv.Atoi(strings.TrimPrefix(parts[0], "/"))
if err != nil {
return 32, 128, err
}
m4 = i
}
if len(parts) >= 2 && parts[1] != "" {
i, err := strconv.Atoi(strings.TrimPrefix(parts[1], "/"))
if err != nil {
return 32, 128, err
}
m6 = i
}
}
}
if m4%8 != 0 || m4 > 32 || m4 < 0 {
return 32, 128, errors.New("Log Mask: ipv4 mask must be divisible by 8 and between 0-32")
}
return m4, m6, nil
}
// MaskedMsgWrapper is to wrap the string() method to mask IP addresses in the log.
type MaskedMsgWrapper struct {
log.Message
config *Config
Mask4 int
Mask6 int
}
var (
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}`)
)
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
maskedMsg := ipv4Regex.ReplaceAllStringFunc(str, func(s string) string {
if m.Mask4 == 32 {
return s
}
if m.Mask4 == 0 {
return "[Masked IPv4]"
}
parts := strings.Split(s, ".")
for i := m.Mask4 / 8; i < 4; i++ {
parts[i] = "*"
}
return strings.Join(parts, ".")
})
// 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
maskedMsg = ipv6Regex.ReplaceAllStringFunc(maskedMsg, func(s string) string {
if m.Mask6 == 128 {
return s
}
return ip
if m.Mask6 == 0 {
return "Masked IPv6"
}
ip := net.ParseIP(s)
if ip == nil {
return s
}
return ip.Mask(net.CIDRMask(m.Mask6, 128)).String() + "/" + strconv.Itoa(m.Mask6)
})
return maskedMsg
+37
View File
@@ -2,6 +2,7 @@ package log_test
import (
"context"
"net"
"testing"
"github.com/golang/mock/gomock"
@@ -50,3 +51,39 @@ func TestCustomLogHandler(t *testing.T) {
common.Must(logger.Close())
}
func TestMaskAddress(t *testing.T) {
m4, m6, err := log.ParseMaskAddress("half")
if err != nil {
t.Fatal(err)
}
maskedAddr := log.MaskedMsgWrapper{
Mask4: m4,
Mask6: m6,
}
maskedAddr.Message = net.ParseIP("11.45.1.4")
if maskedAddr.String() != "11.45.*.*" {
t.Fatal("expected '11.45.*.*', but actually ", maskedAddr.String())
}
maskedAddr.Message = net.ParseIP("11:45:14:19:19:81:0::")
if maskedAddr.String() != "11:45::/32" {
t.Fatal("expected '11:45::/32', but actually", maskedAddr.String())
}
m4, m6, err = log.ParseMaskAddress("/16+/64")
if err != nil {
t.Fatal(err)
}
maskedAddr = log.MaskedMsgWrapper{
Mask4: m4,
Mask6: m6,
}
maskedAddr.Message = net.ParseIP("11.45.1.4")
if maskedAddr.String() != "11.45.*.*" {
t.Fatal("expected '11.45.*.*', but actually ", maskedAddr.String())
}
maskedAddr.Message = net.ParseIP("11:45:14:19:19:81:0::")
if maskedAddr.String() != "11:45:14:19::/64" {
t.Fatal("expected '11:45:14:19::/64', but actually", maskedAddr.String())
}
}
+15
View File
@@ -9,6 +9,7 @@ import (
"github.com/xtls/xray-core/common/mux"
"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/core"
"github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/stats"
@@ -52,6 +53,20 @@ type AlwaysOnInboundHandler struct {
}
func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) {
// Set tag and sniffing config in context before creating proxy
// This allows proxies like TUN to access these settings
ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: tag})
if receiverConfig.SniffingSettings != nil {
ctx = session.ContextWithContent(ctx, &session.Content{
SniffingRequest: session.SniffingRequest{
Enabled: receiverConfig.SniffingSettings.Enabled,
OverrideDestinationForProtocol: receiverConfig.SniffingSettings.DestinationOverride,
ExcludeForDomain: receiverConfig.SniffingSettings.DomainsExcluded,
MetadataOnly: receiverConfig.SniffingSettings.MetadataOnly,
RouteOnly: receiverConfig.SniffingSettings.RouteOnly,
},
})
}
rawProxy, err := common.CreateObject(ctx, proxyConfig)
if err != nil {
return nil, err
-4
View File
@@ -229,10 +229,6 @@ func (w *BridgeWorker) DispatchLink(ctx context.Context, dest net.Destination, l
}
return w.Dispatcher.DispatchLink(ctx, dest, link)
}
if d, ok := w.Dispatcher.(routing.WrapLinkDispatcher); ok {
link = d.WrapLink(ctx, link)
}
w.handleInternalConn(link)
return nil
+15
View File
@@ -60,6 +60,7 @@ func (s *routingServer) AddRule(ctx context.Context, request *AddRuleRequest) (*
return nil, errors.New("unsupported router implementation")
}
func (s *routingServer) RemoveRule(ctx context.Context, request *RemoveRuleRequest) (*RemoveRuleResponse, error) {
if bo, ok := s.router.(routing.Router); ok {
return &RemoveRuleResponse{}, bo.RemoveRule(request.RuleTag)
@@ -67,6 +68,20 @@ func (s *routingServer) RemoveRule(ctx context.Context, request *RemoveRuleReque
return nil, errors.New("unsupported router implementation")
}
func (s *routingServer) ListRule(ctx context.Context, request *ListRuleRequest) (*ListRuleResponse, error) {
if bo, ok := s.router.(routing.Router); ok {
response := &ListRuleResponse{}
for _, v := range bo.ListRule() {
response.Rules = append(response.Rules, &ListRuleItem{
Tag: v.GetOutboundTag(),
RuleTag: v.GetRuleTag(),
})
}
return response, nil
}
return nil, errors.New("unsupported router implementation")
}
// NewRoutingServer creates a statistics service with statistics manager.
func NewRoutingServer(router routing.Router, routingStats stats.Channel) RoutingServiceServer {
return &routingServer{
+316 -273
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.1
// protoc v5.28.2
// protoc-gen-go v1.36.11
// protoc v6.33.2
// source: app/router/command/command.proto
package command
@@ -13,6 +13,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -26,25 +27,24 @@ const (
// It conforms to the structure of xray.features.routing.Context and
// xray.features.routing.Route.
type RoutingContext struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
InboundTag string `protobuf:"bytes,1,opt,name=InboundTag,proto3" json:"InboundTag,omitempty"`
Network net.Network `protobuf:"varint,2,opt,name=Network,proto3,enum=xray.common.net.Network" json:"Network,omitempty"`
SourceIPs [][]byte `protobuf:"bytes,3,rep,name=SourceIPs,proto3" json:"SourceIPs,omitempty"`
TargetIPs [][]byte `protobuf:"bytes,4,rep,name=TargetIPs,proto3" json:"TargetIPs,omitempty"`
SourcePort uint32 `protobuf:"varint,5,opt,name=SourcePort,proto3" json:"SourcePort,omitempty"`
TargetPort uint32 `protobuf:"varint,6,opt,name=TargetPort,proto3" json:"TargetPort,omitempty"`
TargetDomain string `protobuf:"bytes,7,opt,name=TargetDomain,proto3" json:"TargetDomain,omitempty"`
Protocol string `protobuf:"bytes,8,opt,name=Protocol,proto3" json:"Protocol,omitempty"`
User string `protobuf:"bytes,9,opt,name=User,proto3" json:"User,omitempty"`
Attributes map[string]string `protobuf:"bytes,10,rep,name=Attributes,proto3" json:"Attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
OutboundGroupTags []string `protobuf:"bytes,11,rep,name=OutboundGroupTags,proto3" json:"OutboundGroupTags,omitempty"`
OutboundTag string `protobuf:"bytes,12,opt,name=OutboundTag,proto3" json:"OutboundTag,omitempty"`
LocalIPs [][]byte `protobuf:"bytes,13,rep,name=LocalIPs,proto3" json:"LocalIPs,omitempty"`
LocalPort uint32 `protobuf:"varint,14,opt,name=LocalPort,proto3" json:"LocalPort,omitempty"`
VlessRoute uint32 `protobuf:"varint,15,opt,name=VlessRoute,proto3" json:"VlessRoute,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
InboundTag string `protobuf:"bytes,1,opt,name=InboundTag,proto3" json:"InboundTag,omitempty"`
Network net.Network `protobuf:"varint,2,opt,name=Network,proto3,enum=xray.common.net.Network" json:"Network,omitempty"`
SourceIPs [][]byte `protobuf:"bytes,3,rep,name=SourceIPs,proto3" json:"SourceIPs,omitempty"`
TargetIPs [][]byte `protobuf:"bytes,4,rep,name=TargetIPs,proto3" json:"TargetIPs,omitempty"`
SourcePort uint32 `protobuf:"varint,5,opt,name=SourcePort,proto3" json:"SourcePort,omitempty"`
TargetPort uint32 `protobuf:"varint,6,opt,name=TargetPort,proto3" json:"TargetPort,omitempty"`
TargetDomain string `protobuf:"bytes,7,opt,name=TargetDomain,proto3" json:"TargetDomain,omitempty"`
Protocol string `protobuf:"bytes,8,opt,name=Protocol,proto3" json:"Protocol,omitempty"`
User string `protobuf:"bytes,9,opt,name=User,proto3" json:"User,omitempty"`
Attributes map[string]string `protobuf:"bytes,10,rep,name=Attributes,proto3" json:"Attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
OutboundGroupTags []string `protobuf:"bytes,11,rep,name=OutboundGroupTags,proto3" json:"OutboundGroupTags,omitempty"`
OutboundTag string `protobuf:"bytes,12,opt,name=OutboundTag,proto3" json:"OutboundTag,omitempty"`
LocalIPs [][]byte `protobuf:"bytes,13,rep,name=LocalIPs,proto3" json:"LocalIPs,omitempty"`
LocalPort uint32 `protobuf:"varint,14,opt,name=LocalPort,proto3" json:"LocalPort,omitempty"`
VlessRoute uint32 `protobuf:"varint,15,opt,name=VlessRoute,proto3" json:"VlessRoute,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RoutingContext) Reset() {
@@ -201,11 +201,10 @@ func (x *RoutingContext) GetVlessRoute() uint32 {
//
// * If FieldSelectors is left empty, all fields will be returned.
type SubscribeRoutingStatsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
FieldSelectors []string `protobuf:"bytes,1,rep,name=FieldSelectors,proto3" json:"FieldSelectors,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
FieldSelectors []string `protobuf:"bytes,1,rep,name=FieldSelectors,proto3" json:"FieldSelectors,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SubscribeRoutingStatsRequest) Reset() {
@@ -253,13 +252,12 @@ func (x *SubscribeRoutingStatsRequest) GetFieldSelectors() []string {
// * PublishResult broadcasts the routing result to routing statistics channel
// if set true.
type TestRouteRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RoutingContext *RoutingContext `protobuf:"bytes,1,opt,name=RoutingContext,proto3" json:"RoutingContext,omitempty"`
FieldSelectors []string `protobuf:"bytes,2,rep,name=FieldSelectors,proto3" json:"FieldSelectors,omitempty"`
PublishResult bool `protobuf:"varint,3,opt,name=PublishResult,proto3" json:"PublishResult,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
RoutingContext *RoutingContext `protobuf:"bytes,1,opt,name=RoutingContext,proto3" json:"RoutingContext,omitempty"`
FieldSelectors []string `protobuf:"bytes,2,rep,name=FieldSelectors,proto3" json:"FieldSelectors,omitempty"`
PublishResult bool `protobuf:"varint,3,opt,name=PublishResult,proto3" json:"PublishResult,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *TestRouteRequest) Reset() {
@@ -314,11 +312,10 @@ func (x *TestRouteRequest) GetPublishResult() bool {
}
type PrincipleTargetInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Tag []string `protobuf:"bytes,1,rep,name=tag,proto3" json:"tag,omitempty"`
unknownFields protoimpl.UnknownFields
Tag []string `protobuf:"bytes,1,rep,name=tag,proto3" json:"tag,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *PrincipleTargetInfo) Reset() {
@@ -359,11 +356,10 @@ func (x *PrincipleTargetInfo) GetTag() []string {
}
type OverrideInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"`
unknownFields protoimpl.UnknownFields
Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *OverrideInfo) Reset() {
@@ -404,12 +400,11 @@ func (x *OverrideInfo) GetTarget() string {
}
type BalancerMsg struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Override *OverrideInfo `protobuf:"bytes,5,opt,name=override,proto3" json:"override,omitempty"`
PrincipleTarget *PrincipleTargetInfo `protobuf:"bytes,6,opt,name=principle_target,json=principleTarget,proto3" json:"principle_target,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
Override *OverrideInfo `protobuf:"bytes,5,opt,name=override,proto3" json:"override,omitempty"`
PrincipleTarget *PrincipleTargetInfo `protobuf:"bytes,6,opt,name=principle_target,json=principleTarget,proto3" json:"principle_target,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *BalancerMsg) Reset() {
@@ -457,11 +452,10 @@ func (x *BalancerMsg) GetPrincipleTarget() *PrincipleTargetInfo {
}
type GetBalancerInfoRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
unknownFields protoimpl.UnknownFields
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *GetBalancerInfoRequest) Reset() {
@@ -502,11 +496,10 @@ func (x *GetBalancerInfoRequest) GetTag() string {
}
type GetBalancerInfoResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Balancer *BalancerMsg `protobuf:"bytes,1,opt,name=balancer,proto3" json:"balancer,omitempty"`
unknownFields protoimpl.UnknownFields
Balancer *BalancerMsg `protobuf:"bytes,1,opt,name=balancer,proto3" json:"balancer,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *GetBalancerInfoResponse) Reset() {
@@ -547,12 +540,11 @@ func (x *GetBalancerInfoResponse) GetBalancer() *BalancerMsg {
}
type OverrideBalancerTargetRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
BalancerTag string `protobuf:"bytes,1,opt,name=balancerTag,proto3" json:"balancerTag,omitempty"`
Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"`
unknownFields protoimpl.UnknownFields
BalancerTag string `protobuf:"bytes,1,opt,name=balancerTag,proto3" json:"balancerTag,omitempty"`
Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *OverrideBalancerTargetRequest) Reset() {
@@ -600,9 +592,9 @@ func (x *OverrideBalancerTargetRequest) GetTarget() string {
}
type OverrideBalancerTargetResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *OverrideBalancerTargetResponse) Reset() {
@@ -636,12 +628,11 @@ func (*OverrideBalancerTargetResponse) Descriptor() ([]byte, []int) {
}
type AddRuleRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Config *serial.TypedMessage `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"`
ShouldAppend bool `protobuf:"varint,2,opt,name=shouldAppend,proto3" json:"shouldAppend,omitempty"`
unknownFields protoimpl.UnknownFields
Config *serial.TypedMessage `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"`
ShouldAppend bool `protobuf:"varint,2,opt,name=shouldAppend,proto3" json:"shouldAppend,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *AddRuleRequest) Reset() {
@@ -689,9 +680,9 @@ func (x *AddRuleRequest) GetShouldAppend() bool {
}
type AddRuleResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AddRuleResponse) Reset() {
@@ -725,11 +716,10 @@ func (*AddRuleResponse) Descriptor() ([]byte, []int) {
}
type RemoveRuleRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
RuleTag string `protobuf:"bytes,1,opt,name=ruleTag,proto3" json:"ruleTag,omitempty"`
unknownFields protoimpl.UnknownFields
RuleTag string `protobuf:"bytes,1,opt,name=ruleTag,proto3" json:"ruleTag,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *RemoveRuleRequest) Reset() {
@@ -770,9 +760,9 @@ func (x *RemoveRuleRequest) GetRuleTag() string {
}
type RemoveRuleResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RemoveRuleResponse) Reset() {
@@ -805,15 +795,147 @@ func (*RemoveRuleResponse) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{13}
}
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
type ListRuleRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListRuleRequest) Reset() {
*x = ListRuleRequest{}
mi := &file_app_router_command_command_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListRuleRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListRuleRequest) ProtoMessage() {}
func (x *ListRuleRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[14]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListRuleRequest.ProtoReflect.Descriptor instead.
func (*ListRuleRequest) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{14}
}
type ListRuleItem struct {
state protoimpl.MessageState `protogen:"open.v1"`
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
RuleTag string `protobuf:"bytes,2,opt,name=ruleTag,proto3" json:"ruleTag,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListRuleItem) Reset() {
*x = ListRuleItem{}
mi := &file_app_router_command_command_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListRuleItem) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListRuleItem) ProtoMessage() {}
func (x *ListRuleItem) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[15]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListRuleItem.ProtoReflect.Descriptor instead.
func (*ListRuleItem) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{15}
}
func (x *ListRuleItem) GetTag() string {
if x != nil {
return x.Tag
}
return ""
}
func (x *ListRuleItem) GetRuleTag() string {
if x != nil {
return x.RuleTag
}
return ""
}
type ListRuleResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Rules []*ListRuleItem `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListRuleResponse) Reset() {
*x = ListRuleResponse{}
mi := &file_app_router_command_command_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListRuleResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListRuleResponse) ProtoMessage() {}
func (x *ListRuleResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[16]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListRuleResponse.ProtoReflect.Descriptor instead.
func (*ListRuleResponse) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{16}
}
func (x *ListRuleResponse) GetRules() []*ListRuleItem {
if x != nil {
return x.Rules
}
return nil
}
type Config struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Config) Reset() {
*x = Config{}
mi := &file_app_router_command_command_proto_msgTypes[14]
mi := &file_app_router_command_command_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -825,7 +947,7 @@ func (x *Config) String() string {
func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_router_command_command_proto_msgTypes[14]
mi := &file_app_router_command_command_proto_msgTypes[17]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -838,187 +960,103 @@ func (x *Config) ProtoReflect() protoreflect.Message {
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_app_router_command_command_proto_rawDescGZIP(), []int{14}
return file_app_router_command_command_proto_rawDescGZIP(), []int{17}
}
var File_app_router_command_command_proto protoreflect.FileDescriptor
var file_app_router_command_command_proto_rawDesc = []byte{
0x0a, 0x20, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d,
0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x17, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x18, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65,
0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf6, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x49,
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0a, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x32, 0x0a, 0x07, 0x4e,
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e,
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12,
0x1c, 0x0a, 0x09, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x50, 0x73, 0x18, 0x03, 0x20, 0x03,
0x28, 0x0c, 0x52, 0x09, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x50, 0x73, 0x12, 0x1c, 0x0a,
0x09, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x50, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c,
0x52, 0x09, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x50, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x53,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52,
0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52,
0x0a, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0c, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12,
0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x55,
0x73, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12,
0x57, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f,
0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x41, 0x74, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x41, 0x74,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x4f, 0x75, 0x74, 0x62,
0x6f, 0x75, 0x6e, 0x64, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x18, 0x0b, 0x20,
0x03, 0x28, 0x09, 0x52, 0x11, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x47, 0x72, 0x6f,
0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4f, 0x75, 0x74,
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61,
0x6c, 0x49, 0x50, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x4c, 0x6f, 0x63, 0x61,
0x6c, 0x49, 0x50, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72,
0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f,
0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75, 0x74, 0x65,
0x18, 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75,
0x74, 0x65, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x01, 0x22, 0x46, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f,
0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64,
0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x54, 0x65,
0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f,
0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52,
0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12,
0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65,
0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69,
0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d,
0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x27, 0x0a,
0x13, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28,
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x26, 0x0a, 0x0c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xa9,
0x01, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x41,
0x0a, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72,
0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
0x65, 0x12, 0x57, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x74,
0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54,
0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x70, 0x72, 0x69, 0x6e, 0x63,
0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65,
0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x5b, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c,
0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x42, 0x61,
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e,
0x63, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x1d, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42,
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72,
0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e,
0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x20,
0x0a, 0x1e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x6e, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0c,
0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x08, 0x52, 0x0c, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64,
0x22, 0x11, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x2d, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65,
0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54,
0x61, 0x67, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x32, 0xbf, 0x05, 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7b, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x35,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00,
0x30, 0x01, 0x12, 0x61, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12,
0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f,
0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74,
0x65, 0x78, 0x74, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61,
0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x8b, 0x01,
0x0a, 0x16, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x36, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e,
0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72,
0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x07, 0x41,
0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, 0x0a, 0x0a, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x00, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2c, 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, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52,
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
const file_app_router_command_command_proto_rawDesc = "" +
"\n" +
" app/router/command/command.proto\x12\x17xray.app.router.command\x1a\x18common/net/network.proto\x1a!common/serial/typed_message.proto\"\xf6\x04\n" +
"\x0eRoutingContext\x12\x1e\n" +
"\n" +
"InboundTag\x18\x01 \x01(\tR\n" +
"InboundTag\x122\n" +
"\aNetwork\x18\x02 \x01(\x0e2\x18.xray.common.net.NetworkR\aNetwork\x12\x1c\n" +
"\tSourceIPs\x18\x03 \x03(\fR\tSourceIPs\x12\x1c\n" +
"\tTargetIPs\x18\x04 \x03(\fR\tTargetIPs\x12\x1e\n" +
"\n" +
"SourcePort\x18\x05 \x01(\rR\n" +
"SourcePort\x12\x1e\n" +
"\n" +
"TargetPort\x18\x06 \x01(\rR\n" +
"TargetPort\x12\"\n" +
"\fTargetDomain\x18\a \x01(\tR\fTargetDomain\x12\x1a\n" +
"\bProtocol\x18\b \x01(\tR\bProtocol\x12\x12\n" +
"\x04User\x18\t \x01(\tR\x04User\x12W\n" +
"\n" +
"Attributes\x18\n" +
" \x03(\v27.xray.app.router.command.RoutingContext.AttributesEntryR\n" +
"Attributes\x12,\n" +
"\x11OutboundGroupTags\x18\v \x03(\tR\x11OutboundGroupTags\x12 \n" +
"\vOutboundTag\x18\f \x01(\tR\vOutboundTag\x12\x1a\n" +
"\bLocalIPs\x18\r \x03(\fR\bLocalIPs\x12\x1c\n" +
"\tLocalPort\x18\x0e \x01(\rR\tLocalPort\x12\x1e\n" +
"\n" +
"VlessRoute\x18\x0f \x01(\rR\n" +
"VlessRoute\x1a=\n" +
"\x0fAttributesEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"F\n" +
"\x1cSubscribeRoutingStatsRequest\x12&\n" +
"\x0eFieldSelectors\x18\x01 \x03(\tR\x0eFieldSelectors\"\xb1\x01\n" +
"\x10TestRouteRequest\x12O\n" +
"\x0eRoutingContext\x18\x01 \x01(\v2'.xray.app.router.command.RoutingContextR\x0eRoutingContext\x12&\n" +
"\x0eFieldSelectors\x18\x02 \x03(\tR\x0eFieldSelectors\x12$\n" +
"\rPublishResult\x18\x03 \x01(\bR\rPublishResult\"'\n" +
"\x13PrincipleTargetInfo\x12\x10\n" +
"\x03tag\x18\x01 \x03(\tR\x03tag\"&\n" +
"\fOverrideInfo\x12\x16\n" +
"\x06target\x18\x02 \x01(\tR\x06target\"\xa9\x01\n" +
"\vBalancerMsg\x12A\n" +
"\boverride\x18\x05 \x01(\v2%.xray.app.router.command.OverrideInfoR\boverride\x12W\n" +
"\x10principle_target\x18\x06 \x01(\v2,.xray.app.router.command.PrincipleTargetInfoR\x0fprincipleTarget\"*\n" +
"\x16GetBalancerInfoRequest\x12\x10\n" +
"\x03tag\x18\x01 \x01(\tR\x03tag\"[\n" +
"\x17GetBalancerInfoResponse\x12@\n" +
"\bbalancer\x18\x01 \x01(\v2$.xray.app.router.command.BalancerMsgR\bbalancer\"Y\n" +
"\x1dOverrideBalancerTargetRequest\x12 \n" +
"\vbalancerTag\x18\x01 \x01(\tR\vbalancerTag\x12\x16\n" +
"\x06target\x18\x02 \x01(\tR\x06target\" \n" +
"\x1eOverrideBalancerTargetResponse\"n\n" +
"\x0eAddRuleRequest\x128\n" +
"\x06config\x18\x01 \x01(\v2 .xray.common.serial.TypedMessageR\x06config\x12\"\n" +
"\fshouldAppend\x18\x02 \x01(\bR\fshouldAppend\"\x11\n" +
"\x0fAddRuleResponse\"-\n" +
"\x11RemoveRuleRequest\x12\x18\n" +
"\aruleTag\x18\x01 \x01(\tR\aruleTag\"\x14\n" +
"\x12RemoveRuleResponse\"\x11\n" +
"\x0fListRuleRequest\":\n" +
"\fListRuleItem\x12\x10\n" +
"\x03tag\x18\x01 \x01(\tR\x03tag\x12\x18\n" +
"\aruleTag\x18\x02 \x01(\tR\aruleTag\"O\n" +
"\x10ListRuleResponse\x12;\n" +
"\x05rules\x18\x01 \x03(\v2%.xray.app.router.command.ListRuleItemR\x05rules\"\b\n" +
"\x06Config2\xa2\x06\n" +
"\x0eRoutingService\x12{\n" +
"\x15SubscribeRoutingStats\x125.xray.app.router.command.SubscribeRoutingStatsRequest\x1a'.xray.app.router.command.RoutingContext\"\x000\x01\x12a\n" +
"\tTestRoute\x12).xray.app.router.command.TestRouteRequest\x1a'.xray.app.router.command.RoutingContext\"\x00\x12v\n" +
"\x0fGetBalancerInfo\x12/.xray.app.router.command.GetBalancerInfoRequest\x1a0.xray.app.router.command.GetBalancerInfoResponse\"\x00\x12\x8b\x01\n" +
"\x16OverrideBalancerTarget\x126.xray.app.router.command.OverrideBalancerTargetRequest\x1a7.xray.app.router.command.OverrideBalancerTargetResponse\"\x00\x12^\n" +
"\aAddRule\x12'.xray.app.router.command.AddRuleRequest\x1a(.xray.app.router.command.AddRuleResponse\"\x00\x12g\n" +
"\n" +
"RemoveRule\x12*.xray.app.router.command.RemoveRuleRequest\x1a+.xray.app.router.command.RemoveRuleResponse\"\x00\x12a\n" +
"\bListRule\x12(.xray.app.router.command.ListRuleRequest\x1a).xray.app.router.command.ListRuleResponse\"\x00Bg\n" +
"\x1bcom.xray.app.router.commandP\x01Z,github.com/xtls/xray-core/app/router/command\xaa\x02\x17Xray.App.Router.Commandb\x06proto3"
var (
file_app_router_command_command_proto_rawDescOnce sync.Once
file_app_router_command_command_proto_rawDescData = file_app_router_command_command_proto_rawDesc
file_app_router_command_command_proto_rawDescData []byte
)
func file_app_router_command_command_proto_rawDescGZIP() []byte {
file_app_router_command_command_proto_rawDescOnce.Do(func() {
file_app_router_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_router_command_command_proto_rawDescData)
file_app_router_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_router_command_command_proto_rawDesc), len(file_app_router_command_command_proto_rawDesc)))
})
return file_app_router_command_command_proto_rawDescData
}
var file_app_router_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
var file_app_router_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
var file_app_router_command_command_proto_goTypes = []any{
(*RoutingContext)(nil), // 0: xray.app.router.command.RoutingContext
(*SubscribeRoutingStatsRequest)(nil), // 1: xray.app.router.command.SubscribeRoutingStatsRequest
@@ -1034,36 +1072,42 @@ var file_app_router_command_command_proto_goTypes = []any{
(*AddRuleResponse)(nil), // 11: xray.app.router.command.AddRuleResponse
(*RemoveRuleRequest)(nil), // 12: xray.app.router.command.RemoveRuleRequest
(*RemoveRuleResponse)(nil), // 13: xray.app.router.command.RemoveRuleResponse
(*Config)(nil), // 14: xray.app.router.command.Config
nil, // 15: xray.app.router.command.RoutingContext.AttributesEntry
(net.Network)(0), // 16: xray.common.net.Network
(*serial.TypedMessage)(nil), // 17: xray.common.serial.TypedMessage
(*ListRuleRequest)(nil), // 14: xray.app.router.command.ListRuleRequest
(*ListRuleItem)(nil), // 15: xray.app.router.command.ListRuleItem
(*ListRuleResponse)(nil), // 16: xray.app.router.command.ListRuleResponse
(*Config)(nil), // 17: xray.app.router.command.Config
nil, // 18: xray.app.router.command.RoutingContext.AttributesEntry
(net.Network)(0), // 19: xray.common.net.Network
(*serial.TypedMessage)(nil), // 20: xray.common.serial.TypedMessage
}
var file_app_router_command_command_proto_depIdxs = []int32{
16, // 0: xray.app.router.command.RoutingContext.Network:type_name -> xray.common.net.Network
15, // 1: xray.app.router.command.RoutingContext.Attributes:type_name -> xray.app.router.command.RoutingContext.AttributesEntry
19, // 0: xray.app.router.command.RoutingContext.Network:type_name -> xray.common.net.Network
18, // 1: xray.app.router.command.RoutingContext.Attributes:type_name -> xray.app.router.command.RoutingContext.AttributesEntry
0, // 2: xray.app.router.command.TestRouteRequest.RoutingContext:type_name -> xray.app.router.command.RoutingContext
4, // 3: xray.app.router.command.BalancerMsg.override:type_name -> xray.app.router.command.OverrideInfo
3, // 4: xray.app.router.command.BalancerMsg.principle_target:type_name -> xray.app.router.command.PrincipleTargetInfo
5, // 5: xray.app.router.command.GetBalancerInfoResponse.balancer:type_name -> xray.app.router.command.BalancerMsg
17, // 6: xray.app.router.command.AddRuleRequest.config:type_name -> xray.common.serial.TypedMessage
1, // 7: xray.app.router.command.RoutingService.SubscribeRoutingStats:input_type -> xray.app.router.command.SubscribeRoutingStatsRequest
2, // 8: xray.app.router.command.RoutingService.TestRoute:input_type -> xray.app.router.command.TestRouteRequest
6, // 9: xray.app.router.command.RoutingService.GetBalancerInfo:input_type -> xray.app.router.command.GetBalancerInfoRequest
8, // 10: xray.app.router.command.RoutingService.OverrideBalancerTarget:input_type -> xray.app.router.command.OverrideBalancerTargetRequest
10, // 11: xray.app.router.command.RoutingService.AddRule:input_type -> xray.app.router.command.AddRuleRequest
12, // 12: xray.app.router.command.RoutingService.RemoveRule:input_type -> xray.app.router.command.RemoveRuleRequest
0, // 13: xray.app.router.command.RoutingService.SubscribeRoutingStats:output_type -> xray.app.router.command.RoutingContext
0, // 14: xray.app.router.command.RoutingService.TestRoute:output_type -> xray.app.router.command.RoutingContext
7, // 15: xray.app.router.command.RoutingService.GetBalancerInfo:output_type -> xray.app.router.command.GetBalancerInfoResponse
9, // 16: xray.app.router.command.RoutingService.OverrideBalancerTarget:output_type -> xray.app.router.command.OverrideBalancerTargetResponse
11, // 17: xray.app.router.command.RoutingService.AddRule:output_type -> xray.app.router.command.AddRuleResponse
13, // 18: xray.app.router.command.RoutingService.RemoveRule:output_type -> xray.app.router.command.RemoveRuleResponse
13, // [13:19] is the sub-list for method output_type
7, // [7:13] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
20, // 6: xray.app.router.command.AddRuleRequest.config:type_name -> xray.common.serial.TypedMessage
15, // 7: xray.app.router.command.ListRuleResponse.rules:type_name -> xray.app.router.command.ListRuleItem
1, // 8: xray.app.router.command.RoutingService.SubscribeRoutingStats:input_type -> xray.app.router.command.SubscribeRoutingStatsRequest
2, // 9: xray.app.router.command.RoutingService.TestRoute:input_type -> xray.app.router.command.TestRouteRequest
6, // 10: xray.app.router.command.RoutingService.GetBalancerInfo:input_type -> xray.app.router.command.GetBalancerInfoRequest
8, // 11: xray.app.router.command.RoutingService.OverrideBalancerTarget:input_type -> xray.app.router.command.OverrideBalancerTargetRequest
10, // 12: xray.app.router.command.RoutingService.AddRule:input_type -> xray.app.router.command.AddRuleRequest
12, // 13: xray.app.router.command.RoutingService.RemoveRule:input_type -> xray.app.router.command.RemoveRuleRequest
14, // 14: xray.app.router.command.RoutingService.ListRule:input_type -> xray.app.router.command.ListRuleRequest
0, // 15: xray.app.router.command.RoutingService.SubscribeRoutingStats:output_type -> xray.app.router.command.RoutingContext
0, // 16: xray.app.router.command.RoutingService.TestRoute:output_type -> xray.app.router.command.RoutingContext
7, // 17: xray.app.router.command.RoutingService.GetBalancerInfo:output_type -> xray.app.router.command.GetBalancerInfoResponse
9, // 18: xray.app.router.command.RoutingService.OverrideBalancerTarget:output_type -> xray.app.router.command.OverrideBalancerTargetResponse
11, // 19: xray.app.router.command.RoutingService.AddRule:output_type -> xray.app.router.command.AddRuleResponse
13, // 20: xray.app.router.command.RoutingService.RemoveRule:output_type -> xray.app.router.command.RemoveRuleResponse
16, // 21: xray.app.router.command.RoutingService.ListRule:output_type -> xray.app.router.command.ListRuleResponse
15, // [15:22] is the sub-list for method output_type
8, // [8:15] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_app_router_command_command_proto_init() }
@@ -1075,9 +1119,9 @@ func file_app_router_command_command_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_router_command_command_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_router_command_command_proto_rawDesc), len(file_app_router_command_command_proto_rawDesc)),
NumEnums: 0,
NumMessages: 16,
NumMessages: 19,
NumExtensions: 0,
NumServices: 1,
},
@@ -1086,7 +1130,6 @@ func file_app_router_command_command_proto_init() {
MessageInfos: file_app_router_command_command_proto_msgTypes,
}.Build()
File_app_router_command_command_proto = out.File
file_app_router_command_command_proto_rawDesc = nil
file_app_router_command_command_proto_goTypes = nil
file_app_router_command_command_proto_depIdxs = nil
}
+13
View File
@@ -104,6 +104,17 @@ message RemoveRuleRequest {
message RemoveRuleResponse {}
message ListRuleRequest {}
message ListRuleItem {
string tag = 1;
string ruleTag = 2;
}
message ListRuleResponse{
repeated ListRuleItem rules = 1;
}
service RoutingService {
rpc SubscribeRoutingStats(SubscribeRoutingStatsRequest)
returns (stream RoutingContext) {}
@@ -114,6 +125,8 @@ service RoutingService {
rpc AddRule(AddRuleRequest) returns (AddRuleResponse) {}
rpc RemoveRule(RemoveRuleRequest) returns (RemoveRuleResponse) {}
rpc ListRule(ListRuleRequest) returns (ListRuleResponse) {}
}
message Config {}
+47 -9
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.28.2
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.2
// source: app/router/command/command.proto
package command
@@ -25,6 +25,7 @@ const (
RoutingService_OverrideBalancerTarget_FullMethodName = "/xray.app.router.command.RoutingService/OverrideBalancerTarget"
RoutingService_AddRule_FullMethodName = "/xray.app.router.command.RoutingService/AddRule"
RoutingService_RemoveRule_FullMethodName = "/xray.app.router.command.RoutingService/RemoveRule"
RoutingService_ListRule_FullMethodName = "/xray.app.router.command.RoutingService/ListRule"
)
// RoutingServiceClient is the client API for RoutingService service.
@@ -37,6 +38,7 @@ type RoutingServiceClient interface {
OverrideBalancerTarget(ctx context.Context, in *OverrideBalancerTargetRequest, opts ...grpc.CallOption) (*OverrideBalancerTargetResponse, error)
AddRule(ctx context.Context, in *AddRuleRequest, opts ...grpc.CallOption) (*AddRuleResponse, error)
RemoveRule(ctx context.Context, in *RemoveRuleRequest, opts ...grpc.CallOption) (*RemoveRuleResponse, error)
ListRule(ctx context.Context, in *ListRuleRequest, opts ...grpc.CallOption) (*ListRuleResponse, error)
}
type routingServiceClient struct {
@@ -116,6 +118,16 @@ func (c *routingServiceClient) RemoveRule(ctx context.Context, in *RemoveRuleReq
return out, nil
}
func (c *routingServiceClient) ListRule(ctx context.Context, in *ListRuleRequest, opts ...grpc.CallOption) (*ListRuleResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListRuleResponse)
err := c.cc.Invoke(ctx, RoutingService_ListRule_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// RoutingServiceServer is the server API for RoutingService service.
// All implementations must embed UnimplementedRoutingServiceServer
// for forward compatibility.
@@ -126,6 +138,7 @@ type RoutingServiceServer interface {
OverrideBalancerTarget(context.Context, *OverrideBalancerTargetRequest) (*OverrideBalancerTargetResponse, error)
AddRule(context.Context, *AddRuleRequest) (*AddRuleResponse, error)
RemoveRule(context.Context, *RemoveRuleRequest) (*RemoveRuleResponse, error)
ListRule(context.Context, *ListRuleRequest) (*ListRuleResponse, error)
mustEmbedUnimplementedRoutingServiceServer()
}
@@ -137,22 +150,25 @@ type RoutingServiceServer interface {
type UnimplementedRoutingServiceServer struct{}
func (UnimplementedRoutingServiceServer) SubscribeRoutingStats(*SubscribeRoutingStatsRequest, grpc.ServerStreamingServer[RoutingContext]) error {
return status.Errorf(codes.Unimplemented, "method SubscribeRoutingStats not implemented")
return status.Error(codes.Unimplemented, "method SubscribeRoutingStats not implemented")
}
func (UnimplementedRoutingServiceServer) TestRoute(context.Context, *TestRouteRequest) (*RoutingContext, error) {
return nil, status.Errorf(codes.Unimplemented, "method TestRoute not implemented")
return nil, status.Error(codes.Unimplemented, "method TestRoute not implemented")
}
func (UnimplementedRoutingServiceServer) GetBalancerInfo(context.Context, *GetBalancerInfoRequest) (*GetBalancerInfoResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetBalancerInfo not implemented")
return nil, status.Error(codes.Unimplemented, "method GetBalancerInfo not implemented")
}
func (UnimplementedRoutingServiceServer) OverrideBalancerTarget(context.Context, *OverrideBalancerTargetRequest) (*OverrideBalancerTargetResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method OverrideBalancerTarget not implemented")
return nil, status.Error(codes.Unimplemented, "method OverrideBalancerTarget not implemented")
}
func (UnimplementedRoutingServiceServer) AddRule(context.Context, *AddRuleRequest) (*AddRuleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddRule not implemented")
return nil, status.Error(codes.Unimplemented, "method AddRule not implemented")
}
func (UnimplementedRoutingServiceServer) RemoveRule(context.Context, *RemoveRuleRequest) (*RemoveRuleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RemoveRule not implemented")
return nil, status.Error(codes.Unimplemented, "method RemoveRule not implemented")
}
func (UnimplementedRoutingServiceServer) ListRule(context.Context, *ListRuleRequest) (*ListRuleResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListRule not implemented")
}
func (UnimplementedRoutingServiceServer) mustEmbedUnimplementedRoutingServiceServer() {}
func (UnimplementedRoutingServiceServer) testEmbeddedByValue() {}
@@ -165,7 +181,7 @@ type UnsafeRoutingServiceServer interface {
}
func RegisterRoutingServiceServer(s grpc.ServiceRegistrar, srv RoutingServiceServer) {
// If the following call pancis, it indicates UnimplementedRoutingServiceServer was
// If the following call panics, 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.
@@ -276,6 +292,24 @@ func _RoutingService_RemoveRule_Handler(srv interface{}, ctx context.Context, de
return interceptor(ctx, in, info, handler)
}
func _RoutingService_ListRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListRuleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RoutingServiceServer).ListRule(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: RoutingService_ListRule_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RoutingServiceServer).ListRule(ctx, req.(*ListRuleRequest))
}
return interceptor(ctx, in, info, handler)
}
// RoutingService_ServiceDesc is the grpc.ServiceDesc for RoutingService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -303,6 +337,10 @@ var RoutingService_ServiceDesc = grpc.ServiceDesc{
MethodName: "RemoveRule",
Handler: _RoutingService_RemoveRule_Handler,
},
{
MethodName: "ListRule",
Handler: _RoutingService_ListRule_Handler,
},
},
Streams: []grpc.StreamDesc{
{
+103 -3
View File
@@ -1,7 +1,11 @@
package router
import (
"context"
"os"
"path/filepath"
"regexp"
"slices"
"strings"
"github.com/xtls/xray-core/common/errors"
@@ -53,14 +57,17 @@ type DomainMatcher struct {
func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
g := strmatcher.NewMphMatcherGroup()
for _, d := range domains {
for i, d := range domains {
domains[i] = nil
matcherType, f := matcherTypeMap[d.Type]
if !f {
return nil, errors.New("unsupported domain type", d.Type)
errors.LogError(context.Background(), "ignore unsupported domain type ", d.Type, " of rule ", d.Value)
continue
}
_, err := g.AddPattern(d.Value, matcherType)
if err != nil {
return nil, err
errors.LogErrorInner(context.Background(), err, "ignore domain rule ", d.Type, " ", d.Value)
continue
}
}
g.Build()
@@ -302,3 +309,96 @@ func (m *AttributeMatcher) Apply(ctx routing.Context) bool {
}
return m.Match(attributes)
}
type ProcessNameMatcher struct {
ProcessNames []string
AbsPaths []string
Folders []string
MatchXraySelf bool
}
func NewProcessNameMatcher(names []string) *ProcessNameMatcher {
processNames := []string{}
folders := []string{}
absPaths := []string{}
matchXraySelf := false
for _, name := range names {
if name == "self/" {
matchXraySelf = true
continue
}
// replace xray/ with self executable path
if name == "xray/" {
xrayPath, err := os.Executable()
if err != nil {
errors.LogError(context.Background(), "Failed to get xray executable path: ", err)
continue
}
name = xrayPath
}
name := filepath.ToSlash(name)
// /usr/bin/
if strings.HasSuffix(name, "/") {
folders = append(folders, name)
continue
}
// /usr/bin/curl
if strings.Contains(name, "/") {
absPaths = append(absPaths, name)
continue
}
// curl.exe or curl
processNames = append(processNames, strings.TrimSuffix(name, ".exe"))
}
return &ProcessNameMatcher{
ProcessNames: processNames,
AbsPaths: absPaths,
Folders: folders,
MatchXraySelf: matchXraySelf,
}
}
func (m *ProcessNameMatcher) Apply(ctx routing.Context) bool {
if len(ctx.GetSourceIPs()) == 0 {
return false
}
srcPort := ctx.GetSourcePort().String()
srcIP := ctx.GetSourceIPs()[0].String()
var network string
switch ctx.GetNetwork() {
case net.Network_TCP:
network = "tcp"
case net.Network_UDP:
network = "udp"
default:
return false
}
src, err := net.ParseDestination(strings.Join([]string{network, srcIP, srcPort}, ":"))
if err != nil {
return false
}
pid, name, absPath, err := net.FindProcess(src)
if err != nil {
if err != net.ErrNotLocal {
errors.LogError(context.Background(), "Unables to find local process name: ", err)
}
return false
}
if m.MatchXraySelf {
if pid == os.Getpid() {
return true
}
}
if slices.Contains(m.ProcessNames, name) {
return true
}
if slices.Contains(m.AbsPaths, absPath) {
return true
}
for _, f := range m.Folders {
if strings.HasPrefix(absPath, f) {
return true
}
}
return false
}
+2 -1
View File
@@ -822,7 +822,8 @@ func (f *GeoIPSetFactory) Create(cidrGroups ...[]*CIDR) (*GeoIPSet, error) {
var ipv4Builder, ipv6Builder netipx.IPSetBuilder
for _, cidrGroup := range cidrGroups {
for _, cidrEntry := range cidrGroup {
for i, cidrEntry := range cidrGroup {
cidrGroup[i] = nil
ipBytes := cidrEntry.GetIp()
prefixLen := int(cidrEntry.GetPrefix())
+13
View File
@@ -3,6 +3,7 @@ package router
import (
"context"
"regexp"
"runtime"
"strings"
"github.com/xtls/xray-core/common/errors"
@@ -78,6 +79,8 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
return nil, err
}
conds.Add(cond)
rr.Geoip = nil
runtime.GC()
}
if len(rr.SourceGeoip) > 0 {
@@ -86,6 +89,8 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
return nil, err
}
conds.Add(cond)
rr.SourceGeoip = nil
runtime.GC()
}
if len(rr.LocalGeoip) > 0 {
@@ -95,6 +100,8 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
}
conds.Add(cond)
errors.LogWarning(context.Background(), "Due to some limitations, in UDP connections, localIP is always equal to listen interface IP, so \"localIP\" rule condition does not work properly on UDP inbound connections that listen on all interfaces")
rr.LocalGeoip = nil
runtime.GC()
}
if len(rr.Domain) > 0 {
@@ -104,6 +111,12 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
}
errors.LogDebug(context.Background(), "MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)")
conds.Add(matcher)
rr.Domain = nil
runtime.GC()
}
if len(rr.Process) > 0 {
conds.Add(NewProcessNameMatcher(rr.Process))
}
if conds.Len() == 0 {
+71 -61
View File
@@ -490,6 +490,7 @@ type RoutingRule struct {
LocalGeoip []*GeoIP `protobuf:"bytes,17,rep,name=local_geoip,json=localGeoip,proto3" json:"local_geoip,omitempty"`
LocalPortList *net.PortList `protobuf:"bytes,18,opt,name=local_port_list,json=localPortList,proto3" json:"local_port_list,omitempty"`
VlessRouteList *net.PortList `protobuf:"bytes,20,opt,name=vless_route_list,json=vlessRouteList,proto3" json:"vless_route_list,omitempty"`
Process []string `protobuf:"bytes,21,rep,name=process,proto3" json:"process,omitempty"`
}
func (x *RoutingRule) Reset() {
@@ -641,6 +642,13 @@ func (x *RoutingRule) GetVlessRouteList() *net.PortList {
return nil
}
func (x *RoutingRule) GetProcess() []string {
if x != nil {
return x.Process
}
return nil
}
type isRoutingRule_TargetTag interface {
isRoutingRule_TargetTag()
}
@@ -1081,7 +1089,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,
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,
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xe8, 0x06, 0x0a, 0x0b, 0x52, 0x6f,
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x82, 0x07, 0x0a, 0x0b, 0x52, 0x6f,
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,
0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c,
@@ -1131,66 +1139,68 @@ var file_app_router_config_proto_rawDesc = []byte{
0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x14, 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, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f,
0x75, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69,
0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69,
0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62,
0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20,
0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c,
0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x73, 0x65,
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78,
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10,
0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67,
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57,
0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x18,
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x12, 0x14, 0x0a,
0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61,
0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x17, 0x53, 0x74,
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57,
0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09,
0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52,
0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78,
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78,
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54,
0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c,
0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x90, 0x02, 0x0a,
0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69,
0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65,
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67,
0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 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, 0x3c, 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, 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,
0x75, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65,
0x73, 0x73, 0x18, 0x15, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc,
0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65,
0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74,
0x61, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f,
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12,
0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73,
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65,
0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61,
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0b, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a,
0x0e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12,
0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
0x35, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52,
0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69,
0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c,
0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65,
0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c,
0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x90, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61,
0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04,
0x72, 0x75, 0x6c, 0x65, 0x12, 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, 0x3c, 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, 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 (
+1
View File
@@ -113,6 +113,7 @@ message RoutingRule {
xray.common.net.PortList local_port_list = 18;
xray.common.net.PortList vless_route_list = 20;
repeated string process = 21;
}
message BalancingRule {
+16 -1
View File
@@ -2,7 +2,7 @@ package router
import (
"context"
sync "sync"
"sync"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
@@ -181,6 +181,21 @@ func (r *Router) RemoveRule(tag string) error {
return errors.New("empty tag name!")
}
// ListRule implements routing.Router
func (r *Router) ListRule() []routing.Route {
r.mu.Lock()
defer r.mu.Unlock()
ruleList := make([]routing.Route, 0)
for _, rule := range r.rules {
ruleList = append(ruleList, &Route{
outboundTag: rule.Tag,
ruleTag: rule.RuleTag,
})
}
return ruleList
}
func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) {
// SkipDNSResolve is set from DNS module.
// the DOH remote server maybe a domain name,
+6
View File
@@ -80,6 +80,12 @@ func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, request *GetStat
}, nil
}
func (s *statsServer) GetAllOnlineUsers(ctx context.Context, request *GetAllOnlineUsersRequest) (*GetAllOnlineUsersResponse, error) {
return &GetAllOnlineUsersResponse{
Users: s.stats.GetAllOnlineUsers(),
}, nil
}
func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
matcher, err := strmatcher.Substr.New(request.Pattern)
if err != nil {
+245 -217
View File
@@ -1,8 +1,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.1
// protoc v5.28.2
// source: app/stats/command/command.proto
// protoc-gen-go v1.36.8
// protoc v6.32.0
// source: command.proto
package command
@@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -21,19 +22,18 @@ const (
)
type GetStatsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState `protogen:"open.v1"`
// Name of the stat counter.
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// Whether or not to reset the counter to fetching its value.
Reset_ bool `protobuf:"varint,2,opt,name=reset,proto3" json:"reset,omitempty"`
Reset_ bool `protobuf:"varint,2,opt,name=reset,proto3" json:"reset,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetStatsRequest) Reset() {
*x = GetStatsRequest{}
mi := &file_app_stats_command_command_proto_msgTypes[0]
mi := &file_command_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -45,7 +45,7 @@ func (x *GetStatsRequest) String() string {
func (*GetStatsRequest) ProtoMessage() {}
func (x *GetStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[0]
mi := &file_command_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -58,7 +58,7 @@ func (x *GetStatsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetStatsRequest.ProtoReflect.Descriptor instead.
func (*GetStatsRequest) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{0}
return file_command_proto_rawDescGZIP(), []int{0}
}
func (x *GetStatsRequest) GetName() string {
@@ -76,17 +76,16 @@ func (x *GetStatsRequest) GetReset_() bool {
}
type Stat struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"`
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *Stat) Reset() {
*x = Stat{}
mi := &file_app_stats_command_command_proto_msgTypes[1]
mi := &file_command_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -98,7 +97,7 @@ func (x *Stat) String() string {
func (*Stat) ProtoMessage() {}
func (x *Stat) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[1]
mi := &file_command_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -111,7 +110,7 @@ func (x *Stat) ProtoReflect() protoreflect.Message {
// Deprecated: Use Stat.ProtoReflect.Descriptor instead.
func (*Stat) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{1}
return file_command_proto_rawDescGZIP(), []int{1}
}
func (x *Stat) GetName() string {
@@ -129,16 +128,15 @@ func (x *Stat) GetValue() int64 {
}
type GetStatsResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Stat *Stat `protobuf:"bytes,1,opt,name=stat,proto3" json:"stat,omitempty"`
unknownFields protoimpl.UnknownFields
Stat *Stat `protobuf:"bytes,1,opt,name=stat,proto3" json:"stat,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *GetStatsResponse) Reset() {
*x = GetStatsResponse{}
mi := &file_app_stats_command_command_proto_msgTypes[2]
mi := &file_command_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -150,7 +148,7 @@ func (x *GetStatsResponse) String() string {
func (*GetStatsResponse) ProtoMessage() {}
func (x *GetStatsResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[2]
mi := &file_command_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -163,7 +161,7 @@ func (x *GetStatsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetStatsResponse.ProtoReflect.Descriptor instead.
func (*GetStatsResponse) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{2}
return file_command_proto_rawDescGZIP(), []int{2}
}
func (x *GetStatsResponse) GetStat() *Stat {
@@ -174,17 +172,16 @@ func (x *GetStatsResponse) GetStat() *Stat {
}
type QueryStatsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Pattern string `protobuf:"bytes,1,opt,name=pattern,proto3" json:"pattern,omitempty"`
Reset_ bool `protobuf:"varint,2,opt,name=reset,proto3" json:"reset,omitempty"`
unknownFields protoimpl.UnknownFields
Pattern string `protobuf:"bytes,1,opt,name=pattern,proto3" json:"pattern,omitempty"`
Reset_ bool `protobuf:"varint,2,opt,name=reset,proto3" json:"reset,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *QueryStatsRequest) Reset() {
*x = QueryStatsRequest{}
mi := &file_app_stats_command_command_proto_msgTypes[3]
mi := &file_command_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -196,7 +193,7 @@ func (x *QueryStatsRequest) String() string {
func (*QueryStatsRequest) ProtoMessage() {}
func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[3]
mi := &file_command_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -209,7 +206,7 @@ func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use QueryStatsRequest.ProtoReflect.Descriptor instead.
func (*QueryStatsRequest) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{3}
return file_command_proto_rawDescGZIP(), []int{3}
}
func (x *QueryStatsRequest) GetPattern() string {
@@ -227,16 +224,15 @@ func (x *QueryStatsRequest) GetReset_() bool {
}
type QueryStatsResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Stat []*Stat `protobuf:"bytes,1,rep,name=stat,proto3" json:"stat,omitempty"`
unknownFields protoimpl.UnknownFields
Stat []*Stat `protobuf:"bytes,1,rep,name=stat,proto3" json:"stat,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *QueryStatsResponse) Reset() {
*x = QueryStatsResponse{}
mi := &file_app_stats_command_command_proto_msgTypes[4]
mi := &file_command_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -248,7 +244,7 @@ func (x *QueryStatsResponse) String() string {
func (*QueryStatsResponse) ProtoMessage() {}
func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[4]
mi := &file_command_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -261,7 +257,7 @@ func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use QueryStatsResponse.ProtoReflect.Descriptor instead.
func (*QueryStatsResponse) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{4}
return file_command_proto_rawDescGZIP(), []int{4}
}
func (x *QueryStatsResponse) GetStat() []*Stat {
@@ -272,14 +268,14 @@ func (x *QueryStatsResponse) GetStat() []*Stat {
}
type SysStatsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SysStatsRequest) Reset() {
*x = SysStatsRequest{}
mi := &file_app_stats_command_command_proto_msgTypes[5]
mi := &file_command_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -291,7 +287,7 @@ func (x *SysStatsRequest) String() string {
func (*SysStatsRequest) ProtoMessage() {}
func (x *SysStatsRequest) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[5]
mi := &file_command_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -304,29 +300,28 @@ func (x *SysStatsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use SysStatsRequest.ProtoReflect.Descriptor instead.
func (*SysStatsRequest) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{5}
return file_command_proto_rawDescGZIP(), []int{5}
}
type SysStatsResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
NumGoroutine uint32 `protobuf:"varint,1,opt,name=NumGoroutine,proto3" json:"NumGoroutine,omitempty"`
NumGC uint32 `protobuf:"varint,2,opt,name=NumGC,proto3" json:"NumGC,omitempty"`
Alloc uint64 `protobuf:"varint,3,opt,name=Alloc,proto3" json:"Alloc,omitempty"`
TotalAlloc uint64 `protobuf:"varint,4,opt,name=TotalAlloc,proto3" json:"TotalAlloc,omitempty"`
Sys uint64 `protobuf:"varint,5,opt,name=Sys,proto3" json:"Sys,omitempty"`
Mallocs uint64 `protobuf:"varint,6,opt,name=Mallocs,proto3" json:"Mallocs,omitempty"`
Frees uint64 `protobuf:"varint,7,opt,name=Frees,proto3" json:"Frees,omitempty"`
LiveObjects uint64 `protobuf:"varint,8,opt,name=LiveObjects,proto3" json:"LiveObjects,omitempty"`
PauseTotalNs uint64 `protobuf:"varint,9,opt,name=PauseTotalNs,proto3" json:"PauseTotalNs,omitempty"`
Uptime uint32 `protobuf:"varint,10,opt,name=Uptime,proto3" json:"Uptime,omitempty"`
unknownFields protoimpl.UnknownFields
NumGoroutine uint32 `protobuf:"varint,1,opt,name=NumGoroutine,proto3" json:"NumGoroutine,omitempty"`
NumGC uint32 `protobuf:"varint,2,opt,name=NumGC,proto3" json:"NumGC,omitempty"`
Alloc uint64 `protobuf:"varint,3,opt,name=Alloc,proto3" json:"Alloc,omitempty"`
TotalAlloc uint64 `protobuf:"varint,4,opt,name=TotalAlloc,proto3" json:"TotalAlloc,omitempty"`
Sys uint64 `protobuf:"varint,5,opt,name=Sys,proto3" json:"Sys,omitempty"`
Mallocs uint64 `protobuf:"varint,6,opt,name=Mallocs,proto3" json:"Mallocs,omitempty"`
Frees uint64 `protobuf:"varint,7,opt,name=Frees,proto3" json:"Frees,omitempty"`
LiveObjects uint64 `protobuf:"varint,8,opt,name=LiveObjects,proto3" json:"LiveObjects,omitempty"`
PauseTotalNs uint64 `protobuf:"varint,9,opt,name=PauseTotalNs,proto3" json:"PauseTotalNs,omitempty"`
Uptime uint32 `protobuf:"varint,10,opt,name=Uptime,proto3" json:"Uptime,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *SysStatsResponse) Reset() {
*x = SysStatsResponse{}
mi := &file_app_stats_command_command_proto_msgTypes[6]
mi := &file_command_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -338,7 +333,7 @@ func (x *SysStatsResponse) String() string {
func (*SysStatsResponse) ProtoMessage() {}
func (x *SysStatsResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[6]
mi := &file_command_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -351,7 +346,7 @@ func (x *SysStatsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use SysStatsResponse.ProtoReflect.Descriptor instead.
func (*SysStatsResponse) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{6}
return file_command_proto_rawDescGZIP(), []int{6}
}
func (x *SysStatsResponse) GetNumGoroutine() uint32 {
@@ -425,17 +420,16 @@ func (x *SysStatsResponse) GetUptime() uint32 {
}
type GetStatsOnlineIpListResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Ips map[string]int64 `protobuf:"bytes,2,rep,name=ips,proto3" json:"ips,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"`
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Ips map[string]int64 `protobuf:"bytes,2,rep,name=ips,proto3" json:"ips,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
sizeCache protoimpl.SizeCache
}
func (x *GetStatsOnlineIpListResponse) Reset() {
*x = GetStatsOnlineIpListResponse{}
mi := &file_app_stats_command_command_proto_msgTypes[7]
mi := &file_command_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -447,7 +441,7 @@ func (x *GetStatsOnlineIpListResponse) String() string {
func (*GetStatsOnlineIpListResponse) ProtoMessage() {}
func (x *GetStatsOnlineIpListResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[7]
mi := &file_command_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -460,7 +454,7 @@ func (x *GetStatsOnlineIpListResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetStatsOnlineIpListResponse.ProtoReflect.Descriptor instead.
func (*GetStatsOnlineIpListResponse) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{7}
return file_command_proto_rawDescGZIP(), []int{7}
}
func (x *GetStatsOnlineIpListResponse) GetName() string {
@@ -477,15 +471,95 @@ func (x *GetStatsOnlineIpListResponse) GetIps() map[string]int64 {
return nil
}
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
type GetAllOnlineUsersRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetAllOnlineUsersRequest) Reset() {
*x = GetAllOnlineUsersRequest{}
mi := &file_command_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetAllOnlineUsersRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetAllOnlineUsersRequest) ProtoMessage() {}
func (x *GetAllOnlineUsersRequest) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetAllOnlineUsersRequest.ProtoReflect.Descriptor instead.
func (*GetAllOnlineUsersRequest) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{8}
}
type GetAllOnlineUsersResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Users []string `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetAllOnlineUsersResponse) Reset() {
*x = GetAllOnlineUsersResponse{}
mi := &file_command_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetAllOnlineUsersResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetAllOnlineUsersResponse) ProtoMessage() {}
func (x *GetAllOnlineUsersResponse) ProtoReflect() protoreflect.Message {
mi := &file_command_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetAllOnlineUsersResponse.ProtoReflect.Descriptor instead.
func (*GetAllOnlineUsersResponse) Descriptor() ([]byte, []int) {
return file_command_proto_rawDescGZIP(), []int{9}
}
func (x *GetAllOnlineUsersResponse) GetUsers() []string {
if x != nil {
return x.Users
}
return nil
}
type Config struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Config) Reset() {
*x = Config{}
mi := &file_app_stats_command_command_proto_msgTypes[8]
mi := &file_command_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -497,7 +571,7 @@ func (x *Config) String() string {
func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[8]
mi := &file_command_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -510,125 +584,76 @@ func (x *Config) ProtoReflect() protoreflect.Message {
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{8}
return file_command_proto_rawDescGZIP(), []int{10}
}
var File_app_stats_command_command_proto protoreflect.FileDescriptor
var File_command_proto protoreflect.FileDescriptor
var file_app_stats_command_command_proto_rawDesc = []byte{
0x0a, 0x1f, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x16, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74,
0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x3b, 0x0a, 0x0f, 0x47, 0x65, 0x74,
0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x22, 0x30, 0x0a, 0x04, 0x53, 0x74, 0x61, 0x74, 0x12, 0x12,
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x44, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53,
0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04,
0x73, 0x74, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x04, 0x73, 0x74, 0x61, 0x74, 0x22, 0x43,
0x0a, 0x11, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0x14, 0x0a,
0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65,
0x73, 0x65, 0x74, 0x22, 0x46, 0x0a, 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x73, 0x74, 0x61,
0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x04, 0x73, 0x74, 0x61, 0x74, 0x22, 0x11, 0x0a, 0x0f, 0x53,
0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa2,
0x02, 0x0a, 0x10, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x4e, 0x75, 0x6d, 0x47, 0x6f, 0x72, 0x6f, 0x75, 0x74,
0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x4e, 0x75, 0x6d, 0x47, 0x6f,
0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x75, 0x6d, 0x47, 0x43,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x4e, 0x75, 0x6d, 0x47, 0x43, 0x12, 0x14, 0x0a,
0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x41, 0x6c,
0x6c, 0x6f, 0x63, 0x12, 0x1e, 0x0a, 0x0a, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f,
0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c,
0x6c, 0x6f, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x53, 0x79, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04,
0x52, 0x03, 0x53, 0x79, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73,
0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x4d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x12,
0x14, 0x0a, 0x05, 0x46, 0x72, 0x65, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05,
0x46, 0x72, 0x65, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4c, 0x69, 0x76, 0x65, 0x4f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4c, 0x69, 0x76, 0x65,
0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x61, 0x75, 0x73, 0x65,
0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x50,
0x61, 0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x55,
0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x70, 0x74,
0x69, 0x6d, 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73,
0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4f, 0x0a, 0x03, 0x69, 0x70, 0x73, 0x18,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47,
0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x70, 0x4c,
0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x70, 0x73, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x69, 0x70, 0x73, 0x1a, 0x36, 0x0a, 0x08, 0x49, 0x70, 0x73,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x01, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0x9a, 0x04, 0x0a, 0x0c,
0x53, 0x74, 0x61, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x08,
0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61,
0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74,
0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a,
0x0e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12,
0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61,
0x74, 0x73, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74,
0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72,
0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x62, 0x0a, 0x0b, 0x47,
0x65, 0x74, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73,
0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x79, 0x73,
0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
0x77, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e,
0x65, 0x49, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x34, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74,
0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61,
0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x64, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2b, 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, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x63, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x16, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70,
0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
const file_command_proto_rawDesc = "" +
"\n" +
"\rcommand.proto\x12\x16xray.app.stats.command\";\n" +
"\x0fGetStatsRequest\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" +
"\x05reset\x18\x02 \x01(\bR\x05reset\"0\n" +
"\x04Stat\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" +
"\x05value\x18\x02 \x01(\x03R\x05value\"D\n" +
"\x10GetStatsResponse\x120\n" +
"\x04stat\x18\x01 \x01(\v2\x1c.xray.app.stats.command.StatR\x04stat\"C\n" +
"\x11QueryStatsRequest\x12\x18\n" +
"\apattern\x18\x01 \x01(\tR\apattern\x12\x14\n" +
"\x05reset\x18\x02 \x01(\bR\x05reset\"F\n" +
"\x12QueryStatsResponse\x120\n" +
"\x04stat\x18\x01 \x03(\v2\x1c.xray.app.stats.command.StatR\x04stat\"\x11\n" +
"\x0fSysStatsRequest\"\xa2\x02\n" +
"\x10SysStatsResponse\x12\"\n" +
"\fNumGoroutine\x18\x01 \x01(\rR\fNumGoroutine\x12\x14\n" +
"\x05NumGC\x18\x02 \x01(\rR\x05NumGC\x12\x14\n" +
"\x05Alloc\x18\x03 \x01(\x04R\x05Alloc\x12\x1e\n" +
"\n" +
"TotalAlloc\x18\x04 \x01(\x04R\n" +
"TotalAlloc\x12\x10\n" +
"\x03Sys\x18\x05 \x01(\x04R\x03Sys\x12\x18\n" +
"\aMallocs\x18\x06 \x01(\x04R\aMallocs\x12\x14\n" +
"\x05Frees\x18\a \x01(\x04R\x05Frees\x12 \n" +
"\vLiveObjects\x18\b \x01(\x04R\vLiveObjects\x12\"\n" +
"\fPauseTotalNs\x18\t \x01(\x04R\fPauseTotalNs\x12\x16\n" +
"\x06Uptime\x18\n" +
" \x01(\rR\x06Uptime\"\xbb\x01\n" +
"\x1cGetStatsOnlineIpListResponse\x12\x12\n" +
"\x04name\x18\x01 \x01(\tR\x04name\x12O\n" +
"\x03ips\x18\x02 \x03(\v2=.xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntryR\x03ips\x1a6\n" +
"\bIpsEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\x03R\x05value:\x028\x01\"\x1a\n" +
"\x18GetAllOnlineUsersRequest\"1\n" +
"\x19GetAllOnlineUsersResponse\x12\x14\n" +
"\x05users\x18\x01 \x03(\tR\x05users\"\b\n" +
"\x06Config2\x96\x05\n" +
"\fStatsService\x12_\n" +
"\bGetStats\x12'.xray.app.stats.command.GetStatsRequest\x1a(.xray.app.stats.command.GetStatsResponse\"\x00\x12e\n" +
"\x0eGetStatsOnline\x12'.xray.app.stats.command.GetStatsRequest\x1a(.xray.app.stats.command.GetStatsResponse\"\x00\x12e\n" +
"\n" +
"QueryStats\x12).xray.app.stats.command.QueryStatsRequest\x1a*.xray.app.stats.command.QueryStatsResponse\"\x00\x12b\n" +
"\vGetSysStats\x12'.xray.app.stats.command.SysStatsRequest\x1a(.xray.app.stats.command.SysStatsResponse\"\x00\x12w\n" +
"\x14GetStatsOnlineIpList\x12'.xray.app.stats.command.GetStatsRequest\x1a4.xray.app.stats.command.GetStatsOnlineIpListResponse\"\x00\x12z\n" +
"\x11GetAllOnlineUsers\x120.xray.app.stats.command.GetAllOnlineUsersRequest\x1a1.xray.app.stats.command.GetAllOnlineUsersResponse\"\x00Bd\n" +
"\x1acom.xray.app.stats.commandP\x01Z+github.com/xtls/xray-core/app/stats/command\xaa\x02\x16Xray.App.Stats.Commandb\x06proto3"
var (
file_app_stats_command_command_proto_rawDescOnce sync.Once
file_app_stats_command_command_proto_rawDescData = file_app_stats_command_command_proto_rawDesc
file_command_proto_rawDescOnce sync.Once
file_command_proto_rawDescData []byte
)
func file_app_stats_command_command_proto_rawDescGZIP() []byte {
file_app_stats_command_command_proto_rawDescOnce.Do(func() {
file_app_stats_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_stats_command_command_proto_rawDescData)
func file_command_proto_rawDescGZIP() []byte {
file_command_proto_rawDescOnce.Do(func() {
file_command_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_command_proto_rawDesc), len(file_command_proto_rawDesc)))
})
return file_app_stats_command_command_proto_rawDescData
return file_command_proto_rawDescData
}
var file_app_stats_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_app_stats_command_command_proto_goTypes = []any{
var file_command_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_command_proto_goTypes = []any{
(*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest
(*Stat)(nil), // 1: xray.app.stats.command.Stat
(*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse
@@ -637,51 +662,54 @@ var file_app_stats_command_command_proto_goTypes = []any{
(*SysStatsRequest)(nil), // 5: xray.app.stats.command.SysStatsRequest
(*SysStatsResponse)(nil), // 6: xray.app.stats.command.SysStatsResponse
(*GetStatsOnlineIpListResponse)(nil), // 7: xray.app.stats.command.GetStatsOnlineIpListResponse
(*Config)(nil), // 8: xray.app.stats.command.Config
nil, // 9: xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
(*GetAllOnlineUsersRequest)(nil), // 8: xray.app.stats.command.GetAllOnlineUsersRequest
(*GetAllOnlineUsersResponse)(nil), // 9: xray.app.stats.command.GetAllOnlineUsersResponse
(*Config)(nil), // 10: xray.app.stats.command.Config
nil, // 11: xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
}
var file_app_stats_command_command_proto_depIdxs = []int32{
1, // 0: xray.app.stats.command.GetStatsResponse.stat:type_name -> xray.app.stats.command.Stat
1, // 1: xray.app.stats.command.QueryStatsResponse.stat:type_name -> xray.app.stats.command.Stat
9, // 2: xray.app.stats.command.GetStatsOnlineIpListResponse.ips:type_name -> xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
0, // 3: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest
0, // 4: xray.app.stats.command.StatsService.GetStatsOnline:input_type -> xray.app.stats.command.GetStatsRequest
3, // 5: xray.app.stats.command.StatsService.QueryStats:input_type -> xray.app.stats.command.QueryStatsRequest
5, // 6: xray.app.stats.command.StatsService.GetSysStats:input_type -> xray.app.stats.command.SysStatsRequest
0, // 7: xray.app.stats.command.StatsService.GetStatsOnlineIpList:input_type -> xray.app.stats.command.GetStatsRequest
2, // 8: xray.app.stats.command.StatsService.GetStats:output_type -> xray.app.stats.command.GetStatsResponse
2, // 9: xray.app.stats.command.StatsService.GetStatsOnline:output_type -> xray.app.stats.command.GetStatsResponse
4, // 10: xray.app.stats.command.StatsService.QueryStats:output_type -> xray.app.stats.command.QueryStatsResponse
6, // 11: xray.app.stats.command.StatsService.GetSysStats:output_type -> xray.app.stats.command.SysStatsResponse
7, // 12: xray.app.stats.command.StatsService.GetStatsOnlineIpList:output_type -> xray.app.stats.command.GetStatsOnlineIpListResponse
8, // [8:13] is the sub-list for method output_type
3, // [3:8] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
var file_command_proto_depIdxs = []int32{
1, // 0: xray.app.stats.command.GetStatsResponse.stat:type_name -> xray.app.stats.command.Stat
1, // 1: xray.app.stats.command.QueryStatsResponse.stat:type_name -> xray.app.stats.command.Stat
11, // 2: xray.app.stats.command.GetStatsOnlineIpListResponse.ips:type_name -> xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
0, // 3: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest
0, // 4: xray.app.stats.command.StatsService.GetStatsOnline:input_type -> xray.app.stats.command.GetStatsRequest
3, // 5: xray.app.stats.command.StatsService.QueryStats:input_type -> xray.app.stats.command.QueryStatsRequest
5, // 6: xray.app.stats.command.StatsService.GetSysStats:input_type -> xray.app.stats.command.SysStatsRequest
0, // 7: xray.app.stats.command.StatsService.GetStatsOnlineIpList:input_type -> xray.app.stats.command.GetStatsRequest
8, // 8: xray.app.stats.command.StatsService.GetAllOnlineUsers:input_type -> xray.app.stats.command.GetAllOnlineUsersRequest
2, // 9: xray.app.stats.command.StatsService.GetStats:output_type -> xray.app.stats.command.GetStatsResponse
2, // 10: xray.app.stats.command.StatsService.GetStatsOnline:output_type -> xray.app.stats.command.GetStatsResponse
4, // 11: xray.app.stats.command.StatsService.QueryStats:output_type -> xray.app.stats.command.QueryStatsResponse
6, // 12: xray.app.stats.command.StatsService.GetSysStats:output_type -> xray.app.stats.command.SysStatsResponse
7, // 13: xray.app.stats.command.StatsService.GetStatsOnlineIpList:output_type -> xray.app.stats.command.GetStatsOnlineIpListResponse
9, // 14: xray.app.stats.command.StatsService.GetAllOnlineUsers:output_type -> xray.app.stats.command.GetAllOnlineUsersResponse
9, // [9:15] is the sub-list for method output_type
3, // [3:9] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_app_stats_command_command_proto_init() }
func file_app_stats_command_command_proto_init() {
if File_app_stats_command_command_proto != nil {
func init() { file_command_proto_init() }
func file_command_proto_init() {
if File_command_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_stats_command_command_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_command_proto_rawDesc), len(file_command_proto_rawDesc)),
NumEnums: 0,
NumMessages: 10,
NumMessages: 12,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_app_stats_command_command_proto_goTypes,
DependencyIndexes: file_app_stats_command_command_proto_depIdxs,
MessageInfos: file_app_stats_command_command_proto_msgTypes,
GoTypes: file_command_proto_goTypes,
DependencyIndexes: file_command_proto_depIdxs,
MessageInfos: file_command_proto_msgTypes,
}.Build()
File_app_stats_command_command_proto = out.File
file_app_stats_command_command_proto_rawDesc = nil
file_app_stats_command_command_proto_goTypes = nil
file_app_stats_command_command_proto_depIdxs = nil
File_command_proto = out.File
file_command_proto_goTypes = nil
file_command_proto_depIdxs = nil
}
+7
View File
@@ -51,12 +51,19 @@ message GetStatsOnlineIpListResponse {
map<string, int64> ips = 2;
}
message GetAllOnlineUsersRequest {}
message GetAllOnlineUsersResponse {
repeated string users = 1;
}
service StatsService {
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
rpc GetStatsOnline(GetStatsRequest) returns (GetStatsResponse) {}
rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {}
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
rpc GetStatsOnlineIpList(GetStatsRequest) returns (GetStatsOnlineIpListResponse) {}
rpc GetAllOnlineUsers(GetAllOnlineUsersRequest) returns (GetAllOnlineUsersResponse) {}
}
message Config {}
+41 -3
View File
@@ -1,8 +1,8 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.28.2
// source: app/stats/command/command.proto
// - protoc v6.32.0
// source: command.proto
package command
@@ -24,6 +24,7 @@ const (
StatsService_QueryStats_FullMethodName = "/xray.app.stats.command.StatsService/QueryStats"
StatsService_GetSysStats_FullMethodName = "/xray.app.stats.command.StatsService/GetSysStats"
StatsService_GetStatsOnlineIpList_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnlineIpList"
StatsService_GetAllOnlineUsers_FullMethodName = "/xray.app.stats.command.StatsService/GetAllOnlineUsers"
)
// StatsServiceClient is the client API for StatsService service.
@@ -35,6 +36,7 @@ type StatsServiceClient interface {
QueryStats(ctx context.Context, in *QueryStatsRequest, opts ...grpc.CallOption) (*QueryStatsResponse, error)
GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error)
GetStatsOnlineIpList(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsOnlineIpListResponse, error)
GetAllOnlineUsers(ctx context.Context, in *GetAllOnlineUsersRequest, opts ...grpc.CallOption) (*GetAllOnlineUsersResponse, error)
}
type statsServiceClient struct {
@@ -95,6 +97,16 @@ func (c *statsServiceClient) GetStatsOnlineIpList(ctx context.Context, in *GetSt
return out, nil
}
func (c *statsServiceClient) GetAllOnlineUsers(ctx context.Context, in *GetAllOnlineUsersRequest, opts ...grpc.CallOption) (*GetAllOnlineUsersResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetAllOnlineUsersResponse)
err := c.cc.Invoke(ctx, StatsService_GetAllOnlineUsers_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// StatsServiceServer is the server API for StatsService service.
// All implementations must embed UnimplementedStatsServiceServer
// for forward compatibility.
@@ -104,6 +116,7 @@ type StatsServiceServer interface {
QueryStats(context.Context, *QueryStatsRequest) (*QueryStatsResponse, error)
GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error)
GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error)
GetAllOnlineUsers(context.Context, *GetAllOnlineUsersRequest) (*GetAllOnlineUsersResponse, error)
mustEmbedUnimplementedStatsServiceServer()
}
@@ -129,6 +142,9 @@ func (UnimplementedStatsServiceServer) GetSysStats(context.Context, *SysStatsReq
func (UnimplementedStatsServiceServer) GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetStatsOnlineIpList not implemented")
}
func (UnimplementedStatsServiceServer) GetAllOnlineUsers(context.Context, *GetAllOnlineUsersRequest) (*GetAllOnlineUsersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetAllOnlineUsers not implemented")
}
func (UnimplementedStatsServiceServer) mustEmbedUnimplementedStatsServiceServer() {}
func (UnimplementedStatsServiceServer) testEmbeddedByValue() {}
@@ -240,6 +256,24 @@ func _StatsService_GetStatsOnlineIpList_Handler(srv interface{}, ctx context.Con
return interceptor(ctx, in, info, handler)
}
func _StatsService_GetAllOnlineUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetAllOnlineUsersRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(StatsServiceServer).GetAllOnlineUsers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: StatsService_GetAllOnlineUsers_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(StatsServiceServer).GetAllOnlineUsers(ctx, req.(*GetAllOnlineUsersRequest))
}
return interceptor(ctx, in, info, handler)
}
// StatsService_ServiceDesc is the grpc.ServiceDesc for StatsService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -267,7 +301,11 @@ var StatsService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetStatsOnlineIpList",
Handler: _StatsService_GetStatsOnlineIpList_Handler,
},
{
MethodName: "GetAllOnlineUsers",
Handler: _StatsService_GetAllOnlineUsers_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "app/stats/command/command.proto",
Metadata: "command.proto",
}
+15
View File
@@ -161,6 +161,21 @@ func (m *Manager) GetChannel(name string) stats.Channel {
return nil
}
// GetAllOnlineUsers implements stats.Manager.
func (m *Manager) GetAllOnlineUsers() []string {
m.access.Lock()
defer m.access.Unlock()
usersOnline := make([]string, 0, len(m.onlineMap))
for user, onlineMap := range m.onlineMap {
if len(onlineMap.IpTimeMap()) > 0 {
usersOnline = append(usersOnline, user)
}
}
return usersOnline
}
// Start implements common.Runnable.
func (m *Manager) Start() error {
m.access.Lock()
-6
View File
@@ -1,6 +0,0 @@
package antireplay
type GeneralizedReplayFilter interface {
Interval() int64
Check(sum []byte) bool
}
+33
View File
@@ -0,0 +1,33 @@
package antireplay
import (
"bufio"
"crypto/rand"
"testing"
)
func BenchmarkMapFilter(b *testing.B) {
filter := NewMapFilter[[16]byte](120)
var sample [16]byte
reader := bufio.NewReader(rand.Reader)
reader.Read(sample[:])
b.ResetTimer()
for range b.N {
reader.Read(sample[:])
filter.Check(sample)
}
}
func TestMapFilter(t *testing.T) {
filter := NewMapFilter[[16]byte](120)
var sample [16]byte
rand.Read(sample[:])
filter.Check(sample)
if filter.Check(sample) {
t.Error("Unexpected true negative")
}
sample[0]++
if !filter.Check(sample) {
t.Error("Unexpected false positive")
}
}
-36
View File
@@ -1,36 +0,0 @@
package antireplay
import (
"sync"
ss_bloomring "github.com/v2fly/ss-bloomring"
)
type BloomRing struct {
*ss_bloomring.BloomRing
lock *sync.Mutex
}
func (b BloomRing) Interval() int64 {
return 9999999
}
func (b BloomRing) Check(sum []byte) bool {
b.lock.Lock()
defer b.lock.Unlock()
if b.Test(sum) {
return false
}
b.Add(sum)
return true
}
func NewBloomRing() BloomRing {
const (
DefaultSFCapacity = 1e6
// FalsePositiveRate
DefaultSFFPR = 1e-6
DefaultSFSlot = 10
)
return BloomRing{ss_bloomring.NewBloomRing(DefaultSFSlot, DefaultSFCapacity, DefaultSFFPR), &sync.Mutex{}}
}
+46
View File
@@ -0,0 +1,46 @@
package antireplay
import (
"sync"
"time"
)
// ReplayFilter checks for replay attacks.
type ReplayFilter[T comparable] struct {
lock sync.Mutex
poolA map[T]struct{}
poolB map[T]struct{}
interval time.Duration
lastClean time.Time
}
// NewMapFilter create a new filter with specifying the expiration time interval in seconds.
func NewMapFilter[T comparable](interval int64) *ReplayFilter[T] {
filter := &ReplayFilter[T]{
poolA: make(map[T]struct{}),
poolB: make(map[T]struct{}),
interval: time.Duration(interval) * time.Second,
lastClean: time.Now(),
}
return filter
}
// Check determines if there are duplicate records.
func (filter *ReplayFilter[T]) Check(sum T) bool {
filter.lock.Lock()
defer filter.lock.Unlock()
now := time.Now()
if now.Sub(filter.lastClean) >= filter.interval {
filter.poolB = filter.poolA
filter.poolA = make(map[T]struct{})
filter.lastClean = now
}
_, existsA := filter.poolA[sum]
_, existsB := filter.poolB[sum]
if !existsA && !existsB {
filter.poolA[sum] = struct{}{}
}
return !(existsA || existsB)
}
-58
View File
@@ -1,58 +0,0 @@
package antireplay
import (
"sync"
"time"
cuckoo "github.com/seiflotfy/cuckoofilter"
)
const replayFilterCapacity = 100000
// ReplayFilter checks for replay attacks.
type ReplayFilter struct {
lock sync.Mutex
poolA *cuckoo.Filter
poolB *cuckoo.Filter
poolSwap bool
lastSwap int64
interval int64
}
// NewReplayFilter create a new filter with specifying the expiration time interval in seconds.
func NewReplayFilter(interval int64) *ReplayFilter {
filter := &ReplayFilter{}
filter.interval = interval
return filter
}
// Interval in second for expiration time for duplicate records.
func (filter *ReplayFilter) Interval() int64 {
return filter.interval
}
// Check determines if there are duplicate records.
func (filter *ReplayFilter) Check(sum []byte) bool {
filter.lock.Lock()
defer filter.lock.Unlock()
now := time.Now().Unix()
if filter.lastSwap == 0 {
filter.lastSwap = now
filter.poolA = cuckoo.NewFilter(replayFilterCapacity)
filter.poolB = cuckoo.NewFilter(replayFilterCapacity)
}
elapsed := now - filter.lastSwap
if elapsed >= filter.Interval() {
if filter.poolSwap {
filter.poolA.Reset()
} else {
filter.poolB.Reset()
}
filter.poolSwap = !filter.poolSwap
filter.lastSwap = now
}
return filter.poolA.InsertUnique(sum) && filter.poolB.InsertUnique(sum)
}
+1 -117
View File
@@ -2,12 +2,10 @@ package buf
import (
"io"
"sync"
"time"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/stats"
)
@@ -115,12 +113,7 @@ func Copy(reader Reader, writer Writer, options ...CopyOption) error {
for _, option := range options {
option(&handler)
}
var err error
if shouldUseCopyV(reader, writer) {
err = copyVInternal(reader, writer, &handler)
} else {
err = copyInternal(reader, writer, &handler)
}
err := copyInternal(reader, writer, &handler)
if err != nil && errors.Cause(err) != io.EOF {
return err
}
@@ -140,112 +133,3 @@ func CopyOnceTimeout(reader Reader, writer Writer, timeout time.Duration) error
}
return writer.WriteMultiBuffer(mb)
}
func shouldUseCopyV(reader Reader, writer Writer) bool {
// if writer is not support writeV, directly return false
if _, ok := writer.(*BufferToBytesWriter); !ok {
return false
}
// try to figure out if the underlying reader is SingleReader
var doCopyV bool
if tr, ok := reader.(*TimeoutWrapperReader); ok {
if _, ok := tr.Reader.(*SingleReader); ok {
doCopyV = true
}
}
if _, ok := reader.(*SingleReader); ok {
doCopyV = true
}
return doCopyV
}
func copyVInternal(r Reader, w Writer, handler *copyHandler) error {
// channel buffer size is maxBuffer/maxPerPacketLen (ignore the case of many small packets)
// default buffer size:
// 0 in ARM MIPS MIPSLE
// 4kb in ARM64 MIPS64 MIPS64LE
// 512kb in others
channelBuffer := (policy.SessionDefault().Buffer.PerConnection) / Size
if channelBuffer <= 0 {
channelBuffer = 4
}
cache := make(chan *Buffer, channelBuffer)
stopRead := make(chan struct{})
var rErr error
var wErr error
wg := sync.WaitGroup{}
wg.Add(2)
// downlink
go func() {
defer wg.Done()
defer close(cache)
for {
mb, err := r.ReadMultiBuffer()
for _, b := range mb {
if err == nil {
select {
case cache <- b:
// must be write error
case <-stopRead:
b.Release()
return
}
} else {
rErr = err
select {
case cache <- b:
case <-stopRead:
b.Release()
}
return
}
}
}
}()
// uplink
go func() {
defer wg.Done()
for {
b, ok := <-cache
if !ok {
return
}
var buffers = []*Buffer{b}
for stop := false; !stop; {
select {
case b, ok := <-cache:
if !ok {
stop = true
continue
}
buffers = append(buffers, b)
default:
stop = true
}
}
mb := MultiBuffer(buffers)
err := w.WriteMultiBuffer(mb)
for _, handler := range handler.onData {
handler(mb)
}
ReleaseMulti(mb)
if err != nil {
wErr = err
close(stopRead)
return
}
}
}()
wg.Wait()
// drain cache
for b := range cache {
b.Release()
}
if wErr != nil {
return writeError{wErr}
}
if rErr != nil {
return readError{rErr}
}
return nil
}
-5
View File
@@ -159,11 +159,6 @@ func (r *SingleReader) ReadMultiBuffer() (MultiBuffer, error) {
return MultiBuffer{b}, err
}
func (r *SingleReader) readBuffer() (*Buffer, error) {
b, err := ReadBuffer(r.Reader)
return b, err
}
// PacketReader is a Reader that read one Buffer every time.
type PacketReader struct {
io.Reader
+5 -8
View File
@@ -4,22 +4,19 @@ import (
"context"
)
// PrintMigrateFeatureInfo prints a notice of the upcoming feature migration.
// Place it after the source feature related config file pharser code.
// Important note: Only use this when the target migrating feature is under construction.
// Important note: Even when the target migrating feature has finished its construction, this notice can still be used yet before announcing deprecation of the old feature.
// PrintNonRemovalDeprecatedFeatureWarning prints a warning of the deprecated feature that won't be removed in the near future.
// Do not remove this function even there is no reference to it.
func PrintMigrateFeatureInfo(sourceFeature string, targetFeature string) {
LogInfo(context.Background(), "The feature "+sourceFeature+" will be migrated to "+targetFeature+" in the future.")
func PrintNonRemovalDeprecatedFeatureWarning(sourceFeature string, targetFeature string) {
LogWarning(context.Background(), "The feature "+sourceFeature+" is deprecated, not recommended for using and might be removed. Please migrate to "+targetFeature+" as soon as possible.")
}
// PrintDeprecatedFeatureWarning prints a warning for deprecated and going to be removed feature.
// Do not remove this function even there is no reference to it.
func PrintDeprecatedFeatureWarning(feature string, migrateFeature string) {
if len(migrateFeature) > 0 {
LogWarning(context.Background(), "This feature "+feature+" is deprecated and being migrated to "+migrateFeature+". Please update your config(s) according to release note and documentation before removal.")
LogWarning(context.Background(), "This feature "+feature+" is deprecated, will be removed soon and being migrated to "+migrateFeature+". Please update your config(s) according to release note and documentation before removal.")
} else {
LogWarning(context.Background(), "This feature "+feature+" is deprecated. Please update your config(s) according to release note and documentation before removal.")
LogWarning(context.Background(), "This feature "+feature+" is deprecated and will be removed soon. Please update your config(s) according to release note and documentation before removal.")
}
}
-3
View File
@@ -63,9 +63,6 @@ func (s *Server) DispatchLink(ctx context.Context, dest net.Destination, link *t
if dest.Address != muxCoolAddress {
return s.dispatcher.DispatchLink(ctx, dest, link)
}
if d, ok := s.dispatcher.(routing.WrapLinkDispatcher); ok {
link = d.WrapLink(ctx, link)
}
worker, err := NewServerWorker(ctx, s.dispatcher, link)
if err != nil {
return err
+176
View File
@@ -0,0 +1,176 @@
//go:build linux
package net
import (
"bufio"
"encoding/hex"
"fmt"
"os"
"strconv"
"strings"
"github.com/xtls/xray-core/common/errors"
)
func FindProcess(dest Destination) (PID int, Name string, AbsolutePath string, err error) {
isLocal, err := IsLocal(dest.Address.IP())
if err != nil {
return 0, "", "", errors.New("failed to determine if address is local: ", err)
}
if !isLocal {
return 0, "", "", ErrNotLocal
}
if dest.Network != Network_TCP && dest.Network != Network_UDP {
panic("Unsupported network type for process lookup.")
}
// the core should never has a domain as source(?
if dest.Address.Family() == AddressFamilyDomain {
panic("Domain addresses are not supported for process lookup.")
}
var procFile string
switch dest.Network {
case Network_TCP:
if dest.Address.Family() == AddressFamilyIPv4 {
procFile = "/proc/net/tcp"
}
if dest.Address.Family() == AddressFamilyIPv6 {
procFile = "/proc/net/tcp6"
}
case Network_UDP:
if dest.Address.Family() == AddressFamilyIPv4 {
procFile = "/proc/net/udp"
}
if dest.Address.Family() == AddressFamilyIPv6 {
procFile = "/proc/net/udp6"
}
default:
panic("Unsupported network type for process lookup.")
}
targetHexAddr, err := formatLittleEndianString(dest.Address, dest.Port)
if err != nil {
return 0, "", "", errors.New("failed to format address: ", err)
}
inode, err := findInodeInFile(procFile, targetHexAddr)
if err != nil {
return 0, "", "", errors.New("could not search in ", procFile).Base(err)
}
if inode == "" {
return 0, "", "", errors.New("connection for ", dest.Address, ":", dest.Port, " not found in ", procFile)
}
pidStr, err := findPidByInode(inode)
if err != nil {
return 0, "", "", errors.New("could not find PID for inode ", inode, ": ", err)
}
if pidStr == "" {
return 0, "", "", errors.New("no process found for inode ", inode)
}
absPath, err := getAbsPath(pidStr)
if err != nil {
return 0, "", "", errors.New("could not get process name for PID ", pidStr, ":", err)
}
nameSplit := strings.Split(absPath, "/")
procName := nameSplit[len(nameSplit)-1]
pid, err := strconv.Atoi(pidStr)
if err != nil {
return 0, "", "", errors.New("failed to parse PID: ", err)
}
return pid, procName, absPath, nil
}
func formatLittleEndianString(addr Address, port Port) (string, error) {
ip := addr.IP()
var ipBytes []byte
if addr.Family() == AddressFamilyIPv4 {
ipBytes = ip.To4()
} else {
ipBytes = ip.To16()
}
if ipBytes == nil {
return "", errors.New("invalid IP format for ", addr.Family(), ": ", ip)
}
for i, j := 0, len(ipBytes)-1; i < j; i, j = i+1, j-1 {
ipBytes[i], ipBytes[j] = ipBytes[j], ipBytes[i]
}
portHex := fmt.Sprintf("%04X", uint16(port))
ipHex := strings.ToUpper(hex.EncodeToString(ipBytes))
return fmt.Sprintf("%s:%s", ipHex, portHex), nil
}
func findInodeInFile(filePath, targetHexAddr string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) < 10 {
continue
}
localAddress := fields[1]
if localAddress == targetHexAddr {
inode := fields[9]
return inode, nil
}
}
return "", scanner.Err()
}
func findPidByInode(inode string) (string, error) {
procDir, err := os.ReadDir("/proc")
if err != nil {
return "", err
}
targetLink := "socket:[" + inode + "]"
for _, entry := range procDir {
if !entry.IsDir() {
continue
}
pid := entry.Name()
if _, err := strconv.Atoi(pid); err != nil {
continue
}
fdPath := fmt.Sprintf("/proc/%s/fd", pid)
fdDir, err := os.ReadDir(fdPath)
if err != nil {
continue
}
for _, fdEntry := range fdDir {
linkPath := fmt.Sprintf("%s/%s", fdPath, fdEntry.Name())
linkTarget, err := os.Readlink(linkPath)
if err != nil {
continue
}
if linkTarget == targetLink {
return pid, nil
}
}
}
return "", nil
}
func getAbsPath(pid string) (string, error) {
path := fmt.Sprintf("/proc/%s/exe", pid)
return os.Readlink(path)
}
+11
View File
@@ -0,0 +1,11 @@
//go:build !windows && !linux
package net
import (
"github.com/xtls/xray-core/common/errors"
)
func FindProcess(dest Destination) (int, string, string, error) {
return 0, "", "", errors.New("process lookup is not supported on this platform")
}
+243
View File
@@ -0,0 +1,243 @@
//go:build windows
package net
import (
"net/netip"
"path/filepath"
"strings"
"sync"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
"github.com/xtls/xray-core/common/errors"
)
const (
tcpTableFunc = "GetExtendedTcpTable"
tcpTablePidConn = 4
udpTableFunc = "GetExtendedUdpTable"
udpTablePid = 1
)
var (
getExTCPTable uintptr
getExUDPTable uintptr
once sync.Once
initErr error
)
func initWin32API() error {
h, err := windows.LoadLibrary("iphlpapi.dll")
if err != nil {
return errors.New("LoadLibrary iphlpapi.dll failed").Base(err)
}
getExTCPTable, err = windows.GetProcAddress(h, tcpTableFunc)
if err != nil {
return errors.New("GetProcAddress of ", tcpTableFunc, " failed").Base(err)
}
getExUDPTable, err = windows.GetProcAddress(h, udpTableFunc)
if err != nil {
return errors.New("GetProcAddress of ", udpTableFunc, " failed").Base(err)
}
return nil
}
func FindProcess(dest Destination) (PID int, Name string, AbsolutePath string, err error) {
once.Do(func() {
initErr = initWin32API()
})
if initErr != nil {
return 0, "", "", initErr
}
isLocal, err := IsLocal(dest.Address.IP())
if err != nil {
return 0, "", "", errors.New("failed to determine if address is local: ", err)
}
if !isLocal {
return 0, "", "", ErrNotLocal
}
if dest.Network != Network_TCP && dest.Network != Network_UDP {
panic("Unsupported network type for process lookup.")
}
// the core should never has a domain as source(?
if dest.Address.Family() == AddressFamilyDomain {
panic("Domain addresses are not supported for process lookup.")
}
var class int
var fn uintptr
switch dest.Network {
case Network_TCP:
fn = getExTCPTable
class = tcpTablePidConn
case Network_UDP:
fn = getExUDPTable
class = udpTablePid
default:
panic("Unsupported network type for process lookup.")
}
ip := dest.Address.IP()
port := int(dest.Port)
addr, ok := netip.AddrFromSlice(ip)
if !ok {
return 0, "", "", errors.New("invalid IP address")
}
addr = addr.Unmap()
family := windows.AF_INET
if addr.Is6() {
family = windows.AF_INET6
}
buf, err := getTransportTable(fn, family, class)
if err != nil {
return 0, "", "", err
}
s := newSearcher(dest.Network, dest.Address.Family())
pid, err := s.Search(buf, addr, uint16(port))
if err != nil {
return 0, "", "", err
}
NameWithPath, err := getExecPathFromPID(pid)
NameWithPath = filepath.ToSlash(NameWithPath)
// drop .exe and path
nameSplit := strings.Split(NameWithPath, "/")
procName := nameSplit[len(nameSplit)-1]
procName = strings.TrimSuffix(procName, ".exe")
return int(pid), procName, NameWithPath, err
}
type searcher struct {
itemSize int
port int
ip int
ipSize int
pid int
tcpState int
}
func (s *searcher) Search(b []byte, ip netip.Addr, port uint16) (uint32, error) {
n := int(readNativeUint32(b[:4]))
itemSize := s.itemSize
for i := range n {
row := b[4+itemSize*i : 4+itemSize*(i+1)]
if s.tcpState >= 0 {
tcpState := readNativeUint32(row[s.tcpState : s.tcpState+4])
// MIB_TCP_STATE_ESTAB, only check established connections for TCP
if tcpState != 5 {
continue
}
}
// according to MSDN, only the lower 16 bits of dwLocalPort are used and the port number is in network endian.
// this field can be illustrated as follows depends on different machine endianess:
// little endian: [ MSB LSB 0 0 ] interpret as native uint32 is ((LSB<<8)|MSB)
// big endian: [ 0 0 MSB LSB ] interpret as native uint32 is ((MSB<<8)|LSB)
// so we need an syscall.Ntohs on the lower 16 bits after read the port as native uint32
srcPort := syscall.Ntohs(uint16(readNativeUint32(row[s.port : s.port+4])))
if srcPort != port {
continue
}
srcIP, _ := netip.AddrFromSlice(row[s.ip : s.ip+s.ipSize])
srcIP = srcIP.Unmap()
// windows binds an unbound udp socket to 0.0.0.0/[::] while first sendto
if ip != srcIP && (!srcIP.IsUnspecified() || s.tcpState != -1) {
continue
}
pid := readNativeUint32(row[s.pid : s.pid+4])
return pid, nil
}
return 0, errors.New("not found")
}
func newSearcher(network Network, family AddressFamily) *searcher {
var itemSize, port, ip, ipSize, pid int
tcpState := -1
switch network {
case Network_TCP:
if family == AddressFamilyIPv4 {
// struct MIB_TCPROW_OWNER_PID
itemSize, port, ip, ipSize, pid, tcpState = 24, 8, 4, 4, 20, 0
}
if family == AddressFamilyIPv6 {
// struct MIB_TCP6ROW_OWNER_PID
itemSize, port, ip, ipSize, pid, tcpState = 56, 20, 0, 16, 52, 48
}
case Network_UDP:
if family == AddressFamilyIPv4 {
// struct MIB_UDPROW_OWNER_PID
itemSize, port, ip, ipSize, pid = 12, 4, 0, 4, 8
}
if family == AddressFamilyIPv6 {
// struct MIB_UDP6ROW_OWNER_PID
itemSize, port, ip, ipSize, pid = 28, 20, 0, 16, 24
}
}
return &searcher{
itemSize: itemSize,
port: port,
ip: ip,
ipSize: ipSize,
pid: pid,
tcpState: tcpState,
}
}
func getTransportTable(fn uintptr, family int, class int) ([]byte, error) {
for size, buf := uint32(8), make([]byte, 8); ; {
ptr := unsafe.Pointer(&buf[0])
err, _, _ := syscall.Syscall6(fn, 6, uintptr(ptr), uintptr(unsafe.Pointer(&size)), 0, uintptr(family), uintptr(class), 0)
switch err {
case 0:
return buf, nil
case uintptr(syscall.ERROR_INSUFFICIENT_BUFFER):
buf = make([]byte, size)
default:
return nil, errors.New("syscall error: ", int(err))
}
}
}
func readNativeUint32(b []byte) uint32 {
return *(*uint32)(unsafe.Pointer(&b[0]))
}
func getExecPathFromPID(pid uint32) (string, error) {
// kernel process starts with a colon in order to distinguish with normal processes
switch pid {
case 0:
// reserved pid for system idle process
return ":System Idle Process", nil
case 4:
// reserved pid for windows kernel image
return ":System", nil
}
h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, pid)
if err != nil {
return "", err
}
defer windows.CloseHandle(h)
buf := make([]uint16, syscall.MAX_LONG_PATH)
size := uint32(len(buf))
err = windows.QueryFullProcessImageName(h, 0, &buf[0], &size)
if err != nil {
return "", err
}
return syscall.UTF16ToString(buf[:size]), nil
}
+41 -1
View File
@@ -1,7 +1,13 @@
// Package net is a drop-in replacement to Golang's net package, with some more functionalities.
package net // import "github.com/xtls/xray-core/common/net"
import "time"
import (
"net"
"sync/atomic"
"time"
"github.com/xtls/xray-core/common/errors"
)
// defines the maximum time an idle TCP session can survive in the tunnel, so
// it should be consistent across HTTP versions and with other transports.
@@ -12,3 +18,37 @@ const QuicgoH3KeepAlivePeriod = 10 * time.Second
// consistent with chrome
const ChromeH2KeepAlivePeriod = 45 * time.Second
var ErrNotLocal = errors.New("the source address is not from local machine.")
type localIPCacheEntry struct {
addrs []net.Addr
lastUpdate time.Time
}
var localIPCache = atomic.Pointer[localIPCacheEntry]{}
func IsLocal(ip net.IP) (bool, error) {
var addrs []net.Addr
if entry := localIPCache.Load(); entry == nil || time.Since(entry.lastUpdate) > time.Minute {
var err error
addrs, err = net.InterfaceAddrs()
if err != nil {
return false, err
}
localIPCache.Store(&localIPCacheEntry{
addrs: addrs,
lastUpdate: time.Now(),
})
} else {
addrs = entry.addrs
}
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok {
if ipnet.IP.Equal(ip) {
return true, nil
}
}
}
return false, nil
}
+10
View File
@@ -87,6 +87,16 @@ func PortListFromProto(l *PortList) MemoryPortList {
return mpl
}
func (l *PortList) Ports() []uint32 {
var ports []uint32
for _, r := range l.Range {
for i := uint32(r.From); i <= uint32(r.To); i++ {
ports = append(ports, i)
}
}
return ports
}
func (mpl MemoryPortList) Contains(port Port) bool {
for _, pr := range mpl {
if pr.Contains(port) {
+4
View File
@@ -29,6 +29,10 @@ func ReadAsset(file string) ([]byte, error) {
return ReadFile(platform.GetAssetLocation(file))
}
func OpenAsset(file string) (io.ReadCloser, error) {
return NewFileReader(platform.GetAssetLocation(file))
}
func ReadCert(file string) ([]byte, error) {
if filepath.IsAbs(file) {
return ReadFile(file)
+2
View File
@@ -22,6 +22,8 @@ const (
BrowserDialerAddress = "xray.browser.dialer"
XUDPLog = "xray.xudp.show"
XUDPBaseKey = "xray.xudp.basekey"
TunFdKey = "xray.tun.fd"
)
type EnvFlag struct {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"encoding/binary"
"io"
"github.com/quic-go/quic-go/quicvarint"
"github.com/apernet/quic-go/quicvarint"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
+3 -2
View File
@@ -6,6 +6,7 @@ import (
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
@@ -87,10 +88,10 @@ func Organization(org string) Option {
}
}
func MustGenerate(parent *Certificate, opts ...Option) *Certificate {
func MustGenerate(parent *Certificate, opts ...Option) (*Certificate, [32]byte) {
cert, err := Generate(parent, opts...)
common.Must(err)
return cert
return cert, sha256.Sum256(cert.Certificate)
}
func publicKey(priv interface{}) interface{} {
+27 -3
View File
@@ -2,10 +2,12 @@ package singbridge
import (
"context"
"time"
B "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/transport"
@@ -29,6 +31,8 @@ type PacketConnWrapper struct {
cached buf.MultiBuffer
}
// This ReadPacket implemented a timeout to avoid goroutine leak like PipeConnWrapper.Read()
// as a temporarily solution
func (w *PacketConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) {
if w.cached != nil {
mb, bb := buf.SplitFirst(w.cached)
@@ -47,10 +51,30 @@ func (w *PacketConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) {
return ToSocksaddr(destination), nil
}
}
mb, err := w.ReadMultiBuffer()
if err != nil {
return M.Socksaddr{}, err
// timeout
type readResult struct {
mb buf.MultiBuffer
err error
}
c := make(chan readResult, 1)
go func() {
mb, err := w.ReadMultiBuffer()
c <- readResult{mb: mb, err: err}
}()
var mb buf.MultiBuffer
select {
case <-time.After(60 * time.Second):
common.Close(w.Reader)
common.Interrupt(w.Reader)
return M.Socksaddr{}, buf.ErrReadTimeout
case result := <-c:
if result.err != nil {
return M.Socksaddr{}, result.err
}
mb = result.mb
}
nb, bb := buf.SplitFirst(mb)
if bb == nil {
return M.Socksaddr{}, nil
+2 -1
View File
@@ -1,6 +1,7 @@
package strmatcher
import (
"errors"
"regexp"
)
@@ -44,7 +45,7 @@ func (t Type) New(pattern string) (Matcher, error) {
pattern: r,
}, nil
default:
panic("Unknown type")
return nil, errors.New("unk type")
}
}
+5 -1
View File
@@ -85,10 +85,14 @@ func ParseString(str string) (UUID, error) {
b := uuid.Bytes()
for _, byteGroup := range byteGroups {
if text[0] == '-' {
if len(text) > 0 && text[0] == '-' {
text = text[1:]
}
if len(text) < byteGroup {
return uuid, errors.New("invalid UUID: ", str)
}
if _, err := hex.Decode(b[:byteGroup/2], text[:byteGroup]); err != nil {
return uuid, err
}
+5
View File
@@ -44,6 +44,11 @@ func TestParseString(t *testing.T) {
if err == nil {
t.Fatal("Expect error but nil")
}
_, err = ParseString("2418d087-648d-4990-86e8-19dca1d0")
if err == nil {
t.Fatal("Expect error but nil")
}
}
func TestNewUUID(t *testing.T) {
+2 -1
View File
@@ -35,6 +35,7 @@ func init() {
if strings.ToLower(platform.NewEnvFlag(platform.XUDPLog).GetValue(func() string { return "" })) == "true" {
Show = true
}
BaseKey = make([]byte, 32)
rand.Read(BaseKey)
go func() {
time.Sleep(100 * time.Millisecond) // this is not nice, but need to give some time for Android to setup ENV
@@ -52,7 +53,7 @@ func GetGlobalID(ctx context.Context) (globalID [8]byte) {
return
}
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.Network == net.Network_UDP &&
(inbound.Name == "dokodemo-door" || inbound.Name == "socks" || inbound.Name == "shadowsocks") {
(inbound.Name == "dokodemo-door" || inbound.Name == "socks" || inbound.Name == "shadowsocks" || inbound.Name == "tun") {
h := blake3.New(8, BaseKey)
h.Write([]byte(inbound.Source.String()))
copy(globalID[:], h.Sum(nil))
+5 -1
View File
@@ -64,7 +64,11 @@ func GetMergedConfig(args cmdarg.Arg) (string, error) {
var files []*ConfigSource
supported := []string{"json", "yaml", "toml"}
for _, file := range args {
format := GetFormat(file)
format := "json"
if file != "stdin:" {
format = GetFormat(file)
}
if slices.Contains(supported, format) {
files = append(files, &ConfigSource{
Name: file,
+3 -3
View File
@@ -17,9 +17,9 @@ import (
)
var (
Version_x byte = 25
Version_y byte = 12
Version_z byte = 8
Version_x byte = 26
Version_y byte = 1
Version_z byte = 23
)
var (
-6
View File
@@ -26,9 +26,3 @@ type Dispatcher interface {
func DispatcherType() interface{} {
return (*Dispatcher)(nil)
}
// Just for type assertion
type WrapLinkDispatcher interface {
Dispatcher
WrapLink(ctx context.Context, link *transport.Link) *transport.Link
}
+6
View File
@@ -16,6 +16,7 @@ type Router interface {
PickRoute(ctx Context) (Route, error)
AddRule(config *serial.TypedMessage, shouldAppend bool) error
RemoveRule(tag string) error
ListRule() []Route
}
// Route is the routing result of Router feature.
@@ -65,6 +66,11 @@ func (DefaultRouter) RemoveRule(tag string) error {
return common.ErrNoClue
}
// ListRule implements Router.
func (DefaultRouter) ListRule() []Route {
return nil
}
// Start implements common.Runnable.
func (DefaultRouter) Start() error {
return nil
+8
View File
@@ -98,6 +98,9 @@ type Manager interface {
UnregisterChannel(string) error
// GetChannel returns a channel by its identifier.
GetChannel(string) Channel
// GetAllOnlineUsers returns all online users from all OnlineMaps.
GetAllOnlineUsers() []string
}
// GetOrRegisterCounter tries to get the StatCounter first. If not exist, it then tries to create a new counter.
@@ -190,6 +193,11 @@ func (NoopManager) GetChannel(string) Channel {
return nil
}
// GetAllOnlineUsers implements Manager.
func (NoopManager) GetAllOnlineUsers() []string {
return nil
}
// Start implements common.Runnable.
func (NoopManager) Start() error { return nil }
+18 -21
View File
@@ -1,34 +1,34 @@
module github.com/xtls/xray-core
go 1.25
go 1.25.6
require (
github.com/cloudflare/circl v1.6.1
github.com/apernet/quic-go v0.57.2-0.20260111184307-eec823306178
github.com/cloudflare/circl v1.6.3
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
github.com/golang/mock v1.7.0-rc.1
github.com/google/go-cmp v0.7.0
github.com/gorilla/websocket v1.5.3
github.com/miekg/dns v1.1.68
github.com/miekg/dns v1.1.72
github.com/pelletier/go-toml v1.9.5
github.com/pires/go-proxyproto v0.8.1
github.com/quic-go/quic-go v0.57.1
github.com/refraction-networking/utls v1.8.1
github.com/pires/go-proxyproto v0.9.2
github.com/refraction-networking/utls v1.8.2
github.com/sagernet/sing v0.5.1
github.com/sagernet/sing-shadowsocks v0.2.7
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771
github.com/stretchr/testify v1.11.1
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
github.com/vishvananda/netlink v1.3.1
github.com/xtls/reality v0.0.0-20251014195629-e4eec4520535
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.46.0
golang.org/x/net v0.48.0
golang.org/x/crypto v0.47.0
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
golang.org/x/net v0.49.0
golang.org/x/sync v0.19.0
golang.org/x/sys v0.39.0
golang.org/x/sys v0.40.0
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
google.golang.org/grpc v1.77.0
google.golang.org/protobuf v1.36.10
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
google.golang.org/grpc v1.78.0
google.golang.org/protobuf v1.36.11
gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0
h12.io/socks v1.0.3
lukechampine.com/blake3 v1.4.1
)
@@ -36,7 +36,6 @@ require (
require (
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/juju/ratelimit v1.0.2 // indirect
github.com/klauspost/compress v1.17.4 // indirect
@@ -44,14 +43,12 @@ require (
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/vishvananda/netns v0.0.5 // indirect
golang.org/x/mod v0.30.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/mod v0.31.0 // indirect
golang.org/x/text v0.33.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.39.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
golang.org/x/tools v0.40.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+32 -43
View File
@@ -1,13 +1,12 @@
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/apernet/quic-go v0.57.2-0.20260111184307-eec823306178 h1:bSq8n+gX4oO/qnM3MKf4kroW75n+phO9Qp6nigJKZ1E=
github.com/apernet/quic-go v0.57.2-0.20260111184307-eec823306178/go.mod h1:N1WIjPphkqs4efXWuyDNQ6OjjIK04vM3h+bEgwV+eVU=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E=
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
@@ -38,38 +37,28 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0=
github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
github.com/pires/go-proxyproto v0.9.2 h1:H1UdHn695zUVVmB0lQ354lOWHOy6TZSpzBl3tgN0s1U=
github.com/pires/go-proxyproto v0.9.2/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10=
github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s=
github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkrMJI0pRUOCAo=
github.com/refraction-networking/utls v1.8.1/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/refraction-networking/utls v1.8.2 h1:j4Q1gJj0xngdeH+Ox/qND11aEfhpgoEvV+S9iJ2IdQo=
github.com/refraction-networking/utls v1.8.2/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y=
github.com/sagernet/sing v0.5.1/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
@@ -95,16 +84,18 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
@@ -116,21 +107,21 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -140,24 +131,22 @@ golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uI
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda h1:i/Q+bfisr7gq6feoJnS/DlpdwEL4ihp41fvRiM3Ork0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 h1:sfK5nHuG7lRFZ2FdTT3RimOqWBg8IrVm+/Vko1FVOsk=
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g=
gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0 h1:Lk6hARj5UPY47dBep70OD/TIMwikJ5fGUGX0Rm3Xigk=
gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0/go.mod h1:QkHjoMIBaYtpVufgwv3keYAbln78mBoCuShZrPrer1Q=
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
+4 -3
View File
@@ -11,12 +11,13 @@ import (
statsservice "github.com/xtls/xray-core/app/stats/command"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
)
type APIConfig struct {
Tag string `json:"tag"`
Listen string `json:"listen"`
Services []string `json:"services"`
Tag string `json:"tag"`
Listen string `json:"listen"`
Services types.Listable[string] `json:"services"`
}
func (c *APIConfig) Build() (*commander.Config, error) {
@@ -1,4 +1,4 @@
package duration
package types
import (
"encoding/json"
@@ -1,20 +1,20 @@
package duration_test
package types_test
import (
"encoding/json"
"testing"
"time"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
)
type testWithDuration struct {
Duration duration.Duration
Duration types.Duration
}
func TestDurationJSON(t *testing.T) {
expected := &testWithDuration{
Duration: duration.Duration(time.Hour),
Duration: types.Duration(time.Hour),
}
data, err := json.Marshal(expected)
if err != nil {
+47
View File
@@ -0,0 +1,47 @@
package types
import (
"encoding/json"
"reflect"
"slices"
"strings"
)
// Listable allows a field to be unmarshalled from a single object or a list of objects.
// If the json input is a single object, it will be stored as a slice with one element.
// If the json input is null or empty or a single empty object, it will be nil.
type Listable[T any] []T
func (l *Listable[T]) UnmarshalJSON(data []byte) error {
var v T
if len(data) != 0 && !slices.Equal(data, []byte("null")) && data[0] != '[' {
if err := json.Unmarshal(data, &v); err == nil {
// make the list nil if the single value is the zero value
var zero T
if reflect.DeepEqual(v, zero) {
return nil
}
*l = []T{v}
return err
}
}
return json.Unmarshal(data, (*[]T)(l))
}
// ListableSimpleString is like Listable[string], but able to separate by `~`
type ListableSimpleString []string
func (l *ListableSimpleString) UnmarshalJSON(data []byte) error {
var v string
if len(data) != 0 && !slices.Equal(data, []byte("null")) && data[0] != '[' {
if err := json.Unmarshal(data, &v); err == nil {
if v == "" {
// make the list nil if the single value is empty string
return nil
}
*l = strings.Split(v, "~")
return nil
}
}
return json.Unmarshal(data, (*[]string)(l))
}
+159
View File
@@ -0,0 +1,159 @@
package types_test
import (
"encoding/json"
"slices"
"testing"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
)
type TestGroup[T any] struct {
name string
input string
expected []T
}
// intentionally to be so chaos
var rawJson = `{
"field":
["value1",
"value2", "value3"
]
}`
func TestListableUnmarshal(t *testing.T) {
type TestStruct struct {
Field types.Listable[string] `json:"field"`
}
tests := []TestGroup[string]{
{
name: "SingleString",
input: `{"field": "hello"}`,
expected: []string{"hello"},
},
{
name: "ArrayString",
input: `{"field": ["value1", "value2", "value3"]}`,
expected: []string{"value1", "value2", "value3"},
},
{
name: "ComplexArray",
input: rawJson,
expected: []string{"value1", "value2", "value3"},
},
{
name: "SingleStringWithSpace",
input: `{"field": "hello" }`,
expected: []string{"hello"},
},
{
name: "ArrayWithSpace",
input: `{"field": [ "a", "b" ] }`,
expected: []string{"a", "b"},
},
{
name: "SingleEmptyString",
input: `{"field": ""}`,
expected: nil,
},
{
name: "Null",
input: `{"field": null}`,
expected: nil,
},
{
name: "Missing (default)",
input: `{}`,
expected: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var ts TestStruct
err := json.Unmarshal([]byte(tt.input), &ts)
if err != nil {
t.Fatalf("Unmarshal failed: %v", err)
}
if !slices.Equal([]string(ts.Field), tt.expected) {
t.Errorf("Expected %v, got %v", tt.expected, ts.Field)
}
})
}
}
func TestListableInt(t *testing.T) {
tests := []TestGroup[int]{
{
name: "SingleInt",
input: `123`,
expected: []int{123},
},
{
name: "ArrayInt",
input: `[1, 2]`,
expected: []int{1, 2},
},
{
name: "Null",
input: `null`,
expected: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var l types.Listable[int]
err := json.Unmarshal([]byte(tt.input), &l)
if err != nil {
t.Fatalf("Unmarshal failed: %v", err)
}
if !slices.Equal([]int(l), tt.expected) {
t.Errorf("Expected %v, got %v", tt.expected, l)
}
})
}
}
func TestListableSimpleString(t *testing.T) {
type TestStruct struct {
Field types.ListableSimpleString `json:"field"`
}
tests := []TestGroup[string]{
{
name: "SingleString",
input: `{"field": "singleValue"}`,
expected: []string{"singleValue"},
},
{
name: "ArrayString",
input: `{"field": ["value1", "value2", "value3"]}`,
expected: []string{"value1", "value2", "value3"},
},
{
name: "SingleEmptyString",
input: `{"field": ""}`,
expected: nil,
},
{
name: "WaveSplit",
input: `{"field": "value1~value2~value3"}`,
expected: []string{"value1", "value2", "value3"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var ts TestStruct
err := json.Unmarshal([]byte(tt.input), &ts)
if err != nil {
t.Fatalf("Unmarshal failed: %v", err)
}
if !slices.Equal([]string(ts.Field), tt.expected) {
t.Errorf("Expected %v, got %v", tt.expected, ts.Field)
}
})
}
}
+43 -42
View File
@@ -13,24 +13,25 @@ import (
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
)
type NameServerConfig struct {
Address *Address `json:"address"`
ClientIP *Address `json:"clientIp"`
Port uint16 `json:"port"`
SkipFallback bool `json:"skipFallback"`
Domains []string `json:"domains"`
ExpectedIPs StringList `json:"expectedIPs"`
ExpectIPs StringList `json:"expectIPs"`
QueryStrategy string `json:"queryStrategy"`
Tag string `json:"tag"`
TimeoutMs uint64 `json:"timeoutMs"`
DisableCache *bool `json:"disableCache"`
ServeStale *bool `json:"serveStale"`
ServeExpiredTTL *uint32 `json:"serveExpiredTTL"`
FinalQuery bool `json:"finalQuery"`
UnexpectedIPs StringList `json:"unexpectedIPs"`
Address *Address `json:"address"`
ClientIP *Address `json:"clientIp"`
Port uint16 `json:"port"`
SkipFallback bool `json:"skipFallback"`
Domains types.Listable[string] `json:"domains"`
ExpectedIPs StringList `json:"expectedIPs"`
ExpectIPs StringList `json:"expectIPs"`
QueryStrategy string `json:"queryStrategy"`
Tag string `json:"tag"`
TimeoutMs uint64 `json:"timeoutMs"`
DisableCache *bool `json:"disableCache"`
ServeStale *bool `json:"serveStale"`
ServeExpiredTTL *uint32 `json:"serveExpiredTTL"`
FinalQuery bool `json:"finalQuery"`
UnexpectedIPs StringList `json:"unexpectedIPs"`
}
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
@@ -42,21 +43,21 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
}
var advanced struct {
Address *Address `json:"address"`
ClientIP *Address `json:"clientIp"`
Port uint16 `json:"port"`
SkipFallback bool `json:"skipFallback"`
Domains []string `json:"domains"`
ExpectedIPs StringList `json:"expectedIPs"`
ExpectIPs StringList `json:"expectIPs"`
QueryStrategy string `json:"queryStrategy"`
Tag string `json:"tag"`
TimeoutMs uint64 `json:"timeoutMs"`
DisableCache *bool `json:"disableCache"`
ServeStale *bool `json:"serveStale"`
ServeExpiredTTL *uint32 `json:"serveExpiredTTL"`
FinalQuery bool `json:"finalQuery"`
UnexpectedIPs StringList `json:"unexpectedIPs"`
Address *Address `json:"address"`
ClientIP *Address `json:"clientIp"`
Port uint16 `json:"port"`
SkipFallback bool `json:"skipFallback"`
Domains types.Listable[string] `json:"domains"`
ExpectedIPs StringList `json:"expectedIPs"`
ExpectIPs StringList `json:"expectIPs"`
QueryStrategy string `json:"queryStrategy"`
Tag string `json:"tag"`
TimeoutMs uint64 `json:"timeoutMs"`
DisableCache *bool `json:"disableCache"`
ServeStale *bool `json:"serveStale"`
ServeExpiredTTL *uint32 `json:"serveExpiredTTL"`
FinalQuery bool `json:"finalQuery"`
UnexpectedIPs StringList `json:"unexpectedIPs"`
}
if err := json.Unmarshal(data, &advanced); err == nil {
c.Address = advanced.Address
@@ -196,18 +197,18 @@ var typeMap = map[router.Domain_Type]dns.DomainMatchingType{
// DNSConfig is a JSON serializable object for dns.Config.
type DNSConfig struct {
Servers []*NameServerConfig `json:"servers"`
Hosts *HostsWrapper `json:"hosts"`
ClientIP *Address `json:"clientIp"`
Tag string `json:"tag"`
QueryStrategy string `json:"queryStrategy"`
DisableCache bool `json:"disableCache"`
ServeStale bool `json:"serveStale"`
ServeExpiredTTL uint32 `json:"serveExpiredTTL"`
DisableFallback bool `json:"disableFallback"`
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
EnableParallelQuery bool `json:"enableParallelQuery"`
UseSystemHosts bool `json:"useSystemHosts"`
Servers types.Listable[*NameServerConfig] `json:"servers"`
Hosts *HostsWrapper `json:"hosts"`
ClientIP *Address `json:"clientIp"`
Tag string `json:"tag"`
QueryStrategy string `json:"queryStrategy"`
DisableCache bool `json:"disableCache"`
ServeStale bool `json:"serveStale"`
ServeExpiredTTL uint32 `json:"serveExpiredTTL"`
DisableFallback bool `json:"disableFallback"`
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
EnableParallelQuery bool `json:"enableParallelQuery"`
UseSystemHosts bool `json:"useSystemHosts"`
}
type HostAddress struct {
+7 -6
View File
@@ -3,17 +3,18 @@ package conf
import (
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/proxy/dns"
"google.golang.org/protobuf/proto"
)
type DNSOutboundConfig struct {
Network Network `json:"network"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
UserLevel uint32 `json:"userLevel"`
NonIPQuery string `json:"nonIPQuery"`
BlockTypes []int32 `json:"blockTypes"`
Network Network `json:"network"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
UserLevel uint32 `json:"userLevel"`
NonIPQuery string `json:"nonIPQuery"`
BlockTypes types.Listable[int32] `json:"blockTypes"`
}
func (c *DNSOutboundConfig) Build() (proto.Message, error) {
+10 -9
View File
@@ -9,20 +9,21 @@ import (
"github.com/xtls/xray-core/common/errors"
v2net "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/proxy/freedom"
"google.golang.org/protobuf/proto"
"github.com/xtls/xray-core/transport/internet"
"google.golang.org/protobuf/proto"
)
type FreedomConfig struct {
TargetStrategy string `json:"targetStrategy"`
DomainStrategy string `json:"domainStrategy"`
Redirect string `json:"redirect"`
UserLevel uint32 `json:"userLevel"`
Fragment *Fragment `json:"fragment"`
Noise *Noise `json:"noise"`
Noises []*Noise `json:"noises"`
ProxyProtocol uint32 `json:"proxyProtocol"`
TargetStrategy string `json:"targetStrategy"`
DomainStrategy string `json:"domainStrategy"`
Redirect string `json:"redirect"`
UserLevel uint32 `json:"userLevel"`
Fragment *Fragment `json:"fragment"`
Noise *Noise `json:"noise"`
Noises types.Listable[*Noise] `json:"noises"`
ProxyProtocol uint32 `json:"proxyProtocol"`
}
type Fragment struct {
+15 -14
View File
@@ -6,6 +6,7 @@ import (
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/proxy/http"
"google.golang.org/protobuf/proto"
)
@@ -23,9 +24,9 @@ func (v *HTTPAccount) Build() *http.Account {
}
type HTTPServerConfig struct {
Accounts []*HTTPAccount `json:"accounts"`
Transparent bool `json:"allowTransparent"`
UserLevel uint32 `json:"userLevel"`
Accounts types.Listable[*HTTPAccount] `json:"accounts"`
Transparent bool `json:"allowTransparent"`
UserLevel uint32 `json:"userLevel"`
}
func (c *HTTPServerConfig) Build() (proto.Message, error) {
@@ -45,20 +46,20 @@ func (c *HTTPServerConfig) Build() (proto.Message, error) {
}
type HTTPRemoteConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users []json.RawMessage `json:"users"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users types.Listable[json.RawMessage] `json:"users"`
}
type HTTPClientConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level uint32 `json:"level"`
Email string `json:"email"`
Username string `json:"user"`
Password string `json:"pass"`
Servers []*HTTPRemoteConfig `json:"servers"`
Headers map[string]string `json:"headers"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level uint32 `json:"level"`
Email string `json:"email"`
Username string `json:"user"`
Password string `json:"pass"`
Servers types.Listable[*HTTPRemoteConfig] `json:"servers"`
Headers map[string]string `json:"headers"`
}
func (v *HTTPClientConfig) Build() (proto.Message, error) {
+29
View File
@@ -0,0 +1,29 @@
package conf
import (
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/proxy/hysteria"
"google.golang.org/protobuf/proto"
)
type HysteriaClientConfig struct {
Version int32 `json:"version"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
}
func (c *HysteriaClientConfig) Build() (proto.Message, error) {
if c.Version != 2 {
return nil, errors.New("version != 2")
}
config := &hysteria.ClientConfig{}
config.Version = c.Version
config.Server = &protocol.ServerEndpoint{
Address: c.Address.Build(),
Port: uint32(c.Port),
}
return config, nil
}
+7 -8
View File
@@ -1,19 +1,18 @@
package conf
import (
"google.golang.org/protobuf/proto"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/app/observatory/burst"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"google.golang.org/protobuf/proto"
)
type ObservatoryConfig struct {
SubjectSelector []string `json:"subjectSelector"`
ProbeURL string `json:"probeURL"`
ProbeInterval duration.Duration `json:"probeInterval"`
EnableConcurrency bool `json:"enableConcurrency"`
SubjectSelector types.Listable[string] `json:"subjectSelector"`
ProbeURL string `json:"probeURL"`
ProbeInterval types.Duration `json:"probeInterval"`
EnableConcurrency bool `json:"enableConcurrency"`
}
func (o *ObservatoryConfig) Build() (proto.Message, error) {
@@ -21,7 +20,7 @@ func (o *ObservatoryConfig) Build() (proto.Message, error) {
}
type BurstObservatoryConfig struct {
SubjectSelector []string `json:"subjectSelector"`
SubjectSelector types.Listable[string] `json:"subjectSelector"`
// health check settings
HealthCheck *healthCheckSettings `json:"pingConfig,omitempty"`
}
+3 -2
View File
@@ -2,6 +2,7 @@ package conf
import (
"github.com/xtls/xray-core/app/reverse"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"google.golang.org/protobuf/proto"
)
@@ -30,8 +31,8 @@ func (c *PortalConfig) Build() (*reverse.PortalConfig, error) {
}
type ReverseConfig struct {
Bridges []BridgeConfig `json:"bridges"`
Portals []PortalConfig `json:"portals"`
Bridges types.Listable[BridgeConfig] `json:"bridges"`
Portals types.Listable[PortalConfig] `json:"portals"`
}
func (c *ReverseConfig) Build() (proto.Message, error) {
+97 -94
View File
@@ -1,7 +1,10 @@
package conf
import (
"bufio"
"bytes"
"encoding/json"
"io"
"runtime"
"strconv"
"strings"
@@ -11,6 +14,7 @@ import (
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"google.golang.org/protobuf/proto"
)
@@ -71,9 +75,9 @@ func (r *BalancingRule) Build() (*router.BalancingRule, error) {
}
type RouterConfig struct {
RuleList []json.RawMessage `json:"rules"`
DomainStrategy *string `json:"domainStrategy"`
Balancers []*BalancingRule `json:"balancers"`
RuleList types.Listable[json.RawMessage] `json:"rules"`
DomainStrategy *string `json:"domainStrategy"`
Balancers types.Listable[*BalancingRule] `json:"balancers"`
}
func (c *RouterConfig) getDomainStrategy() router.Config_DomainStrategy {
@@ -102,7 +106,7 @@ func (c *RouterConfig) Build() (*router.Config, error) {
}
for _, rawRule := range rawRuleList {
rule, err := ParseRule(rawRule)
rule, err := parseRule(rawRule)
if err != nil {
return nil, err
}
@@ -125,7 +129,7 @@ type RouterRule struct {
BalancerTag string `json:"balancerTag"`
}
func ParseIP(s string) (*router.CIDR, error) {
func parseIP(s string) (*router.CIDR, error) {
var addr, mask string
i := strings.Index(s, "/")
if i < 0 {
@@ -173,125 +177,119 @@ func ParseIP(s string) (*router.CIDR, error) {
}
}
func loadGeoIP(code string) ([]*router.CIDR, error) {
return loadIP("geoip.dat", code)
}
var (
FileCache = make(map[string][]byte)
IPCache = make(map[string]*router.GeoIP)
SiteCache = make(map[string]*router.GeoSite)
)
func loadFile(file string) ([]byte, error) {
if FileCache[file] == nil {
bs, err := filesystem.ReadAsset(file)
if err != nil {
return nil, errors.New("failed to open file: ", file).Base(err)
}
if len(bs) == 0 {
return nil, errors.New("empty file: ", file)
}
// Do not cache file, may save RAM when there
// are many files, but consume CPU each time.
return bs, nil
FileCache[file] = bs
func loadFile(file, code string) ([]byte, error) {
runtime.GC()
r, err := filesystem.OpenAsset(file)
defer r.Close()
if err != nil {
return nil, errors.New("failed to open file: ", file).Base(err)
}
return FileCache[file], nil
bs := find(r, []byte(code))
if bs == nil {
return nil, errors.New("code not found in ", file, ": ", code)
}
return bs, nil
}
func loadIP(file, code string) ([]*router.CIDR, error) {
index := file + ":" + code
if IPCache[index] == nil {
bs, err := loadFile(file)
if err != nil {
return nil, errors.New("failed to load file: ", file).Base(err)
}
bs = find(bs, []byte(code))
if bs == nil {
return nil, errors.New("code not found in ", file, ": ", code)
}
var geoip router.GeoIP
if err := proto.Unmarshal(bs, &geoip); err != nil {
return nil, errors.New("error unmarshal IP in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return geoip.Cidr, nil // do not cache geoip
IPCache[index] = &geoip
bs, err := loadFile(file, code)
if err != nil {
return nil, err
}
return IPCache[index].Cidr, nil
var geoip router.GeoIP
if err := proto.Unmarshal(bs, &geoip); err != nil {
return nil, errors.New("error unmarshal IP in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return geoip.Cidr, nil
}
func loadSite(file, code string) ([]*router.Domain, error) {
index := file + ":" + code
if SiteCache[index] == nil {
bs, err := loadFile(file)
if err != nil {
return nil, errors.New("failed to load file: ", file).Base(err)
}
bs = find(bs, []byte(code))
if bs == nil {
return nil, errors.New("list not found in ", file, ": ", code)
}
var geosite router.GeoSite
if err := proto.Unmarshal(bs, &geosite); err != nil {
return nil, errors.New("error unmarshal Site in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return geosite.Domain, nil // do not cache geosite
SiteCache[index] = &geosite
bs, err := loadFile(file, code)
if err != nil {
return nil, err
}
return SiteCache[index].Domain, nil
var geosite router.GeoSite
if err := proto.Unmarshal(bs, &geosite); err != nil {
return nil, errors.New("error unmarshal Site in ", file, ": ", code).Base(err)
}
defer runtime.GC() // or debug.FreeOSMemory()
return geosite.Domain, nil
}
func DecodeVarint(buf []byte) (x uint64, n int) {
func decodeVarint(r *bufio.Reader) (uint64, error) {
var x uint64
for shift := uint(0); shift < 64; shift += 7 {
if n >= len(buf) {
return 0, 0
b, err := r.ReadByte()
if err != nil {
return 0, err
}
b := uint64(buf[n])
n++
x |= (b & 0x7F) << shift
x |= (uint64(b) & 0x7F) << shift
if (b & 0x80) == 0 {
return x, n
return x, nil
}
}
// The number is too large to represent in a 64-bit value.
return 0, 0
return 0, errors.New("varint overflow")
}
func find(data, code []byte) []byte {
func find(r io.Reader, code []byte) []byte {
codeL := len(code)
if codeL == 0 {
return nil
}
br := bufio.NewReaderSize(r, 64*1024)
need := 2 + codeL
prefixBuf := make([]byte, need)
for {
dataL := len(data)
if dataL < 2 {
if _, err := br.ReadByte(); err != nil {
return nil
}
x, y := DecodeVarint(data[1:])
if x == 0 && y == 0 {
x, err := decodeVarint(br)
if err != nil {
return nil
}
headL, bodyL := 1+y, int(x)
dataL -= headL
if dataL < bodyL {
bodyL := int(x)
if bodyL <= 0 {
return nil
}
data = data[headL:]
if int(data[1]) == codeL {
for i := 0; i < codeL && data[2+i] == code[i]; i++ {
if i+1 == codeL {
return data[:bodyL]
}
prefixL := bodyL
if prefixL > need {
prefixL = need
}
prefix := prefixBuf[:prefixL]
if _, err := io.ReadFull(br, prefix); err != nil {
return nil
}
match := false
if bodyL >= need {
if int(prefix[1]) == codeL && bytes.Equal(prefix[2:need], code) {
match = true
}
}
if dataL == bodyL {
return nil
remain := bodyL - prefixL
if match {
out := make([]byte, bodyL)
copy(out, prefix)
if remain > 0 {
if _, err := io.ReadFull(br, out[prefixL:]); err != nil {
return nil
}
}
return out
}
if remain > 0 {
if _, err := br.Discard(remain); err != nil {
return nil
}
}
data = data[bodyL:]
}
}
@@ -447,7 +445,7 @@ func ToCidrList(ips StringList) ([]*router.GeoIP, error) {
if len(country) == 0 {
return nil, errors.New("empty country name in rule")
}
geoip, err := loadGeoIP(strings.ToUpper(country))
geoip, err := loadIP("geoip.dat", strings.ToUpper(country))
if err != nil {
return nil, errors.New("failed to load GeoIP: ", country).Base(err)
}
@@ -501,7 +499,7 @@ func ToCidrList(ips StringList) ([]*router.GeoIP, error) {
continue
}
ipRule, err := ParseIP(ip)
ipRule, err := parseIP(ip)
if err != nil {
return nil, errors.New("invalid IP: ", ip).Base(err)
}
@@ -535,6 +533,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
Attributes map[string]string `json:"attrs"`
LocalIP *StringList `json:"localIP"`
LocalPort *PortList `json:"localPort"`
Process *StringList `json:"process"`
}
rawFieldRule := new(RawFieldRule)
err := json.Unmarshal(msg, rawFieldRule)
@@ -647,10 +646,14 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
rule.Attributes = rawFieldRule.Attributes
}
if rawFieldRule.Process != nil && len(*rawFieldRule.Process) > 0 {
rule.Process = *rawFieldRule.Process
}
return rule, nil
}
func ParseRule(msg json.RawMessage) (*router.RoutingRule, error) {
func parseRule(msg json.RawMessage) (*router.RoutingRule, error) {
rawRule := new(RouterRule)
err := json.Unmarshal(msg, rawRule)
if err != nil {
+11 -11
View File
@@ -1,12 +1,12 @@
package conf
import (
"google.golang.org/protobuf/proto"
"strings"
"github.com/xtls/xray-core/app/observatory/burst"
"github.com/xtls/xray-core/app/router"
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"google.golang.org/protobuf/proto"
)
const (
@@ -34,25 +34,25 @@ func (v *strategyEmptyConfig) Build() (proto.Message, error) {
type strategyLeastLoadConfig struct {
// weight settings
Costs []*router.StrategyWeight `json:"costs,omitempty"`
Costs types.Listable[*router.StrategyWeight] `json:"costs,omitempty"`
// ping rtt baselines
Baselines []duration.Duration `json:"baselines,omitempty"`
Baselines types.Listable[types.Duration] `json:"baselines,omitempty"`
// expected nodes count to select
Expected int32 `json:"expected,omitempty"`
// max acceptable rtt, filter away high delay nodes. default 0
MaxRTT duration.Duration `json:"maxRTT,omitempty"`
MaxRTT types.Duration `json:"maxRTT,omitempty"`
// acceptable failure rate
Tolerance float64 `json:"tolerance,omitempty"`
}
// healthCheckSettings holds settings for health Checker
type healthCheckSettings struct {
Destination string `json:"destination"`
Connectivity string `json:"connectivity"`
Interval duration.Duration `json:"interval"`
SamplingCount int `json:"sampling"`
Timeout duration.Duration `json:"timeout"`
HttpMethod string `json:"httpMethod"`
Destination string `json:"destination"`
Connectivity string `json:"connectivity"`
Interval types.Duration `json:"interval"`
SamplingCount int `json:"sampling"`
Timeout types.Duration `json:"timeout"`
HttpMethod string `json:"httpMethod"`
}
func (h healthCheckSettings) Build() (proto.Message, error) {
+21 -24
View File
@@ -8,6 +8,7 @@ import (
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/proxy/shadowsocks"
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
"google.golang.org/protobuf/proto"
@@ -40,16 +41,17 @@ type ShadowsocksUserConfig struct {
}
type ShadowsocksServerConfig struct {
Cipher string `json:"method"`
Password string `json:"password"`
Level byte `json:"level"`
Email string `json:"email"`
Users []*ShadowsocksUserConfig `json:"clients"`
NetworkList *NetworkList `json:"network"`
IVCheck bool `json:"ivCheck"`
Cipher string `json:"method"`
Password string `json:"password"`
Level byte `json:"level"`
Email string `json:"email"`
Users types.Listable[*ShadowsocksUserConfig] `json:"clients"`
NetworkList *NetworkList `json:"network"`
}
func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
errors.PrintNonRemovalDeprecatedFeatureWarning("Shadowsocks (with no Forward Secrecy, etc.)", "VLESS Encryption")
if C.Contains(shadowaead_2022.List, v.Cipher) {
return buildShadowsocks2022(v)
}
@@ -62,7 +64,6 @@ func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
account := &shadowsocks.Account{
Password: user.Password,
CipherType: cipherFromString(user.Cipher),
IvCheck: v.IVCheck,
}
if account.Password == "" {
return nil, errors.New("Shadowsocks password is not specified.")
@@ -81,7 +82,6 @@ func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
account := &shadowsocks.Account{
Password: v.Password,
CipherType: cipherFromString(v.Cipher),
IvCheck: v.IVCheck,
}
if account.Password == "" {
return nil, errors.New("Shadowsocks password is not specified.")
@@ -166,25 +166,25 @@ type ShadowsocksServerTarget struct {
Email string `json:"email"`
Cipher string `json:"method"`
Password string `json:"password"`
IVCheck bool `json:"ivCheck"`
UoT bool `json:"uot"`
UoTVersion int `json:"uotVersion"`
}
type ShadowsocksClientConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level byte `json:"level"`
Email string `json:"email"`
Cipher string `json:"method"`
Password string `json:"password"`
IVCheck bool `json:"ivCheck"`
UoT bool `json:"uot"`
UoTVersion int `json:"uotVersion"`
Servers []*ShadowsocksServerTarget `json:"servers"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level byte `json:"level"`
Email string `json:"email"`
Cipher string `json:"method"`
Password string `json:"password"`
UoT bool `json:"uot"`
UoTVersion int `json:"uotVersion"`
Servers types.Listable[*ShadowsocksServerTarget] `json:"servers"`
}
func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
errors.PrintNonRemovalDeprecatedFeatureWarning("Shadowsocks (with no Forward Secrecy, etc.)", "VLESS Encryption")
if v.Address != nil {
v.Servers = []*ShadowsocksServerTarget{
{
@@ -194,7 +194,6 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
Email: v.Email,
Cipher: v.Cipher,
Password: v.Password,
IVCheck: v.IVCheck,
UoT: v.UoT,
UoTVersion: v.UoTVersion,
},
@@ -250,12 +249,10 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
return nil, errors.New("unknown cipher method: ", server.Cipher)
}
account.IvCheck = server.IVCheck
ss := &protocol.ServerEndpoint{
Address: server.Address.Build(),
Port: uint32(server.Port),
User: &protocol.User{
User: &protocol.User{
Level: uint32(server.Level),
Email: server.Email,
Account: serial.ToTypedMessage(account),
+16 -15
View File
@@ -6,6 +6,7 @@ import (
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/proxy/socks"
"google.golang.org/protobuf/proto"
)
@@ -28,11 +29,11 @@ const (
)
type SocksServerConfig struct {
AuthMethod string `json:"auth"`
Accounts []*SocksAccount `json:"accounts"`
UDP bool `json:"udp"`
Host *Address `json:"ip"`
UserLevel uint32 `json:"userLevel"`
AuthMethod string `json:"auth"`
Accounts types.Listable[*SocksAccount] `json:"accounts"`
UDP bool `json:"udp"`
Host *Address `json:"ip"`
UserLevel uint32 `json:"userLevel"`
}
func (v *SocksServerConfig) Build() (proto.Message, error) {
@@ -64,19 +65,19 @@ func (v *SocksServerConfig) Build() (proto.Message, error) {
}
type SocksRemoteConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users []json.RawMessage `json:"users"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users types.Listable[json.RawMessage] `json:"users"`
}
type SocksClientConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level uint32 `json:"level"`
Email string `json:"email"`
Username string `json:"user"`
Password string `json:"pass"`
Servers []*SocksRemoteConfig `json:"servers"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level uint32 `json:"level"`
Email string `json:"email"`
Username string `json:"user"`
Password string `json:"pass"`
Servers types.Listable[*SocksRemoteConfig] `json:"servers"`
}
func (v *SocksClientConfig) Build() (proto.Message, error) {
+348 -107
View File
@@ -15,8 +15,11 @@ import (
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/finalmask/salamander"
"github.com/xtls/xray-core/transport/internet/httpupgrade"
"github.com/xtls/xray-core/transport/internet/hysteria"
"github.com/xtls/xray-core/transport/internet/kcp"
"github.com/xtls/xray-core/transport/internet/reality"
"github.com/xtls/xray-core/transport/internet/splithttp"
@@ -332,6 +335,177 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
return config, nil
}
const (
Byte = 1
Kilobyte = 1024 * Byte
Megabyte = 1024 * Kilobyte
Gigabyte = 1024 * Megabyte
Terabyte = 1024 * Gigabyte
)
type Bandwidth string
func (b Bandwidth) Bps() (uint64, error) {
s := strings.TrimSpace(strings.ToLower(string(b)))
if s == "" {
return 0, nil
}
idx := len(s)
for i, c := range s {
if (c < '0' || c > '9') && c != '.' {
idx = i
break
}
}
numStr := s[:idx]
unit := strings.TrimSpace(s[idx:])
val, err := strconv.ParseFloat(numStr, 64)
if err != nil {
return 0, err
}
mul := uint64(1)
switch unit {
case "", "b", "bps":
mul = Byte
case "k", "kb", "kbps":
mul = Kilobyte
case "m", "mb", "mbps":
mul = Megabyte
case "g", "gb", "gbps":
mul = Gigabyte
case "t", "tb", "tbps":
mul = Terabyte
default:
return 0, errors.New("unsupported unit: " + unit)
}
return uint64(val*float64(mul)) / 8, nil
}
type UdpHop struct {
PortList json.RawMessage `json:"port"`
Interval *Int32Range `json:"interval"`
}
type HysteriaConfig struct {
Version int32 `json:"version"`
Auth string `json:"auth"`
Congestion string `json:"congestion"`
Up Bandwidth `json:"up"`
Down Bandwidth `json:"down"`
UdpHop UdpHop `json:"udphop"`
InitStreamReceiveWindow uint64 `json:"initStreamReceiveWindow"`
MaxStreamReceiveWindow uint64 `json:"maxStreamReceiveWindow"`
InitConnectionReceiveWindow uint64 `json:"initConnectionReceiveWindow"`
MaxConnectionReceiveWindow uint64 `json:"maxConnectionReceiveWindow"`
MaxIdleTimeout int64 `json:"maxIdleTimeout"`
KeepAlivePeriod int64 `json:"keepAlivePeriod"`
DisablePathMTUDiscovery bool `json:"disablePathMTUDiscovery"`
}
func (c *HysteriaConfig) Build() (proto.Message, error) {
if c.Version != 2 {
return nil, errors.New("version != 2")
}
up, err := c.Up.Bps()
if err != nil {
return nil, err
}
down, err := c.Down.Bps()
if err != nil {
return nil, err
}
c.Congestion = strings.ToLower(c.Congestion)
if c.Congestion == "force-brutal" && up == 0 {
return nil, errors.New("force-brutal require up")
}
var hop *PortList
if err := json.Unmarshal(c.UdpHop.PortList, &hop); err != nil {
hop = &PortList{}
}
var inertvalMin, inertvalMax int64
if c.UdpHop.Interval != nil {
inertvalMin = int64(c.UdpHop.Interval.From)
inertvalMax = int64(c.UdpHop.Interval.To)
}
if up > 0 && up < 65536 {
return nil, errors.New("Up must be at least 65536 Bps")
}
if down > 0 && down < 65536 {
return nil, errors.New("Down must be at least 65536 Bps")
}
if (inertvalMin != 0 && inertvalMin < 5) || (inertvalMax != 0 && inertvalMax < 5) {
return nil, errors.New("Interval must be at least 5")
}
if c.InitStreamReceiveWindow > 0 && c.InitStreamReceiveWindow < 16384 {
return nil, errors.New("InitStreamReceiveWindow must be at least 16384")
}
if c.MaxStreamReceiveWindow > 0 && c.MaxStreamReceiveWindow < 16384 {
return nil, errors.New("MaxStreamReceiveWindow must be at least 16384")
}
if c.InitConnectionReceiveWindow > 0 && c.InitConnectionReceiveWindow < 16384 {
return nil, errors.New("InitConnectionReceiveWindow must be at least 16384")
}
if c.MaxConnectionReceiveWindow > 0 && c.MaxConnectionReceiveWindow < 16384 {
return nil, errors.New("MaxConnectionReceiveWindow must be at least 16384")
}
if c.MaxIdleTimeout != 0 && (c.MaxIdleTimeout < 4 || c.MaxIdleTimeout > 120) {
return nil, errors.New("MaxIdleTimeout must be between 4 and 120")
}
if c.KeepAlivePeriod != 0 && (c.KeepAlivePeriod < 2 || c.KeepAlivePeriod > 60) {
return nil, errors.New("KeepAlivePeriod must be between 2 and 60")
}
config := &hysteria.Config{}
config.Version = c.Version
config.Auth = c.Auth
config.Congestion = c.Congestion
config.Up = up
config.Down = down
config.Ports = hop.Build().Ports()
config.IntervalMin = inertvalMin
config.IntervalMax = inertvalMax
config.InitStreamReceiveWindow = c.InitStreamReceiveWindow
config.MaxStreamReceiveWindow = c.MaxStreamReceiveWindow
config.InitConnReceiveWindow = c.InitConnectionReceiveWindow
config.MaxConnReceiveWindow = c.MaxConnectionReceiveWindow
config.MaxIdleTimeout = c.MaxIdleTimeout
config.KeepAlivePeriod = c.KeepAlivePeriod
config.DisablePathMtuDiscovery = c.DisablePathMTUDiscovery
if config.InitStreamReceiveWindow == 0 {
config.InitStreamReceiveWindow = 8388608
}
if config.MaxStreamReceiveWindow == 0 {
config.MaxStreamReceiveWindow = 8388608
}
if config.InitConnReceiveWindow == 0 {
config.InitConnReceiveWindow = 8388608 * 5 / 2
}
if config.MaxConnReceiveWindow == 0 {
config.MaxConnReceiveWindow = 8388608 * 5 / 2
}
if config.MaxIdleTimeout == 0 {
config.MaxIdleTimeout = 30
}
// if config.KeepAlivePeriod == 0 {
// config.KeepAlivePeriod = 10
// }
return config, nil
}
func readFileOrString(f string, s []string) ([]byte, error) {
if len(f) > 0 {
return filesystem.ReadCert(f)
@@ -343,14 +517,14 @@ func readFileOrString(f string, s []string) ([]byte, error) {
}
type TLSCertConfig struct {
CertFile string `json:"certificateFile"`
CertStr []string `json:"certificate"`
KeyFile string `json:"keyFile"`
KeyStr []string `json:"key"`
Usage string `json:"usage"`
OcspStapling uint64 `json:"ocspStapling"`
OneTimeLoading bool `json:"oneTimeLoading"`
BuildChain bool `json:"buildChain"`
CertFile string `json:"certificateFile"`
CertStr types.Listable[string] `json:"certificate"`
KeyFile string `json:"keyFile"`
KeyStr types.Listable[string] `json:"key"`
Usage string `json:"usage"`
OcspStapling uint64 `json:"ocspStapling"`
OneTimeLoading bool `json:"oneTimeLoading"`
BuildChain bool `json:"buildChain"`
}
// Build implements Buildable.
@@ -395,27 +569,26 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
}
type TLSConfig struct {
Insecure bool `json:"allowInsecure"`
Certs []*TLSCertConfig `json:"certificates"`
ServerName string `json:"serverName"`
ALPN *StringList `json:"alpn"`
EnableSessionResumption bool `json:"enableSessionResumption"`
DisableSystemRoot bool `json:"disableSystemRoot"`
MinVersion string `json:"minVersion"`
MaxVersion string `json:"maxVersion"`
CipherSuites string `json:"cipherSuites"`
Fingerprint string `json:"fingerprint"`
RejectUnknownSNI bool `json:"rejectUnknownSni"`
PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"`
CurvePreferences *StringList `json:"curvePreferences"`
MasterKeyLog string `json:"masterKeyLog"`
ServerNameToVerify string `json:"serverNameToVerify"`
VerifyPeerCertInNames []string `json:"verifyPeerCertInNames"`
ECHServerKeys string `json:"echServerKeys"`
ECHConfigList string `json:"echConfigList"`
ECHForceQuery string `json:"echForceQuery"`
ECHSocketSettings *SocketConfig `json:"echSockopt"`
AllowInsecure bool `json:"allowInsecure"`
Certs types.Listable[*TLSCertConfig] `json:"certificates"`
ServerName string `json:"serverName"`
ALPN *StringList `json:"alpn"`
EnableSessionResumption bool `json:"enableSessionResumption"`
DisableSystemRoot bool `json:"disableSystemRoot"`
MinVersion string `json:"minVersion"`
MaxVersion string `json:"maxVersion"`
CipherSuites string `json:"cipherSuites"`
Fingerprint string `json:"fingerprint"`
RejectUnknownSNI bool `json:"rejectUnknownSni"`
CurvePreferences *StringList `json:"curvePreferences"`
MasterKeyLog string `json:"masterKeyLog"`
PinnedPeerCertSha256 string `json:"pinnedPeerCertSha256"`
VerifyPeerCertByName string `json:"verifyPeerCertByName"`
VerifyPeerCertInNames types.Listable[string] `json:"verifyPeerCertInNames"`
ECHServerKeys string `json:"echServerKeys"`
ECHConfigList string `json:"echConfigList"`
ECHForceQuery string `json:"echForceQuery"`
ECHSocketSettings *SocketConfig `json:"echSockopt"`
}
// Build implements Buildable.
@@ -430,7 +603,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.Certificate[idx] = cert
}
serverName := c.ServerName
config.AllowInsecure = c.Insecure
if len(c.ServerName) > 0 {
config.ServerName = serverName
}
@@ -457,35 +629,37 @@ func (c *TLSConfig) Build() (proto.Message, error) {
return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint)
}
config.RejectUnknownSni = c.RejectUnknownSNI
if c.PinnedPeerCertificateChainSha256 != nil {
config.PinnedPeerCertificateChainSha256 = [][]byte{}
for _, v := range *c.PinnedPeerCertificateChainSha256 {
hashValue, err := base64.StdEncoding.DecodeString(v)
if err != nil {
return nil, err
}
config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue)
}
}
if c.PinnedPeerCertificatePublicKeySha256 != nil {
config.PinnedPeerCertificatePublicKeySha256 = [][]byte{}
for _, v := range *c.PinnedPeerCertificatePublicKeySha256 {
hashValue, err := base64.StdEncoding.DecodeString(v)
if err != nil {
return nil, err
}
config.PinnedPeerCertificatePublicKeySha256 = append(config.PinnedPeerCertificatePublicKeySha256, hashValue)
}
}
config.MasterKeyLog = c.MasterKeyLog
if c.ServerNameToVerify != "" {
return nil, errors.PrintRemovedFeatureError(`"serverNameToVerify"`, `"verifyPeerCertInNames"`)
if c.AllowInsecure {
return nil, errors.PrintRemovedFeatureError(`"allowInsecure"`, `"pinnedPeerCertSha256"`)
}
if c.PinnedPeerCertSha256 != "" {
for v := range strings.SplitSeq(c.PinnedPeerCertSha256, ",") {
v = strings.TrimSpace(v)
if v == "" {
continue
}
hashValue, err := hex.DecodeString(v)
if err != nil {
return nil, err
}
config.PinnedPeerCertSha256 = append(config.PinnedPeerCertSha256, hashValue)
}
}
if c.VerifyPeerCertInNames != nil {
return nil, errors.PrintRemovedFeatureError(`"verifyPeerCertInNames"`, `"verifyPeerCertByName"`)
}
if c.VerifyPeerCertByName != "" {
for v := range strings.SplitSeq(c.VerifyPeerCertByName, ",") {
v = strings.TrimSpace(v)
if v == "" {
continue
}
config.VerifyPeerCertByName = append(config.VerifyPeerCertByName, v)
}
}
config.VerifyPeerCertInNames = c.VerifyPeerCertInNames
if c.ECHServerKeys != "" {
EchPrivateKey, err := base64.StdEncoding.DecodeString(c.ECHServerKeys)
@@ -520,19 +694,19 @@ type LimitFallback struct {
}
type REALITYConfig struct {
MasterKeyLog string `json:"masterKeyLog"`
Show bool `json:"show"`
Target json.RawMessage `json:"target"`
Dest json.RawMessage `json:"dest"`
Type string `json:"type"`
Xver uint64 `json:"xver"`
ServerNames []string `json:"serverNames"`
PrivateKey string `json:"privateKey"`
MinClientVer string `json:"minClientVer"`
MaxClientVer string `json:"maxClientVer"`
MaxTimeDiff uint64 `json:"maxTimeDiff"`
ShortIds []string `json:"shortIds"`
Mldsa65Seed string `json:"mldsa65Seed"`
MasterKeyLog string `json:"masterKeyLog"`
Show bool `json:"show"`
Target json.RawMessage `json:"target"`
Dest json.RawMessage `json:"dest"`
Type string `json:"type"`
Xver uint64 `json:"xver"`
ServerNames types.Listable[string] `json:"serverNames"`
PrivateKey string `json:"privateKey"`
MinClientVer string `json:"minClientVer"`
MaxClientVer string `json:"maxClientVer"`
MaxTimeDiff uint64 `json:"maxTimeDiff"`
ShortIds types.Listable[string] `json:"shortIds"`
Mldsa65Seed string `json:"mldsa65Seed"`
LimitFallbackUpload LimitFallback `json:"limitFallbackUpload"`
LimitFallbackDownload LimitFallback `json:"limitFallbackDownload"`
@@ -740,18 +914,20 @@ func (p TransportProtocol) Build() (string, error) {
case "kcp", "mkcp":
return "mkcp", nil
case "grpc":
errors.PrintDeprecatedFeatureWarning("gRPC transport (with unnecessary costs, etc.)", "XHTTP stream-up H2")
errors.PrintNonRemovalDeprecatedFeatureWarning("gRPC transport (with unnecessary costs, etc.)", "XHTTP stream-up H2")
return "grpc", nil
case "ws", "websocket":
errors.PrintDeprecatedFeatureWarning("WebSocket transport (with ALPN http/1.1, etc.)", "XHTTP H2 & H3")
errors.PrintNonRemovalDeprecatedFeatureWarning("WebSocket transport (with ALPN http/1.1, etc.)", "XHTTP H2 & H3")
return "websocket", nil
case "httpupgrade":
errors.PrintDeprecatedFeatureWarning("HTTPUpgrade transport (with ALPN http/1.1, etc.)", "XHTTP H2 & H3")
errors.PrintNonRemovalDeprecatedFeatureWarning("HTTPUpgrade transport (with ALPN http/1.1, etc.)", "XHTTP H2 & H3")
return "httpupgrade", nil
case "h2", "h3", "http":
return "", errors.PrintRemovedFeatureError("HTTP transport (without header padding, etc.)", "XHTTP stream-one H2 & H3")
case "quic":
return "", errors.PrintRemovedFeatureError("QUIC transport (without web service, etc.)", "XHTTP stream-one H3")
case "hysteria":
return "hysteria", nil
default:
return "", errors.New("Config: unknown transport protocol: ", p)
}
@@ -791,26 +967,26 @@ func (h *HappyEyeballsConfig) UnmarshalJSON(data []byte) error {
}
type SocketConfig struct {
Mark int32 `json:"mark"`
TFO interface{} `json:"tcpFastOpen"`
TProxy string `json:"tproxy"`
AcceptProxyProtocol bool `json:"acceptProxyProtocol"`
DomainStrategy string `json:"domainStrategy"`
DialerProxy string `json:"dialerProxy"`
TCPKeepAliveInterval int32 `json:"tcpKeepAliveInterval"`
TCPKeepAliveIdle int32 `json:"tcpKeepAliveIdle"`
TCPCongestion string `json:"tcpCongestion"`
TCPWindowClamp int32 `json:"tcpWindowClamp"`
TCPMaxSeg int32 `json:"tcpMaxSeg"`
Penetrate bool `json:"penetrate"`
TCPUserTimeout int32 `json:"tcpUserTimeout"`
V6only bool `json:"v6only"`
Interface string `json:"interface"`
TcpMptcp bool `json:"tcpMptcp"`
CustomSockopt []*CustomSockoptConfig `json:"customSockopt"`
AddressPortStrategy string `json:"addressPortStrategy"`
HappyEyeballsSettings *HappyEyeballsConfig `json:"happyEyeballs"`
TrustedXForwardedFor []string `json:"trustedXForwardedFor"`
Mark int32 `json:"mark"`
TFO interface{} `json:"tcpFastOpen"`
TProxy string `json:"tproxy"`
AcceptProxyProtocol bool `json:"acceptProxyProtocol"`
DomainStrategy string `json:"domainStrategy"`
DialerProxy string `json:"dialerProxy"`
TCPKeepAliveInterval int32 `json:"tcpKeepAliveInterval"`
TCPKeepAliveIdle int32 `json:"tcpKeepAliveIdle"`
TCPCongestion string `json:"tcpCongestion"`
TCPWindowClamp int32 `json:"tcpWindowClamp"`
TCPMaxSeg int32 `json:"tcpMaxSeg"`
Penetrate bool `json:"penetrate"`
TCPUserTimeout int32 `json:"tcpUserTimeout"`
V6only bool `json:"v6only"`
Interface string `json:"interface"`
TcpMptcp bool `json:"tcpMptcp"`
CustomSockopt types.Listable[*CustomSockoptConfig] `json:"customSockopt"`
AddressPortStrategy string `json:"addressPortStrategy"`
HappyEyeballsSettings *HappyEyeballsConfig `json:"happyEyeballs"`
TrustedXForwardedFor types.Listable[string] `json:"trustedXForwardedFor"`
}
// Build implements Buildable.
@@ -934,22 +1110,66 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
}, nil
}
var (
udpmaskLoader = NewJSONConfigLoader(ConfigCreatorCache{
"salamander": func() interface{} { return new(Salamander) },
}, "type", "settings")
)
type Salamander struct {
Password string `json:"password"`
}
func (c *Salamander) Build() (proto.Message, error) {
config := &salamander.Config{}
config.Password = c.Password
return config, nil
}
type FinalMask struct {
Type string `json:"type"`
Settings *json.RawMessage `json:"settings"`
}
func (c *FinalMask) Build(tcpmaskLoader bool) (proto.Message, error) {
loader := udpmaskLoader
if tcpmaskLoader {
return nil, errors.New("")
}
settings := []byte("{}")
if c.Settings != nil {
settings = ([]byte)(*c.Settings)
}
rawConfig, err := loader.LoadWithID(settings, c.Type)
if err != nil {
return nil, err
}
ts, err := rawConfig.(Buildable).Build()
if err != nil {
return nil, err
}
return ts, nil
}
type StreamConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Network *TransportProtocol `json:"network"`
Security string `json:"security"`
TLSSettings *TLSConfig `json:"tlsSettings"`
REALITYSettings *REALITYConfig `json:"realitySettings"`
RAWSettings *TCPConfig `json:"rawSettings"`
TCPSettings *TCPConfig `json:"tcpSettings"`
XHTTPSettings *SplitHTTPConfig `json:"xhttpSettings"`
SplitHTTPSettings *SplitHTTPConfig `json:"splithttpSettings"`
KCPSettings *KCPConfig `json:"kcpSettings"`
GRPCSettings *GRPCConfig `json:"grpcSettings"`
WSSettings *WebSocketConfig `json:"wsSettings"`
HTTPUPGRADESettings *HttpUpgradeConfig `json:"httpupgradeSettings"`
SocketSettings *SocketConfig `json:"sockopt"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Network *TransportProtocol `json:"network"`
Security string `json:"security"`
Udpmasks types.Listable[*FinalMask] `json:"udpmasks"`
TLSSettings *TLSConfig `json:"tlsSettings"`
REALITYSettings *REALITYConfig `json:"realitySettings"`
RAWSettings *TCPConfig `json:"rawSettings"`
TCPSettings *TCPConfig `json:"tcpSettings"`
XHTTPSettings *SplitHTTPConfig `json:"xhttpSettings"`
SplitHTTPSettings *SplitHTTPConfig `json:"splithttpSettings"`
KCPSettings *KCPConfig `json:"kcpSettings"`
GRPCSettings *GRPCConfig `json:"grpcSettings"`
WSSettings *WebSocketConfig `json:"wsSettings"`
HTTPUPGRADESettings *HttpUpgradeConfig `json:"httpupgradeSettings"`
HysteriaSettings *HysteriaConfig `json:"hysteriaSettings"`
SocketSettings *SocketConfig `json:"sockopt"`
}
// Build implements Buildable.
@@ -968,6 +1188,7 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
}
config.ProtocolName = protocol
}
switch strings.ToLower(c.Security) {
case "", "none":
case "tls":
@@ -1001,6 +1222,7 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
default:
return nil, errors.New(`Unknown security "` + c.Security + `".`)
}
if c.RAWSettings != nil {
c.TCPSettings = c.RAWSettings
}
@@ -1067,6 +1289,16 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
Settings: serial.ToTypedMessage(hs),
})
}
if c.HysteriaSettings != nil {
hs, err := c.HysteriaSettings.Build()
if err != nil {
return nil, errors.New("Failed to build Hysteria config.").Base(err)
}
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
ProtocolName: "hysteria",
Settings: serial.ToTypedMessage(hs),
})
}
if c.SocketSettings != nil {
ss, err := c.SocketSettings.Build()
if err != nil {
@@ -1074,6 +1306,15 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
}
config.SocketSettings = ss
}
for _, mask := range c.Udpmasks {
u, err := mask.Build(false)
if err != nil {
return nil, errors.New("failed to build mask with type ", mask.Type).Base(err)
}
config.Udpmasks = append(config.Udpmasks, serial.ToTypedMessage(u))
}
return config, nil
}
+15 -10
View File
@@ -12,6 +12,7 @@ import (
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/proxy/trojan"
"google.golang.org/protobuf/proto"
)
@@ -28,17 +29,19 @@ type TrojanServerTarget struct {
// TrojanClientConfig is configuration of trojan servers
type TrojanClientConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level byte `json:"level"`
Email string `json:"email"`
Password string `json:"password"`
Flow string `json:"flow"`
Servers []*TrojanServerTarget `json:"servers"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level byte `json:"level"`
Email string `json:"email"`
Password string `json:"password"`
Flow string `json:"flow"`
Servers types.Listable[*TrojanServerTarget] `json:"servers"`
}
// Build implements Buildable
func (c *TrojanClientConfig) Build() (proto.Message, error) {
errors.PrintNonRemovalDeprecatedFeatureWarning("Trojan (with no Flow, etc.)", "VLESS with Flow & Seed")
if c.Address != nil {
c.Servers = []*TrojanServerTarget{
{
@@ -74,7 +77,7 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
config.Server = &protocol.ServerEndpoint{
Address: rec.Address.Build(),
Port: uint32(rec.Port),
User: &protocol.User{
User: &protocol.User{
Level: uint32(rec.Level),
Email: rec.Email,
Account: serial.ToTypedMessage(&trojan.Account{
@@ -109,12 +112,14 @@ type TrojanUserConfig struct {
// TrojanServerConfig is Inbound configuration
type TrojanServerConfig struct {
Clients []*TrojanUserConfig `json:"clients"`
Fallbacks []*TrojanInboundFallback `json:"fallbacks"`
Clients types.Listable[*TrojanUserConfig] `json:"clients"`
Fallbacks types.Listable[*TrojanInboundFallback] `json:"fallbacks"`
}
// Build implements Buildable
func (c *TrojanServerConfig) Build() (proto.Message, error) {
errors.PrintNonRemovalDeprecatedFeatureWarning("Trojan (with no Flow, etc.)", "VLESS with Flow & Seed")
config := &trojan.ServerConfig{
Users: make([]*protocol.User, len(c.Clients)),
}
+30
View File
@@ -0,0 +1,30 @@
package conf
import (
"github.com/xtls/xray-core/proxy/tun"
"google.golang.org/protobuf/proto"
)
type TunConfig struct {
Name string `json:"name"`
MTU uint32 `json:"MTU"`
UserLevel uint32 `json:"userLevel"`
}
func (v *TunConfig) Build() (proto.Message, error) {
config := &tun.Config{
Name: v.Name,
MTU: v.MTU,
UserLevel: v.UserLevel,
}
if v.Name == "" {
config.Name = "xray0"
}
if v.MTU == 0 {
config.MTU = 1500
}
return config, nil
}
+2 -1
View File
@@ -1,9 +1,10 @@
package conf
import (
"strconv"
"github.com/xtls/xray-core/app/version"
"github.com/xtls/xray-core/core"
"strconv"
)
type VersionConfig struct {
+27 -25
View File
@@ -14,6 +14,7 @@ import (
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/uuid"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/proxy/vless"
"github.com/xtls/xray-core/proxy/vless/inbound"
"github.com/xtls/xray-core/proxy/vless/outbound"
@@ -30,11 +31,11 @@ type VLessInboundFallback struct {
}
type VLessInboundConfig struct {
Clients []json.RawMessage `json:"clients"`
Decryption string `json:"decryption"`
Fallbacks []*VLessInboundFallback `json:"fallbacks"`
Flow string `json:"flow"`
Testseed []uint32 `json:"testseed"`
Clients types.Listable[json.RawMessage] `json:"clients"`
Decryption string `json:"decryption"`
Fallbacks types.Listable[*VLessInboundFallback] `json:"fallbacks"`
Flow string `json:"flow"`
Testseed types.Listable[uint32] `json:"testseed"`
}
// Build implements Buildable
@@ -42,8 +43,6 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
config := new(inbound.Config)
config.Clients = make([]*protocol.User, len(c.Clients))
switch c.Flow {
case vless.None:
c.Flow = ""
case "", vless.XRV:
default:
return nil, errors.New(`VLESS "settings.flow" doesn't support "` + c.Flow + `" in this version`)
@@ -67,12 +66,13 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
switch account.Flow {
case "":
account.Flow = c.Flow
case vless.None:
account.Flow = ""
case vless.XRV:
default:
return nil, errors.New(`VLESS clients: "flow" doesn't support "` + account.Flow + `" in this version`)
}
if account.Flow == "" {
errors.PrintNonRemovalDeprecatedFeatureWarning("VLESS (with no Flow, etc.)", "VLESS with Flow & Seed")
}
if len(account.Testseed) < 4 {
account.Testseed = c.Testseed
@@ -202,24 +202,24 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
}
type VLessOutboundVnext struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users []json.RawMessage `json:"users"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users types.Listable[json.RawMessage] `json:"users"`
}
type VLessOutboundConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level uint32 `json:"level"`
Email string `json:"email"`
Id string `json:"id"`
Flow string `json:"flow"`
Seed string `json:"seed"`
Encryption string `json:"encryption"`
Reverse *vless.Reverse `json:"reverse"`
Testpre uint32 `json:"testpre"`
Testseed []uint32 `json:"testseed"`
Vnext []*VLessOutboundVnext `json:"vnext"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level uint32 `json:"level"`
Email string `json:"email"`
Id string `json:"id"`
Flow string `json:"flow"`
Seed string `json:"seed"`
Encryption string `json:"encryption"`
Reverse *vless.Reverse `json:"reverse"`
Testpre uint32 `json:"testpre"`
Testseed types.Listable[uint32] `json:"testseed"`
Vnext types.Listable[*VLessOutboundVnext] `json:"vnext"`
}
// Build implements Buildable
@@ -280,7 +280,9 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
account.Id = u.String()
switch account.Flow {
case "", vless.XRV, vless.XRV + "-udp443":
case "":
errors.PrintNonRemovalDeprecatedFeatureWarning("VLESS (with no Flow, etc.)", "VLESS with Flow & Seed")
case vless.XRV, vless.XRV + "-udp443":
default:
return nil, errors.New(`VLESS users: "flow" doesn't support "` + account.Flow + `" in this version`)
}
+18 -13
View File
@@ -8,6 +8,7 @@ import (
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/uuid"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/proxy/vmess"
"github.com/xtls/xray-core/proxy/vmess/inbound"
"github.com/xtls/xray-core/proxy/vmess/outbound"
@@ -58,12 +59,14 @@ func (c *VMessDefaultConfig) Build() *inbound.DefaultConfig {
}
type VMessInboundConfig struct {
Users []json.RawMessage `json:"clients"`
Defaults *VMessDefaultConfig `json:"default"`
Users types.Listable[json.RawMessage] `json:"clients"`
Defaults *VMessDefaultConfig `json:"default"`
}
// Build implements Buildable
func (c *VMessInboundConfig) Build() (proto.Message, error) {
errors.PrintNonRemovalDeprecatedFeatureWarning("VMess (with no Forward Secrecy, etc.)", "VLESS Encryption")
config := &inbound.Config{}
if c.Defaults != nil {
@@ -95,24 +98,26 @@ func (c *VMessInboundConfig) Build() (proto.Message, error) {
}
type VMessOutboundTarget struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users []json.RawMessage `json:"users"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Users types.Listable[json.RawMessage] `json:"users"`
}
type VMessOutboundConfig struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level uint32 `json:"level"`
Email string `json:"email"`
ID string `json:"id"`
Security string `json:"security"`
Experiments string `json:"experiments"`
Receivers []*VMessOutboundTarget `json:"vnext"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
Level uint32 `json:"level"`
Email string `json:"email"`
ID string `json:"id"`
Security string `json:"security"`
Experiments string `json:"experiments"`
Receivers types.Listable[*VMessOutboundTarget] `json:"vnext"`
}
// Build implements Buildable
func (c *VMessOutboundConfig) Build() (proto.Message, error) {
errors.PrintNonRemovalDeprecatedFeatureWarning("VMess (with no Forward Secrecy, etc.)", "VLESS Encryption")
config := new(outbound.Config)
if c.Address != nil {
c.Receivers = []*VMessOutboundTarget{
+14 -13
View File
@@ -6,16 +6,17 @@ import (
"strings"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/proxy/wireguard"
"google.golang.org/protobuf/proto"
)
type WireGuardPeerConfig struct {
PublicKey string `json:"publicKey"`
PreSharedKey string `json:"preSharedKey"`
Endpoint string `json:"endpoint"`
KeepAlive uint32 `json:"keepAlive"`
AllowedIPs []string `json:"allowedIPs,omitempty"`
PublicKey string `json:"publicKey"`
PreSharedKey string `json:"preSharedKey"`
Endpoint string `json:"endpoint"`
KeepAlive uint32 `json:"keepAlive"`
AllowedIPs types.Listable[string] `json:"allowedIPs,omitempty"`
}
func (c *WireGuardPeerConfig) Build() (proto.Message, error) {
@@ -51,14 +52,14 @@ func (c *WireGuardPeerConfig) Build() (proto.Message, error) {
type WireGuardConfig struct {
IsClient bool `json:""`
NoKernelTun bool `json:"noKernelTun"`
SecretKey string `json:"secretKey"`
Address []string `json:"address"`
Peers []*WireGuardPeerConfig `json:"peers"`
MTU int32 `json:"mtu"`
NumWorkers int32 `json:"workers"`
Reserved []byte `json:"reserved"`
DomainStrategy string `json:"domainStrategy"`
NoKernelTun bool `json:"noKernelTun"`
SecretKey string `json:"secretKey"`
Address types.Listable[string] `json:"address"`
Peers types.Listable[*WireGuardPeerConfig] `json:"peers"`
MTU int32 `json:"mtu"`
NumWorkers int32 `json:"workers"`
Reserved []byte `json:"reserved"`
DomainStrategy string `json:"domainStrategy"`
}
func (c *WireGuardConfig) Build() (proto.Message, error) {
+28 -22
View File
@@ -13,6 +13,7 @@ import (
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/serial"
core "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/infra/conf/cfgcommon/types"
"github.com/xtls/xray-core/transport/internet"
)
@@ -28,6 +29,7 @@ var (
"vmess": func() interface{} { return new(VMessInboundConfig) },
"trojan": func() interface{} { return new(TrojanServerConfig) },
"wireguard": func() interface{} { return &WireGuardConfig{IsClient: false} },
"tun": func() interface{} { return new(TunConfig) },
}, "protocol", "settings")
outboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
@@ -42,6 +44,7 @@ var (
"vless": func() interface{} { return new(VLessOutboundConfig) },
"vmess": func() interface{} { return new(VMessOutboundConfig) },
"trojan": func() interface{} { return new(TrojanClientConfig) },
"hysteria": func() interface{} { return new(HysteriaClientConfig) },
"dns": func() interface{} { return new(DNSOutboundConfig) },
"wireguard": func() interface{} { return &WireGuardConfig{IsClient: true} },
}, "protocol", "settings")
@@ -116,20 +119,23 @@ func (m *MuxConfig) Build() (*proxyman.MultiplexingConfig, error) {
}
type InboundDetourConfig struct {
Protocol string `json:"protocol"`
PortList *PortList `json:"port"`
ListenOn *Address `json:"listen"`
Settings *json.RawMessage `json:"settings"`
Tag string `json:"tag"`
StreamSetting *StreamConfig `json:"streamSettings"`
SniffingConfig *SniffingConfig `json:"sniffing"`
Protocol string `json:"protocol"`
PortList *PortList `json:"port"`
ListenOn *Address `json:"listen"`
Settings *json.RawMessage `json:"settings"`
Tag string `json:"tag"`
StreamSetting *StreamConfig `json:"streamSettings"`
SniffingConfig *SniffingConfig `json:"sniffing"`
}
// Build implements Buildable.
func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
receiverSettings := &proxyman.ReceiverConfig{}
if c.ListenOn == nil {
// TUN inbound doesn't need port configuration as it uses network interface instead
if strings.ToLower(c.Protocol) == "tun" {
// Skip port validation for TUN
} else if c.ListenOn == nil {
// Listen on anyip, must set PortList
if c.PortList == nil {
return nil, errors.New("Listen on AnyIP but no Port(s) set in InboundDetour.")
@@ -333,20 +339,20 @@ type Config struct {
// left for returning error
Transport map[string]json.RawMessage `json:"transport"`
LogConfig *LogConfig `json:"log"`
RouterConfig *RouterConfig `json:"routing"`
DNSConfig *DNSConfig `json:"dns"`
InboundConfigs []InboundDetourConfig `json:"inbounds"`
OutboundConfigs []OutboundDetourConfig `json:"outbounds"`
Policy *PolicyConfig `json:"policy"`
API *APIConfig `json:"api"`
Metrics *MetricsConfig `json:"metrics"`
Stats *StatsConfig `json:"stats"`
Reverse *ReverseConfig `json:"reverse"`
FakeDNS *FakeDNSConfig `json:"fakeDns"`
Observatory *ObservatoryConfig `json:"observatory"`
BurstObservatory *BurstObservatoryConfig `json:"burstObservatory"`
Version *VersionConfig `json:"version"`
LogConfig *LogConfig `json:"log"`
RouterConfig *RouterConfig `json:"routing"`
DNSConfig *DNSConfig `json:"dns"`
InboundConfigs types.Listable[InboundDetourConfig] `json:"inbounds"`
OutboundConfigs types.Listable[OutboundDetourConfig] `json:"outbounds"`
Policy *PolicyConfig `json:"policy"`
API *APIConfig `json:"api"`
Metrics *MetricsConfig `json:"metrics"`
Stats *StatsConfig `json:"stats"`
Reverse *ReverseConfig `json:"reverse"`
FakeDNS *FakeDNSConfig `json:"fakeDns"`
Observatory *ObservatoryConfig `json:"observatory"`
BurstObservatory *BurstObservatoryConfig `json:"burstObservatory"`
Version *VersionConfig `json:"version"`
}
func (c *Config) findInboundTag(tag string) int {
+2
View File
@@ -29,8 +29,10 @@ var CmdAPI = &base.Command{
cmdInboundUserCount,
cmdAddRules,
cmdRemoveRules,
cmdListRules,
cmdSourceIpBlock,
cmdOnlineStats,
cmdOnlineStatsIpList,
cmdGetAllOnlineUsers,
},
}
+43
View File
@@ -0,0 +1,43 @@
package api
import (
routerService "github.com/xtls/xray-core/app/router/command"
"github.com/xtls/xray-core/main/commands/base"
)
var cmdListRules = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api lsrules [--server=127.0.0.1:8080]",
Short: "List routing rules",
Long: `
List routing rules in Xray.
Arguments:
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080
`,
Run: executeListRules,
}
func executeListRules(cmd *base.Command, args []string) {
setSharedFlags(cmd)
cmd.Flag.Parse(args)
conn, ctx, close := dialAPIServer()
defer close()
client := routerService.NewRoutingServiceClient(conn)
resp, err := client.ListRule(ctx, &routerService.ListRuleRequest{})
if err != nil {
base.Fatalf("failed to list rules: %s", err)
}
showJSONResponse(resp)
}
@@ -0,0 +1,43 @@
package api
import (
statsService "github.com/xtls/xray-core/app/stats/command"
"github.com/xtls/xray-core/main/commands/base"
)
var cmdGetAllOnlineUsers = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api statsgetallonlineusers [--server=127.0.0.1:8080]",
Short: "Retrieve array of all online users",
Long: `
Retrieve array of all online users.
Arguments:
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080"
`,
Run: executeGetAllOnlineUsers,
}
func executeGetAllOnlineUsers(cmd *base.Command, args []string) {
setSharedFlags(cmd)
cmd.Flag.Parse(args)
conn, ctx, close := dialAPIServer()
defer close()
client := statsService.NewStatsServiceClient(conn)
r := &statsService.GetAllOnlineUsersRequest{}
resp, err := client.GetAllOnlineUsers(ctx, r)
if err != nil {
base.Fatalf("failed to get stats: %s", err)
}
showJSONResponse(resp)
}
-40
View File
@@ -1,40 +0,0 @@
package tls
import (
"flag"
"fmt"
"os"
"github.com/xtls/xray-core/main/commands/base"
"github.com/xtls/xray-core/transport/internet/tls"
)
var cmdCertChainHash = &base.Command{
UsageLine: "{{.Exec}} certChainHash",
Short: "Calculate TLS certificates hash.",
Long: `
xray tls certChainHash --cert <cert.pem>
Calculate TLS certificate chain hash.
`,
}
func init() {
cmdCertChainHash.Run = executeCertChainHash // break init loop
}
var input = cmdCertChainHash.Flag.String("cert", "fullchain.pem", "The file path of the certificates chain")
func executeCertChainHash(cmd *base.Command, args []string) {
fs := flag.NewFlagSet("certChainHash", flag.ContinueOnError)
if err := fs.Parse(args); err != nil {
fmt.Println(err)
return
}
certContent, err := os.ReadFile(*input)
if err != nil {
fmt.Println(err)
return
}
certChainHashB64 := tls.CalculatePEMCertChainSHA256Hash(certContent)
fmt.Println(certChainHashB64)
}
+44
View File
@@ -0,0 +1,44 @@
package tls
import (
"flag"
"fmt"
"os"
"github.com/xtls/xray-core/main/commands/base"
"github.com/xtls/xray-core/transport/internet/tls"
)
var cmdLeafCertHash = &base.Command{
UsageLine: "{{.Exec}} tls leafCertHash",
Short: "Calculate TLS leaf certificate hash.",
Long: `
xray tls leafCertHash --cert <cert.pem>
Calculate TLS leaf certificate hash.
`,
}
func init() {
cmdLeafCertHash.Run = executeLeafCertHash // break init loop
}
var input = cmdLeafCertHash.Flag.String("cert", "fullchain.pem", "The file path of the leaf certificate")
func executeLeafCertHash(cmd *base.Command, args []string) {
fs := flag.NewFlagSet("leafCertHash", flag.ContinueOnError)
if err := fs.Parse(args); err != nil {
fmt.Println(err)
return
}
certContent, err := os.ReadFile(*input)
if err != nil {
fmt.Println(err)
return
}
certChainHashB64, err := tls.CalculatePEMLeafCertSHA256Hash(certContent)
if err != nil {
fmt.Println("failed to decode cert", err)
return
}
fmt.Println(certChainHashB64)
}
+9 -3
View File
@@ -3,7 +3,7 @@ package tls
import (
gotls "crypto/tls"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"fmt"
"net"
"strconv"
@@ -156,8 +156,14 @@ func printTLSConnDetail(tlsConn *gotls.Conn) {
func showCert() func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
hash := GenerateCertChainHash(rawCerts)
fmt.Println("Certificate Chain Hash: ", base64.StdEncoding.EncodeToString(hash))
var hash []byte
for _, asn1Data := range rawCerts {
cert, _ := x509.ParseCertificate(asn1Data)
if cert.IsCA {
hash = GenerateCertHash(cert)
}
}
fmt.Println("Certificate Leaf Hash: ", hex.EncodeToString(hash))
return nil
}
}
+1 -1
View File
@@ -13,7 +13,7 @@ var CmdTLS = &base.Command{
Commands: []*base.Command{
cmdCert,
cmdPing,
cmdCertChainHash,
cmdLeafCertHash,
cmdECH,
},
}
+2 -1
View File
@@ -111,7 +111,8 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
destinationOverridden = true
}
}
if tlsConn, ok := conn.(tls.Interface); ok && !destinationOverridden {
iConn := stat.TryUnwrapStatsConn(conn)
if tlsConn, ok := iConn.(tls.Interface); ok && !destinationOverridden {
if serverName := tlsConn.HandshakeContextServerName(ctx); serverName != "" {
dest.Address = net.DomainAddress(serverName)
destinationOverridden = true
+1 -4
View File
@@ -296,10 +296,7 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u
return nil, err
}
iConn := rawConn
if statConn, ok := iConn.(*stat.CounterConnection); ok {
iConn = statConn.Connection
}
iConn := stat.TryUnwrapStatsConn(rawConn)
nextProto := ""
if tlsConn, ok := iConn.(*tls.Conn); ok {
+264
View File
@@ -0,0 +1,264 @@
package hysteria
import (
"context"
go_errors "errors"
"io"
"math/rand"
"github.com/apernet/quic-go"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/common/task"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/policy"
hyCtx "github.com/xtls/xray-core/proxy/hysteria/ctx"
"github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/hysteria"
"github.com/xtls/xray-core/transport/internet/stat"
)
type Client struct {
server *protocol.ServerSpec
policyManager policy.Manager
}
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
if config.Server == nil {
return nil, errors.New(`no target server found`)
}
server, err := protocol.NewServerSpecFromPB(config.Server)
if err != nil {
return nil, errors.New("failed to get server spec").Base(err)
}
v := core.MustFromContext(ctx)
client := &Client{
server: server,
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
}
return client, nil
}
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
if !ob.Target.IsValid() {
return errors.New("target not specified")
}
ob.Name = "hysteria"
ob.CanSpliceCopy = 3
target := ob.Target
conn, err := dialer.Dial(hyCtx.ContextWithRequireDatagram(ctx, target.Network == net.Network_UDP), c.server.Destination)
if err != nil {
return errors.New("failed to find an available destination").AtWarning().Base(err)
}
defer conn.Close()
errors.LogInfo(ctx, "tunneling request to ", target, " via ", target.Network, ":", c.server.Destination.NetAddr())
var newCtx context.Context
var newCancel context.CancelFunc
if session.TimeoutOnlyFromContext(ctx) {
newCtx, newCancel = context.WithCancel(context.Background())
}
sessionPolicy := c.policyManager.ForLevel(0)
ctx, cancel := context.WithCancel(ctx)
timer := signal.CancelAfterInactivity(ctx, func() {
cancel()
if newCancel != nil {
newCancel()
}
}, sessionPolicy.Timeouts.ConnectionIdle)
if newCtx != nil {
ctx = newCtx
}
if target.Network == net.Network_TCP {
requestDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
bufferedWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
err := WriteTCPRequest(bufferedWriter, target.NetAddr())
if err != nil {
return errors.New("failed to write request").Base(err)
}
if err := bufferedWriter.SetBuffered(false); err != nil {
return err
}
return buf.Copy(link.Reader, bufferedWriter, buf.UpdateActivity(timer))
}
responseDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
ok, msg, err := ReadTCPResponse(conn)
if err != nil {
return err
}
if !ok {
return errors.New(msg)
}
return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
}
responseDoneAndCloseWriter := task.OnSuccess(responseDone, task.Close(link.Writer))
if err := task.Run(ctx, requestDone, responseDoneAndCloseWriter); err != nil {
return errors.New("connection ends").Base(err)
}
return nil
}
if target.Network == net.Network_UDP {
iConn := stat.TryUnwrapStatsConn(conn)
_, ok := iConn.(*hysteria.InterUdpConn)
if !ok {
return errors.New("udp requires hysteria udp transport")
}
requestDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
writer := &UDPWriter{
Writer: conn,
buf: make([]byte, MaxUDPSize),
addr: target.NetAddr(),
}
if err := buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to transport all UDP request").Base(err)
}
return nil
}
responseDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
reader := &UDPReader{
Reader: conn,
df: &Defragger{},
}
if err := buf.Copy(reader, link.Writer, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to transport all UDP response").Base(err)
}
return nil
}
responseDoneAndCloseWriter := task.OnSuccess(responseDone, task.Close(link.Writer))
if err := task.Run(ctx, requestDone, responseDoneAndCloseWriter); err != nil {
return errors.New("connection ends").Base(err)
}
return nil
}
return nil
}
func init() {
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewClient(ctx, config.(*ClientConfig))
}))
}
type UDPWriter struct {
Writer io.Writer
buf []byte
addr string
}
func (w *UDPWriter) sendMsg(msg *UDPMessage) error {
msgN := msg.Serialize(w.buf)
if msgN < 0 {
// Message larger than buffer, silent drop
return nil
}
_, err := w.Writer.Write(w.buf[:msgN])
return err
}
func (w *UDPWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
for {
mb2, b := buf.SplitFirst(mb)
mb = mb2
if b == nil {
break
}
addr := w.addr
if b.UDP != nil {
addr = b.UDP.NetAddr()
}
msg := &UDPMessage{
SessionID: 0,
PacketID: 0,
FragID: 0,
FragCount: 1,
Addr: addr,
Data: b.Bytes(),
}
if err := w.sendMsg(msg); err != nil {
var errTooLarge *quic.DatagramTooLargeError
if go_errors.As(err, &errTooLarge) {
msg.PacketID = uint16(rand.Intn(0xFFFF)) + 1
fMsgs := FragUDPMessage(msg, int(errTooLarge.MaxDatagramPayloadSize))
for _, fMsg := range fMsgs {
err := w.sendMsg(&fMsg)
if err != nil {
b.Release()
buf.ReleaseMulti(mb)
return err
}
}
} else {
b.Release()
buf.ReleaseMulti(mb)
return err
}
}
b.Release()
}
return nil
}
type UDPReader struct {
Reader io.Reader
df *Defragger
}
func (r *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
for {
b := buf.New()
_, err := b.ReadFrom(r.Reader)
if err != nil {
b.Release()
return nil, err
}
msg, err := ParseUDPMessage(b.Bytes())
if err != nil {
b.Release()
continue
}
dfMsg := r.df.Feed(msg)
if dfMsg == nil {
continue
}
dest, _ := net.ParseDestination("udp:" + dfMsg.Addr)
buffer := buf.New()
buffer.Write(dfMsg.Data)
buffer.UDP = &dest
return buf.MultiBuffer{buffer}, nil
}
}
+10
View File
@@ -0,0 +1,10 @@
package hysteria
import (
"github.com/xtls/xray-core/transport/internet/hysteria/padding"
)
var (
tcpRequestPadding = padding.Padding{Min: 64, Max: 512}
// tcpResponsePadding = padding.Padding{Min: 128, Max: 1024}
)
+135
View File
@@ -0,0 +1,135 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.10
// protoc v6.33.1
// source: proxy/hysteria/config.proto
package hysteria
import (
protocol "github.com/xtls/xray-core/common/protocol"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type ClientConfig struct {
state protoimpl.MessageState `protogen:"open.v1"`
Version int32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
Server *protocol.ServerEndpoint `protobuf:"bytes,2,opt,name=server,proto3" json:"server,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ClientConfig) Reset() {
*x = ClientConfig{}
mi := &file_proxy_hysteria_config_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ClientConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ClientConfig) ProtoMessage() {}
func (x *ClientConfig) ProtoReflect() protoreflect.Message {
mi := &file_proxy_hysteria_config_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ClientConfig.ProtoReflect.Descriptor instead.
func (*ClientConfig) Descriptor() ([]byte, []int) {
return file_proxy_hysteria_config_proto_rawDescGZIP(), []int{0}
}
func (x *ClientConfig) GetVersion() int32 {
if x != nil {
return x.Version
}
return 0
}
func (x *ClientConfig) GetServer() *protocol.ServerEndpoint {
if x != nil {
return x.Server
}
return nil
}
var File_proxy_hysteria_config_proto protoreflect.FileDescriptor
const file_proxy_hysteria_config_proto_rawDesc = "" +
"\n" +
"\x1bproxy/hysteria/config.proto\x12\x13xray.proxy.hysteria\x1a!common/protocol/server_spec.proto\"f\n" +
"\fClientConfig\x12\x18\n" +
"\aversion\x18\x01 \x01(\x05R\aversion\x12<\n" +
"\x06server\x18\x02 \x01(\v2$.xray.common.protocol.ServerEndpointR\x06serverB[\n" +
"\x17com.xray.proxy.hysteriaP\x01Z(github.com/xtls/xray-core/proxy/hysteria\xaa\x02\x13Xray.Proxy.Hysteriab\x06proto3"
var (
file_proxy_hysteria_config_proto_rawDescOnce sync.Once
file_proxy_hysteria_config_proto_rawDescData []byte
)
func file_proxy_hysteria_config_proto_rawDescGZIP() []byte {
file_proxy_hysteria_config_proto_rawDescOnce.Do(func() {
file_proxy_hysteria_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proxy_hysteria_config_proto_rawDesc), len(file_proxy_hysteria_config_proto_rawDesc)))
})
return file_proxy_hysteria_config_proto_rawDescData
}
var file_proxy_hysteria_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_proxy_hysteria_config_proto_goTypes = []any{
(*ClientConfig)(nil), // 0: xray.proxy.hysteria.ClientConfig
(*protocol.ServerEndpoint)(nil), // 1: xray.common.protocol.ServerEndpoint
}
var file_proxy_hysteria_config_proto_depIdxs = []int32{
1, // 0: xray.proxy.hysteria.ClientConfig.server:type_name -> xray.common.protocol.ServerEndpoint
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_proxy_hysteria_config_proto_init() }
func file_proxy_hysteria_config_proto_init() {
if File_proxy_hysteria_config_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proxy_hysteria_config_proto_rawDesc), len(file_proxy_hysteria_config_proto_rawDesc)),
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proxy_hysteria_config_proto_goTypes,
DependencyIndexes: file_proxy_hysteria_config_proto_depIdxs,
MessageInfos: file_proxy_hysteria_config_proto_msgTypes,
}.Build()
File_proxy_hysteria_config_proto = out.File
file_proxy_hysteria_config_proto_goTypes = nil
file_proxy_hysteria_config_proto_depIdxs = nil
}
+14
View File
@@ -0,0 +1,14 @@
syntax = "proto3";
package xray.proxy.hysteria;
option csharp_namespace = "Xray.Proxy.Hysteria";
option go_package = "github.com/xtls/xray-core/proxy/hysteria";
option java_package = "com.xray.proxy.hysteria";
option java_multiple_files = true;
import "common/protocol/server_spec.proto";
message ClientConfig {
int32 version = 1;
xray.common.protocol.ServerEndpoint server = 2;
}
+23
View File
@@ -0,0 +1,23 @@
package ctx
import (
"context"
)
type key int
const (
requireDatagram key = iota
)
func ContextWithRequireDatagram(ctx context.Context, udp bool) context.Context {
if !udp {
return ctx
}
return context.WithValue(ctx, requireDatagram, struct{}{})
}
func RequireDatagramFromContext(ctx context.Context) bool {
_, ok := ctx.Value(requireDatagram).(struct{})
return ok
}
+73
View File
@@ -0,0 +1,73 @@
package hysteria
func FragUDPMessage(m *UDPMessage, maxSize int) []UDPMessage {
if m.Size() <= maxSize {
return []UDPMessage{*m}
}
fullPayload := m.Data
maxPayloadSize := maxSize - m.HeaderSize()
off := 0
fragID := uint8(0)
fragCount := uint8((len(fullPayload) + maxPayloadSize - 1) / maxPayloadSize) // round up
frags := make([]UDPMessage, fragCount)
for off < len(fullPayload) {
payloadSize := len(fullPayload) - off
if payloadSize > maxPayloadSize {
payloadSize = maxPayloadSize
}
frag := *m
frag.FragID = fragID
frag.FragCount = fragCount
frag.Data = fullPayload[off : off+payloadSize]
frags[fragID] = frag
off += payloadSize
fragID++
}
return frags
}
// Defragger handles the defragmentation of UDP messages.
// The current implementation can only handle one packet ID at a time.
// If another packet arrives before a packet has received all fragments
// in their entirety, any previous state is discarded.
type Defragger struct {
pktID uint16
frags []*UDPMessage
count uint8
size int // data size
}
func (d *Defragger) Feed(m *UDPMessage) *UDPMessage {
if m.FragCount <= 1 {
return m
}
if m.FragID >= m.FragCount {
// wtf is this?
return nil
}
if m.PacketID != d.pktID || m.FragCount != uint8(len(d.frags)) {
// new message, clear previous state
d.pktID = m.PacketID
d.frags = make([]*UDPMessage, m.FragCount)
d.frags[m.FragID] = m
d.count = 1
d.size = len(m.Data)
} else if d.frags[m.FragID] == nil {
d.frags[m.FragID] = m
d.count++
d.size += len(m.Data)
if int(d.count) == len(d.frags) {
// all fragments received, assemble
data := make([]byte, d.size)
off := 0
for _, frag := range d.frags {
off += copy(data[off:], frag.Data)
}
m.Data = data
m.FragID = 0
m.FragCount = 1
return m
}
}
return nil
}

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