From 255ff5e9779238254e9289f5bcbaf6acbe2b5076 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Tue, 10 Jun 2025 10:38:05 +0800 Subject: [PATCH] chore: add rate limiting support for reality listener --- docs/config.yaml | 30 ++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 ++-- listener/inbound/reality.go | 20 ++++++++++++++++++++ listener/reality/reality.go | 7 +++++++ 5 files changed, 60 insertions(+), 3 deletions(-) diff --git a/docs/config.yaml b/docs/config.yaml index 42a3307c..6f1a9fef 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -1276,6 +1276,16 @@ listeners: # - 0123456789abcdef # server-names: # - test.com + # #下列两个 limit 为选填,可对未通过验证的回落连接限速,bytesPerSec 默认为 0 即不启用 + # #回落限速是一种特征,不建议启用,如果您是面板/一键脚本开发者,务必让这些参数随机化 + # limit-fallback-upload: + # after-bytes: 0 # 传输指定字节后开始限速 + # bytes-per-sec: 0 # 基准速率(字节/秒) + # burst-bytes-per-sec: 0 # 突发速率(字节/秒),大于 bytesPerSec 时生效 + # limit-fallback-download: + # after-bytes: 0 # 传输指定字节后开始限速 + # bytes-per-sec: 0 # 基准速率(字节/秒) + # burst-bytes-per-sec: 0 # 突发速率(字节/秒),大于 bytesPerSec 时生效 - name: tuic-in-1 type: tuic @@ -1343,6 +1353,16 @@ listeners: - 0123456789abcdef server-names: - test.com + #下列两个 limit 为选填,可对未通过验证的回落连接限速,bytesPerSec 默认为 0 即不启用 + #回落限速是一种特征,不建议启用,如果您是面板/一键脚本开发者,务必让这些参数随机化 + limit-fallback-upload: + after-bytes: 0 # 传输指定字节后开始限速 + bytes-per-sec: 0 # 基准速率(字节/秒) + burst-bytes-per-sec: 0 # 突发速率(字节/秒),大于 bytesPerSec 时生效 + limit-fallback-download: + after-bytes: 0 # 传输指定字节后开始限速 + bytes-per-sec: 0 # 基准速率(字节/秒) + burst-bytes-per-sec: 0 # 突发速率(字节/秒),大于 bytesPerSec 时生效 ### 注意,对于vless listener, 至少需要填写 “certificate和private-key” 或 “reality-config” 的其中一项 ### - name: anytls-in-1 @@ -1393,6 +1413,16 @@ listeners: # - 0123456789abcdef # server-names: # - test.com + # #下列两个 limit 为选填,可对未通过验证的回落连接限速,bytesPerSec 默认为 0 即不启用 + # #回落限速是一种特征,不建议启用,如果您是面板/一键脚本开发者,务必让这些参数随机化 + # limit-fallback-upload: + # after-bytes: 0 # 传输指定字节后开始限速 + # bytes-per-sec: 0 # 基准速率(字节/秒) + # burst-bytes-per-sec: 0 # 突发速率(字节/秒),大于 bytesPerSec 时生效 + # limit-fallback-download: + # after-bytes: 0 # 传输指定字节后开始限速 + # bytes-per-sec: 0 # 基准速率(字节/秒) + # burst-bytes-per-sec: 0 # 突发速率(字节/秒),大于 bytesPerSec 时生效 # ss-option: # like trojan-go's `shadowsocks` config # enabled: false # method: aes-128-gcm # aes-128-gcm/aes-256-gcm/chacha20-ietf-poly1305 diff --git a/go.mod b/go.mod index 31b96a08..21ae1114 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/smux v0.0.0-20250503055512-501391591dee github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 - github.com/metacubex/utls v1.7.3 + github.com/metacubex/utls v1.7.4-0.20250610022031-808d767c8c73 github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 github.com/miekg/dns v1.1.63 // lastest version compatible with golang1.20 github.com/mroth/weightedrand/v2 v2.1.0 diff --git a/go.sum b/go.sum index 040073a9..e93e1c70 100644 --- a/go.sum +++ b/go.sum @@ -138,8 +138,8 @@ github.com/metacubex/smux v0.0.0-20250503055512-501391591dee h1:lp6hJ+4wCLZu113a github.com/metacubex/smux v0.0.0-20250503055512-501391591dee/go.mod h1:4bPD8HWx9jPJ9aE4uadgyN7D1/Wz3KmPy+vale8sKLE= github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 h1:j1VRTiC9JLR4nUbSikx9OGdu/3AgFDqgcLj4GoqyQkc= github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= -github.com/metacubex/utls v1.7.3 h1:yDcMEWojFh+t8rU9X0HPcZDPAoFze/rIIyssqivzj8A= -github.com/metacubex/utls v1.7.3/go.mod h1:oknYT0qTOwE4hjPmZOEpzVdefnW7bAdGLvZcqmk4TLU= +github.com/metacubex/utls v1.7.4-0.20250610022031-808d767c8c73 h1:HWKsf92BqLYqugATFIJ3hYiEBZ7JF6AoqyvqF39afuI= +github.com/metacubex/utls v1.7.4-0.20250610022031-808d767c8c73/go.mod h1:oknYT0qTOwE4hjPmZOEpzVdefnW7bAdGLvZcqmk4TLU= github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ= github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y= github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= diff --git a/listener/inbound/reality.go b/listener/inbound/reality.go index 7653cd38..7932b060 100644 --- a/listener/inbound/reality.go +++ b/listener/inbound/reality.go @@ -9,6 +9,15 @@ type RealityConfig struct { ServerNames []string `inbound:"server-names"` MaxTimeDifference int `inbound:"max-time-difference,omitempty"` Proxy string `inbound:"proxy,omitempty"` + + LimitFallbackUpload RealityLimitFallback `inbound:"limit-fallback-upload,omitempty"` + LimitFallbackDownload RealityLimitFallback `inbound:"limit-fallback-download,omitempty"` +} + +type RealityLimitFallback struct { + AfterBytes uint64 `inbound:"after-bytes,omitempty"` + BytesPerSec uint64 `inbound:"bytes-per-sec,omitempty"` + BurstBytesPerSec uint64 `inbound:"burst-bytes-per-sec,omitempty"` } func (c RealityConfig) Build() reality.Config { @@ -19,5 +28,16 @@ func (c RealityConfig) Build() reality.Config { ServerNames: c.ServerNames, MaxTimeDifference: c.MaxTimeDifference, Proxy: c.Proxy, + + LimitFallbackUpload: reality.LimitFallback{ + AfterBytes: c.LimitFallbackUpload.AfterBytes, + BytesPerSec: c.LimitFallbackUpload.BytesPerSec, + BurstBytesPerSec: c.LimitFallbackUpload.BurstBytesPerSec, + }, + LimitFallbackDownload: reality.LimitFallback{ + AfterBytes: c.LimitFallbackDownload.AfterBytes, + BytesPerSec: c.LimitFallbackDownload.BytesPerSec, + BurstBytesPerSec: c.LimitFallbackDownload.BurstBytesPerSec, + }, } } diff --git a/listener/reality/reality.go b/listener/reality/reality.go index 64de7cf8..d91055f8 100644 --- a/listener/reality/reality.go +++ b/listener/reality/reality.go @@ -20,6 +20,7 @@ import ( ) type Conn = utls.Conn +type LimitFallback = utls.RealityLimitFallback type Config struct { Dest string @@ -28,6 +29,9 @@ type Config struct { ServerNames []string MaxTimeDifference int Proxy string + + LimitFallbackUpload LimitFallback + LimitFallbackDownload LimitFallback } func (c Config) Build(tunnel C.Tunnel) (*Builder, error) { @@ -73,6 +77,9 @@ func (c Config) Build(tunnel C.Tunnel) (*Builder, error) { return inner.HandleTcp(tunnel, address, c.Proxy) } + realityConfig.LimitFallbackUpload = c.LimitFallbackUpload + realityConfig.LimitFallbackDownload = c.LimitFallbackDownload + return &Builder{realityConfig}, nil }