diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index f2ce56c9..ba991bfc 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -21,6 +21,7 @@ type Base struct { udp bool xudp bool tfo bool + mpTcp bool rmark int id string prefer C.DNSPrefer @@ -143,11 +144,16 @@ func (b *Base) DialOptions(opts ...dialer.Option) []dialer.Option { opts = append(opts, dialer.WithTFO(true)) } + if b.mpTcp { + opts = append(opts, dialer.WithMPTCP(true)) + } + return opts } type BasicOption struct { TFO bool `proxy:"tfo,omitempty" group:"tfo,omitempty"` + MPTCP bool `proxy:"mptcp,omitempty" group:"mptcp,omitempty"` Interface string `proxy:"interface-name,omitempty" group:"interface-name,omitempty"` RoutingMark int `proxy:"routing-mark,omitempty" group:"routing-mark,omitempty"` IPVersion string `proxy:"ip-version,omitempty" group:"ip-version,omitempty"` @@ -161,6 +167,7 @@ type BaseOption struct { UDP bool XUDP bool TFO bool + MPTCP bool Interface string RoutingMark int Prefer C.DNSPrefer @@ -174,6 +181,7 @@ func NewBase(opt BaseOption) *Base { udp: opt.UDP, xudp: opt.XUDP, tfo: opt.TFO, + mpTcp: opt.MPTCP, iface: opt.Interface, rmark: opt.RoutingMark, prefer: opt.Prefer, diff --git a/adapter/outbound/http.go b/adapter/outbound/http.go index 78735b2d..0b652ca9 100644 --- a/adapter/outbound/http.go +++ b/adapter/outbound/http.go @@ -177,6 +177,7 @@ func NewHttp(option HttpOption) (*Http, error) { addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)), tp: C.Http, tfo: option.TFO, + mpTcp: option.MPTCP, iface: option.Interface, rmark: option.RoutingMark, prefer: C.NewDNSPrefer(option.IPVersion), diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 32558eac..c1481622 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -315,6 +315,7 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) { tp: C.Shadowsocks, udp: option.UDP, tfo: option.TFO, + mpTcp: option.MPTCP, iface: option.Interface, rmark: option.RoutingMark, prefer: C.NewDNSPrefer(option.IPVersion), diff --git a/adapter/outbound/shadowsocksr.go b/adapter/outbound/shadowsocksr.go index 07778032..cd6854af 100644 --- a/adapter/outbound/shadowsocksr.go +++ b/adapter/outbound/shadowsocksr.go @@ -181,6 +181,7 @@ func NewShadowSocksR(option ShadowSocksROption) (*ShadowSocksR, error) { tp: C.ShadowsocksR, udp: option.UDP, tfo: option.TFO, + mpTcp: option.MPTCP, iface: option.Interface, rmark: option.RoutingMark, prefer: C.NewDNSPrefer(option.IPVersion), diff --git a/adapter/outbound/snell.go b/adapter/outbound/snell.go index e542d84d..d0b9e748 100644 --- a/adapter/outbound/snell.go +++ b/adapter/outbound/snell.go @@ -181,6 +181,7 @@ func NewSnell(option SnellOption) (*Snell, error) { tp: C.Snell, udp: option.UDP, tfo: option.TFO, + mpTcp: option.MPTCP, iface: option.Interface, rmark: option.RoutingMark, prefer: C.NewDNSPrefer(option.IPVersion), diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index 9af4d0fc..f451cd1a 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -196,6 +196,7 @@ func NewSocks5(option Socks5Option) (*Socks5, error) { tp: C.Socks5, udp: option.UDP, tfo: option.TFO, + mpTcp: option.MPTCP, iface: option.Interface, rmark: option.RoutingMark, prefer: C.NewDNSPrefer(option.IPVersion), diff --git a/adapter/outbound/trojan.go b/adapter/outbound/trojan.go index 3af71b7d..ec420bf3 100644 --- a/adapter/outbound/trojan.go +++ b/adapter/outbound/trojan.go @@ -238,6 +238,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) { tp: C.Trojan, udp: option.UDP, tfo: option.TFO, + mpTcp: option.MPTCP, iface: option.Interface, rmark: option.RoutingMark, prefer: C.NewDNSPrefer(option.IPVersion), diff --git a/adapter/outbound/vless.go b/adapter/outbound/vless.go index 44d05ba6..83ce4e57 100644 --- a/adapter/outbound/vless.go +++ b/adapter/outbound/vless.go @@ -543,6 +543,7 @@ func NewVless(option VlessOption) (*Vless, error) { udp: option.UDP, xudp: option.XUDP, tfo: option.TFO, + mpTcp: option.MPTCP, iface: option.Interface, rmark: option.RoutingMark, prefer: C.NewDNSPrefer(option.IPVersion), diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index acf6de75..8a94c082 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -436,6 +436,7 @@ func NewVmess(option VmessOption) (*Vmess, error) { udp: option.UDP, xudp: option.XUDP, tfo: option.TFO, + mpTcp: option.MPTCP, iface: option.Interface, rmark: option.RoutingMark, prefer: C.NewDNSPrefer(option.IPVersion), diff --git a/component/dialer/dialer.go b/component/dialer/dialer.go index 5e19046c..89c7564a 100644 --- a/component/dialer/dialer.go +++ b/component/dialer/dialer.go @@ -132,6 +132,9 @@ func dialContext(ctx context.Context, network string, destination netip.Addr, po if opt.routingMark != 0 { bindMarkToDialer(opt.routingMark, dialer, network, destination) } + if opt.mpTcp { + setMultiPathTCP(dialer) + } if opt.tfo { return dialTFO(ctx, *dialer, network, address) } diff --git a/component/dialer/mptcp_go120.go b/component/dialer/mptcp_go120.go new file mode 100644 index 00000000..6e564673 --- /dev/null +++ b/component/dialer/mptcp_go120.go @@ -0,0 +1,12 @@ +//go:build !go1.21 + +package dialer + +import ( + "net" +) + +const multipathTCPAvailable = false + +func setMultiPathTCP(dialer *net.Dialer) { +} diff --git a/component/dialer/mptcp_go121.go b/component/dialer/mptcp_go121.go new file mode 100644 index 00000000..360826c8 --- /dev/null +++ b/component/dialer/mptcp_go121.go @@ -0,0 +1,11 @@ +//go:build go1.21 + +package dialer + +import "net" + +const multipathTCPAvailable = true + +func setMultiPathTCP(dialer *net.Dialer) { + dialer.SetMultipathTCP(true) +} diff --git a/component/dialer/options.go b/component/dialer/options.go index 096c7a5c..30771e71 100644 --- a/component/dialer/options.go +++ b/component/dialer/options.go @@ -25,6 +25,7 @@ type option struct { network int prefer int tfo bool + mpTcp bool resolver resolver.Resolver netDialer NetDialer } @@ -83,6 +84,12 @@ func WithTFO(tfo bool) Option { } } +func WithMPTCP(mpTcp bool) Option { + return func(opt *option) { + opt.mpTcp = mpTcp + } +} + func WithNetDialer(netDialer NetDialer) Option { return func(opt *option) { opt.netDialer = netDialer