diff --git a/adapter/outbound/direct.go b/adapter/outbound/direct.go index d9793b3e..4b05ee60 100644 --- a/adapter/outbound/direct.go +++ b/adapter/outbound/direct.go @@ -12,6 +12,10 @@ type Direct struct { *Base } +func (d *Direct) IsProxyGroup() bool { + return false +} + // DialContext implements C.ProxyAdapter func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) { opts = append(opts, dialer.WithDirect()) diff --git a/adapter/outbound/http.go b/adapter/outbound/http.go index 81bf2e57..c547333e 100644 --- a/adapter/outbound/http.go +++ b/adapter/outbound/http.go @@ -38,6 +38,10 @@ type HttpOption struct { Headers map[string]string `proxy:"headers,omitempty"` } +func (h *Http) IsProxyGroup() bool { + return false +} + // StreamConn implements C.ProxyAdapter func (h *Http) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { if h.tlsConfig != nil { diff --git a/adapter/outbound/reject.go b/adapter/outbound/reject.go index f4752104..f873c625 100644 --- a/adapter/outbound/reject.go +++ b/adapter/outbound/reject.go @@ -14,6 +14,10 @@ type Reject struct { *Base } +func (r *Reject) IsProxyGroup() bool { + return false +} + // DialContext implements C.ProxyAdapter func (r *Reject) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) { return NewConn(&nopConn{}, r), nil diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index d80c7962..3b7d480f 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -54,6 +54,10 @@ type v2rayObfsOption struct { Mux bool `obfs:"mux,omitempty"` } +func (ss *ShadowSocks) IsProxyGroup() bool { + return false +} + // StreamConn implements C.ProxyAdapter func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { switch ss.obfsMode { diff --git a/adapter/outbound/shadowsocksr.go b/adapter/outbound/shadowsocksr.go index ea1c2838..cca01bdf 100644 --- a/adapter/outbound/shadowsocksr.go +++ b/adapter/outbound/shadowsocksr.go @@ -37,6 +37,10 @@ type ShadowSocksROption struct { UDP bool `proxy:"udp,omitempty"` } +func (ssr *ShadowSocksR) IsProxyGroup() bool { + return false +} + // StreamConn implements C.ProxyAdapter func (ssr *ShadowSocksR) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { c = ssr.obfs.StreamConn(c) diff --git a/adapter/outbound/snell.go b/adapter/outbound/snell.go index 07f3d89d..ed3e8180 100644 --- a/adapter/outbound/snell.go +++ b/adapter/outbound/snell.go @@ -39,6 +39,10 @@ type streamOption struct { obfsOption *simpleObfsOption } +func (s *Snell) IsProxyGroup() bool { + return false +} + func streamConn(c net.Conn, option streamOption) *snell.Snell { switch option.obfsOption.Mode { case "tls": diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index 398ee3b2..df5d956c 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -22,7 +22,6 @@ type Socks5 struct { skipCertVerify bool tlsConfig *tls.Config } - type Socks5Option struct { BasicOption Name string `proxy:"name"` @@ -35,6 +34,10 @@ type Socks5Option struct { SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` } +func (ss *Socks5) IsProxyGroup() bool { + return false +} + // StreamConn implements C.ProxyAdapter func (ss *Socks5) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { if ss.tls { diff --git a/adapter/outbound/trojan.go b/adapter/outbound/trojan.go index aa389b34..c3febef4 100644 --- a/adapter/outbound/trojan.go +++ b/adapter/outbound/trojan.go @@ -27,7 +27,6 @@ type Trojan struct { gunConfig *gun.Config transport *http2.Transport } - type TrojanOption struct { BasicOption Name string `proxy:"name"` @@ -45,6 +44,10 @@ type TrojanOption struct { FlowShow bool `proxy:"flow-show,omitempty"` } +func (t *Trojan) IsProxyGroup() bool { + return false +} + func (t *Trojan) plainStream(c net.Conn) (net.Conn, error) { if t.option.Network == "ws" { host, port, _ := net.SplitHostPort(t.addr) diff --git a/adapter/outbound/vless.go b/adapter/outbound/vless.go index d8e8e18f..110d79b5 100644 --- a/adapter/outbound/vless.go +++ b/adapter/outbound/vless.go @@ -59,6 +59,10 @@ type VlessOption struct { ServerName string `proxy:"servername,omitempty"` } +func (v *Vless) IsProxyGroup() bool { + return false +} + func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { var err error switch v.option.Network { diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index b32349d0..613867aa 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -75,6 +75,10 @@ type WSOptions struct { EarlyDataHeaderName string `proxy:"early-data-header-name,omitempty"` } +func (v *Vmess) IsProxyGroup() bool { + return false +} + // StreamConn implements C.ProxyAdapter func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { var err error diff --git a/adapter/outboundgroup/common.go b/adapter/outboundgroup/common.go index 0dc53ef5..4492d98c 100644 --- a/adapter/outboundgroup/common.go +++ b/adapter/outboundgroup/common.go @@ -29,8 +29,9 @@ func getProvidersProxies(providers []provider.ProxyProvider, touch bool, filter //filterReg = regexp.MustCompile(filter) filterReg = regexp2.MustCompile(filter, 0) for _, p := range proxies { - if p.Type() < 8 { + if p.IsProxyGroup() { matchedProxies = append(matchedProxies, p) + continue } //if filterReg.MatchString(p.Name()) { diff --git a/adapter/outboundgroup/fallback.go b/adapter/outboundgroup/fallback.go index 2e754133..2192aaaa 100644 --- a/adapter/outboundgroup/fallback.go +++ b/adapter/outboundgroup/fallback.go @@ -24,6 +24,10 @@ type Fallback struct { failedTime *atomic.Int64 } +func (f *Fallback) IsProxyGroup() bool { + return true +} + func (f *Fallback) Now() string { proxy := f.findAliveProxy(false) return proxy.Name() diff --git a/adapter/outboundgroup/loadbalance.go b/adapter/outboundgroup/loadbalance.go index 7c16f48c..c4c5748a 100644 --- a/adapter/outboundgroup/loadbalance.go +++ b/adapter/outboundgroup/loadbalance.go @@ -28,6 +28,10 @@ type LoadBalance struct { strategyFn strategyFn } +func (lb *LoadBalance) IsProxyGroup() bool { + return true +} + var errStrategy = errors.New("unsupported strategy") func parseStrategy(config map[string]any) string { diff --git a/adapter/outboundgroup/relay.go b/adapter/outboundgroup/relay.go index d9b29637..8a4b0c6f 100644 --- a/adapter/outboundgroup/relay.go +++ b/adapter/outboundgroup/relay.go @@ -19,6 +19,10 @@ type Relay struct { filter string } +func (r *Relay) IsProxyGroup() bool { + return true +} + // DialContext implements C.ProxyAdapter func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) { var proxies []C.Proxy diff --git a/adapter/outboundgroup/selector.go b/adapter/outboundgroup/selector.go index d3b58b3f..11c02414 100644 --- a/adapter/outboundgroup/selector.go +++ b/adapter/outboundgroup/selector.go @@ -21,6 +21,10 @@ type Selector struct { providers []provider.ProxyProvider } +func (s *Selector) IsProxyGroup() bool { + return true +} + // DialContext implements C.ProxyAdapter func (s *Selector) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) { c, err := s.selectedProxy(true).DialContext(ctx, metadata, s.Base.DialOptions(opts...)...) diff --git a/adapter/outboundgroup/urltest.go b/adapter/outboundgroup/urltest.go index 98269e6a..8f94b43a 100644 --- a/adapter/outboundgroup/urltest.go +++ b/adapter/outboundgroup/urltest.go @@ -35,6 +35,10 @@ type URLTest struct { failedTime *atomic.Int64 } +func (u *URLTest) IsProxyGroup() bool { + return true +} + func (u *URLTest) Now() string { return u.fast(false).Name() } diff --git a/constant/adapters.go b/constant/adapters.go index b91704de..7a3244f6 100644 --- a/constant/adapters.go +++ b/constant/adapters.go @@ -83,6 +83,7 @@ type ProxyAdapter interface { Addr() string SupportUDP() bool MarshalJSON() ([]byte, error) + IsProxyGroup() bool // StreamConn wraps a protocol around net.Conn with Metadata. //