Skip to content

Commit

Permalink
chore: don't retry when rejected loopback connection
Browse files Browse the repository at this point in the history
  • Loading branch information
wwqgtxx committed Apr 3, 2024
1 parent d48517b commit 40f5c5b
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 23 deletions.
18 changes: 9 additions & 9 deletions adapter/outbound/direct.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package outbound
import (
"context"
"errors"
"fmt"
"net/netip"

N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/loopback"
"github.com/metacubex/mihomo/component/resolver"
C "github.com/metacubex/mihomo/constant"
)

type Direct struct {
*Base
loopBack *loopBackDetector
loopBack *loopback.Detector
}

type DirectOption struct {
Expand All @@ -24,8 +24,8 @@ type DirectOption struct {

// DialContext implements C.ProxyAdapter
func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
if d.loopBack.CheckConn(metadata.SourceAddrPort()) {
return nil, fmt.Errorf("reject loopback connection to: %s", metadata.RemoteAddress())
if err := d.loopBack.CheckConn(metadata); err != nil {
return nil, err
}
opts = append(opts, dialer.WithResolver(resolver.DefaultResolver))
c, err := dialer.DialContext(ctx, "tcp", metadata.RemoteAddress(), d.Base.DialOptions(opts...)...)
Expand All @@ -38,8 +38,8 @@ func (d *Direct) DialContext(ctx context.Context, metadata *C.Metadata, opts ...

// ListenPacketContext implements C.ProxyAdapter
func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
if d.loopBack.CheckPacketConn(metadata.SourceAddrPort()) {
return nil, fmt.Errorf("reject loopback connection to: %s", metadata.RemoteAddress())
if err := d.loopBack.CheckPacketConn(metadata); err != nil {
return nil, err
}
// net.UDPConn.WriteTo only working with *net.UDPAddr, so we need a net.UDPAddr
if !metadata.Resolved() {
Expand Down Expand Up @@ -68,7 +68,7 @@ func NewDirectWithOption(option DirectOption) *Direct {
rmark: option.RoutingMark,
prefer: C.NewDNSPrefer(option.IPVersion),
},
loopBack: newLoopBackDetector(),
loopBack: loopback.NewDetector(),
}
}

Expand All @@ -80,7 +80,7 @@ func NewDirect() *Direct {
udp: true,
prefer: C.DualStack,
},
loopBack: newLoopBackDetector(),
loopBack: loopback.NewDetector(),
}
}

Expand All @@ -92,6 +92,6 @@ func NewCompatible() *Direct {
udp: true,
prefer: C.DualStack,
},
loopBack: newLoopBackDetector(),
loopBack: loopback.NewDetector(),
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package outbound
package loopback

import (
"errors"
"fmt"
"net/netip"

"github.com/metacubex/mihomo/common/callback"
Expand All @@ -9,19 +11,21 @@ import (
"github.com/puzpuzpuz/xsync/v3"
)

type loopBackDetector struct {
var ErrReject = errors.New("reject loopback connection")

type Detector struct {
connMap *xsync.MapOf[netip.AddrPort, struct{}]
packetConnMap *xsync.MapOf[netip.AddrPort, struct{}]
}

func newLoopBackDetector() *loopBackDetector {
return &loopBackDetector{
func NewDetector() *Detector {
return &Detector{
connMap: xsync.NewMapOf[netip.AddrPort, struct{}](),
packetConnMap: xsync.NewMapOf[netip.AddrPort, struct{}](),
}
}

func (l *loopBackDetector) NewConn(conn C.Conn) C.Conn {
func (l *Detector) NewConn(conn C.Conn) C.Conn {
metadata := C.Metadata{}
if metadata.SetRemoteAddr(conn.LocalAddr()) != nil {
return conn
Expand All @@ -36,7 +40,7 @@ func (l *loopBackDetector) NewConn(conn C.Conn) C.Conn {
})
}

func (l *loopBackDetector) NewPacketConn(conn C.PacketConn) C.PacketConn {
func (l *Detector) NewPacketConn(conn C.PacketConn) C.PacketConn {
metadata := C.Metadata{}
if metadata.SetRemoteAddr(conn.LocalAddr()) != nil {
return conn
Expand All @@ -51,18 +55,24 @@ func (l *loopBackDetector) NewPacketConn(conn C.PacketConn) C.PacketConn {
})
}

func (l *loopBackDetector) CheckConn(connAddr netip.AddrPort) bool {
func (l *Detector) CheckConn(metadata *C.Metadata) error {
connAddr := metadata.SourceAddrPort()
if !connAddr.IsValid() {
return false
return nil
}
if _, ok := l.connMap.Load(connAddr); ok {
return fmt.Errorf("%w to: %s", ErrReject, metadata.RemoteAddress())
}
_, ok := l.connMap.Load(connAddr)
return ok
return nil
}

func (l *loopBackDetector) CheckPacketConn(connAddr netip.AddrPort) bool {
func (l *Detector) CheckPacketConn(metadata *C.Metadata) error {
connAddr := metadata.SourceAddrPort()
if !connAddr.IsValid() {
return false
return nil
}
if _, ok := l.packetConnMap.Load(connAddr); ok {
return fmt.Errorf("%w to: %s", ErrReject, metadata.RemoteAddress())
}
_, ok := l.packetConnMap.Load(connAddr)
return ok
return nil
}
4 changes: 4 additions & 0 deletions tunnel/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/component/loopback"
"github.com/metacubex/mihomo/component/nat"
P "github.com/metacubex/mihomo/component/process"
"github.com/metacubex/mihomo/component/resolver"
Expand Down Expand Up @@ -694,6 +695,9 @@ func shouldStopRetry(err error) bool {
if errors.Is(err, resolver.ErrIPv6Disabled) {
return true
}
if errors.Is(err, loopback.ErrReject) {
return true
}
return false
}

Expand Down

0 comments on commit 40f5c5b

Please sign in to comment.