chore: adjustable cwnd for cc in quic

This commit is contained in:
Larvan2 2023-06-18 00:47:26 +08:00
parent 61734e5cac
commit 6c8631d5cc
7 changed files with 101 additions and 86 deletions

View file

@ -49,6 +49,7 @@ type TuicOption struct {
FastOpen bool `proxy:"fast-open,omitempty"`
MaxOpenStreams int `proxy:"max-open-streams,omitempty"`
CWND int `proxy:"cwnd,omitempty"`
SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"`
Fingerprint string `proxy:"fingerprint,omitempty"`
CustomCA string `proxy:"ca,omitempty"`
@ -188,6 +189,10 @@ func NewTuic(option TuicOption) (*Tuic, error) {
option.MaxOpenStreams = 100
}
if option.CWND == 0 {
option.CWND = 32
}
packetOverHead := tuic.PacketOverHeadV4
if len(option.Token) == 0 {
packetOverHead = tuic.PacketOverHeadV5
@ -272,6 +277,7 @@ func NewTuic(option TuicOption) (*Tuic, error) {
MaxUdpRelayPacketSize: option.MaxUdpRelayPacketSize,
FastOpen: option.FastOpen,
MaxOpenStreams: clientMaxOpenStreams,
CWND: option.CWND,
}
t.client = tuic.NewPoolClientV4(clientOption)
@ -286,6 +292,7 @@ func NewTuic(option TuicOption) (*Tuic, error) {
ReduceRtt: option.ReduceRtt,
MaxUdpRelayPacketSize: option.MaxUdpRelayPacketSize,
MaxOpenStreams: clientMaxOpenStreams,
CWND: option.CWND,
}
t.client = tuic.NewPoolClientV5(clientOption)

View file

@ -64,7 +64,7 @@ hosts:
profile: # 存储 select 选择记录
store-selected: false
# 持久化 fake-ip
store-fake-ip: true
@ -93,10 +93,10 @@ tun:
#- 1000
# exclude-uid-range: # 排除路由的的用户范围
# - 1000-99999
# Android 用户和应用规则仅在 Android 下被支持
# 并且需要 auto-route
# include-android-user: # 限制被路由的 Android 用户
# - 0
# - 10
@ -126,10 +126,9 @@ sniffer:
sniff: # TLS 默认如果不配置 ports 默认嗅探 443
TLS:
# ports: [443, 8443]
# 默认嗅探 80
HTTP: # 需要嗅探的端口
ports: [80, 8080-8880]
# 可覆盖 sniffer.override-destination
override-destination: true
@ -144,7 +143,7 @@ sniffer:
- tls
- http
# 强制对此域名进行嗅探
# 仅对白名单中的端口进行嗅探,默认为 44380
# 已废弃,若 sniffer.sniff 配置则此项无效
port-whitelist:
@ -152,7 +151,6 @@ sniffer:
- "443"
# - 8000-9999
tunnels: # one line config
- tcp/udp,127.0.0.1:6553,114.114.114.114:53,proxy
- tcp,127.0.0.1:6666,rds.mysql.com:3306,vpn
@ -162,7 +160,6 @@ tunnels: # one line config
target: target.com
proxy: proxy
# DNS配置
dns:
enable: false # 关闭将使用系统 DNS
@ -177,18 +174,18 @@ dns:
- 8.8.8.8
- tls://1.12.12.12:853
- tls://223.5.5.5:853
- system # append DNS server from system configuration. If not found, it would print an error log and skip.
- system # append DNS server from system configuration. If not found, it would print an error log and skip.
enhanced-mode: fake-ip # or redir-host
fake-ip-range: 198.18.0.1/16 # fake-ip 池设置
# use-hosts: true # 查询 hosts
# 配置不使用fake-ip的域名
# fake-ip-filter:
# - '*.lan'
# - localhost.ptlogin2.qq.com
# DNS主要域名配置
# 支持 UDPTCPDoTDoHDoQ
# 这部分为主要 DNS 配置,影响所有直连,确保使用对大陆解析精准的 DNS
@ -202,20 +199,20 @@ dns:
- dhcp://en0 # dns from dhcp
- quic://dns.adguard.com:784 # DNS over QUIC
# - '8.8.8.8#en0' # 兼容指定DNS出口网卡
# 当配置 fallback 时,会查询 nameserver 中返回的 IP 是否为 CN非必要配置
# 当不是 CN则使用 fallback 中的 DNS 查询结果
# 确保配置 fallback 时能够正常查询
# fallback:
# - tcp://1.1.1.1
# - 'tcp://1.1.1.1#ProxyGroupName' # 指定 DNS 过代理查询ProxyGroupName 为策略组名或节点名,过代理配置优先于配置出口网卡,当找不到策略组或节点名则设置为出口网卡
# 专用于节点域名解析的 DNS 服务器,非必要配置项
# 配置服务器若查询失败将使用 nameserver非并发查询
# proxy-server-nameserver:
# - https://dns.google/dns-query
# - tls://one.one.one.one
# 配置 fallback 使用条件
# fallback-filter:
# geoip: true # 配置是否使用 geoip
@ -230,7 +227,7 @@ dns:
# - '+.google.com'
# - '+.facebook.com'
# - '+.youtube.com'
# 配置查询域名使用的 DNS 服务器
nameserver-policy:
# 'www.baidu.com': '114.114.114.114'
@ -241,7 +238,7 @@ dns:
"geosite:category-ads-all": rcode://success
"www.baidu.com,+.google.cn": [223.5.5.5, https://dns.alidns.com/dns-query]
## globaldns 为 rule-providers 中的名为 global 和 dns 规则订阅,
## 且 behavior 必须为 domain/classical当为 classical 时仅会生效域名类规则
## 且 behavior 必须为 domain/classical当为 classical 时仅会生效域名类规则
# "rule-set:global,dns": 8.8.8.8
proxies: # socks5
@ -256,7 +253,7 @@ proxies: # socks5
# skip-cert-verify: true
# udp: true
# ip-version: ipv6
# http
- name: "http"
type: http
@ -269,7 +266,7 @@ proxies: # socks5
# sni: custom.com
# fingerprint: xxxx # 同 experimental.fingerprints 使用 sha256 指纹,配置协议独立的指纹,将忽略 experimental.fingerprints
# ip-version: dual
# Snell
# Beware that there's currently no UDP support yet
- name: "snell"
@ -281,7 +278,7 @@ proxies: # socks5
# obfs-opts:
# mode: http # or tls
# host: bing.com
# Shadowsocks
# cipher支持:
# aes-128-gcm aes-192-gcm aes-256-gcm
@ -313,7 +310,7 @@ proxies: # socks5
# padding: false # Enable padding. Requires sing-box server version 1.3-beta9 or later.
# statistic: false # 控制是否将底层连接显示在面板中,方便打断底层连接
# only-tcp: false # 如果设置为true, smux的设置将不会对udp生效udp连接会直接走底层协议
- name: "ss2"
type: ss
server: server
@ -324,7 +321,7 @@ proxies: # socks5
plugin-opts:
mode: tls # or http
# host: bing.com
- name: "ss3"
type: ss
server: server
@ -344,7 +341,7 @@ proxies: # socks5
# mux: true
# headers:
# custom: value
- name: "ss4-shadow-tls"
type: ss
server: server
@ -364,20 +361,22 @@ proxies: # socks5
port: 443
cipher: chacha20-ietf-poly1305
password: [YOUR_SS_PASSWORD]
client-fingerprint: chrome # One of: chrome, ios, firefox or safari
# 可以是chrome, ios, firefox, safari中的一个
client-fingerprint:
chrome # One of: chrome, ios, firefox or safari
# 可以是chrome, ios, firefox, safari中的一个
plugin: restls
plugin-opts:
host: "www.microsoft.com" # Must be a TLS 1.3 server
# 应当是一个TLS 1.3 服务器
password: [YOUR_RESTLS_PASSWORD]
version-hint: "tls13"
# Control your post-handshake traffic through restls-script
# Hide proxy behaviors like "tls in tls".
# see https://github.com/3andne/restls/blob/main/Restls-Script:%20Hide%20Your%20Proxy%20Traffic%20Behavior.md
# 用restls剧本来控制握手后的行为隐藏"tls in tls"等特征
# 详情https://github.com/3andne/restls/blob/main/Restls-Script:%20%E9%9A%90%E8%97%8F%E4%BD%A0%E7%9A%84%E4%BB%A3%E7%90%86%E8%A1%8C%E4%B8%BA.md
restls-script: "300?100<1,400~100,350~100,600~100,300~200,300~100"
host:
"www.microsoft.com" # Must be a TLS 1.3 server
# 应当是一个TLS 1.3 服务器
password: [YOUR_RESTLS_PASSWORD]
version-hint: "tls13"
# Control your post-handshake traffic through restls-script
# Hide proxy behaviors like "tls in tls".
# see https://github.com/3andne/restls/blob/main/Restls-Script:%20Hide%20Your%20Proxy%20Traffic%20Behavior.md
# 用restls剧本来控制握手后的行为隐藏"tls in tls"等特征
# 详情https://github.com/3andne/restls/blob/main/Restls-Script:%20%E9%9A%90%E8%97%8F%E4%BD%A0%E7%9A%84%E4%BB%A3%E7%90%86%E8%A1%8C%E4%B8%BA.md
restls-script: "300?100<1,400~100,350~100,600~100,300~200,300~100"
- name: "ss-restls-tls12"
type: ss
@ -385,16 +384,18 @@ proxies: # socks5
port: 443
cipher: chacha20-ietf-poly1305
password: [YOUR_SS_PASSWORD]
client-fingerprint: chrome # One of: chrome, ios, firefox or safari
# 可以是chrome, ios, firefox, safari中的一个
client-fingerprint:
chrome # One of: chrome, ios, firefox or safari
# 可以是chrome, ios, firefox, safari中的一个
plugin: restls
plugin-opts:
host: "vscode.dev" # Must be a TLS 1.2 server
# 应当是一个TLS 1.2 服务器
password: [YOUR_RESTLS_PASSWORD]
version-hint: "tls12"
restls-script: "1000?100<1,500~100,350~100,600~100,400~200"
host:
"vscode.dev" # Must be a TLS 1.2 server
# 应当是一个TLS 1.2 服务器
password: [YOUR_RESTLS_PASSWORD]
version-hint: "tls12"
restls-script: "1000?100<1,500~100,350~100,600~100,400~200"
# vmess
# cipher支持 auto/aes-128-gcm/chacha20-poly1305/none
- name: "vmess"
@ -417,7 +418,7 @@ proxies: # socks5
# Host: v2ray.com
# max-early-data: 2048
# early-data-header-name: Sec-WebSocket-Protocol
- name: "vmess-h2"
type: vmess
server: server
@ -433,7 +434,7 @@ proxies: # socks5
- http.example.com
- http-alt.example.com
path: /
- name: "vmess-http"
type: vmess
server: server
@ -452,7 +453,7 @@ proxies: # socks5
# Connection:
# - keep-alive
# ip-version: ipv4 # 设置使用 IP 类型偏好可选ipv4ipv6dual默认值dual
- name: vmess-grpc
server: server
port: 443
@ -468,7 +469,7 @@ proxies: # socks5
grpc-opts:
grpc-service-name: "example"
# ip-version: ipv4
# vless
- name: "vless-tcp"
type: vless
@ -481,7 +482,7 @@ proxies: # socks5
# skip-cert-verify: true
# fingerprint: xxxx
# client-fingerprint: random # Available: "chrome","firefox","safari","random","none"
- name: "vless-vision"
type: vless
server: server
@ -494,7 +495,7 @@ proxies: # socks5
client-fingerprint: chrome
# fingerprint: xxxx
# skip-cert-verify: true
- name: "vless-reality-vision"
type: vless
server: server
@ -509,7 +510,7 @@ proxies: # socks5
public-key: xxx
short-id: xxx # optional
client-fingerprint: chrome # cannot be empty
- name: "vless-reality-grpc"
type: vless
server: server
@ -527,7 +528,7 @@ proxies: # socks5
reality-opts:
public-key: CrrQSjAG_YkHLwvM2M-7XkKJilgL5upBKCp0od0tLhE
short-id: 10f897e26c4b9478
- name: "vless-ws"
type: vless
server: server
@ -544,7 +545,7 @@ proxies: # socks5
path: "/"
headers:
Host: example.com
# Trojan
- name: "trojan"
type: trojan
@ -559,7 +560,7 @@ proxies: # socks5
# - h2
# - http/1.1
# skip-cert-verify: true
- name: trojan-grpc
server: server
port: 443
@ -572,7 +573,7 @@ proxies: # socks5
udp: true
grpc-opts:
grpc-service-name: "example"
- name: trojan-ws
server: server
port: 443
@ -587,7 +588,7 @@ proxies: # socks5
# path: /path
# headers:
# Host: example.com
- name: "trojan-xtls"
type: trojan
server: server
@ -599,7 +600,7 @@ proxies: # socks5
# sni: example.com # aka server name
# skip-cert-verify: true
# fingerprint: xxxx
#hysteria
- name: "hysteria"
type: hysteria
@ -626,7 +627,7 @@ proxies: # socks5
# disable_mtu_discovery: false
# fingerprint: xxxx
# fast-open: true # 支持 TCP 快速打开,默认为 false
# wireguard
- name: "wg"
type: wireguard
@ -655,7 +656,7 @@ proxies: # socks5
# # pre-shared-key: 31aIhAPwktDGpH4JDhA8GNvjFXEf/a6+UaQRyOAiyfM=
# allowed_ips: ['0.0.0.0/0']
# reserved: [209,98,59]
# tuic
- name: tuic
server: www.example.com
@ -674,12 +675,13 @@ proxies: # socks5
request-timeout: 8000
udp-relay-mode: native # Available: "native", "quic". Default: "native"
# congestion-controller: bbr # Available: "cubic", "new_reno", "bbr". Default: "cubic"
# cwnd: 10 # default: 32
# max-udp-relay-packet-size: 1500
# fast-open: true
# skip-cert-verify: true
# max-open-streams: 20 # default 100, too many open streams may hurt performance
# sni: example.com
# ShadowsocksR
# The supported ciphers (encryption methods): all stream ciphers in ss
# The supported obfses:
@ -711,7 +713,7 @@ proxy-groups:
- vmess
- ss1
- ss2
# url-test 将按照 url 测试结果使用延迟最低节点
- name: "auto"
type: url-test
@ -723,7 +725,7 @@ proxy-groups:
# lazy: true
url: "https://cp.cloudflare.com/generate_204"
interval: 300
# fallback 将按照 url 测试结果按照节点顺序选择
- name: "fallback-auto"
type: fallback
@ -733,7 +735,7 @@ proxy-groups:
- vmess1
url: "https://cp.cloudflare.com/generate_204"
interval: 300
# load-balance 将按照算法随机选择节点
- name: "load-balance"
type: load-balance
@ -744,7 +746,7 @@ proxy-groups:
url: "https://cp.cloudflare.com/generate_204"
interval: 300
# strategy: consistent-hashing # 可选 round-robin 和 sticky-sessions
# select 用户自行选择节点
- name: Proxy
type: select
@ -754,7 +756,7 @@ proxy-groups:
- ss2
- vmess1
- auto
# 配置指定 interface-name 和 fwmark 的 DIRECT
- name: en1
type: select
@ -762,7 +764,7 @@ proxy-groups:
routing-mark: 6667
proxies:
- DIRECT
- name: UseProvider
type: select
filter: "HK|TW" # 正则表达式,过滤 provider1 中节点名包含 HK 或 TW
@ -778,7 +780,7 @@ proxy-providers:
type: http
url: "url"
interval: 3600
path: ./provider1.yaml # 默认只允许存储在 clash 的 Home Dir如果想存储到任意位置添加环境变量 SKIP_SAFE_PATH_CHECK=1
path: ./provider1.yaml # 默认只允许存储在 clash 的 Home Dir如果想存储到任意位置添加环境变量 SKIP_SAFE_PATH_CHECK=1
health-check:
enable: true
interval: 600
@ -795,7 +797,7 @@ rule-providers:
rule1:
behavior: classical # domain ipcidr
interval: 259200
path: /path/to/save/file.yaml # 默认只允许存储在 clash 的 Home Dir如果想存储到任意位置添加环境变量 SKIP_SAFE_PATH_CHECK=1
path: /path/to/save/file.yaml # 默认只允许存储在 clash 的 Home Dir如果想存储到任意位置添加环境变量 SKIP_SAFE_PATH_CHECK=1
type: http
url: "url"
rule2:
@ -846,14 +848,14 @@ listeners:
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定proxy处理
# udp: false # 默认 true
- name: http-in-1
type: http
port: 10809
listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定proxy处理(当proxy不为空时这里的proxy名称必须合法否则会出错)
- name: mixed-in-1
type: mixed # HTTP(S) 和 SOCKS 代理混合
port: 10810
@ -861,14 +863,14 @@ listeners:
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定proxy处理(当proxy不为空时这里的proxy名称必须合法否则会出错)
# udp: false # 默认 true
- name: reidr-in-1
type: redir
port: 10811
listen: 0.0.0.0
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定proxy处理(当proxy不为空时这里的proxy名称必须合法否则会出错)
- name: tproxy-in-1
type: tproxy
port: 10812
@ -876,7 +878,7 @@ listeners:
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
# proxy: proxy # 如果不为空则直接将该入站流量交由指定proxy处理(当proxy不为空时这里的proxy名称必须合法否则会出错)
# udp: false # 默认 true
- name: shadowsocks-in-1
type: shadowsocks
port: 10813
@ -885,7 +887,7 @@ listeners:
# proxy: proxy # 如果不为空则直接将该入站流量交由指定proxy处理(当proxy不为空时这里的proxy名称必须合法否则会出错)
password: vlmpIPSyHH6f4S8WVPdRIHIlzmB+GIRfoH3aNJ/t9Gg=
cipher: 2022-blake3-aes-256-gcm
- name: vmess-in-1
type: vmess
port: 10814
@ -896,7 +898,7 @@ listeners:
- username: 1
uuid: 9d0cb9d0-964f-4ef6-897d-6c6b3ccf9e68
alterId: 1
- name: tuic-in-1
type: tuic
port: 10815
@ -916,7 +918,7 @@ listeners:
# alpn:
# - h3
# max-udp-relay-packet-size: 1500
- name: tunnel-in-1
type: tunnel
port: 10816
@ -925,7 +927,7 @@ listeners:
# proxy: proxy # 如果不为空则直接将该入站流量交由指定proxy处理(当proxy不为空时这里的proxy名称必须合法否则会出错)
network: [tcp, udp]
target: target.com
- name: tun-in-1
type: tun
# rule: sub-rule-name1 # 默认使用 rules如果未找到 sub-rule 则直接使用 rules
@ -956,10 +958,10 @@ listeners:
# - 1000
# exclude_uid_range: # 排除路由的的用户范围
# - 1000-99999
# Android 用户和应用规则仅在 Android 下被支持
# 并且需要 auto_route
# include_android_user: # 限制被路由的 Android 用户
# - 0
# - 10
@ -967,7 +969,6 @@ listeners:
# - com.android.chrome
# exclude_package: # 排除被路由的 Android 应用包名
# - com.android.captiveportallogin
# 入口配置与 Listener 等价,传入流量将和 socks,mixed 等入口一样按照 mode 所指定的方式进行匹配处理
# shadowsocks,vmess 入口配置传入流量将和socks,mixed等入口一样按照mode所指定的方式进行匹配处理
# ss-config: ss://2022-blake3-aes-256-gcm:vlmpIPSyHH6f4S8WVPdRIHIlzmB+GIRfoH3aNJ/t9Gg=@:23456

View file

@ -4,6 +4,7 @@ import (
"github.com/Dreamacro/clash/transport/tuic/congestion"
"github.com/metacubex/quic-go"
c "github.com/metacubex/quic-go/congestion"
)
const (
@ -11,7 +12,8 @@ const (
DefaultConnectionReceiveWindow = 67108864 // 64 MB/s
)
func SetCongestionController(quicConn quic.Connection, cc string) {
func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) {
CWND := c.ByteCount(cwnd)
switch cc {
case "cubic":
quicConn.SetCongestionControl(
@ -36,7 +38,7 @@ func SetCongestionController(quicConn quic.Connection, cc string) {
congestion.NewBBRSender(
congestion.DefaultClock{},
congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
congestion.InitialCongestionWindow*congestion.InitialMaxDatagramSize,
CWND*congestion.InitialMaxDatagramSize,
congestion.DefaultBBRMaxCongestionWindow*congestion.InitialMaxDatagramSize,
),
)

View file

@ -36,6 +36,7 @@ type ClientOption struct {
MaxUdpRelayPacketSize int
FastOpen bool
MaxOpenStreams int64
CWND int
}
type clientImpl struct {
@ -91,7 +92,7 @@ func (t *clientImpl) getQuicConn(ctx context.Context, dialer C.Dialer, dialFn co
return nil, err
}
common.SetCongestionController(quicConn, t.CongestionController)
common.SetCongestionController(quicConn, t.CongestionController, t.CWND)
go func() {
_ = t.sendAuthentication(quicConn)

View file

@ -33,6 +33,7 @@ type ServerOption struct {
CongestionController string
AuthenticationTimeout time.Duration
MaxUdpRelayPacketSize int
CWND int
}
type Server struct {
@ -57,7 +58,7 @@ func (s *Server) Serve() error {
if err != nil {
return err
}
common.SetCongestionController(conn, s.CongestionController)
common.SetCongestionController(conn, s.CongestionController, s.CWND)
h := &serverHandler{
Server: s,
quicConn: conn,

View file

@ -33,6 +33,7 @@ type ClientOption struct {
ReduceRtt bool
MaxUdpRelayPacketSize int
MaxOpenStreams int64
CWND int
}
type clientImpl struct {
@ -88,7 +89,7 @@ func (t *clientImpl) getQuicConn(ctx context.Context, dialer C.Dialer, dialFn co
return nil, err
}
common.SetCongestionController(quicConn, t.CongestionController)
common.SetCongestionController(quicConn, t.CongestionController, t.CWND)
go func() {
_ = t.sendAuthentication(quicConn)

View file

@ -6,6 +6,7 @@ import (
"context"
"crypto/tls"
"fmt"
"net"
"sync"
"sync/atomic"
@ -32,6 +33,7 @@ type ServerOption struct {
CongestionController string
AuthenticationTimeout time.Duration
MaxUdpRelayPacketSize int
CWND int
}
type Server struct {
@ -56,7 +58,7 @@ func (s *Server) Serve() error {
if err != nil {
return err
}
common.SetCongestionController(conn, s.CongestionController)
common.SetCongestionController(conn, s.CongestionController, s.CWND)
h := &serverHandler{
Server: s,
quicConn: conn,