Feature: support relay Socks5 UDP
supports relaying of all UDP traffic except the HTTP outbound.
This commit is contained in:
parent
68cf94a866
commit
6ad2cde909
@ -37,12 +37,59 @@ type Socks5Option struct {
|
|||||||
|
|
||||||
// StreamConn implements C.ProxyAdapter
|
// StreamConn implements C.ProxyAdapter
|
||||||
func (ss *Socks5) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
func (ss *Socks5) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
||||||
|
var err error
|
||||||
|
c, _, err = ss.streamConn(c, metadata)
|
||||||
|
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *Socks5) StreamSocks5PacketConn(c net.Conn, pc net.PacketConn, metadata *C.Metadata) (net.PacketConn, error) {
|
||||||
|
if c == nil {
|
||||||
|
return pc, fmt.Errorf("%s connect error: parameter net.Conn is nil", ss.addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pc == nil {
|
||||||
|
return pc, fmt.Errorf("%s connect error: parameter net.PacketConn is nil", ss.addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
cc, bindAddr, err := ss.streamConn(c, metadata)
|
||||||
|
if err != nil {
|
||||||
|
return pc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c = cc
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
_, _ = io.Copy(io.Discard, c)
|
||||||
|
_ = c.Close()
|
||||||
|
// A UDP association terminates when the TCP connection that the UDP
|
||||||
|
// ASSOCIATE request arrived on terminates. RFC1928
|
||||||
|
_ = pc.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Support unspecified UDP bind address.
|
||||||
|
bindUDPAddr := bindAddr.UDPAddr()
|
||||||
|
if bindUDPAddr == nil {
|
||||||
|
return pc, errors.New("invalid UDP bind address")
|
||||||
|
} else if bindUDPAddr.IP.IsUnspecified() {
|
||||||
|
serverAddr, err := resolveUDPAddr("udp", ss.Addr())
|
||||||
|
if err != nil {
|
||||||
|
return pc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bindUDPAddr.IP = serverAddr.IP
|
||||||
|
}
|
||||||
|
|
||||||
|
return &socksPacketConn{PacketConn: pc, rAddr: bindUDPAddr, tcpConn: c}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *Socks5) streamConn(c net.Conn, metadata *C.Metadata) (_ net.Conn, bindAddr socks5.Addr, err error) {
|
||||||
if ss.tls {
|
if ss.tls {
|
||||||
cc := tls.Client(c, ss.tlsConfig)
|
cc := tls.Client(c, ss.tlsConfig)
|
||||||
err := cc.Handshake()
|
err := cc.Handshake()
|
||||||
c = cc
|
c = cc
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
return c, nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,10 +100,14 @@ func (ss *Socks5) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error)
|
|||||||
Password: ss.pass,
|
Password: ss.pass,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err := socks5.ClientHandshake(c, serializesSocksAddr(metadata), socks5.CmdConnect, user); err != nil {
|
|
||||||
return nil, err
|
if metadata.NetWork == C.UDP {
|
||||||
|
bindAddr, err = socks5.ClientHandshake(c, serializesSocksAddr(metadata), socks5.CmdUDPAssociate, user)
|
||||||
|
} else {
|
||||||
|
bindAddr, err = socks5.ClientHandshake(c, serializesSocksAddr(metadata), socks5.CmdConnect, user)
|
||||||
}
|
}
|
||||||
return c, nil
|
|
||||||
|
return c, bindAddr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
@ -81,61 +132,24 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata, opts ..
|
|||||||
func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
|
func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("%s connect error: %w", ss.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ss.tls {
|
|
||||||
cc := tls.Client(c, ss.tlsConfig)
|
|
||||||
err = cc.Handshake()
|
|
||||||
c = cc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defer safeConnClose(c, err)
|
defer safeConnClose(c, err)
|
||||||
|
|
||||||
tcpKeepAlive(c)
|
|
||||||
var user *socks5.User
|
|
||||||
if ss.user != "" {
|
|
||||||
user = &socks5.User{
|
|
||||||
Username: ss.user,
|
|
||||||
Password: ss.pass,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bindAddr, err := socks5.ClientHandshake(c, serializesSocksAddr(metadata), socks5.CmdUDPAssociate, user)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("client hanshake error: %w", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pc, err := dialer.ListenPacket(ctx, "udp", "", ss.Base.DialOptions(opts...)...)
|
pc, err := dialer.ListenPacket(ctx, "udp", "", ss.Base.DialOptions(opts...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
tcpKeepAlive(c)
|
||||||
_, _ = io.Copy(io.Discard, c)
|
|
||||||
_ = c.Close()
|
|
||||||
// A UDP association terminates when the TCP connection that the UDP
|
|
||||||
// ASSOCIATE request arrived on terminates. RFC1928
|
|
||||||
_ = pc.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Support unspecified UDP bind address.
|
pc, err = ss.StreamSocks5PacketConn(c, pc, metadata)
|
||||||
bindUDPAddr := bindAddr.UDPAddr()
|
|
||||||
if bindUDPAddr == nil {
|
|
||||||
err = errors.New("invalid UDP bind address")
|
|
||||||
return
|
|
||||||
} else if bindUDPAddr.IP.IsUnspecified() {
|
|
||||||
serverAddr, err := resolveUDPAddr("udp", ss.Addr())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bindUDPAddr.IP = serverAddr.IP
|
return NewPacketConn(pc, ss), nil
|
||||||
}
|
|
||||||
|
|
||||||
return NewPacketConn(&socksPacketConn{PacketConn: pc, rAddr: bindUDPAddr, tcpConn: c}, ss), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSocks5(option Socks5Option) *Socks5 {
|
func NewSocks5(option Socks5Option) *Socks5 {
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/adapter"
|
||||||
"github.com/Dreamacro/clash/adapter/outbound"
|
"github.com/Dreamacro/clash/adapter/outbound"
|
||||||
"github.com/Dreamacro/clash/common/singledo"
|
"github.com/Dreamacro/clash/common/singledo"
|
||||||
"github.com/Dreamacro/clash/component/dialer"
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
@ -37,30 +38,12 @@ func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
|||||||
return proxies[0].DialContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
return proxies[0].DialContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
first := proxies[0]
|
c, err := r.streamContext(ctx, proxies, r.Base.DialOptions(opts...)...)
|
||||||
last := proxies[len(proxies)-1]
|
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", first.Addr(), r.Base.DialOptions(opts...)...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
tcpKeepAlive(c)
|
|
||||||
|
|
||||||
var currentMeta *C.Metadata
|
|
||||||
for _, proxy := range proxies[1:] {
|
|
||||||
currentMeta, err = addrToMetadata(proxy.Addr())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err = first.StreamConn(c, currentMeta)
|
last := proxies[len(proxies)-1]
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
first = proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
c, err = last.StreamConn(c, metadata)
|
c, err = last.StreamConn(c, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", last.Addr(), err)
|
return nil, fmt.Errorf("%s connect error: %w", last.Addr(), err)
|
||||||
@ -78,7 +61,9 @@ func (r *Relay) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch len(proxies) {
|
length := len(proxies)
|
||||||
|
|
||||||
|
switch length {
|
||||||
case 0:
|
case 0:
|
||||||
return outbound.NewDirect().ListenPacketContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
return outbound.NewDirect().ListenPacketContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
||||||
case 1:
|
case 1:
|
||||||
@ -90,12 +75,16 @@ func (r *Relay) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
first = proxies[0]
|
firstIndex = 0
|
||||||
last = proxies[len(proxies)-1]
|
nextIndex = 1
|
||||||
rawUDPRelay bool
|
lastUDPOverTCPIndex = -1
|
||||||
udpOverTCPEndIndex = -1
|
rawUDPRelay = false
|
||||||
|
|
||||||
|
first = proxies[firstIndex]
|
||||||
|
last = proxies[length-1]
|
||||||
|
|
||||||
c net.Conn
|
c net.Conn
|
||||||
|
cc net.Conn
|
||||||
err error
|
err error
|
||||||
currentMeta *C.Metadata
|
currentMeta *C.Metadata
|
||||||
)
|
)
|
||||||
@ -104,38 +93,47 @@ func (r *Relay) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
|||||||
return nil, fmt.Errorf("%s connect error: proxy [%s] UDP is not supported in relay chains", last.Addr(), last.Name())
|
return nil, fmt.Errorf("%s connect error: proxy [%s] UDP is not supported in relay chains", last.Addr(), last.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
rawUDPRelay, udpOverTCPEndIndex = isRawUDPRelay(proxies)
|
rawUDPRelay, lastUDPOverTCPIndex = isRawUDPRelay(proxies)
|
||||||
|
|
||||||
if rawUDPRelay {
|
if first.Type() == C.Socks5 {
|
||||||
|
cc1, err1 := dialer.DialContext(ctx, "tcp", first.Addr(), r.Base.DialOptions(opts...)...)
|
||||||
|
if err1 != nil {
|
||||||
|
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||||
|
}
|
||||||
|
cc = cc1
|
||||||
|
tcpKeepAlive(cc)
|
||||||
|
|
||||||
|
var pc net.PacketConn
|
||||||
|
pc, err = dialer.ListenPacket(ctx, "udp", "", r.Base.DialOptions(opts...)...)
|
||||||
|
c = outbound.WrapConn(pc)
|
||||||
|
} else if rawUDPRelay {
|
||||||
var pc net.PacketConn
|
var pc net.PacketConn
|
||||||
pc, err = dialer.ListenPacket(ctx, "udp", "", r.Base.DialOptions(opts...)...)
|
pc, err = dialer.ListenPacket(ctx, "udp", "", r.Base.DialOptions(opts...)...)
|
||||||
c = outbound.WrapConn(pc)
|
c = outbound.WrapConn(pc)
|
||||||
} else {
|
} else {
|
||||||
c, err = dialer.DialContext(ctx, "tcp", first.Addr(), r.Base.DialOptions(opts...)...)
|
firstIndex = lastUDPOverTCPIndex
|
||||||
|
nextIndex = firstIndex + 1
|
||||||
|
first = proxies[firstIndex]
|
||||||
|
c, err = r.streamContext(ctx, proxies[:nextIndex], r.Base.DialOptions(opts...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
if nextIndex < length {
|
||||||
if err != nil && c != nil {
|
for i, proxy := range proxies[nextIndex:] { // raw udp in loop
|
||||||
_ = c.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
for i, proxy := range proxies[1:] {
|
|
||||||
currentMeta, err = addrToMetadata(proxy.Addr())
|
currentMeta, err = addrToMetadata(proxy.Addr())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
currentMeta.NetWork = C.UDP
|
||||||
|
|
||||||
if outbound.IsPacketConn(c) || udpOverTCPEndIndex == i {
|
|
||||||
if !isRawUDP(first) && !first.SupportUDP() {
|
if !isRawUDP(first) && !first.SupportUDP() {
|
||||||
return nil, fmt.Errorf("%s connect error: proxy [%s] UDP is not supported in relay chains", first.Addr(), first.Name())
|
return nil, fmt.Errorf("%s connect error: proxy [%s] UDP is not supported in relay chains", first.Addr(), first.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !currentMeta.Resolved() && needResolveIP(first) {
|
if needResolveIP(first, currentMeta) {
|
||||||
var ip netip.Addr
|
var ip netip.Addr
|
||||||
ip, err = resolver.ResolveProxyServerHost(currentMeta.Host)
|
ip, err = resolver.ResolveProxyServerHost(currentMeta.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -144,28 +142,57 @@ func (r *Relay) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
|||||||
currentMeta.DstIP = ip
|
currentMeta.DstIP = ip
|
||||||
}
|
}
|
||||||
|
|
||||||
currentMeta.NetWork = C.UDP
|
if cc != nil { // socks5
|
||||||
c, err = first.StreamPacketConn(c, currentMeta)
|
c, err = streamSocks5PacketConn(first, cc, c, currentMeta)
|
||||||
|
cc = nil
|
||||||
} else {
|
} else {
|
||||||
c, err = first.StreamConn(c, currentMeta)
|
c, err = first.StreamPacketConn(c, currentMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if proxy.Type() == C.Socks5 {
|
||||||
|
endIndex := nextIndex + i + 1
|
||||||
|
cc, err = r.streamContext(ctx, proxies[:endIndex], r.Base.DialOptions(opts...)...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
first = proxy
|
first = proxy
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cc != nil {
|
||||||
|
c, err = streamSocks5PacketConn(last, cc, c, metadata)
|
||||||
|
} else {
|
||||||
c, err = last.StreamPacketConn(c, metadata)
|
c, err = last.StreamPacketConn(c, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
return nil, fmt.Errorf("%s connect error: %w", last.Addr(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return outbound.NewPacketConn(c.(net.PacketConn), r), nil
|
return outbound.NewPacketConn(c.(net.PacketConn), r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportUDP implements C.ProxyAdapter
|
||||||
|
func (r *Relay) SupportUDP() bool {
|
||||||
|
proxies := r.rawProxies(true)
|
||||||
|
|
||||||
|
l := len(proxies)
|
||||||
|
|
||||||
|
if l == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
last := proxies[l-1]
|
||||||
|
|
||||||
|
return isRawUDP(last) || last.SupportUDP()
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalJSON implements C.ProxyAdapter
|
// MarshalJSON implements C.ProxyAdapter
|
||||||
func (r *Relay) MarshalJSON() ([]byte, error) {
|
func (r *Relay) MarshalJSON() ([]byte, error) {
|
||||||
var all []string
|
var all []string
|
||||||
@ -200,12 +227,47 @@ func (r *Relay) proxies(metadata *C.Metadata, touch bool) []C.Proxy {
|
|||||||
return proxies
|
return proxies
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Relay) streamContext(ctx context.Context, proxies []C.Proxy, opts ...dialer.Option) (net.Conn, error) {
|
||||||
|
first := proxies[0]
|
||||||
|
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", first.Addr(), opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||||
|
}
|
||||||
|
tcpKeepAlive(c)
|
||||||
|
|
||||||
|
if len(proxies) > 1 {
|
||||||
|
var currentMeta *C.Metadata
|
||||||
|
for _, proxy := range proxies[1:] {
|
||||||
|
currentMeta, err = addrToMetadata(proxy.Addr())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err = first.StreamConn(c, currentMeta)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
first = proxy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func streamSocks5PacketConn(proxy C.Proxy, cc, c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
||||||
|
pc, err := proxy.(*adapter.Proxy).ProxyAdapter.(*outbound.Socks5).StreamSocks5PacketConn(cc, c.(net.PacketConn), metadata)
|
||||||
|
return outbound.WrapConn(pc), err
|
||||||
|
}
|
||||||
|
|
||||||
func isRawUDPRelay(proxies []C.Proxy) (bool, int) {
|
func isRawUDPRelay(proxies []C.Proxy) (bool, int) {
|
||||||
var (
|
var (
|
||||||
lastIndex = len(proxies) - 1
|
lastIndex = len(proxies) - 1
|
||||||
isLastRawUDP = isRawUDP(proxies[lastIndex])
|
last = proxies[lastIndex]
|
||||||
|
isLastRawUDP = isRawUDP(last)
|
||||||
isUDPOverTCP = false
|
isUDPOverTCP = false
|
||||||
udpOverTCPEndIndex = -1
|
lastUDPOverTCPIndex = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
for i := lastIndex; i >= 0; i-- {
|
for i := lastIndex; i >= 0; i-- {
|
||||||
@ -213,26 +275,33 @@ func isRawUDPRelay(proxies []C.Proxy) (bool, int) {
|
|||||||
|
|
||||||
isUDPOverTCP = isUDPOverTCP || !isRawUDP(p)
|
isUDPOverTCP = isUDPOverTCP || !isRawUDP(p)
|
||||||
|
|
||||||
if isLastRawUDP && isUDPOverTCP && udpOverTCPEndIndex == -1 {
|
if isLastRawUDP && isUDPOverTCP && lastUDPOverTCPIndex == -1 {
|
||||||
udpOverTCPEndIndex = i
|
lastUDPOverTCPIndex = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return !isUDPOverTCP, udpOverTCPEndIndex
|
if !isLastRawUDP {
|
||||||
|
lastUDPOverTCPIndex = lastIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
return !isUDPOverTCP, lastUDPOverTCPIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
func isRawUDP(proxy C.ProxyAdapter) bool {
|
func isRawUDP(proxy C.ProxyAdapter) bool {
|
||||||
if proxy.Type() == C.Shadowsocks || proxy.Type() == C.ShadowsocksR {
|
if proxy.Type() == C.Shadowsocks || proxy.Type() == C.ShadowsocksR || proxy.Type() == C.Socks5 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func needResolveIP(proxy C.ProxyAdapter) bool {
|
func needResolveIP(proxy C.ProxyAdapter, metadata *C.Metadata) bool {
|
||||||
if proxy.Type() == C.Vmess || proxy.Type() == C.Vless {
|
if metadata.Resolved() {
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
|
if proxy.Type() != C.Vmess && proxy.Type() != C.Vless {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Relay {
|
func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Relay {
|
||||||
@ -240,7 +309,6 @@ func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Re
|
|||||||
Base: outbound.NewBase(outbound.BaseOption{
|
Base: outbound.NewBase(outbound.BaseOption{
|
||||||
Name: option.Name,
|
Name: option.Name,
|
||||||
Type: C.Relay,
|
Type: C.Relay,
|
||||||
UDP: true,
|
|
||||||
Interface: option.Interface,
|
Interface: option.Interface,
|
||||||
RoutingMark: option.RoutingMark,
|
RoutingMark: option.RoutingMark,
|
||||||
}),
|
}),
|
||||||
|
@ -24,8 +24,7 @@ func addrToMetadata(rawAddress string) (addr *C.Metadata, err error) {
|
|||||||
DstIP: netip.Addr{},
|
DstIP: netip.Addr{},
|
||||||
DstPort: port,
|
DstPort: port,
|
||||||
}
|
}
|
||||||
err = nil
|
return addr, nil
|
||||||
return
|
|
||||||
} else if ip.Is4() {
|
} else if ip.Is4() {
|
||||||
addr = &C.Metadata{
|
addr = &C.Metadata{
|
||||||
AddrType: C.AtypIPv4,
|
AddrType: C.AtypIPv4,
|
||||||
|
Reference in New Issue
Block a user