fix: random panic by race in proxy id init

This commit is contained in:
wwqgtxx
2026-04-13 13:52:24 +08:00
parent 6fb9d9e433
commit 9613f02a05
22 changed files with 295 additions and 291 deletions
+12 -12
View File
@@ -86,18 +86,18 @@ func (t *AnyTLS) Close() error {
func NewAnyTLS(option AnyTLSOption) (*AnyTLS, error) {
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
outbound := &AnyTLS{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.AnyTLS,
pdName: option.ProviderName,
udp: option.UDP,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.AnyTLS,
ProviderName: option.ProviderName,
UDP: option.UDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
}
outbound.dialer = option.NewDialer(outbound.DialOptions())
+35 -34
View File
@@ -16,6 +16,8 @@ import (
"github.com/metacubex/mihomo/component/resolver"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log"
"github.com/gofrs/uuid/v5"
)
type ProxyAdapter interface {
@@ -37,7 +39,38 @@ type Base struct {
rmark int
prefer C.DNSPrefer
dialer C.Dialer
id string
id uuid.UUID
}
type BaseOption struct {
Name string
Addr string
Type C.AdapterType
ProviderName string
UDP bool
XUDP bool
TFO bool
MPTCP bool
Interface string
RoutingMark int
Prefer C.DNSPrefer
}
func NewBase(opt BaseOption) *Base {
return &Base{
name: opt.Name,
addr: opt.Addr,
tp: opt.Type,
pdName: opt.ProviderName,
udp: opt.UDP,
xudp: opt.XUDP,
tfo: opt.TFO,
mpTcp: opt.MPTCP,
iface: opt.Interface,
rmark: opt.RoutingMark,
prefer: opt.Prefer,
id: utils.NewUUIDV6(),
}
}
// Name implements C.ProxyAdapter
@@ -47,11 +80,7 @@ func (b *Base) Name() string {
// Id implements C.ProxyAdapter
func (b *Base) Id() string {
if b.id == "" {
b.id = utils.NewUUIDV6().String()
}
return b.id
return b.id.String()
}
// Type implements C.ProxyAdapter
@@ -188,34 +217,6 @@ func (b *BasicOption) NewDialer(opts []dialer.Option) C.Dialer {
return cDialer
}
type BaseOption struct {
Name string
Addr string
Type C.AdapterType
UDP bool
XUDP bool
TFO bool
MPTCP bool
Interface string
RoutingMark int
Prefer C.DNSPrefer
}
func NewBase(opt BaseOption) *Base {
return &Base{
name: opt.Name,
addr: opt.Addr,
tp: opt.Type,
udp: opt.UDP,
xudp: opt.XUDP,
tfo: opt.TFO,
mpTcp: opt.MPTCP,
iface: opt.Interface,
rmark: opt.RoutingMark,
prefer: opt.Prefer,
}
}
type conn struct {
N.ExtendedConn
chain C.Chain
+23 -23
View File
@@ -66,41 +66,41 @@ func (d *Direct) IsL3Protocol(metadata *C.Metadata) bool {
func NewDirectWithOption(option DirectOption) *Direct {
return &Direct{
Base: &Base{
name: option.Name,
tp: C.Direct,
pdName: option.ProviderName,
udp: true,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Type: C.Direct,
ProviderName: option.ProviderName,
UDP: true,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
loopBack: loopback.NewDetector(),
}
}
func NewDirect() *Direct {
return &Direct{
Base: &Base{
name: "DIRECT",
tp: C.Direct,
udp: true,
prefer: C.DualStack,
},
Base: NewBase(BaseOption{
Name: "DIRECT",
Type: C.Direct,
UDP: true,
Prefer: C.DualStack,
}),
loopBack: loopback.NewDetector(),
}
}
func NewCompatible() *Direct {
return &Direct{
Base: &Base{
name: "COMPATIBLE",
tp: C.Compatible,
udp: true,
prefer: C.DualStack,
},
Base: NewBase(BaseOption{
Name: "COMPATIBLE",
Type: C.Compatible,
UDP: true,
Prefer: C.DualStack,
}),
loopBack: loopback.NewDetector(),
}
}
+11 -11
View File
@@ -155,16 +155,16 @@ func (*dnsPacketConn) SetWriteDeadline(t time.Time) error {
func NewDnsWithOption(option DnsOption) *Dns {
return &Dns{
Base: &Base{
name: option.Name,
tp: C.Dns,
pdName: option.ProviderName,
udp: true,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Type: C.Dns,
ProviderName: option.ProviderName,
UDP: true,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
}
}
+11 -11
View File
@@ -167,17 +167,17 @@ func NewHttp(option HttpOption) (*Http, error) {
}
outbound := &Http{
Base: &Base{
name: option.Name,
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
tp: C.Http,
pdName: option.ProviderName,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
Type: C.Http,
ProviderName: option.ProviderName,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
user: option.UserName,
pass: option.Password,
tlsConfig: tlsConfig,
+11 -11
View File
@@ -239,17 +239,17 @@ func NewHysteria(option HysteriaOption) (*Hysteria, error) {
return nil, fmt.Errorf("hysteria %s create error: %w", addr, err)
}
outbound := &Hysteria{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.Hysteria,
pdName: option.ProviderName,
udp: true,
tfo: option.FastOpen,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.Hysteria,
ProviderName: option.ProviderName,
UDP: true,
TFO: option.FastOpen,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
client: client,
tlsConfig: tlsClientConfig,
+10 -10
View File
@@ -105,16 +105,16 @@ func (h *Hysteria2) ProxyInfo() C.ProxyInfo {
func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
outbound := &Hysteria2{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.Hysteria2,
pdName: option.ProviderName,
udp: true,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.Hysteria2,
ProviderName: option.ProviderName,
UDP: true,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
}
outbound.dialer = option.NewDialer(outbound.DialOptions())
+10 -10
View File
@@ -104,16 +104,16 @@ func (option MasqueOption) Prefixes() ([]netip.Prefix, error) {
func NewMasque(option MasqueOption) (*Masque, error) {
outbound := &Masque{
Base: &Base{
name: option.Name,
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
tp: C.Masque,
pdName: option.ProviderName,
udp: option.UDP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
Type: C.Masque,
ProviderName: option.ProviderName,
UDP: option.UDP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
}
outbound.dialer = option.NewDialer(outbound.DialOptions())
+12 -11
View File
@@ -166,17 +166,18 @@ func NewMieru(option MieruOption) (*Mieru, error) {
addr = net.JoinHostPort(option.Server, strconv.Itoa(beginPort))
}
outbound := &Mieru{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.Mieru,
pdName: option.ProviderName,
udp: option.UDP,
xudp: false,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.Mieru,
ProviderName: option.ProviderName,
UDP: option.UDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
client: c,
}
+17 -17
View File
@@ -46,33 +46,33 @@ func (r *Reject) ResolveUDP(ctx context.Context, metadata *C.Metadata) error {
func NewRejectWithOption(option RejectOption) *Reject {
return &Reject{
Base: &Base{
name: option.Name,
tp: C.Reject,
udp: true,
},
Base: NewBase(BaseOption{
Name: option.Name,
Type: C.Reject,
UDP: true,
}),
}
}
func NewReject() *Reject {
return &Reject{
Base: &Base{
name: "REJECT",
tp: C.Reject,
udp: true,
prefer: C.DualStack,
},
Base: NewBase(BaseOption{
Name: "REJECT",
Type: C.Reject,
UDP: true,
Prefer: C.DualStack,
}),
}
}
func NewRejectDrop() *Reject {
return &Reject{
Base: &Base{
name: "REJECT-DROP",
tp: C.RejectDrop,
udp: true,
prefer: C.DualStack,
},
Base: NewBase(BaseOption{
Name: "REJECT-DROP",
Type: C.RejectDrop,
UDP: true,
Prefer: C.DualStack,
}),
drop: true,
}
}
+12 -12
View File
@@ -446,18 +446,18 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) {
}
outbound := &ShadowSocks{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.Shadowsocks,
pdName: option.ProviderName,
udp: option.UDP,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.Shadowsocks,
ProviderName: option.ProviderName,
UDP: option.UDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
method: method,
option: &option,
+12 -12
View File
@@ -158,18 +158,18 @@ func NewShadowSocksR(option ShadowSocksROption) (*ShadowSocksR, error) {
}
outbound := &ShadowSocksR{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.ShadowsocksR,
pdName: option.ProviderName,
udp: option.UDP,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.ShadowsocksR,
ProviderName: option.ProviderName,
UDP: option.UDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
cipher: coreCiph,
obfs: obfs,
+12 -12
View File
@@ -161,18 +161,18 @@ func NewSnell(option SnellOption) (*Snell, error) {
}
s := &Snell{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.Snell,
pdName: option.ProviderName,
udp: option.UDP,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.Snell,
ProviderName: option.ProviderName,
UDP: option.UDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
psk: psk,
obfsOption: obfsOption,
+12 -12
View File
@@ -187,18 +187,18 @@ func NewSocks5(option Socks5Option) (*Socks5, error) {
}
outbound := &Socks5{
Base: &Base{
name: option.Name,
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
tp: C.Socks5,
pdName: option.ProviderName,
udp: option.UDP,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
Type: C.Socks5,
ProviderName: option.ProviderName,
UDP: option.UDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
user: option.UserName,
pass: option.Password,
+12 -10
View File
@@ -182,16 +182,18 @@ func NewSsh(option SshOption) (*Ssh, error) {
config.ClientVersion = version
outbound := &Ssh{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.Ssh,
pdName: option.ProviderName,
udp: false,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.Ssh,
ProviderName: option.ProviderName,
UDP: false,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
config: &config,
}
+12 -12
View File
@@ -223,18 +223,18 @@ func NewSudoku(option SudokuOption) (*Sudoku, error) {
}
outbound := &Sudoku{
Base: &Base{
name: option.Name,
addr: baseConf.ServerAddress,
tp: C.Sudoku,
pdName: option.ProviderName,
udp: true,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: baseConf.ServerAddress,
Type: C.Sudoku,
ProviderName: option.ProviderName,
UDP: true,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
baseConf: baseConf,
}
+12 -12
View File
@@ -253,18 +253,18 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
}
t := &Trojan{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.Trojan,
pdName: option.ProviderName,
udp: option.UDP,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.Trojan,
ProviderName: option.ProviderName,
UDP: option.UDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
hexPassword: trojan.Key(option.Password),
}
+12 -12
View File
@@ -85,18 +85,18 @@ func (t *TrustTunnel) Close() error {
func NewTrustTunnel(option TrustTunnelOption) (*TrustTunnel, error) {
addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port))
outbound := &TrustTunnel{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.TrustTunnel,
pdName: option.ProviderName,
udp: option.UDP,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.TrustTunnel,
ProviderName: option.ProviderName,
UDP: option.UDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
}
outbound.dialer = option.NewDialer(outbound.DialOptions())
+11 -11
View File
@@ -236,17 +236,17 @@ func NewTuic(option TuicOption) (*Tuic, error) {
}
t := &Tuic{
Base: &Base{
name: option.Name,
addr: addr,
tp: C.Tuic,
pdName: option.ProviderName,
udp: true,
tfo: option.FastOpen,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: addr,
Type: C.Tuic,
ProviderName: option.ProviderName,
UDP: true,
TFO: option.FastOpen,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
option: &option,
quicConfig: quicConfig,
tlsConfig: tlsConfig,
+13 -13
View File
@@ -436,19 +436,19 @@ func NewVless(option VlessOption) (*Vless, error) {
}
v := &Vless{
Base: &Base{
name: option.Name,
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
tp: C.Vless,
pdName: option.ProviderName,
udp: option.UDP,
xudp: option.XUDP,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
Type: C.Vless,
ProviderName: option.ProviderName,
UDP: option.UDP,
XUDP: option.XUDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
client: client,
option: &option,
}
+13 -13
View File
@@ -374,19 +374,19 @@ func NewVmess(option VmessOption) (*Vmess, error) {
}
v := &Vmess{
Base: &Base{
name: option.Name,
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
tp: C.Vmess,
pdName: option.ProviderName,
udp: option.UDP,
xudp: option.XUDP,
tfo: option.TFO,
mpTcp: option.MPTCP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
Type: C.Vmess,
ProviderName: option.ProviderName,
UDP: option.UDP,
XUDP: option.XUDP,
TFO: option.TFO,
MPTCP: option.MPTCP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
client: client,
option: &option,
}
+10 -10
View File
@@ -166,16 +166,16 @@ func (option WireGuardOption) Prefixes() ([]netip.Prefix, error) {
func NewWireGuard(option WireGuardOption) (*WireGuard, error) {
outbound := &WireGuard{
Base: &Base{
name: option.Name,
addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
tp: C.WireGuard,
pdName: option.ProviderName,
udp: option.UDP,
iface: option.Interface,
rmark: option.RoutingMark,
prefer: option.IPVersion,
},
Base: NewBase(BaseOption{
Name: option.Name,
Addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)),
Type: C.WireGuard,
ProviderName: option.ProviderName,
UDP: option.UDP,
Interface: option.Interface,
RoutingMark: option.RoutingMark,
Prefer: option.IPVersion,
}),
}
outbound.dialer = option.NewDialer(outbound.DialOptions())
singDialer := proxydialer.NewSingDialer(proxydialer.NewSlowDownDialer(outbound.dialer, slowdown.New()))