Compare commits

..

90 Commits

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

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

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2025-02-13 14:01:33 +00:00
yiguous
94c7970fd6 Config: Correctly marshal PortList and NameServerConfig to JSON (#4386) 2025-02-12 14:55:16 +00:00
𐲓𐳛𐳪𐳂𐳐 𐲀𐳢𐳦𐳫𐳢 𐲥𐳔𐳛𐳪𐳌𐳑𐳖𐳇
a71762b5da Workflows: Fix Actions' manual dispatch for assets update (#4378) 2025-02-11 13:19:03 +00:00
dependabot[bot]
5033cbceea Bump golang.org/x/net from 0.34.0 to 0.35.0 (#4382)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.34.0 to 0.35.0.
- [Commits](https://github.com/golang/net/compare/v0.34.0...v0.35.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 13:14:22 +00:00
RPRX
dcd7e92c45 XHTTP server: Finish stream-up's HTTP POST when its request.Body is closed
https://github.com/XTLS/Xray-core/issues/4373#issuecomment-2647908310

Fixes https://github.com/XTLS/Xray-core/issues/4373
2025-02-10 13:56:13 +00:00
dependabot[bot]
2d7ca4a6a6 Bump golang.org/x/crypto from 0.32.0 to 0.33.0 (#4375)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.32.0 to 0.33.0.
- [Commits](https://github.com/golang/crypto/compare/v0.32.0...v0.33.0)

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-07 10:09:50 +00:00
RPRX
117de1fd3c MITM freedom RAW TLS: Report website with unexpected Negotiated Protocol / invalid Domain Fronting certificate
https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2639965524

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-06 11:31:13 +00:00
dependabot[bot]
e17c068821 Bump golang.org/x/sync from 0.10.0 to 0.11.0 (#4351)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/sync/compare/v0.10.0...v0.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-06 11:30:58 +00:00
dependabot[bot]
88d40d6367 Bump golang.org/x/sys from 0.29.0 to 0.30.0 (#4350)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.29.0 to 0.30.0.
- [Commits](https://github.com/golang/sys/compare/v0.29.0...v0.30.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-06 11:28:02 +00:00
RPRX
527caa3711 Log: Add microseconds for golang's standard logger
Completes 5679d717ee
2025-02-06 07:50:48 +00:00
RPRX
c6a31f457c MITM: Allow using local received SNI in the outgoing serverName & verifyPeerCertInNames
https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2637370175

Local received SNI was sent by browser/app.

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

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

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

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 20:45:59 +00:00
dependabot[bot]
1bb0beaa43 Bump github.com/miekg/dns from 1.1.62 to 1.1.63 (#4330)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.62 to 1.1.63.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.62...v1.1.63)

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

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

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

Closes https://github.com/XTLS/Xray-core/issues/4313
2025-01-25 10:51:44 +00:00
dependabot[bot]
a0822cb440 Bump google.golang.org/grpc from 1.69.4 to 1.70.0 (#4322)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.69.4 to 1.70.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.4...v1.70.0)

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-16 13:21:31 +00:00
dependabot[bot]
4576f56ec8 Bump google.golang.org/grpc from 1.69.2 to 1.69.4 (#4288)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.69.2 to 1.69.4.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.2...v1.69.4)

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 02:02:00 +00:00
dependabot[bot]
5635254ebc Bump golang.org/x/net from 0.33.0 to 0.34.0 (#4262)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.33.0 to 0.34.0.
- [Commits](https://github.com/golang/net/compare/v0.33.0...v0.34.0)

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-01 08:22:00 +00:00
dependabot[bot]
1a1c49de36 Bump google.golang.org/grpc from 1.67.1 to 1.69.2 (#4181)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.1 to 1.69.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.67.1...v1.69.2)

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

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

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

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

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

* Add mutex to injection resolution

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

* Add OptionalFeatures injection

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-24 13:03:17 +00:00
leo
b287d6419b chore: use errors.New to replace fmt.Errorf with no parameters (#4204)
Signed-off-by: RiceChuan <lc582041246@gmail.com>
2024-12-24 00:17:00 -05:00
dependabot[bot]
d54d20abea Bump golang.org/x/net from 0.32.0 to 0.33.0 (#4182)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.32.0 to 0.33.0.
- [Commits](https://github.com/golang/net/compare/v0.32.0...v0.33.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-22 09:21:06 +00:00
maoxikun
868799ef04 DNS: Always use a DNS Message ID of 0 for DoH and DoQ (#4193)
Co-authored-by: dyhkwong <50692134+dyhkwong@users.noreply.github.com>
2024-12-22 09:19:09 +00:00
RPRX
db934f0832 XHTTP client: Merge Open* into OpenStream(), and more
https://github.com/XTLS/Xray-core/issues/4148#issuecomment-2557066988
2024-12-20 14:35:33 +00:00
RPRX
53b04d560b XHTTP client: Make H3 httptrace work on v2rayNG
Introduced in https://github.com/XTLS/Xray-core/pull/4150
2024-12-20 07:19:41 +00:00
RPRX
1410b6335b XHTTP XMUX: Fix OpenUsage never gets reduced
Introduced in https://github.com/XTLS/Xray-core/pull/4163
2024-12-20 06:19:10 +00:00
RPRX
cab2fdefd3 v24.12.18
XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
2024-12-18 13:39:35 +00:00
RPRX
ff8b66aacb XHTTP client: scMaxEachPostBytes should be bigger than buf.Size (8192)
To avoid no size limit.
2024-12-18 13:25:34 +00:00
dependabot[bot]
15318976f6 Bump google.golang.org/protobuf from 1.35.2 to 1.36.0 (#4175)
Bumps google.golang.org/protobuf from 1.35.2 to 1.36.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-18 11:43:48 +00:00
dependabot[bot]
a168f5360e Bump golang.org/x/crypto from 0.30.0 to 0.31.0 (#4156)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.30.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.30.0...v0.31.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-18 11:32:11 +00:00
RPRX
9dbdf92c27 XHTTP downloadSettings: Inherit sockopt if its own doesn't exist (e.g., in extra)
If you want `downloadSettings` to use its own `sockopt`, make sure that `extra` doesn't exist.
2024-12-18 11:22:29 +00:00
RPRX
96fb680d45 REALITY, TLS config: Set "chrome" as the default fingerprint
Other VLESS implementations should follow this change.
2024-12-17 11:02:51 +00:00
珐琅彩山水佩奇童车游春马蹄杯
5836afc41f WebSocket config: Fix headers (#4177)
Fixes https://github.com/XTLS/Xray-core/issues/4176
2024-12-17 08:53:16 +00:00
119 changed files with 2292 additions and 1475 deletions

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

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

View File

@@ -1,76 +1,15 @@
name: Build and Release
# NOTE: This Github Actions file depends on the Makefile.
# Building the correct package requires the correct binaries generated by the Makefile. To
# ensure the correct output, the Makefile must accept the appropriate input and compile the
# correct file with the correct name. If you need to modify this file, please ensure it won't
# disrupt the Makefile.
on:
workflow_dispatch:
release:
types: [published]
push:
branches:
- main
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/release.yml"
pull_request:
types: [opened, synchronize, reopened]
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/release.yml"
jobs:
prepare:
runs-on: ubuntu-latest
steps:
- name: Restore Cache
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
- name: Update Geodat
id: update
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
retry_wait_seconds: 60
max_attempts: 60
command: |
[ -d 'resources' ] || mkdir resources
LIST=('geoip geoip geoip' 'domain-list-community dlc geosite')
for i in "${LIST[@]}"
do
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3}'))
FILE_NAME="${INFO[2]}.dat"
echo -e "Verifying HASH key..."
HASH="$(curl -sL "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
continue
else
echo -e "Downloading https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat..."
curl -L "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat" -o ./resources/${FILE_NAME}
echo -e "Verifying HASH key..."
[ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
echo "unhit=true" >> $GITHUB_OUTPUT
fi
done
- name: Save Cache
uses: actions/cache/save@v4
if: ${{ steps.update.outputs.unhit }}
with:
path: resources
key: xray-geodat-${{ github.sha }}-${{ github.run_number }}
build:
needs: prepare
permissions:
contents: write
strategy:
@@ -78,9 +17,7 @@ jobs:
# Include amd64 on all platforms.
goos: [windows, freebsd, openbsd, linux, darwin]
goarch: [amd64, 386]
gotoolchain: [""]
patch-assetname: [""]
exclude:
# Exclude i386 on darwin
- goarch: 386
@@ -155,16 +92,6 @@ jobs:
goarch: arm
goarm: 7
# END OPENBSD ARM
# BEGIN Windows 7
- goos: windows
goarch: amd64
gotoolchain: 1.21.4
patch-assetname: win7-64
- goos: windows
goarch: 386
gotoolchain: 1.21.4
patch-assetname: win7-32
# END Windows 7
fail-fast: false
runs-on: ubuntu-latest
@@ -187,7 +114,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.gotoolchain || '1.23' }}
go-version-file: go.mod
check-latest: true
- name: Get project dependencies
@@ -196,10 +123,24 @@ jobs:
- name: Build Xray
run: |
mkdir -p build_assets
make
find . -maxdepth 1 -type f -regex './\(wxray\|xray\|xray_softfloat\)\(\|.exe\)' -exec mv {} ./build_assets/ \;
COMMID=$(git describe --always --dirty)
if [[ ${GOOS} == 'windows' ]]; then
echo 'Building Xray for Windows...'
go build -o build_assets/xray.exe -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
# The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
else
echo 'Building Xray...'
go build -o build_assets/xray -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
if [[ ${GOARCH} == 'mips' || ${GOARCH} == 'mipsle' ]]; then
echo 'Building soft-float Xray for MIPS/MIPSLE 32-bit...'
GOMIPS=softfloat go build -o build_assets/xray_softfloat -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
fi
fi
- name: Restore Cache
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
with:
path: resources

View File

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

View File

@@ -2,20 +2,8 @@ name: Test
on:
push:
branches:
- main
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/*.yml"
pull_request:
types: [opened, synchronize, reopened]
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/*.yml"
jobs:
test:
@@ -32,9 +20,9 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version-file: go.mod
check-latest: true
- name: Restore Cache
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
with:
path: resources

View File

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

View File

@@ -24,7 +24,9 @@
[Project X Channel](https://t.me/projectXtls)
[Project VLESS](https://t.me/projectVless) (non-Chinese)
[Project VLESS](https://t.me/projectVless) (Русский)
[Project XHTTP](https://t.me/projectXhttp) (Persian)
## Installation
@@ -72,6 +74,8 @@
- [PassWall](https://github.com/xiaorouji/openwrt-passwall), [PassWall 2](https://github.com/xiaorouji/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)
- Windows
- [v2rayN](https://github.com/2dust/v2rayN)
- [Furious](https://github.com/LorenEteval/Furious)
@@ -98,6 +102,7 @@
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
- Xray Tools
- [xray-knife](https://github.com/lilendian0x00/xray-knife)
- [xray-checker](https://github.com/kutovoys/xray-checker)
- Xray Wrapper
- [XTLS/libXray](https://github.com/XTLS/libXray)
- [xtlsapi](https://github.com/hiddify/xtlsapi)
@@ -121,25 +126,27 @@
- [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases).
- For third-party projects used in [Xray-core](https://github.com/XTLS/Xray-core), check your local or [the latest go.mod](https://github.com/XTLS/Xray-core/blob/main/go.mod).
## Compilation
## One-line Compilation
### Windows (PowerShell)
```powershell
$env:CGO_ENABLED=0
go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main
go build -o xray.exe -trimpath -buildvcs=false -ldflags="-s -w -buildid=" -v ./main
```
### Linux / macOS
```bash
CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags="-s -w -buildid=" -v ./main
```
### Reproducible Releases
Make sure that you are using the same Go version, and remember to set the git commit id (7 bytes):
```bash
make
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=REPLACE -s -w -buildid=" -v ./main
```
## Stargazers over time

View File

@@ -106,7 +106,7 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
d := new(DefaultDispatcher)
if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error {
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { // FakeDNSEngine is optional
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
d.fdns = fdns
})
return d.Init(config.(*Config), om, router, pm, sm, dc)

View File

@@ -43,10 +43,12 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
}
switch {
case strings.EqualFold(u.String(), "localhost"):
return NewLocalNameServer(), nil
case strings.EqualFold(u.Scheme, "https"): // DOH Remote mode
return NewDoHNameServer(u, dispatcher, queryStrategy)
case strings.EqualFold(u.Scheme, "https+local"): // DOH Local mode
return NewLocalNameServer(queryStrategy), nil
case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode
return NewDoHNameServer(u, dispatcher, queryStrategy, false)
case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode
return NewDoHNameServer(u, dispatcher, queryStrategy, true)
case strings.EqualFold(u.Scheme, "https+local"): // DNS-over-HTTPS Local mode
return NewDoHLocalNameServer(u, queryStrategy), nil
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
return NewQUICNameServer(u, queryStrategy)
@@ -56,7 +58,7 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
return NewTCPLocalNameServer(u, queryStrategy)
case strings.EqualFold(u.String(), "fakedns"):
var fd dns.FakeDNSEngine
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { // FakeDNSEngine is optional
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
fd = fdns
})
return NewFakeDNSServer(fd), nil

View File

@@ -3,12 +3,12 @@ package dns
import (
"bytes"
"context"
"crypto/tls"
"fmt"
"io"
"net/http"
"net/url"
"sync"
"sync/atomic"
"time"
"github.com/xtls/xray-core/common"
@@ -24,6 +24,7 @@ import (
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet"
"golang.org/x/net/dns/dnsmessage"
"golang.org/x/net/http2"
)
// DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format,
@@ -35,7 +36,6 @@ type DoHNameServer struct {
ips map[string]*record
pub *pubsub.Service
cleanup *task.Periodic
reqID uint32
httpClient *http.Client
dohURL string
name string
@@ -43,49 +43,64 @@ type DoHNameServer struct {
}
// NewDoHNameServer creates DOH server object for remote resolving.
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (*DoHNameServer, error) {
errors.LogInfo(context.Background(), "DNS: created Remote DOH client for ", url.String())
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, queryStrategy QueryStrategy, h2c bool) (*DoHNameServer, error) {
url.Scheme = "https"
errors.LogInfo(context.Background(), "DNS: created Remote DNS-over-HTTPS client for ", url.String(), ", with h2c ", h2c)
s := baseDOHNameServer(url, "DOH", queryStrategy)
s.dispatcher = dispatcher
tr := &http.Transport{
MaxIdleConns: 30,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 30 * time.Second,
ForceAttemptHTTP2: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
link, err := s.dispatcher.Dispatch(toDnsContext(ctx, s.dohURL), dest)
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
dialContext := func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
dnsCtx := toDnsContext(ctx, s.dohURL)
if h2c {
dnsCtx = session.ContextWithMitmAlpn11(dnsCtx, false) // for insurance
dnsCtx = session.ContextWithMitmServerName(dnsCtx, url.Hostname())
}
link, err := s.dispatcher.Dispatch(dnsCtx, dest)
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if err != nil {
return nil, err
}
}
if err != nil {
return nil, err
}
cc := common.ChainedClosable{}
if cw, ok := link.Writer.(common.Closable); ok {
cc = append(cc, cw)
}
if cr, ok := link.Reader.(common.Closable); ok {
cc = append(cc, cr)
}
return cnc.NewConnection(
cnc.ConnectionInputMulti(link.Writer),
cnc.ConnectionOutputMulti(link.Reader),
cnc.ConnectionOnClose(cc),
), nil
cc := common.ChainedClosable{}
if cw, ok := link.Writer.(common.Closable); ok {
cc = append(cc, cw)
}
if cr, ok := link.Reader.(common.Closable); ok {
cc = append(cc, cr)
}
return cnc.NewConnection(
cnc.ConnectionInputMulti(link.Writer),
cnc.ConnectionOutputMulti(link.Reader),
cnc.ConnectionOnClose(cc),
), nil
}
s.httpClient = &http.Client{
Timeout: time.Second * 180,
Transport: &http.Transport{
MaxIdleConns: 30,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 30 * time.Second,
ForceAttemptHTTP2: true,
DialContext: dialContext,
},
}
s.httpClient = &http.Client{
Timeout: time.Second * 180,
Transport: tr,
if h2c {
s.httpClient.Transport = &http2.Transport{
IdleConnTimeout: 90 * time.Second,
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
return dialContext(ctx, network, addr)
},
}
}
return s, nil
@@ -120,7 +135,7 @@ func NewDoHLocalNameServer(url *url.URL, queryStrategy QueryStrategy) *DoHNameSe
Timeout: time.Second * 180,
Transport: tr,
}
errors.LogInfo(context.Background(), "DNS: created Local DOH client for ", url.String())
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-HTTPS client for ", url.String())
return s
}
@@ -222,7 +237,7 @@ func (s *DoHNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
}
func (s *DoHNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1))
return 0
}
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {

View File

@@ -14,13 +14,19 @@ import (
// LocalNameServer is an wrapper over local DNS feature.
type LocalNameServer struct {
client *localdns.Client
client *localdns.Client
queryStrategy QueryStrategy
}
const errEmptyResponse = "No address associated with hostname"
// QueryIP implements Server.
func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) (ips []net.IP, err error) {
option = ResolveIpOptionOverride(s.queryStrategy, option)
if !option.IPv4Enable && !option.IPv6Enable {
return nil, dns.ErrEmptyResponse
}
start := time.Now()
ips, err = s.client.LookupIP(domain, option)
@@ -42,14 +48,15 @@ func (s *LocalNameServer) Name() string {
}
// NewLocalNameServer creates localdns server object for directly lookup in system DNS.
func NewLocalNameServer() *LocalNameServer {
func NewLocalNameServer(queryStrategy QueryStrategy) *LocalNameServer {
errors.LogInfo(context.Background(), "DNS: created localhost client")
return &LocalNameServer{
client: localdns.New(),
queryStrategy: queryStrategy,
client: localdns.New(),
}
}
// NewLocalDNSClient creates localdns client object for directly lookup in system DNS.
func NewLocalDNSClient() *Client {
return &Client{server: NewLocalNameServer()}
return &Client{server: NewLocalNameServer(QueryStrategy_USE_IP)}
}

View File

@@ -12,7 +12,7 @@ import (
)
func TestLocalNameServer(t *testing.T) {
s := NewLocalNameServer()
s := NewLocalNameServer(QueryStrategy_USE_IP)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{
IPv4Enable: true,

View File

@@ -6,7 +6,6 @@ import (
"encoding/binary"
"net/url"
"sync"
"sync/atomic"
"time"
"github.com/quic-go/quic-go"
@@ -37,7 +36,6 @@ type QUICNameServer struct {
ips map[string]*record
pub *pubsub.Service
cleanup *task.Periodic
reqID uint32
name string
destination *net.Destination
connection quic.Connection
@@ -156,7 +154,7 @@ func (s *QUICNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
}
func (s *QUICNameServer) newReqID() uint16 {
return uint16(atomic.AddUint32(&s.reqID, 1))
return 0
}
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {

View File

@@ -27,7 +27,8 @@ type Config struct {
unknownFields protoimpl.UnknownFields
// Tag of the outbound handler that handles metrics http connections.
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
Listen string `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
}
func (x *Config) Reset() {
@@ -67,20 +68,28 @@ func (x *Config) GetTag() string {
return ""
}
func (x *Config) GetListen() string {
if x != nil {
return x.Listen
}
return ""
}
var File_app_metrics_config_proto protoreflect.FileDescriptor
var file_app_metrics_config_proto_rawDesc = []byte{
0x0a, 0x18, 0x61, 0x70, 0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x1a, 0x0a, 0x06,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x32, 0x0a, 0x06,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x42, 0x52, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x50, 0x01, 0x5a, 0x25, 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, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0xaa, 0x02, 0x10, 0x58, 0x72, 0x61, 0x79,
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74,
0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e,
0x42, 0x52, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x50, 0x01, 0x5a, 0x25, 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, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
0x73, 0xaa, 0x02, 0x10, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4d, 0x65, 0x74,
0x72, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

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

View File

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

View File

@@ -66,10 +66,10 @@ func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *H
settings.Timeout = time.Duration(5) * time.Second
}
return &HealthPing{
ctx: ctx,
ctx: ctx,
dispatcher: dispatcher,
Settings: settings,
Results: nil,
Settings: settings,
Results: nil,
}
}

View File

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

View File

@@ -32,7 +32,7 @@ type Observer struct {
finished *done.Instance
ohm outbound.Manager
ohm outbound.Manager
dispatcher routing.Dispatcher
}
@@ -226,9 +226,9 @@ func New(ctx context.Context, config *Config) (*Observer, error) {
return nil, errors.New("Cannot get depended features").Base(err)
}
return &Observer{
config: config,
ctx: ctx,
ohm: outboundManager,
config: config,
ctx: ctx,
ohm: outboundManager,
dispatcher: dispatcher,
}, nil
}

View File

@@ -177,7 +177,7 @@ func (s *service) Register(server *grpc.Server) {
common.Must(s.v.RequireFeatures(func(im inbound.Manager, om outbound.Manager) {
hs.ihm = im
hs.ohm = om
}))
}, false))
RegisterHandlerServiceServer(server, hs)
// For compatibility purposes

View File

@@ -23,7 +23,7 @@ type DynamicInboundHandler struct {
receiverConfig *proxyman.ReceiverConfig
streamSettings *internet.MemoryStreamConfig
portMutex sync.Mutex
portsInUse map[net.Port]bool
portsInUse map[net.Port]struct{}
workerMutex sync.RWMutex
worker []worker
lastRefresh time.Time
@@ -39,7 +39,7 @@ func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *p
tag: tag,
proxyConfig: proxyConfig,
receiverConfig: receiverConfig,
portsInUse: make(map[net.Port]bool),
portsInUse: make(map[net.Port]struct{}),
mux: mux.NewServer(ctx),
v: v,
ctx: ctx,
@@ -84,7 +84,7 @@ func (h *DynamicInboundHandler) allocatePort() net.Port {
port := net.Port(allPorts[r])
_, used := h.portsInUse[port]
if !used {
h.portsInUse[port] = true
h.portsInUse[port] = struct{}{}
return port
}
}

View File

@@ -464,8 +464,7 @@ func (w *dsWorker) callback(conn stat.Connection) {
}
}
ctx = session.ContextWithInbound(ctx, &session.Inbound{
// Unix have no source addr, so we use gateway as source for log.
Source: net.UnixDestination(w.address),
Source: net.DestinationFromAddr(conn.RemoteAddr()),
Gateway: net.UnixDestination(w.address),
Tag: w.tag,
Conn: conn,

View File

@@ -5,6 +5,7 @@ import (
sync "sync"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension"
@@ -31,9 +32,10 @@ type RoundRobinStrategy struct {
func (s *RoundRobinStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx
if len(s.FallbackTag) > 0 {
core.RequireFeaturesAsync(s.ctx, func(observatory extension.Observatory) {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
})
return nil
}))
}
}

View File

@@ -135,7 +135,7 @@ func (s *service) Register(server *grpc.Server) {
vCoreDesc := RoutingService_ServiceDesc
vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService"
server.RegisterService(&vCoreDesc, rs)
}))
}, false))
}
func init() {

View File

@@ -7,6 +7,7 @@ import (
"time"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core"
@@ -59,9 +60,10 @@ type node struct {
func (s *LeastLoadStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx
core.RequireFeaturesAsync(s.ctx, func(observatory extension.Observatory) {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observer = observatory
})
return nil
}))
}
func (s *LeastLoadStrategy) PickOutbound(candidates []string) string {

View File

@@ -4,6 +4,7 @@ import (
"context"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension"
@@ -20,9 +21,10 @@ func (l *LeastPingStrategy) GetPrincipleTarget(strings []string) []string {
func (l *LeastPingStrategy) InjectContext(ctx context.Context) {
l.ctx = ctx
core.RequireFeaturesAsync(l.ctx, func(observatory extension.Observatory) {
common.Must(core.RequireFeatures(l.ctx, func(observatory extension.Observatory) error {
l.observatory = observatory
})
return nil
}))
}
func (l *LeastPingStrategy) PickOutbound(strings []string) string {

View File

@@ -4,6 +4,7 @@ import (
"context"
"github.com/xtls/xray-core/app/observatory"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension"
@@ -20,9 +21,10 @@ type RandomStrategy struct {
func (s *RandomStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx
if len(s.FallbackTag) > 0 {
core.RequireFeaturesAsync(s.ctx, func(observatory extension.Observatory) {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
})
return nil
}))
}
}

View File

@@ -60,6 +60,24 @@ func (s *statsServer) GetStatsOnline(ctx context.Context, request *GetStatsReque
}, nil
}
func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, request *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
c := s.stats.GetOnlineMap(request.Name)
if c == nil {
return nil, errors.New(request.Name, " not found.")
}
ips := make(map[string]int64)
for ip, t := range c.IpTimeMap() {
ips[ip] = t.Unix()
}
return &GetStatsOnlineIpListResponse{
Name: request.Name,
Ips: ips,
}, nil
}
func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
matcher, err := strmatcher.Substr.New(request.Pattern)
if err != nil {

View File

@@ -424,6 +424,59 @@ func (x *SysStatsResponse) GetUptime() uint32 {
return 0
}
type GetStatsOnlineIpListResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
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"`
}
func (x *GetStatsOnlineIpListResponse) Reset() {
*x = GetStatsOnlineIpListResponse{}
mi := &file_app_stats_command_command_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetStatsOnlineIpListResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetStatsOnlineIpListResponse) ProtoMessage() {}
func (x *GetStatsOnlineIpListResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[7]
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 GetStatsOnlineIpListResponse.ProtoReflect.Descriptor instead.
func (*GetStatsOnlineIpListResponse) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{7}
}
func (x *GetStatsOnlineIpListResponse) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *GetStatsOnlineIpListResponse) GetIps() map[string]int64 {
if x != nil {
return x.Ips
}
return nil
}
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -432,7 +485,7 @@ type Config struct {
func (x *Config) Reset() {
*x = Config{}
mi := &file_app_stats_command_command_proto_msgTypes[7]
mi := &file_app_stats_command_command_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -444,7 +497,7 @@ func (x *Config) String() string {
func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[7]
mi := &file_app_stats_command_command_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -457,7 +510,7 @@ 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{7}
return file_app_stats_command_command_proto_rawDescGZIP(), []int{8}
}
var File_app_stats_command_command_proto protoreflect.FileDescriptor
@@ -506,40 +559,60 @@ var file_app_stats_command_command_proto_rawDesc = []byte{
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, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xa1, 0x03,
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,
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, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61,
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, 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, 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,
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,
}
var (
@@ -554,33 +627,38 @@ func file_app_stats_command_command_proto_rawDescGZIP() []byte {
return file_app_stats_command_command_proto_rawDescData
}
var file_app_stats_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_app_stats_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_app_stats_command_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
(*QueryStatsRequest)(nil), // 3: xray.app.stats.command.QueryStatsRequest
(*QueryStatsResponse)(nil), // 4: xray.app.stats.command.QueryStatsResponse
(*SysStatsRequest)(nil), // 5: xray.app.stats.command.SysStatsRequest
(*SysStatsResponse)(nil), // 6: xray.app.stats.command.SysStatsResponse
(*Config)(nil), // 7: xray.app.stats.command.Config
(*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest
(*Stat)(nil), // 1: xray.app.stats.command.Stat
(*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse
(*QueryStatsRequest)(nil), // 3: xray.app.stats.command.QueryStatsRequest
(*QueryStatsResponse)(nil), // 4: xray.app.stats.command.QueryStatsResponse
(*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
}
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
0, // 2: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest
0, // 3: xray.app.stats.command.StatsService.GetStatsOnline:input_type -> xray.app.stats.command.GetStatsRequest
3, // 4: xray.app.stats.command.StatsService.QueryStats:input_type -> xray.app.stats.command.QueryStatsRequest
5, // 5: xray.app.stats.command.StatsService.GetSysStats:input_type -> xray.app.stats.command.SysStatsRequest
2, // 6: xray.app.stats.command.StatsService.GetStats:output_type -> xray.app.stats.command.GetStatsResponse
2, // 7: xray.app.stats.command.StatsService.GetStatsOnline:output_type -> xray.app.stats.command.GetStatsResponse
4, // 8: xray.app.stats.command.StatsService.QueryStats:output_type -> xray.app.stats.command.QueryStatsResponse
6, // 9: xray.app.stats.command.StatsService.GetSysStats:output_type -> xray.app.stats.command.SysStatsResponse
6, // [6:10] is the sub-list for method output_type
2, // [2:6] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
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
}
func init() { file_app_stats_command_command_proto_init() }
@@ -594,7 +672,7 @@ func file_app_stats_command_command_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_stats_command_command_proto_rawDesc,
NumEnums: 0,
NumMessages: 8,
NumMessages: 10,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -46,11 +46,17 @@ message SysStatsResponse {
uint32 Uptime = 10;
}
message GetStatsOnlineIpListResponse {
string name = 1;
map<string, int64> ips = 2;
}
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) {}
}
message Config {}

View File

@@ -19,10 +19,11 @@ import (
const _ = grpc.SupportPackageIsVersion9
const (
StatsService_GetStats_FullMethodName = "/xray.app.stats.command.StatsService/GetStats"
StatsService_GetStatsOnline_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnline"
StatsService_QueryStats_FullMethodName = "/xray.app.stats.command.StatsService/QueryStats"
StatsService_GetSysStats_FullMethodName = "/xray.app.stats.command.StatsService/GetSysStats"
StatsService_GetStats_FullMethodName = "/xray.app.stats.command.StatsService/GetStats"
StatsService_GetStatsOnline_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnline"
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"
)
// StatsServiceClient is the client API for StatsService service.
@@ -33,6 +34,7 @@ type StatsServiceClient interface {
GetStatsOnline(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error)
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)
}
type statsServiceClient struct {
@@ -83,6 +85,16 @@ func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysStatsReques
return out, nil
}
func (c *statsServiceClient) GetStatsOnlineIpList(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsOnlineIpListResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetStatsOnlineIpListResponse)
err := c.cc.Invoke(ctx, StatsService_GetStatsOnlineIpList_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.
@@ -91,6 +103,7 @@ type StatsServiceServer interface {
GetStatsOnline(context.Context, *GetStatsRequest) (*GetStatsResponse, error)
QueryStats(context.Context, *QueryStatsRequest) (*QueryStatsResponse, error)
GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error)
GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error)
mustEmbedUnimplementedStatsServiceServer()
}
@@ -113,6 +126,9 @@ func (UnimplementedStatsServiceServer) QueryStats(context.Context, *QueryStatsRe
func (UnimplementedStatsServiceServer) GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetSysStats not implemented")
}
func (UnimplementedStatsServiceServer) GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetStatsOnlineIpList not implemented")
}
func (UnimplementedStatsServiceServer) mustEmbedUnimplementedStatsServiceServer() {}
func (UnimplementedStatsServiceServer) testEmbeddedByValue() {}
@@ -206,6 +222,24 @@ func _StatsService_GetSysStats_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _StatsService_GetStatsOnlineIpList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetStatsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(StatsServiceServer).GetStatsOnlineIpList(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: StatsService_GetStatsOnlineIpList_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(StatsServiceServer).GetStatsOnlineIpList(ctx, req.(*GetStatsRequest))
}
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)
@@ -229,6 +263,10 @@ var StatsService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetSysStats",
Handler: _StatsService_GetSysStats_Handler,
},
{
MethodName: "GetStatsOnlineIpList",
Handler: _StatsService_GetStatsOnlineIpList_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "app/stats/command/command.proto",

View File

@@ -78,3 +78,13 @@ func (c *OnlineMap) RemoveExpiredIPs(list map[string]time.Time) map[string]time.
}
return list
}
func (c *OnlineMap) IpTimeMap() map[string]time.Time {
list := c.ipList
if time.Since(c.lastCleanup) > c.cleanupPeriod {
list = c.RemoveExpiredIPs(list)
c.lastCleanup = time.Now()
}
return c.ipList
}

View File

@@ -38,7 +38,7 @@ func Error2(v interface{}, err error) error {
func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" {
if file == "off" {
return "", fmt.Errorf("GOENV=off")
return "", errors.New("GOENV=off")
}
return file, nil
}
@@ -47,7 +47,7 @@ func envFile() (string, error) {
return "", err
}
if dir == "" {
return "", fmt.Errorf("missing user-config dir")
return "", errors.New("missing user-config dir")
}
return filepath.Join(dir, "go", "env"), nil
}
@@ -60,7 +60,7 @@ func GetRuntimeEnv(key string) (string, error) {
return "", err
}
if file == "" {
return "", fmt.Errorf("missing runtime env file")
return "", errors.New("missing runtime env file")
}
var data []byte
var runtimeEnv string

View File

@@ -146,7 +146,7 @@ func (w *fileLogWriter) Close() error {
func CreateStdoutLogWriter() WriterCreator {
return func() Writer {
return &consoleLogWriter{
logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
logger: log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lmicroseconds),
}
}
}
@@ -155,7 +155,7 @@ func CreateStdoutLogWriter() WriterCreator {
func CreateStderrLogWriter() WriterCreator {
return func() Writer {
return &consoleLogWriter{
logger: log.New(os.Stderr, "", log.Ldate|log.Ltime),
logger: log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lmicroseconds),
}
}
}
@@ -174,7 +174,7 @@ func CreateFileLogWriter(path string) (WriterCreator, error) {
}
return &fileLogWriter{
file: file,
logger: log.New(file, "", log.Ldate|log.Ltime),
logger: log.New(file, "", log.Ldate|log.Ltime|log.Lmicroseconds),
}
}, nil
}

View File

@@ -89,12 +89,10 @@ func UnixDestination(address Address) Destination {
// NetAddr returns the network address in this Destination in string form.
func (d Destination) NetAddr() string {
addr := ""
if d.Address != nil {
if d.Network == Network_TCP || d.Network == Network_UDP {
addr = d.Address.String() + ":" + d.Port.String()
} else if d.Network == Network_UNIX {
addr = d.Address.String()
}
if d.Network == Network_TCP || d.Network == Network_UDP {
addr = d.Address.String() + ":" + d.Port.String()
} else if d.Network == Network_UNIX {
addr = d.Address.String()
}
return addr
}

View File

@@ -76,8 +76,9 @@ type (
)
var (
ResolveUnixAddr = net.ResolveUnixAddr
ResolveTCPAddr = net.ResolveTCPAddr
ResolveUDPAddr = net.ResolveUDPAddr
ResolveUnixAddr = net.ResolveUnixAddr
)
type Resolver = net.Resolver

View File

@@ -1 +1,2 @@
*.pem
*.crt
*.key

View File

@@ -78,9 +78,9 @@ func printJSON(certificate *Certificate) {
func printFile(certificate *Certificate, name string) error {
certPEM, keyPEM := certificate.ToPEM()
return task.Run(context.Background(), func() error {
return writeFile(certPEM, name+"_cert.pem")
return writeFile(certPEM, name+".crt")
}, func() error {
return writeFile(keyPEM, name+"_key.pem")
return writeFile(keyPEM, name+".key")
})
}

View File

@@ -58,7 +58,9 @@ func marshalSlice(v reflect.Value, ignoreNullValue bool, insertTypeInfo bool) in
}
func isNullValue(f reflect.StructField, rv reflect.Value) bool {
if rv.Kind() == reflect.String && rv.Len() == 0 {
if rv.Kind() == reflect.Struct {
return false
} else if rv.Kind() == reflect.String && rv.Len() == 0 {
return true
} else if !isValueKind(rv.Kind()) && rv.IsNil() {
return true
@@ -184,6 +186,12 @@ func marshalKnownType(v interface{}, ignoreNullValue bool, insertTypeInfo bool)
case *conf.PortList:
cpl := v.(*conf.PortList)
return serializePortList(cpl.Build())
case conf.Int32Range:
i32rng := v.(conf.Int32Range)
if i32rng.Left == i32rng.Right {
return i32rng.Left, true
}
return i32rng.String(), true
case cnet.Address:
if addr := v.(cnet.Address); addr != nil {
return addr.String(), true

View File

@@ -116,98 +116,129 @@ func TestMarshalConfigJson(t *testing.T) {
"system",
"inboundDownlink",
"outboundUplink",
"XHTTP_IN",
"\"host\": \"bing.com\"",
"scMaxEachPostBytes",
"\"from\": 100",
"\"to\": 1000",
"\"from\": 1000000",
"\"to\": 1000000",
}
for _, kw := range keywords {
if !strings.Contains(tc, kw) {
t.Error("marshaled config error")
t.Log("config.json:", tc)
t.Error("keyword not found:", kw)
break
}
}
}
func getConfig() string {
return `{
"log": {
"loglevel": "debug"
},
"stats": {},
"policy": {
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true,
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
},
"inbounds": [
{
"tag": "agentin",
"protocol": "http",
"port": 8080,
"listen": "127.0.0.1",
"settings": {}
},
{
"listen": "127.0.0.1",
"port": 10085,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
},
"tag": "api-in"
}
],
"api": {
"tag": "api",
"services": [
"HandlerService",
"StatsService"
]
},
"routing": {
"rules": [
{
"inboundTag": [
"api-in"
],
"outboundTag": "api",
"type": "field"
}
],
"domainStrategy": "AsIs"
},
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "1.2.3.4",
"port": 1234,
"users": [
{
"id": "4784f9b8-a879-4fec-9718-ebddefa47750",
"encryption": "none"
}
]
}
]
},
"tag": "agentout",
"streamSettings": {
"network": "ws",
"security": "none",
"wsSettings": {
"path": "/?ed=2048",
"host": "bing.com"
}
}
}
]
}`
"log": {
"loglevel": "debug"
},
"stats": {},
"policy": {
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true,
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
},
"inbounds": [
{
"tag": "agentin",
"protocol": "http",
"port": 18080,
"listen": "127.0.0.1",
"settings": {}
},
{
"listen": "127.0.0.1",
"port": 10085,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
},
"tag": "api-in"
}
],
"api": {
"tag": "api",
"services": [
"HandlerService",
"StatsService"
]
},
"routing": {
"rules": [
{
"inboundTag": [
"api-in"
],
"outboundTag": "api",
"type": "field"
}
],
"domainStrategy": "AsIs"
},
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "1.2.3.4",
"port": 1234,
"users": [
{
"id": "4784f9b8-a879-4fec-9718-ebddefa47750",
"encryption": "none"
}
]
}
]
},
"tag": "XHTTP_IN",
"streamSettings": {
"network": "xhttp",
"xhttpSettings": {
"host": "bing.com",
"path": "/xhttp_client_upload",
"mode": "auto",
"extra": {
"noSSEHeader": false,
"scMaxEachPostBytes": 1000000,
"scMaxBufferedPosts": 30,
"xPaddingBytes": "100-1000"
}
},
"sockopt": {
"tcpFastOpen": true,
"acceptProxyProtocol": false,
"tcpcongestion": "bbr",
"tcpMptcp": true
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
],
"metadataOnly": false,
"routeOnly": true
}
}
]
}`
}

View File

@@ -23,6 +23,8 @@ const (
timeoutOnlyKey ctx.SessionKey = 8
allowedNetworkKey ctx.SessionKey = 9
handlerSessionKey ctx.SessionKey = 10
mitmAlpn11Key ctx.SessionKey = 11
mitmServerNameKey ctx.SessionKey = 12
)
func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context {
@@ -162,3 +164,25 @@ func AllowedNetworkFromContext(ctx context.Context) net.Network {
}
return net.Network_Unknown
}
func ContextWithMitmAlpn11(ctx context.Context, alpn11 bool) context.Context {
return context.WithValue(ctx, mitmAlpn11Key, alpn11)
}
func MitmAlpn11FromContext(ctx context.Context) bool {
if val, ok := ctx.Value(mitmAlpn11Key).(bool); ok {
return val
}
return false
}
func ContextWithMitmServerName(ctx context.Context, serverName string) context.Context {
return context.WithValue(ctx, mitmServerNameKey, serverName)
}
func MitmServerNameFromContext(ctx context.Context) string {
if val, ok := ctx.Value(mitmServerNameKey).(string); ok {
return val
}
return ""
}

View File

@@ -2,6 +2,7 @@ package core
import (
"io"
"slices"
"strings"
"github.com/xtls/xray-core/common"
@@ -64,14 +65,11 @@ func GetMergedConfig(args cmdarg.Arg) (string, error) {
supported := []string{"json", "yaml", "toml"}
for _, file := range args {
format := getFormat(file)
for _, s := range supported {
if s == format {
files = append(files, &ConfigSource{
Name: file,
Format: format,
})
break
}
if slices.Contains(supported, format) {
files = append(files, &ConfigSource{
Name: file,
Format: format,
})
}
}
return ConfigMergedFormFiles(files)

View File

@@ -17,9 +17,9 @@ import (
)
var (
Version_x byte = 24
Version_y byte = 12
Version_z byte = 15
Version_x byte = 25
Version_y byte = 2
Version_z byte = 18
)
var (

View File

@@ -4,7 +4,6 @@ import (
"context"
"reflect"
"sync"
"time"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
@@ -45,22 +44,13 @@ func getFeature(allFeatures []features.Feature, t reflect.Type) features.Feature
return nil
}
func (r *resolution) resolve(allFeatures []features.Feature) (bool, error) {
var fs []features.Feature
for _, d := range r.deps {
f := getFeature(allFeatures, d)
if f == nil {
return false, nil
}
fs = append(fs, f)
}
func (r *resolution) callbackResolution(allFeatures []features.Feature) error {
callback := reflect.ValueOf(r.callback)
var input []reflect.Value
callbackType := callback.Type()
for i := 0; i < callbackType.NumIn(); i++ {
pt := callbackType.In(i)
for _, f := range fs {
for _, f := range allFeatures {
if reflect.TypeOf(f).AssignableTo(pt) {
input = append(input, reflect.ValueOf(f))
break
@@ -85,15 +75,17 @@ func (r *resolution) resolve(allFeatures []features.Feature) (bool, error) {
}
}
return true, err
return err
}
// Instance combines all Xray features.
type Instance struct {
access sync.Mutex
features []features.Feature
featureResolutions []resolution
running bool
statusLock sync.Mutex
features []features.Feature
pendingResolutions []resolution
pendingOptionalResolutions []resolution
running bool
resolveLock sync.Mutex
ctx context.Context
}
@@ -154,13 +146,14 @@ func addOutboundHandlers(server *Instance, configs []*OutboundHandlerConfig) err
// See Instance.RequireFeatures for more information.
func RequireFeatures(ctx context.Context, callback interface{}) error {
v := MustFromContext(ctx)
return v.RequireFeatures(callback)
return v.RequireFeatures(callback, false)
}
// RequireFeaturesAsync registers a callback, which will be called when all dependent features are registered. The order of app init doesn't matter
func RequireFeaturesAsync(ctx context.Context, callback interface{}) {
// OptionalFeatures is a helper function to aquire features from Instance in context.
// See Instance.RequireFeatures for more information.
func OptionalFeatures(ctx context.Context, callback interface{}) error {
v := MustFromContext(ctx)
v.RequireFeaturesAsync(callback)
return v.RequireFeatures(callback, true)
}
// New returns a new Xray instance based on given configuration.
@@ -234,9 +227,12 @@ func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
}(),
)
if server.featureResolutions != nil {
server.resolveLock.Lock()
if server.pendingResolutions != nil {
server.resolveLock.Unlock()
return true, errors.New("not all dependencies are resolved.")
}
server.resolveLock.Unlock()
if err := addInboundHandlers(server, config.Inbound); err != nil {
return true, err
@@ -255,8 +251,8 @@ func (s *Instance) Type() interface{} {
// Close shutdown the Xray instance.
func (s *Instance) Close() error {
s.access.Lock()
defer s.access.Unlock()
s.statusLock.Lock()
defer s.statusLock.Unlock()
s.running = false
@@ -275,7 +271,7 @@ func (s *Instance) Close() error {
// RequireFeatures registers a callback, which will be called when all dependent features are registered.
// The callback must be a func(). All its parameters must be features.Feature.
func (s *Instance) RequireFeatures(callback interface{}) error {
func (s *Instance) RequireFeatures(callback interface{}, optional bool) error {
callbackType := reflect.TypeOf(callback)
if callbackType.Kind() != reflect.Func {
panic("not a function")
@@ -290,47 +286,32 @@ func (s *Instance) RequireFeatures(callback interface{}) error {
deps: featureTypes,
callback: callback,
}
if finished, err := r.resolve(s.features); finished {
return err
}
s.featureResolutions = append(s.featureResolutions, r)
return nil
}
// RequireFeaturesAsync registers a callback, which will be called when all dependent features are registered. The order of app init doesn't matter
func (s *Instance) RequireFeaturesAsync(callback interface{}) {
callbackType := reflect.TypeOf(callback)
if callbackType.Kind() != reflect.Func {
panic("not a function")
}
var featureTypes []reflect.Type
for i := 0; i < callbackType.NumIn(); i++ {
featureTypes = append(featureTypes, reflect.PtrTo(callbackType.In(i)))
}
r := resolution{
deps: featureTypes,
callback: callback,
}
go func() {
var finished = false
for i := 0; !finished; i++ {
if i > 100000 {
errors.LogError(s.ctx, "RequireFeaturesAsync failed after count ", i)
break;
}
finished, _ = r.resolve(s.features)
time.Sleep(time.Millisecond)
s.resolveLock.Lock()
foundAll := true
for _, d := range r.deps {
f := getFeature(s.features, d)
if f == nil {
foundAll = false
break
}
s.featureResolutions = append(s.featureResolutions, r)
}()
}
if foundAll {
s.resolveLock.Unlock()
return r.callbackResolution(s.features)
} else {
if optional {
s.pendingOptionalResolutions = append(s.pendingOptionalResolutions, r)
} else {
s.pendingResolutions = append(s.pendingResolutions, r)
}
s.resolveLock.Unlock()
return nil
}
}
// AddFeature registers a feature into current Instance.
func (s *Instance) AddFeature(feature features.Feature) error {
s.features = append(s.features, feature)
if s.running {
if err := feature.Start(); err != nil {
errors.LogInfoInner(s.ctx, err, "failed to start feature")
@@ -338,27 +319,52 @@ func (s *Instance) AddFeature(feature features.Feature) error {
return nil
}
if s.featureResolutions == nil {
return nil
}
s.resolveLock.Lock()
s.features = append(s.features, feature)
var pendingResolutions []resolution
for _, r := range s.featureResolutions {
finished, err := r.resolve(s.features)
if finished && err != nil {
return err
var availableResolution []resolution
var pending []resolution
for _, r := range s.pendingResolutions {
foundAll := true
for _, d := range r.deps {
f := getFeature(s.features, d)
if f == nil {
foundAll = false
break
}
}
if !finished {
pendingResolutions = append(pendingResolutions, r)
if foundAll {
availableResolution = append(availableResolution, r)
} else {
pending = append(pending, r)
}
}
if len(pendingResolutions) == 0 {
s.featureResolutions = nil
} else if len(pendingResolutions) < len(s.featureResolutions) {
s.featureResolutions = pendingResolutions
}
s.pendingResolutions = pending
return nil
var pendingOptional []resolution
for _, r := range s.pendingOptionalResolutions {
foundAll := true
for _, d := range r.deps {
f := getFeature(s.features, d)
if f == nil {
foundAll = false
break
}
}
if foundAll {
availableResolution = append(availableResolution, r)
} else {
pendingOptional = append(pendingOptional, r)
}
}
s.pendingOptionalResolutions = pendingOptional
s.resolveLock.Unlock()
var err error
for _, r := range availableResolution {
err = r.callbackResolution(s.features) // only return the last error for now
}
return err
}
// GetFeature returns a feature of the given type, or nil if such feature is not registered.
@@ -371,8 +377,8 @@ func (s *Instance) GetFeature(featureType interface{}) features.Feature {
//
// xray:api:stable
func (s *Instance) Start() error {
s.access.Lock()
defer s.access.Unlock()
s.statusLock.Lock()
defer s.statusLock.Unlock()
s.running = true
for _, f := range s.features {

View File

@@ -30,7 +30,7 @@ func TestXrayDependency(t *testing.T) {
t.Error("expected dns client fulfilled, but actually nil")
}
wait <- true
})
}, false)
instance.AddFeature(localdns.New())
<-wait
}

View File

@@ -25,7 +25,7 @@ type Handler interface {
// xray:api:stable
type Manager interface {
features.Feature
// GetHandlers returns an InboundHandler for the given tag.
// GetHandler returns an InboundHandler for the given tag.
GetHandler(ctx context.Context, tag string) (Handler, error)
// AddHandler adds the given handler into this Manager.
AddHandler(ctx context.Context, handler Handler) error

View File

@@ -11,7 +11,7 @@ type Context interface {
// GetInboundTag returns the tag of the inbound the connection was from.
GetInboundTag() string
// GetSourcesIPs returns the source IPs bound to the connection.
// GetSourceIPs returns the source IPs bound to the connection.
GetSourceIPs() []net.IP
// GetSourcePort returns the source port of the connection.

View File

@@ -2,6 +2,7 @@ package stats
import (
"context"
"time"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
@@ -30,6 +31,8 @@ type OnlineMap interface {
AddIP(string)
// List is the current OnlineMap ip list.
List() []string
// IpTimeMap return client ips and their last access time.
IpTimeMap() map[string]time.Time
}
// Channel is the interface for stats channel.

38
go.mod
View File

@@ -1,20 +1,18 @@
module github.com/xtls/xray-core
go 1.21.4
replace github.com/quic-go/quic-go v0.46.0 => github.com/xtls/quic-go v0.46.2
go 1.23
require (
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0
github.com/cloudflare/circl v1.4.0
github.com/cloudflare/circl v1.6.0
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.6.0
github.com/gorilla/websocket v1.5.3
github.com/miekg/dns v1.1.62
github.com/miekg/dns v1.1.63
github.com/pelletier/go-toml v1.9.5
github.com/pires/go-proxyproto v0.8.0
github.com/quic-go/quic-go v0.46.0
github.com/quic-go/quic-go v0.49.0
github.com/refraction-networking/utls v1.6.7
github.com/sagernet/sing v0.5.1
github.com/sagernet/sing-shadowsocks v0.2.7
@@ -24,14 +22,14 @@ require (
github.com/vishvananda/netlink v1.3.0
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.30.0
golang.org/x/net v0.32.0
golang.org/x/sync v0.10.0
golang.org/x/sys v0.28.0
golang.org/x/crypto v0.33.0
golang.org/x/net v0.35.0
golang.org/x/sync v0.11.0
golang.org/x/sys v0.30.0
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
google.golang.org/grpc v1.67.1
google.golang.org/protobuf v1.35.2
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489
google.golang.org/grpc v1.70.0
google.golang.org/protobuf v1.36.5
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0
h12.io/socks v1.0.3
lukechampine.com/blake3 v1.3.0
)
@@ -47,17 +45,17 @@ require (
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
go.uber.org/mock v0.4.0 // indirect
go.uber.org/mock v0.5.0 // indirect
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.22.0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.26.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

88
go.sum
View File

@@ -2,8 +2,8 @@ github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJS
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY=
github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
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=
@@ -12,18 +12,24 @@ github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFP
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/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.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g=
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
@@ -32,8 +38,8 @@ github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0N
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
@@ -46,8 +52,10 @@ github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKp
github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY=
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.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
@@ -68,33 +76,41 @@ github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQ
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/xtls/quic-go v0.46.2 h1:bzUnZIQIH8SyqYGR6fAXzEvZauA+32J/2w2AtnEFa1o=
github.com/xtls/quic-go v0.46.2/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg=
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
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.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
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.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
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.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -103,21 +119,21 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
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.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
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=
@@ -125,12 +141,12 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -140,8 +156,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
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-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE=
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk=
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 h1:P+U/06iIKPQ3DLcg+zBfSCia1luZ2msPZrJ8jYDFPs0=
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0/go.mod h1:NQHVAzMwvZ+Qe3ElSiHmq9RUm1MdNHpUZ52fiEqvn+0=
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.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=

View File

@@ -2,6 +2,7 @@ package conf
import (
"encoding/json"
"fmt"
"strconv"
"strings"
@@ -202,6 +203,24 @@ func (list *PortList) Build() *net.PortList {
return portList
}
func (v PortList) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
func (v PortList) String() string {
ports := []string{}
for _, port := range v.Range {
if port.From == port.To {
p := strconv.Itoa(int(port.From))
ports = append(ports, p)
} else {
p := fmt.Sprintf("%d-%d", port.From, port.To)
ports = append(ports, p)
}
}
return strings.Join(ports, ",")
}
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (list *PortList) UnmarshalJSON(data []byte) error {
var listStr string
@@ -258,6 +277,18 @@ type Int32Range struct {
To int32
}
func (v Int32Range) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
func (v Int32Range) String() string {
if v.Left == v.Right {
return strconv.Itoa(int(v.Left))
} else {
return fmt.Sprintf("%d-%d", v.Left, v.Right)
}
}
func (v *Int32Range) UnmarshalJSON(data []byte) error {
defer v.ensureOrder()
var str string

View File

@@ -12,13 +12,13 @@ import (
)
type NameServerConfig struct {
Address *Address
ClientIP *Address
Port uint16
SkipFallback bool
Domains []string
ExpectIPs StringList
QueryStrategy string
Address *Address `json:"address"`
ClientIP *Address `json:"clientIp"`
Port uint16 `json:"port"`
SkipFallback bool `json:"skipFallback"`
Domains []string `json:"domains"`
ExpectIPs StringList `json:"expectIps"`
QueryStrategy string `json:"queryStrategy"`
}
func (c *NameServerConfig) UnmarshalJSON(data []byte) error {

View File

@@ -2,6 +2,7 @@ package conf
import (
"encoding/base64"
"encoding/hex"
"net"
"strings"
@@ -152,8 +153,9 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
func ParseNoise(noise *Noise) (*freedom.Noise, error) {
var err error
NConfig := new(freedom.Noise)
noise.Packet = strings.TrimSpace(noise.Packet)
switch strings.ToLower(noise.Type) {
switch noise.Type {
case "rand":
min, max, err := ParseRangeString(noise.Packet)
if err != nil {
@@ -161,42 +163,35 @@ func ParseNoise(noise *Noise) (*freedom.Noise, error) {
}
NConfig.LengthMin = uint64(min)
NConfig.LengthMax = uint64(max)
if NConfig.LengthMin > NConfig.LengthMax {
NConfig.LengthMin, NConfig.LengthMax = NConfig.LengthMax, NConfig.LengthMin
}
if NConfig.LengthMin == 0 {
return nil, errors.New("rand lengthMin or lengthMax cannot be 0")
}
case "str":
//user input string
NConfig.StrNoise = []byte(strings.TrimSpace(noise.Packet))
// user input string
NConfig.Packet = []byte(noise.Packet)
case "hex":
// user input hex
NConfig.Packet, err = hex.DecodeString(noise.Packet)
if err != nil {
return nil, errors.New("Invalid hex string").Base(err)
}
case "base64":
//user input base64
NConfig.StrNoise, err = base64.StdEncoding.DecodeString(strings.TrimSpace(noise.Packet))
// user input base64
NConfig.Packet, err = base64.RawURLEncoding.DecodeString(strings.NewReplacer("+", "-", "/", "_", "=", "").Replace(noise.Packet))
if err != nil {
return nil, errors.New("Invalid base64 string")
return nil, errors.New("Invalid base64 string").Base(err)
}
default:
return nil, errors.New("Invalid packet,only rand,str,base64 are supported")
return nil, errors.New("Invalid packet, only rand/str/hex/base64 are supported")
}
if noise.Delay != nil {
if noise.Delay.From != 0 && noise.Delay.To != 0 {
NConfig.DelayMin = uint64(noise.Delay.From)
NConfig.DelayMax = uint64(noise.Delay.To)
if NConfig.DelayMin > NConfig.LengthMax {
NConfig.DelayMin, NConfig.DelayMax = NConfig.LengthMax, NConfig.DelayMin
}
} else {
return nil, errors.New("DelayMin or DelayMax cannot be zero")
}
} else {
NConfig.DelayMin = 0
NConfig.DelayMax = 0
NConfig.DelayMin = uint64(noise.Delay.From)
NConfig.DelayMax = uint64(noise.Delay.To)
}
return NConfig, nil
}

View File

@@ -6,15 +6,21 @@ import (
)
type MetricsConfig struct {
Tag string `json:"tag"`
Tag string `json:"tag"`
Listen string `json:"listen"`
}
func (c *MetricsConfig) Build() (*metrics.Config, error) {
if c.Listen == "" && c.Tag == "" {
return nil, errors.New("Metrics must have a tag or listen address.")
}
// If the tag is empty but have "listen" set a default "Metrics" for compatibility.
if c.Tag == "" {
return nil, errors.New("metrics tag can't be empty.")
c.Tag = "Metrics"
}
return &metrics.Config{
Tag: c.Tag,
Tag: c.Tag,
Listen: c.Listen,
}, nil
}

View File

@@ -165,11 +165,13 @@ func (c *WebSocketConfig) Build() (proto.Message, error) {
}
// Priority (client): host > serverName > address
for k, v := range c.Headers {
errors.PrintDeprecatedFeatureWarning(`"host" in "headers"`, `independent "host"`)
if c.Host == "" {
c.Host = v
if strings.ToLower(k) == "host" {
errors.PrintDeprecatedFeatureWarning(`"host" in "headers"`, `independent "host"`)
if c.Host == "" {
c.Host = v
}
delete(c.Headers, k)
}
delete(c.Headers, k)
}
config := &websocket.Config{
Path: path,
@@ -229,6 +231,7 @@ type SplitHTTPConfig struct {
ScMaxEachPostBytes Int32Range `json:"scMaxEachPostBytes"`
ScMinPostsIntervalMs Int32Range `json:"scMinPostsIntervalMs"`
ScMaxBufferedPosts int64 `json:"scMaxBufferedPosts"`
ScStreamUpServerSecs Int32Range `json:"scStreamUpServerSecs"`
Xmux XmuxConfig `json:"xmux"`
DownloadSettings *StreamConfig `json:"downloadSettings"`
Extra json.RawMessage `json:"extra"`
@@ -238,8 +241,8 @@ type XmuxConfig struct {
MaxConcurrency Int32Range `json:"maxConcurrency"`
MaxConnections Int32Range `json:"maxConnections"`
CMaxReuseTimes Int32Range `json:"cMaxReuseTimes"`
CMaxLifetimeMs Int32Range `json:"cMaxLifetimeMs"`
HMaxRequestTimes Int32Range `json:"hMaxRequestTimes"`
HMaxReusableSecs Int32Range `json:"hMaxReusableSecs"`
HKeepAlivePeriod int64 `json:"hKeepAlivePeriod"`
}
@@ -260,7 +263,6 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
extra.Host = c.Host
extra.Path = c.Path
extra.Mode = c.Mode
extra.Extra = c.Extra
c = &extra
}
@@ -279,16 +281,20 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
}
}
if c.XPaddingBytes != (Int32Range{}) && (c.XPaddingBytes.From <= 0 || c.XPaddingBytes.To <= 0) {
return nil, errors.New("xPaddingBytes cannot be disabled")
}
if c.Xmux.MaxConnections.To > 0 && c.Xmux.MaxConcurrency.To > 0 {
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
}
if c.Xmux == (XmuxConfig{}) {
c.Xmux.MaxConcurrency.From = 16
c.Xmux.MaxConcurrency.To = 32
c.Xmux.CMaxReuseTimes.From = 64
c.Xmux.CMaxReuseTimes.To = 128
c.Xmux.HMaxRequestTimes.From = 800
c.Xmux.HMaxRequestTimes.From = 600
c.Xmux.HMaxRequestTimes.To = 900
c.Xmux.HMaxReusableSecs.From = 1800
c.Xmux.HMaxReusableSecs.To = 3000
}
config := &splithttp.Config{
@@ -302,12 +308,13 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
ScMaxEachPostBytes: newRangeConfig(c.ScMaxEachPostBytes),
ScMinPostsIntervalMs: newRangeConfig(c.ScMinPostsIntervalMs),
ScMaxBufferedPosts: c.ScMaxBufferedPosts,
ScStreamUpServerSecs: newRangeConfig(c.ScStreamUpServerSecs),
Xmux: &splithttp.XmuxConfig{
MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency),
MaxConnections: newRangeConfig(c.Xmux.MaxConnections),
CMaxReuseTimes: newRangeConfig(c.Xmux.CMaxReuseTimes),
CMaxLifetimeMs: newRangeConfig(c.Xmux.CMaxLifetimeMs),
HMaxRequestTimes: newRangeConfig(c.Xmux.HMaxRequestTimes),
HMaxReusableSecs: newRangeConfig(c.Xmux.HMaxReusableSecs),
HKeepAlivePeriod: c.Xmux.HKeepAlivePeriod,
},
}
@@ -316,9 +323,6 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
if c.Mode == "stream-one" {
return nil, errors.New(`Can not use "downloadSettings" in "stream-one" mode.`)
}
if c.Extra != nil {
c.DownloadSettings.SocketSettings = nil
}
var err error
if config.DownloadSettings, err = c.DownloadSettings.Build(); err != nil {
return nil, errors.New(`Failed to build "downloadSettings".`).Base(err)
@@ -406,6 +410,8 @@ type TLSConfig struct {
PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"`
CurvePreferences *StringList `json:"curvePreferences"`
MasterKeyLog string `json:"masterKeyLog"`
ServerNameToVerify string `json:"serverNameToVerify"`
VerifyPeerCertInNames []string `json:"verifyPeerCertInNames"`
}
// Build implements Buildable.
@@ -427,6 +433,13 @@ func (c *TLSConfig) Build() (proto.Message, error) {
if c.ALPN != nil && len(*c.ALPN) > 0 {
config.NextProtocol = []string(*c.ALPN)
}
if len(config.NextProtocol) > 1 {
for _, p := range config.NextProtocol {
if tcp.IsFromMitm(p) {
return nil, errors.New(`only one element is allowed in "alpn" when using "fromMitm" in it`)
}
}
}
if c.CurvePreferences != nil && len(*c.CurvePreferences) > 0 {
config.CurvePreferences = []string(*c.CurvePreferences)
}
@@ -436,8 +449,8 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.MaxVersion = c.MaxVersion
config.CipherSuites = c.CipherSuites
config.Fingerprint = strings.ToLower(c.Fingerprint)
if config.Fingerprint != "" && tls.GetFingerprint(config.Fingerprint) == nil {
return nil, errors.New(`unknown fingerprint: `, config.Fingerprint)
if config.Fingerprint != "unsafe" && tls.GetFingerprint(config.Fingerprint) == nil {
return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint)
}
config.RejectUnknownSni = c.RejectUnknownSNI
@@ -465,6 +478,11 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.MasterKeyLog = c.MasterKeyLog
if c.ServerNameToVerify != "" {
return nil, errors.PrintRemovedFeatureError(`"serverNameToVerify"`, `"verifyPeerCertInNames"`)
}
config.VerifyPeerCertInNames = c.VerifyPeerCertInNames
return config, nil
}
@@ -582,15 +600,13 @@ func (c *REALITYConfig) Build() (proto.Message, error) {
config.ServerNames = c.ServerNames
config.MaxTimeDiff = c.MaxTimeDiff
} else {
if c.Fingerprint == "" {
return nil, errors.New(`empty "fingerprint"`)
}
if config.Fingerprint = strings.ToLower(c.Fingerprint); tls.GetFingerprint(config.Fingerprint) == nil {
return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint)
}
if config.Fingerprint == "hellogolang" {
config.Fingerprint = strings.ToLower(c.Fingerprint)
if config.Fingerprint == "unsafe" || config.Fingerprint == "hellogolang" {
return nil, errors.New(`invalid "fingerprint": `, config.Fingerprint)
}
if tls.GetFingerprint(config.Fingerprint) == nil {
return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint)
}
if len(c.ServerNames) != 0 {
return nil, errors.New(`non-empty "serverNames", please use "serverName" instead`)
}
@@ -689,7 +705,7 @@ type SocketConfig struct {
TCPCongestion string `json:"tcpCongestion"`
TCPWindowClamp int32 `json:"tcpWindowClamp"`
TCPMaxSeg int32 `json:"tcpMaxSeg"`
TcpNoDelay bool `json:"tcpNoDelay"`
Penetrate bool `json:"penetrate"`
TCPUserTimeout int32 `json:"tcpUserTimeout"`
V6only bool `json:"v6only"`
Interface string `json:"interface"`
@@ -776,7 +792,7 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
TcpCongestion: c.TCPCongestion,
TcpWindowClamp: c.TCPWindowClamp,
TcpMaxSeg: c.TCPMaxSeg,
TcpNoDelay: c.TcpNoDelay,
Penetrate: c.Penetrate,
TcpUserTimeout: c.TCPUserTimeout,
V6Only: c.V6only,
Interface: c.Interface,

View File

@@ -24,6 +24,7 @@ var (
"dokodemo-door": func() interface{} { return new(DokodemoConfig) },
"http": func() interface{} { return new(HTTPServerConfig) },
"shadowsocks": func() interface{} { return new(ShadowsocksServerConfig) },
"mixed": func() interface{} { return new(SocksServerConfig) },
"socks": func() interface{} { return new(SocksServerConfig) },
"vless": func() interface{} { return new(VLessInboundConfig) },
"vmess": func() interface{} { return new(VMessInboundConfig) },

View File

@@ -1,6 +1,7 @@
package main
import (
"errors"
"flag"
"fmt"
"go/build"
@@ -18,7 +19,7 @@ var directory = flag.String("pwd", "", "Working directory of Xray vformat.")
func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" {
if file == "off" {
return "", fmt.Errorf("GOENV=off")
return "", errors.New("GOENV=off")
}
return file, nil
}
@@ -27,7 +28,7 @@ func envFile() (string, error) {
return "", err
}
if dir == "" {
return "", fmt.Errorf("missing user-config dir")
return "", errors.New("missing user-config dir")
}
return filepath.Join(dir, "go", "env"), nil
}
@@ -40,7 +41,7 @@ func GetRuntimeEnv(key string) (string, error) {
return "", err
}
if file == "" {
return "", fmt.Errorf("missing runtime env file")
return "", errors.New("missing runtime env file")
}
var data []byte
var runtimeEnv string

View File

@@ -1,6 +1,7 @@
package main
import (
"errors"
"flag"
"fmt"
"go/build"
@@ -22,7 +23,7 @@ var directory = flag.String("pwd", "", "Working directory of Xray vprotogen.")
func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" {
if file == "off" {
return "", fmt.Errorf("GOENV=off")
return "", errors.New("GOENV=off")
}
return file, nil
}
@@ -31,7 +32,7 @@ func envFile() (string, error) {
return "", err
}
if dir == "" {
return "", fmt.Errorf("missing user-config dir")
return "", errors.New("missing user-config dir")
}
return filepath.Join(dir, "go", "env"), nil
}
@@ -44,7 +45,7 @@ func GetRuntimeEnv(key string) (string, error) {
return "", err
}
if file == "" {
return "", fmt.Errorf("missing runtime env file")
return "", errors.New("missing runtime env file")
}
var data []byte
var runtimeEnv string
@@ -101,12 +102,12 @@ Download %s v%s or later from https://github.com/protocolbuffers/protobuf/releas
func getProjectProtocVersion(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
return "", fmt.Errorf("can not get the version of protobuf used in xray project")
return "", errors.New("can not get the version of protobuf used in xray project")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("can not read from body")
return "", errors.New("can not read from body")
}
versionRegexp := regexp.MustCompile(`\/\/\s*protoc\s*v\d+\.(\d+\.\d+)`)
matched := versionRegexp.FindStringSubmatch(string(body))

View File

@@ -27,5 +27,6 @@ var CmdAPI = &base.Command{
cmdRemoveRules,
cmdSourceIpBlock,
cmdOnlineStats,
cmdOnlineStatsIpList,
},
}

View File

@@ -13,25 +13,20 @@ import (
var cmdBalancerInfo = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api bi [--server=127.0.0.1:8080] [balancer]...",
Short: "balancer information",
Short: "Retrieve balancer information",
Long: `
Get information of specified balancers, including health, strategy
and selecting. If no balancer tag specified, get information of
all balancers.
Retrieve information of specified balancers, including health, strategy and selecting.
If no balancer tag specified, information for all balancers is returned.
> Make sure you have "RoutingService" set in "config.api.services"
of server config.
> Ensure that "RoutingService" is enabled under "config.api.services" in the server configuration.
Arguments:
-json
Use json output.
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout <seconds>
Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
Example:

View File

@@ -7,31 +7,27 @@ import (
var cmdBalancerOverride = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api bo [--server=127.0.0.1:8080] <-b balancer> outboundTag",
Short: "balancer override",
UsageLine: "{{.Exec}} api bo [--server=127.0.0.1:8080] <-b balancer> outboundTag <-r>",
Short: "Override balancer",
Long: `
Override a balancer's selection.
Override the selection target of a balancer.
> Make sure you have "RoutingService" set in "config.api.services"
of server config.
> Ensure that the "RoutingService" is properly configured under "config.api.services" in the server configuration.
Once a balancer's selecting is overridden:
Once the balancer's selection is overridden:
- The balancer's selection result will always be outboundTag
Arguments:
-r, -remove
Remove the overridden
-r, -remove
Remove the override
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
-r, -remove
Remove the existing override.
Example:

View File

@@ -8,20 +8,28 @@ import (
var cmdInboundUser = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api inbounduser [--server=127.0.0.1:8080] -tag=tag [-email=email]",
Short: "Get Inbound User",
Short: "Retrieve inbound user(s)",
Long: `
Get User info from an inbound.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
-tag
Inbound tag
-email
User email. If email is not given, will get all users
-email
The user's email address. If not provided, all users will be retrieved.
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name" -email="xray@love.com"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name" -email="xray@love.com"
`,
Run: executeInboundUser,
}

View File

@@ -8,18 +8,24 @@ import (
var cmdInboundUserCount = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api inboundusercount [--server=127.0.0.1:8080] -tag=tag",
Short: "Get Inbound User Count",
Short: "Retrieve inbound user count",
Long: `
Get User count from an inbound.
Retrieve the user count for a specified inbound tag.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
-tag
Inbound tag
Inbound tag
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name"
`,
Run: executeInboundUserCount,
}

View File

@@ -15,13 +15,18 @@ var cmdAddInbounds = &base.Command{
Short: "Add inbounds",
Long: `
Add inbounds to Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
`,
Run: executeAddInbounds,
}

View File

@@ -14,13 +14,18 @@ var cmdRemoveInbounds = &base.Command{
Short: "Remove inbounds",
Long: `
Remove inbounds from Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
`,
Run: executeRemoveInbounds,
}

View File

@@ -11,11 +11,18 @@ var cmdRestartLogger = &base.Command{
Short: "Restart the logger",
Long: `
Restart the logger of Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080
`,
Run: executeRestartLogger,
}

View File

@@ -15,13 +15,18 @@ var cmdAddOutbounds = &base.Command{
Short: "Add outbounds",
Long: `
Add outbounds to Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
`,
Run: executeAddOutbounds,
}

View File

@@ -14,13 +14,18 @@ var cmdRemoveOutbounds = &base.Command{
Short: "Remove outbounds",
Long: `
Remove outbounds from Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
`,
Run: executeRemoveOutbounds,
}

View File

@@ -16,16 +16,21 @@ var cmdAddRules = &base.Command{
Short: "Add routing rules",
Long: `
Add routing rules to Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds>
Timeout seconds to call API. Default 3
-append
append or replace config. Default false
Append to the existing configuration instead of replacing it. Default false
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
`,
Run: executeAddRules,
}

View File

@@ -9,17 +9,22 @@ import (
var cmdRemoveRules = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api rmrules [--server=127.0.0.1:8080] ruleTag1 ruleTag2...",
UsageLine: "{{.Exec}} api rmrules [--server=127.0.0.1:8080] [ruleTag]...",
Short: "Remove routing rules by ruleTag",
Long: `
Remove routing rules by ruleTag from Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 ruleTag1 ruleTag2
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 ruleTag1 ruleTag2
`,
Run: executeRemoveRules,
}

View File

@@ -3,6 +3,7 @@ package api
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/http"
@@ -101,7 +102,7 @@ func fetchHTTPContent(target string) ([]byte, error) {
content, err := buf.ReadAllToBytes(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read HTTP response")
return nil, errors.New("failed to read HTTP response")
}
return content, nil

View File

@@ -14,25 +14,34 @@ import (
var cmdSourceIpBlock = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api sib [--server=127.0.0.1:8080] -outbound=blocked -inbound=socks 1.2.3.4",
Short: "Drop connections by source ip",
Short: "Block connections by source IP",
Long: `
Drop connections by source ip.
Block connections by source IP address.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
-outbound
route traffic to specific outbound.
Specifies the outbound tag.
-inbound
target traffig from specific inbound.
Specifies the inbound tag.
-ruletag
set ruleTag. Default sourceIpBlock
The ruleTag. Default sourceIpBlock
-reset
remove ruletag and apply new source IPs. Default false
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -outbound=blocked -inbound=socks 1.2.3.4
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -outbound=blocked -inbound=socks 1.2.3.4 -reset
`,
Run: executeSourceIpBlock,
}

View File

@@ -8,19 +8,26 @@ import (
var cmdGetStats = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api stats [--server=127.0.0.1:8080] [-name '']",
Short: "Get statistics",
Short: "Retrieve statistics",
Long: `
Get statistics from Xray.
Retrieve the statistics from Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
-name
Name of the stat counter.
Name of the counter.
-reset
Reset the counter to fetching its value.
Reset the counter after fetching their values. Default false
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -name "inbound>>>statin>>>traffic>>>downlink"
`,
Run: executeGetStats,

View File

@@ -7,21 +7,25 @@ import (
var cmdOnlineStats = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api statsonline [--server=127.0.0.1:8080] [-name '']",
Short: "Get online user",
UsageLine: "{{.Exec}} api statsonline [--server=127.0.0.1:8080] [-email '']",
Short: "Retrieve the online session count for a user",
Long: `
Get statistics from Xray.
Retrieve the current number of active sessions for a user from Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
-email
email of the user.
-reset
Reset the counter to fetching its value.
The user's email address.
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "user1@test.com"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "xray@love.com"
`,
Run: executeOnlineStats,
}

View File

@@ -0,0 +1,51 @@
package api
import (
statsService "github.com/xtls/xray-core/app/stats/command"
"github.com/xtls/xray-core/main/commands/base"
)
var cmdOnlineStatsIpList = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api statsonlineiplist [--server=127.0.0.1:8080] [-email '']",
Short: "Retrieve a user's online IP addresses and access times",
Long: `
Retrieve the online IP addresses and corresponding access timestamps for a user from 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
-email
The user's email address.
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "xray@love.com"
`,
Run: executeOnlineStatsIpList,
}
func executeOnlineStatsIpList(cmd *base.Command, args []string) {
setSharedFlags(cmd)
email := cmd.Flag.String("email", "", "")
cmd.Flag.Parse(args)
statName := "user>>>" + *email + ">>>online"
conn, ctx, close := dialAPIServer()
defer close()
client := statsService.NewStatsServiceClient(conn)
r := &statsService.GetStatsRequest{
Name: statName,
Reset_: false,
}
resp, err := client.GetStatsOnlineIpList(ctx, r)
if err != nil {
base.Fatalf("failed to get stats: %s", err)
}
showJSONResponse(resp)
}

View File

@@ -11,16 +11,23 @@ var cmdQueryStats = &base.Command{
Short: "Query statistics",
Long: `
Query statistics from Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
-pattern
Pattern of the query.
Filter pattern for the statistics query.
-reset
Reset the counter to fetching its value.
Reset the counter after fetching their values. Default false
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -pattern "counter_"
`,
Run: executeQueryStats,

View File

@@ -8,14 +8,21 @@ import (
var cmdSysStats = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api statssys [--server=127.0.0.1:8080]",
Short: "Get system statistics",
Short: "Retrieve system statistics",
Long: `
Get system statistics from Xray.
Retrieve system statistics from Xray.
Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080
`,
Run: executeSysStats,
}

View File

@@ -42,7 +42,8 @@ func Curve25519Genkey(StdEncoding bool, input_base64 string) {
// Modify random bytes using algorithm described at:
// https://cr.yp.to/ecdh.html.
privateKey[0] &= 248
privateKey[31] &= 127 | 64
privateKey[31] &= 127
privateKey[31] |= 64
if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
output = err.Error()

View File

@@ -120,9 +120,9 @@ func writeFile(content []byte, name string) error {
func printFile(certificate *cert.Certificate, name string) error {
certPEM, keyPEM := certificate.ToPEM()
return task.Run(context.Background(), func() error {
return writeFile(certPEM, name+"_cert.pem")
return writeFile(certPEM, name+".crt")
}, func() error {
return writeFile(keyPEM, name+"_key.pem")
return writeFile(keyPEM, name+".key")
})
}

View File

@@ -45,6 +45,7 @@ The -dump flag tells Xray to print the merged config.
func init() {
cmdRun.Run = executeRun // break init loop
log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
}
var (

View File

@@ -27,7 +27,7 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
h := new(Handler)
if err := core.RequireFeatures(ctx, func(dnsClient dns.Client, policyManager policy.Manager) error {
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) { // FakeDNSEngine is optional
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
h.fdns = fdns
})
return h.Init(config.(*Config), dnsClient, policyManager)

View File

@@ -2,6 +2,7 @@ package dokodemo
import (
"context"
"runtime"
"sync/atomic"
"github.com/xtls/xray-core/common"
@@ -17,6 +18,7 @@ import (
"github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls"
)
func init() {
@@ -62,10 +64,6 @@ func (d *DokodemoDoor) policy() policy.Session {
return p
}
type hasHandshakeAddressContext interface {
HandshakeAddressContext(ctx context.Context) net.Address
}
// Process implements proxy.Inbound.
func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
errors.LogDebug(ctx, "processing connection from: ", conn.RemoteAddr())
@@ -85,11 +83,14 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
destinationOverridden = true
}
}
if handshake, ok := conn.(hasHandshakeAddressContext); ok && !destinationOverridden {
addr := handshake.HandshakeAddressContext(ctx)
if addr != nil {
dest.Address = addr
if tlsConn, ok := conn.(tls.Interface); ok && !destinationOverridden {
if serverName := tlsConn.HandshakeContextServerName(ctx); serverName != "" {
dest.Address = net.DomainAddress(serverName)
destinationOverridden = true
ctx = session.ContextWithMitmServerName(ctx, serverName)
}
if tlsConn.NegotiatedProtocol() != "h2" {
ctx = session.ContextWithMitmAlpn11(ctx, true)
}
}
}
@@ -147,10 +148,6 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
return nil
}
tproxyRequest := func() error {
return nil
}
var writer buf.Writer
if network == net.Network_TCP {
writer = buf.NewWriter(conn)
@@ -180,7 +177,12 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
return err
}
writer = NewPacketWriter(pConn, &dest, mark, back)
defer writer.(*PacketWriter).Close()
defer func() {
runtime.Gosched()
common.Interrupt(link.Reader) // maybe duplicated
runtime.Gosched()
writer.(*PacketWriter).Close() // close fake UDP conns
}()
/*
sockopt := &internet.SocketConfig{
Tproxy: internet.SocketConfig_TProxy,
@@ -219,17 +221,24 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
responseDone := func() error {
defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)
if network == net.Network_UDP && destinationOverridden {
buf.Copy(link.Reader, writer) // respect upload's timeout
return nil
}
if err := buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to transport response").Base(err)
}
return nil
}
if err := task.Run(ctx, task.OnSuccess(func() error {
return task.Run(ctx, requestDone, tproxyRequest)
}, task.Close(link.Writer)), responseDone); err != nil {
common.Interrupt(link.Reader)
if err := task.Run(ctx,
task.OnSuccess(func() error { return task.Run(ctx, requestDone) }, task.Close(link.Writer)),
responseDone); err != nil {
runtime.Gosched()
common.Interrupt(link.Writer)
runtime.Gosched()
common.Interrupt(link.Reader)
return errors.New("connection ends").Base(err)
}

View File

@@ -233,7 +233,7 @@ type Noise struct {
LengthMax uint64 `protobuf:"varint,2,opt,name=length_max,json=lengthMax,proto3" json:"length_max,omitempty"`
DelayMin uint64 `protobuf:"varint,3,opt,name=delay_min,json=delayMin,proto3" json:"delay_min,omitempty"`
DelayMax uint64 `protobuf:"varint,4,opt,name=delay_max,json=delayMax,proto3" json:"delay_max,omitempty"`
StrNoise []byte `protobuf:"bytes,5,opt,name=str_noise,json=strNoise,proto3" json:"str_noise,omitempty"`
Packet []byte `protobuf:"bytes,5,opt,name=packet,proto3" json:"packet,omitempty"`
}
func (x *Noise) Reset() {
@@ -294,9 +294,9 @@ func (x *Noise) GetDelayMax() uint64 {
return 0
}
func (x *Noise) GetStrNoise() []byte {
func (x *Noise) GetPacket() []byte {
if x != nil {
return x.StrNoise
return x.Packet
}
return nil
}
@@ -412,7 +412,7 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x22, 0x9c, 0x01, 0x0a, 0x05,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x22, 0x97, 0x01, 0x0a, 0x05,
0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f,
0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74,
0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d,
@@ -420,49 +420,49 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e,
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e,
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20,
0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a,
0x09, 0x73, 0x74, 0x72, 0x5f, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x08, 0x73, 0x74, 0x72, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29,
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65,
0x64, 0x6f, 0x6d, 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, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73,
0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73,
0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a,
0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70,
0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74,
0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 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, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e,
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13, 0x64, 0x65, 0x73,
0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65,
0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65,
0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c,
0x65, 0x76, 0x65, 0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74,
0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72,
0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67,
0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25,
0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f,
0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18,
0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65,
0x52, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d,
0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41,
0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12,
0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08,
0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53,
0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43,
0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49,
0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
0x36, 0x34, 0x10, 0x0a, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01,
0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c,
0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78,
0x79, 0x2f, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79,
0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12,
0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66,
0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52,
0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f,
0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72,
0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06, 0x6e, 0x6f, 0x69,
0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10,
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a,
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53,
0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49,
0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36,
0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10,
0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07,
0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12,
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12,
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42,
0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x66, 0x72, 0x65,
0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78,
0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (

View File

@@ -25,7 +25,7 @@ message Noise {
uint64 length_max = 2;
uint64 delay_min = 3;
uint64 delay_max = 4;
bytes str_noise = 5;
bytes packet = 5;
}
message Config {

View File

@@ -266,6 +266,9 @@ func isTLSConn(conn stat.Connection) bool {
if _, ok := conn.(*tls.Conn); ok {
return true
}
if _, ok := conn.(*tls.UConn); ok {
return true
}
}
return false
}
@@ -407,8 +410,8 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
var err error
for _, n := range w.noises {
//User input string or base64 encoded string
if n.StrNoise != nil {
noise = n.StrNoise
if n.Packet != nil {
noise = n.Packet
} else {
//Random noise
noise, err = GenerateRandomBytes(randBetween(int64(n.LengthMin),
@@ -419,7 +422,7 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
}
w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
if n.DelayMin != 0 {
if n.DelayMin != 0 || n.DelayMax != 0 {
time.Sleep(time.Duration(randBetween(int64(n.DelayMin), int64(n.DelayMax))) * time.Millisecond)
}
}

View File

@@ -151,6 +151,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer))
}
responseFunc := func() error {
ob.CanSpliceCopy = 1
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
}

View File

@@ -207,6 +207,7 @@ func (s *Server) handleConnect(ctx context.Context, _ *http.Request, reader *buf
}
responseDone := func() error {
inbound.CanSpliceCopy = 1
defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)
v2writer := buf.NewWriter(conn)

View File

@@ -107,37 +107,65 @@ type TrafficState struct {
IsTLS bool
Cipher uint16
RemainingServerHello int32
Inbound InboundState
Outbound OutboundState
}
type InboundState struct {
// reader link state
WithinPaddingBuffers bool
UplinkReaderDirectCopy bool
RemainingCommand int32
RemainingContent int32
RemainingPadding int32
CurrentCommand int
// write link state
IsPadding bool
DownlinkWriterDirectCopy bool
}
type OutboundState struct {
// reader link state
WithinPaddingBuffers bool
ReaderSwitchToDirectCopy bool
DownlinkReaderDirectCopy bool
RemainingCommand int32
RemainingContent int32
RemainingPadding int32
CurrentCommand int
// write link state
IsPadding bool
WriterSwitchToDirectCopy bool
IsPadding bool
UplinkWriterDirectCopy bool
}
func NewTrafficState(userUUID []byte) *TrafficState {
return &TrafficState{
UserUUID: userUUID,
NumberOfPacketToFilter: 8,
EnableXtls: false,
IsTLS12orAbove: false,
IsTLS: false,
Cipher: 0,
RemainingServerHello: -1,
WithinPaddingBuffers: true,
ReaderSwitchToDirectCopy: false,
RemainingCommand: -1,
RemainingContent: -1,
RemainingPadding: -1,
CurrentCommand: 0,
IsPadding: true,
WriterSwitchToDirectCopy: false,
UserUUID: userUUID,
NumberOfPacketToFilter: 8,
EnableXtls: false,
IsTLS12orAbove: false,
IsTLS: false,
Cipher: 0,
RemainingServerHello: -1,
Inbound: InboundState{
WithinPaddingBuffers: true,
UplinkReaderDirectCopy: false,
RemainingCommand: -1,
RemainingContent: -1,
RemainingPadding: -1,
CurrentCommand: 0,
IsPadding: true,
DownlinkWriterDirectCopy: false,
},
Outbound: OutboundState{
WithinPaddingBuffers: true,
DownlinkReaderDirectCopy: false,
RemainingCommand: -1,
RemainingContent: -1,
RemainingPadding: -1,
CurrentCommand: 0,
IsPadding: true,
UplinkWriterDirectCopy: false,
},
}
}
@@ -147,37 +175,58 @@ type VisionReader struct {
buf.Reader
trafficState *TrafficState
ctx context.Context
isUplink bool
}
func NewVisionReader(reader buf.Reader, state *TrafficState, context context.Context) *VisionReader {
func NewVisionReader(reader buf.Reader, state *TrafficState, isUplink bool, context context.Context) *VisionReader {
return &VisionReader{
Reader: reader,
trafficState: state,
ctx: context,
isUplink: isUplink,
}
}
func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
buffer, err := w.Reader.ReadMultiBuffer()
if !buffer.IsEmpty() {
if w.trafficState.WithinPaddingBuffers || w.trafficState.NumberOfPacketToFilter > 0 {
var withinPaddingBuffers *bool
var remainingContent *int32
var remainingPadding *int32
var currentCommand *int
var switchToDirectCopy *bool
if w.isUplink {
withinPaddingBuffers = &w.trafficState.Inbound.WithinPaddingBuffers
remainingContent = &w.trafficState.Inbound.RemainingContent
remainingPadding = &w.trafficState.Inbound.RemainingPadding
currentCommand = &w.trafficState.Inbound.CurrentCommand
switchToDirectCopy = &w.trafficState.Inbound.UplinkReaderDirectCopy
} else {
withinPaddingBuffers = &w.trafficState.Outbound.WithinPaddingBuffers
remainingContent = &w.trafficState.Outbound.RemainingContent
remainingPadding = &w.trafficState.Outbound.RemainingPadding
currentCommand = &w.trafficState.Outbound.CurrentCommand
switchToDirectCopy = &w.trafficState.Outbound.DownlinkReaderDirectCopy
}
if *withinPaddingBuffers || w.trafficState.NumberOfPacketToFilter > 0 {
mb2 := make(buf.MultiBuffer, 0, len(buffer))
for _, b := range buffer {
newbuffer := XtlsUnpadding(b, w.trafficState, w.ctx)
newbuffer := XtlsUnpadding(b, w.trafficState, w.isUplink, w.ctx)
if newbuffer.Len() > 0 {
mb2 = append(mb2, newbuffer)
}
}
buffer = mb2
if w.trafficState.RemainingContent > 0 || w.trafficState.RemainingPadding > 0 || w.trafficState.CurrentCommand == 0 {
w.trafficState.WithinPaddingBuffers = true
} else if w.trafficState.CurrentCommand == 1 {
w.trafficState.WithinPaddingBuffers = false
} else if w.trafficState.CurrentCommand == 2 {
w.trafficState.WithinPaddingBuffers = false
w.trafficState.ReaderSwitchToDirectCopy = true
if *remainingContent > 0 || *remainingPadding > 0 || *currentCommand == 0 {
*withinPaddingBuffers = true
} else if *currentCommand == 1 {
*withinPaddingBuffers = false
} else if *currentCommand == 2 {
*withinPaddingBuffers = false
*switchToDirectCopy = true
} else {
errors.LogInfo(w.ctx, "XtlsRead unknown command ", w.trafficState.CurrentCommand, buffer.Len())
errors.LogInfo(w.ctx, "XtlsRead unknown command ", *currentCommand, buffer.Len())
}
}
if w.trafficState.NumberOfPacketToFilter > 0 {
@@ -194,9 +243,10 @@ type VisionWriter struct {
trafficState *TrafficState
ctx context.Context
writeOnceUserUUID []byte
isUplink bool
}
func NewVisionWriter(writer buf.Writer, state *TrafficState, context context.Context) *VisionWriter {
func NewVisionWriter(writer buf.Writer, state *TrafficState, isUplink bool, context context.Context) *VisionWriter {
w := make([]byte, len(state.UserUUID))
copy(w, state.UserUUID)
return &VisionWriter{
@@ -204,6 +254,7 @@ func NewVisionWriter(writer buf.Writer, state *TrafficState, context context.Con
trafficState: state,
ctx: context,
writeOnceUserUUID: w,
isUplink: isUplink,
}
}
@@ -211,7 +262,16 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
if w.trafficState.NumberOfPacketToFilter > 0 {
XtlsFilterTls(mb, w.trafficState, w.ctx)
}
if w.trafficState.IsPadding {
var isPadding *bool
var switchToDirectCopy *bool
if w.isUplink {
isPadding = &w.trafficState.Outbound.IsPadding
switchToDirectCopy = &w.trafficState.Outbound.UplinkWriterDirectCopy
} else {
isPadding = &w.trafficState.Inbound.IsPadding
switchToDirectCopy = &w.trafficState.Inbound.DownlinkWriterDirectCopy
}
if *isPadding {
if len(mb) == 1 && mb[0] == nil {
mb[0] = XtlsPadding(nil, CommandPaddingContinue, &w.writeOnceUserUUID, true, w.ctx) // we do a long padding to hide vless header
return w.Writer.WriteMultiBuffer(mb)
@@ -221,7 +281,7 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
for i, b := range mb {
if w.trafficState.IsTLS && b.Len() >= 6 && bytes.Equal(TlsApplicationDataStart, b.BytesTo(3)) {
if w.trafficState.EnableXtls {
w.trafficState.WriterSwitchToDirectCopy = true
*switchToDirectCopy = true
}
var command byte = CommandPaddingContinue
if i == len(mb)-1 {
@@ -231,16 +291,16 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
}
}
mb[i] = XtlsPadding(b, command, &w.writeOnceUserUUID, true, w.ctx)
w.trafficState.IsPadding = false // padding going to end
*isPadding = false // padding going to end
longPadding = false
continue
} else if !w.trafficState.IsTLS12orAbove && w.trafficState.NumberOfPacketToFilter <= 1 { // For compatibility with earlier vision receiver, we finish padding 1 packet early
w.trafficState.IsPadding = false
*isPadding = false
mb[i] = XtlsPadding(b, CommandPaddingEnd, &w.writeOnceUserUUID, longPadding, w.ctx)
break
}
var command byte = CommandPaddingContinue
if i == len(mb)-1 && !w.trafficState.IsPadding {
if i == len(mb)-1 && !*isPadding {
command = CommandPaddingEnd
if w.trafficState.EnableXtls {
command = CommandPaddingDirect
@@ -327,38 +387,53 @@ func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, longPadding bool
}
// XtlsUnpadding remove padding and parse command
func XtlsUnpadding(b *buf.Buffer, s *TrafficState, ctx context.Context) *buf.Buffer {
if s.RemainingCommand == -1 && s.RemainingContent == -1 && s.RemainingPadding == -1 { // initial state
func XtlsUnpadding(b *buf.Buffer, s *TrafficState, isUplink bool, ctx context.Context) *buf.Buffer {
var remainingCommand *int32
var remainingContent *int32
var remainingPadding *int32
var currentCommand *int
if isUplink {
remainingCommand = &s.Inbound.RemainingCommand
remainingContent = &s.Inbound.RemainingContent
remainingPadding = &s.Inbound.RemainingPadding
currentCommand = &s.Inbound.CurrentCommand
} else {
remainingCommand = &s.Outbound.RemainingCommand
remainingContent = &s.Outbound.RemainingContent
remainingPadding = &s.Outbound.RemainingPadding
currentCommand = &s.Outbound.CurrentCommand
}
if *remainingCommand == -1 && *remainingContent == -1 && *remainingPadding == -1 { // initial state
if b.Len() >= 21 && bytes.Equal(s.UserUUID, b.BytesTo(16)) {
b.Advance(16)
s.RemainingCommand = 5
*remainingCommand = 5
} else {
return b
}
}
newbuffer := buf.New()
for b.Len() > 0 {
if s.RemainingCommand > 0 {
if *remainingCommand > 0 {
data, err := b.ReadByte()
if err != nil {
return newbuffer
}
switch s.RemainingCommand {
switch *remainingCommand {
case 5:
s.CurrentCommand = int(data)
*currentCommand = int(data)
case 4:
s.RemainingContent = int32(data) << 8
*remainingContent = int32(data) << 8
case 3:
s.RemainingContent = s.RemainingContent | int32(data)
*remainingContent = *remainingContent | int32(data)
case 2:
s.RemainingPadding = int32(data) << 8
*remainingPadding = int32(data) << 8
case 1:
s.RemainingPadding = s.RemainingPadding | int32(data)
errors.LogInfo(ctx, "Xtls Unpadding new block, content ", s.RemainingContent, " padding ", s.RemainingPadding, " command ", s.CurrentCommand)
*remainingPadding = *remainingPadding | int32(data)
errors.LogInfo(ctx, "Xtls Unpadding new block, content ", *remainingContent, " padding ", *remainingPadding, " command ", *currentCommand)
}
s.RemainingCommand--
} else if s.RemainingContent > 0 {
len := s.RemainingContent
*remainingCommand--
} else if *remainingContent > 0 {
len := *remainingContent
if b.Len() < len {
len = b.Len()
}
@@ -367,22 +442,22 @@ func XtlsUnpadding(b *buf.Buffer, s *TrafficState, ctx context.Context) *buf.Buf
return newbuffer
}
newbuffer.Write(data)
s.RemainingContent -= len
*remainingContent -= len
} else { // remainingPadding > 0
len := s.RemainingPadding
len := *remainingPadding
if b.Len() < len {
len = b.Len()
}
b.Advance(len)
s.RemainingPadding -= len
*remainingPadding -= len
}
if s.RemainingCommand <= 0 && s.RemainingContent <= 0 && s.RemainingPadding <= 0 { // this block done
if s.CurrentCommand == 0 {
s.RemainingCommand = 5
if *remainingCommand <= 0 && *remainingContent <= 0 && *remainingPadding <= 0 { // this block done
if *currentCommand == 0 {
*remainingCommand = 5
} else {
s.RemainingCommand = -1 // set to initial state
s.RemainingContent = -1
s.RemainingPadding = -1
*remainingCommand = -1 // set to initial state
*remainingContent = -1
*remainingPadding = -1
if b.Len() > 0 { // shouldn't happen
newbuffer.Write(b.Bytes())
}
@@ -449,7 +524,7 @@ func XtlsFilterTls(buffer buf.MultiBuffer, trafficState *TrafficState, ctx conte
}
}
// UnwrapRawConn support unwrap stats, tls, utls, reality and proxyproto conn and get raw tcp conn from it
// UnwrapRawConn support unwrap stats, tls, utls, reality, proxyproto, uds-wrapper conn and get raw tcp/uds conn from it
func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
var readCounter, writerCounter stats.Counter
if conn != nil {
@@ -472,6 +547,9 @@ func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
conn = pc.Raw()
// 8192 > 4096, there is no need to process pc's bufReader
}
if uc, ok := conn.(*internet.UDSWrapperConn); ok {
conn = uc.Conn
}
}
return conn, readCounter, writerCounter
}

View File

@@ -146,6 +146,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer))
}
responseFunc = func() error {
ob.CanSpliceCopy = 1
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
}
@@ -161,6 +162,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
return buf.Copy(link.Reader, writer, buf.UpdateActivity(timer))
}
responseFunc = func() error {
ob.CanSpliceCopy = 1
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
reader := &UDPReader{Reader: udpConn}
return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))

View File

@@ -2,6 +2,7 @@ package socks
import (
"context"
goerrors "errors"
"io"
"time"
@@ -78,7 +79,13 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
switch network {
case net.Network_TCP:
firstbyte := make([]byte, 1)
conn.Read(firstbyte)
if n, err := conn.Read(firstbyte); n == 0 {
if goerrors.Is(err, io.EOF) {
errors.LogInfo(ctx, "Connection closed immediately, likely health check connection")
return nil
}
return errors.New("failed to read from connection").Base(err)
}
if firstbyte[0] != 5 && firstbyte[0] != 4 { // Check if it is Socks5/4/4a
errors.LogDebug(ctx, "Not Socks request, try to parse as HTTP request")
return s.httpServer.ProcessWithFirstbyte(ctx, network, conn, dispatcher, firstbyte...)
@@ -192,6 +199,7 @@ func (s *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ
}
responseDone := func() error {
inbound.CanSpliceCopy = 1
defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)
v2writer := buf.NewWriter(writer)
@@ -249,6 +257,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis
if inbound != nil && inbound.Source.IsValid() {
errors.LogInfo(ctx, "client UDP connection from ", inbound.Source)
}
inbound.CanSpliceCopy = 1
var dest *net.Destination

View File

@@ -61,13 +61,13 @@ func DecodeHeaderAddons(buffer *buf.Buffer, reader io.Reader) (*Addons, error) {
}
// EncodeBodyAddons returns a Writer that auto-encrypt content written by caller.
func EncodeBodyAddons(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons, state *proxy.TrafficState, context context.Context) buf.Writer {
func EncodeBodyAddons(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons, state *proxy.TrafficState, isUplink bool, context context.Context) buf.Writer {
if request.Command == protocol.RequestCommandUDP {
return NewMultiLengthPacketWriter(writer.(buf.Writer))
}
w := buf.NewWriter(writer)
if requestAddons.Flow == vless.XRV {
w = proxy.NewVisionWriter(w, state, context)
w = proxy.NewVisionWriter(w, state, isUplink, context)
}
return w
}

View File

@@ -172,19 +172,19 @@ func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*A
}
// XtlsRead filter and read xtls protocol
func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, conn net.Conn, input *bytes.Reader, rawInput *bytes.Buffer, trafficState *proxy.TrafficState, ob *session.Outbound, ctx context.Context) error {
func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, conn net.Conn, input *bytes.Reader, rawInput *bytes.Buffer, trafficState *proxy.TrafficState, ob *session.Outbound, isUplink bool, ctx context.Context) error {
err := func() error {
for {
if trafficState.ReaderSwitchToDirectCopy {
if isUplink && trafficState.Inbound.UplinkReaderDirectCopy || !isUplink && trafficState.Outbound.DownlinkReaderDirectCopy {
var writerConn net.Conn
var inTimer *signal.ActivityTimer
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil {
writerConn = inbound.Conn
inTimer = inbound.Timer
if inbound.CanSpliceCopy == 2 {
if isUplink && inbound.CanSpliceCopy == 2 {
inbound.CanSpliceCopy = 1
}
if ob != nil && ob.CanSpliceCopy == 2 { // ob need to be passed in due to context can change
if !isUplink && ob != nil && ob.CanSpliceCopy == 2 { // ob need to be passed in due to context can change
ob.CanSpliceCopy = 1
}
}
@@ -193,7 +193,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer,
buffer, err := reader.ReadMultiBuffer()
if !buffer.IsEmpty() {
timer.Update()
if trafficState.ReaderSwitchToDirectCopy {
if isUplink && trafficState.Inbound.UplinkReaderDirectCopy || !isUplink && trafficState.Outbound.DownlinkReaderDirectCopy {
// XTLS Vision processes struct TLS Conn's input and rawInput
if inputBuffer, err := buf.ReadFrom(input); err == nil {
if !inputBuffer.IsEmpty() {
@@ -222,24 +222,28 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer,
}
// XtlsWrite filter and write xtls protocol
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, trafficState *proxy.TrafficState, ob *session.Outbound, ctx context.Context) error {
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, trafficState *proxy.TrafficState, ob *session.Outbound, isUplink bool, ctx context.Context) error {
err := func() error {
var ct stats.Counter
for {
buffer, err := reader.ReadMultiBuffer()
if trafficState.WriterSwitchToDirectCopy {
if isUplink && trafficState.Outbound.UplinkWriterDirectCopy || !isUplink && trafficState.Inbound.DownlinkWriterDirectCopy {
if inbound := session.InboundFromContext(ctx); inbound != nil {
if inbound.CanSpliceCopy == 2 {
if !isUplink && inbound.CanSpliceCopy == 2 {
inbound.CanSpliceCopy = 1
}
if ob != nil && ob.CanSpliceCopy == 2 {
if isUplink && ob != nil && ob.CanSpliceCopy == 2 {
ob.CanSpliceCopy = 1
}
}
rawConn, _, writerCounter := proxy.UnwrapRawConn(conn)
writer = buf.NewWriter(rawConn)
ct = writerCounter
trafficState.WriterSwitchToDirectCopy = false
if isUplink {
trafficState.Outbound.UplinkWriterDirectCopy = false
} else {
trafficState.Inbound.DownlinkWriterDirectCopy = false
}
}
if !buffer.IsEmpty() {
if ct != nil {

View File

@@ -538,8 +538,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
if requestAddons.Flow == vless.XRV {
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
clientReader = proxy.NewVisionReader(clientReader, trafficState, ctx1)
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, input, rawInput, trafficState, nil, ctx1)
clientReader = proxy.NewVisionReader(clientReader, trafficState, true, ctx1)
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, input, rawInput, trafficState, nil, true, ctx1)
} else {
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
@@ -561,7 +561,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
}
// default: clientWriter := bufferWriter
clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, ctx)
clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, false, ctx)
multiBuffer, err1 := serverReader.ReadMultiBuffer()
if err1 != nil {
return err1 // ...
@@ -576,7 +576,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
var err error
if requestAddons.Flow == vless.XRV {
err = encoding.XtlsWrite(serverReader, clientWriter, timer, connection, trafficState, nil, ctx)
err = encoding.XtlsWrite(serverReader, clientWriter, timer, connection, trafficState, nil, false, ctx)
} else {
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBuffer
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))

View File

@@ -194,7 +194,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
// default: serverWriter := bufferWriter
serverWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, ctx)
serverWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, true, ctx)
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
serverWriter = xudp.NewPacketWriter(serverWriter, target, xudp.GetGlobalID(ctx))
}
@@ -234,7 +234,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
}
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
err = encoding.XtlsWrite(clientReader, serverWriter, timer, conn, trafficState, ob, ctx1)
err = encoding.XtlsWrite(clientReader, serverWriter, timer, conn, trafficState, ob, true, ctx1)
} else {
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
@@ -261,7 +261,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
// default: serverReader := buf.NewReader(conn)
serverReader := encoding.DecodeBodyAddons(conn, request, responseAddons)
if requestAddons.Flow == vless.XRV {
serverReader = proxy.NewVisionReader(serverReader, trafficState, ctx)
serverReader = proxy.NewVisionReader(serverReader, trafficState, false, ctx)
}
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
if requestAddons.Flow == vless.XRV {
@@ -272,7 +272,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
if requestAddons.Flow == vless.XRV {
err = encoding.XtlsRead(serverReader, clientWriter, timer, conn, input, rawInput, trafficState, ob, ctx)
err = encoding.XtlsRead(serverReader, clientWriter, timer, conn, input, rawInput, trafficState, ob, false, ctx)
} else {
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBuffer
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))

View File

@@ -157,7 +157,7 @@ func (tun *netTun) Write(buf [][]byte, offset int) (int, error) {
// WriteNotify implements channel.Notification
func (tun *netTun) WriteNotify() {
pkt := tun.ep.Read()
if pkt.IsNil() {
if pkt == nil {
return
}

View File

@@ -194,7 +194,7 @@ func createGVisorTun(localAddresses []netip.Addr, mtu int, handler promiscuousMo
Timeout: 15 * time.Second,
})
handler(xnet.UDPDestination(xnet.IPAddress(id.LocalAddress.AsSlice()), xnet.Port(id.LocalPort)), gonet.NewUDPConn(stack, &wq, ep))
handler(xnet.UDPDestination(xnet.IPAddress(id.LocalAddress.AsSlice()), xnet.Port(id.LocalPort)), gonet.NewUDPConn(&wq, ep))
}(r)
})
stack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)

View File

@@ -5,6 +5,7 @@ import (
"context"
_ "embed"
"encoding/base64"
"encoding/json"
"net/http"
"time"
@@ -17,6 +18,12 @@ import (
//go:embed dialer.html
var webpage []byte
type task struct {
Method string `json:"method"`
URL string `json:"url"`
Extra any `json:"extra,omitempty"`
}
var conns chan *websocket.Conn
var upgrader = &websocket.Upgrader{
@@ -55,23 +62,69 @@ func HasBrowserDialer() bool {
return conns != nil
}
type webSocketExtra struct {
Protocol string `json:"protocol,omitempty"`
}
func DialWS(uri string, ed []byte) (*websocket.Conn, error) {
data := []byte("WS " + uri)
if ed != nil {
data = append(data, " "+base64.RawURLEncoding.EncodeToString(ed)...)
task := task{
Method: "WS",
URL: uri,
}
return dialRaw(data)
if ed != nil {
task.Extra = webSocketExtra{
Protocol: base64.RawURLEncoding.EncodeToString(ed),
}
}
return dialTask(task)
}
func DialGet(uri string) (*websocket.Conn, error) {
data := []byte("GET " + uri)
return dialRaw(data)
type httpExtra struct {
Referrer string `json:"referrer,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
}
func DialPost(uri string, payload []byte) error {
data := []byte("POST " + uri)
conn, err := dialRaw(data)
func httpExtraFromHeaders(headers http.Header) *httpExtra {
if len(headers) == 0 {
return nil
}
extra := httpExtra{}
if referrer := headers.Get("Referer"); referrer != "" {
extra.Referrer = referrer
headers.Del("Referer")
}
if len(headers) > 0 {
extra.Headers = make(map[string]string)
for header := range headers {
extra.Headers[header] = headers.Get(header)
}
}
return &extra
}
func DialGet(uri string, headers http.Header) (*websocket.Conn, error) {
task := task{
Method: "GET",
URL: uri,
Extra: httpExtraFromHeaders(headers),
}
return dialTask(task)
}
func DialPost(uri string, headers http.Header, payload []byte) error {
task := task{
Method: "POST",
URL: uri,
Extra: httpExtraFromHeaders(headers),
}
conn, err := dialTask(task)
if err != nil {
return err
}
@@ -90,7 +143,12 @@ func DialPost(uri string, payload []byte) error {
return nil
}
func dialRaw(data []byte) (*websocket.Conn, error) {
func dialTask(task task) (*websocket.Conn, error) {
data, err := json.Marshal(task)
if err != nil {
return nil, err
}
var conn *websocket.Conn
for {
conn = <-conns
@@ -100,7 +158,7 @@ func dialRaw(data []byte) (*websocket.Conn, error) {
break
}
}
err := CheckOK(conn)
err = CheckOK(conn)
if err != nil {
return nil, err
}

View File

@@ -14,10 +14,28 @@
let upstreamGetCount = 0;
let upstreamWsCount = 0;
let upstreamPostCount = 0;
function prepareRequestInit(extra) {
const requestInit = {};
if (extra.referrer) {
// note: we have to strip the protocol and host part.
// Browsers disallow that, and will reset the value to current page if attempted.
const referrer = URL.parse(extra.referrer);
requestInit.referrer = referrer.pathname + referrer.search + referrer.hash;
requestInit.referrerPolicy = "unsafe-url";
}
if (extra.headers) {
requestInit.headers = extra.headers;
}
return requestInit;
}
let check = function () {
if (clientIdleCount > 0) {
return;
};
}
clientIdleCount += 1;
console.log("Prepare", url);
let ws = new WebSocket(url);
@@ -29,12 +47,12 @@
// double-checking that this continues to work
ws.onmessage = function (event) {
clientIdleCount -= 1;
let [method, url, protocol] = event.data.split(" ");
switch (method) {
let task = JSON.parse(event.data);
switch (task.method) {
case "WS": {
upstreamWsCount += 1;
console.log("Dial WS", url, protocol);
const wss = new WebSocket(url, protocol);
console.log("Dial WS", task.url, task.extra.protocol);
const wss = new WebSocket(task.url, task.extra.protocol);
wss.binaryType = "arraybuffer";
let opened = false;
ws.onmessage = function (event) {
@@ -60,10 +78,12 @@
wss.close()
};
break;
};
}
case "GET": {
(async () => {
console.log("Dial GET", url);
const requestInit = prepareRequestInit(task.extra);
console.log("Dial GET", task.url);
ws.send("ok");
const controller = new AbortController();
@@ -83,58 +103,62 @@
ws.onclose = (event) => {
try {
reader && reader.cancel();
} catch(e) {};
} catch(e) {}
try {
controller.abort();
} catch(e) {};
} catch(e) {}
};
try {
upstreamGetCount += 1;
const response = await fetch(url, {signal: controller.signal});
requestInit.signal = controller.signal;
const response = await fetch(task.url, requestInit);
const body = await response.body;
reader = body.getReader();
while (true) {
const { done, value } = await reader.read();
ws.send(value);
if (value) ws.send(value); // don't send back "undefined" string when received nothing
if (done) break;
};
}
} finally {
upstreamGetCount -= 1;
console.log("Dial GET DONE, remaining: ", upstreamGetCount);
ws.close();
};
}
})();
break;
};
}
case "POST": {
upstreamPostCount += 1;
console.log("Dial POST", url);
const requestInit = prepareRequestInit(task.extra);
requestInit.method = "POST";
console.log("Dial POST", task.url);
ws.send("ok");
ws.onmessage = async (event) => {
try {
const response = await fetch(
url,
{method: "POST", body: event.data}
);
requestInit.body = event.data;
const response = await fetch(task.url, requestInit);
if (response.ok) {
ws.send("ok");
} else {
console.error("bad status code");
ws.send("fail");
};
}
} finally {
upstreamPostCount -= 1;
console.log("Dial POST DONE, remaining: ", upstreamPostCount);
ws.close();
};
}
};
break;
};
};
}
}
check();
};

View File

@@ -448,7 +448,7 @@ type SocketConfig struct {
TcpWindowClamp int32 `protobuf:"varint,15,opt,name=tcp_window_clamp,json=tcpWindowClamp,proto3" json:"tcp_window_clamp,omitempty"`
TcpUserTimeout int32 `protobuf:"varint,16,opt,name=tcp_user_timeout,json=tcpUserTimeout,proto3" json:"tcp_user_timeout,omitempty"`
TcpMaxSeg int32 `protobuf:"varint,17,opt,name=tcp_max_seg,json=tcpMaxSeg,proto3" json:"tcp_max_seg,omitempty"`
TcpNoDelay bool `protobuf:"varint,18,opt,name=tcp_no_delay,json=tcpNoDelay,proto3" json:"tcp_no_delay,omitempty"`
Penetrate bool `protobuf:"varint,18,opt,name=penetrate,proto3" json:"penetrate,omitempty"`
TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"`
CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"`
}
@@ -602,9 +602,9 @@ func (x *SocketConfig) GetTcpMaxSeg() int32 {
return 0
}
func (x *SocketConfig) GetTcpNoDelay() bool {
func (x *SocketConfig) GetPenetrate() bool {
if x != nil {
return x.TcpNoDelay
return x.Penetrate
}
return false
}
@@ -678,7 +678,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{
0x28, 0x09, 0x52, 0x03, 0x6f, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a,
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
0x65, 0x22, 0x9f, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66,
0x65, 0x22, 0x9b, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20,
0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72, 0x6f,
@@ -724,36 +724,36 @@ var file_transport_internet_config_proto_rawDesc = []byte{
0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x63, 0x70, 0x55, 0x73, 0x65, 0x72, 0x54, 0x69,
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x74, 0x63, 0x70, 0x5f, 0x6d, 0x61, 0x78,
0x5f, 0x73, 0x65, 0x67, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x63, 0x70, 0x4d,
0x61, 0x78, 0x53, 0x65, 0x67, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x63, 0x70, 0x5f, 0x6e, 0x6f, 0x5f,
0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x74, 0x63, 0x70,
0x4e, 0x6f, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x63, 0x70, 0x5f, 0x6d,
0x70, 0x74, 0x63, 0x70, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x63, 0x70, 0x4d,
0x70, 0x74, 0x63, 0x70, 0x12, 0x4c, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f,
0x63, 0x6b, 0x6f, 0x70, 0x74, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x72,
0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b,
0x6f, 0x70, 0x74, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f,
0x70, 0x74, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65,
0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72,
0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63,
0x74, 0x10, 0x02, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10,
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a,
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53,
0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49,
0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36,
0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10,
0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07,
0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12,
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12,
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42,
0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 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, 0x74, 0x72, 0x61, 0x6e,
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02,
0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e,
0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x61, 0x78, 0x53, 0x65, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x6e, 0x65, 0x74, 0x72, 0x61,
0x74, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x6e, 0x65, 0x74, 0x72,
0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x63, 0x70, 0x5f, 0x6d, 0x70, 0x74, 0x63, 0x70,
0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x63, 0x70, 0x4d, 0x70, 0x74, 0x63, 0x70,
0x12, 0x4c, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70,
0x74, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x52,
0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x22, 0x2f,
0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03,
0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10,
0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a,
0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a,
0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45,
0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10,
0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12,
0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a,
0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09,
0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46,
0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46,
0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42, 0x67, 0x0a, 0x1b, 0x63,
0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 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, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61,
0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -103,7 +103,7 @@ message SocketConfig {
string interface = 13;
bool v6only = 14;
bool v6only = 14;
int32 tcp_window_clamp = 15;
@@ -111,7 +111,7 @@ message SocketConfig {
int32 tcp_max_seg = 17;
bool tcp_no_delay = 18;
bool penetrate = 18;
bool tcp_mptcp = 19;

View File

@@ -180,12 +180,12 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
prefix := []byte("https://" + uConn.ServerName)
maps.Lock()
if maps.maps == nil {
maps.maps = make(map[string]map[string]bool)
maps.maps = make(map[string]map[string]struct{})
}
paths := maps.maps[uConn.ServerName]
if paths == nil {
paths = make(map[string]bool)
paths[config.SpiderX] = true
paths = make(map[string]struct{})
paths[config.SpiderX] = struct{}{}
maps.maps[uConn.ServerName] = paths
}
firstURL := string(prefix) + getPathLocked(paths)
@@ -232,7 +232,7 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
for _, m := range href.FindAllSubmatch(body, -1) {
m[1] = bytes.TrimPrefix(m[1], prefix)
if !bytes.Contains(m[1], dot) {
paths[string(m[1])] = true
paths[string(m[1])] = struct{}{}
}
}
req.URL.Path = getPathLocked(paths)
@@ -267,10 +267,10 @@ var (
var maps struct {
sync.Mutex
maps map[string]map[string]bool
maps map[string]map[string]struct{}
}
func getPathLocked(paths map[string]bool) string {
func getPathLocked(paths map[string]struct{}) string {
stopAt := int(randBetween(0, int64(len(paths)-1)))
i := 0
for s := range paths {

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