1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- package loopback
- import (
- "errors"
- "fmt"
- "net/netip"
- "github.com/metacubex/mihomo/common/callback"
- "github.com/metacubex/mihomo/component/iface"
- C "github.com/metacubex/mihomo/constant"
- "github.com/puzpuzpuz/xsync/v3"
- )
- var ErrReject = errors.New("reject loopback connection")
- type Detector struct {
- connMap *xsync.MapOf[netip.AddrPort, struct{}]
- packetConnMap *xsync.MapOf[uint16, struct{}]
- }
- func NewDetector() *Detector {
- return &Detector{
- connMap: xsync.NewMapOf[netip.AddrPort, struct{}](),
- packetConnMap: xsync.NewMapOf[uint16, struct{}](),
- }
- }
- func (l *Detector) NewConn(conn C.Conn) C.Conn {
- metadata := C.Metadata{}
- if metadata.SetRemoteAddr(conn.LocalAddr()) != nil {
- return conn
- }
- connAddr := metadata.AddrPort()
- if !connAddr.IsValid() {
- return conn
- }
- l.connMap.Store(connAddr, struct{}{})
- return callback.NewCloseCallbackConn(conn, func() {
- l.connMap.Delete(connAddr)
- })
- }
- func (l *Detector) NewPacketConn(conn C.PacketConn) C.PacketConn {
- metadata := C.Metadata{}
- if metadata.SetRemoteAddr(conn.LocalAddr()) != nil {
- return conn
- }
- connAddr := metadata.AddrPort()
- if !connAddr.IsValid() {
- return conn
- }
- port := connAddr.Port()
- l.packetConnMap.Store(port, struct{}{})
- return callback.NewCloseCallbackPacketConn(conn, func() {
- l.packetConnMap.Delete(port)
- })
- }
- func (l *Detector) CheckConn(metadata *C.Metadata) error {
- connAddr := metadata.SourceAddrPort()
- if !connAddr.IsValid() {
- return nil
- }
- if _, ok := l.connMap.Load(connAddr); ok {
- return fmt.Errorf("%w to: %s", ErrReject, metadata.RemoteAddress())
- }
- return nil
- }
- func (l *Detector) CheckPacketConn(metadata *C.Metadata) error {
- connAddr := metadata.SourceAddrPort()
- if !connAddr.IsValid() {
- return nil
- }
- isLocalIp, err := iface.IsLocalIp(connAddr.Addr())
- if err != nil {
- return err
- }
- if !isLocalIp && !connAddr.Addr().IsLoopback() {
- return nil
- }
- if _, ok := l.packetConnMap.Load(connAddr.Port()); ok {
- return fmt.Errorf("%w to: %s", ErrReject, metadata.RemoteAddress())
- }
- return nil
- }
|