2024-04-03 08:42:15 +08:00
|
|
|
package loopback
|
2023-12-20 13:11:00 +08:00
|
|
|
|
|
|
|
import (
|
2024-04-03 08:42:15 +08:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2023-12-20 13:11:00 +08:00
|
|
|
"net/netip"
|
|
|
|
|
|
|
|
"github.com/metacubex/mihomo/common/callback"
|
2024-04-11 09:24:53 +08:00
|
|
|
"github.com/metacubex/mihomo/component/iface"
|
2023-12-20 13:11:00 +08:00
|
|
|
C "github.com/metacubex/mihomo/constant"
|
|
|
|
|
|
|
|
"github.com/puzpuzpuz/xsync/v3"
|
|
|
|
)
|
|
|
|
|
2024-04-03 08:42:15 +08:00
|
|
|
var ErrReject = errors.New("reject loopback connection")
|
|
|
|
|
|
|
|
type Detector struct {
|
2023-12-20 13:11:00 +08:00
|
|
|
connMap *xsync.MapOf[netip.AddrPort, struct{}]
|
2024-04-11 09:24:53 +08:00
|
|
|
packetConnMap *xsync.MapOf[uint16, struct{}]
|
2023-12-20 13:11:00 +08:00
|
|
|
}
|
|
|
|
|
2024-04-03 08:42:15 +08:00
|
|
|
func NewDetector() *Detector {
|
|
|
|
return &Detector{
|
2023-12-20 13:11:00 +08:00
|
|
|
connMap: xsync.NewMapOf[netip.AddrPort, struct{}](),
|
2024-04-11 09:24:53 +08:00
|
|
|
packetConnMap: xsync.NewMapOf[uint16, struct{}](),
|
2023-12-20 13:11:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-03 08:42:15 +08:00
|
|
|
func (l *Detector) NewConn(conn C.Conn) C.Conn {
|
2023-12-20 13:11:00 +08:00
|
|
|
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)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-04-03 08:42:15 +08:00
|
|
|
func (l *Detector) NewPacketConn(conn C.PacketConn) C.PacketConn {
|
2023-12-20 13:11:00 +08:00
|
|
|
metadata := C.Metadata{}
|
|
|
|
if metadata.SetRemoteAddr(conn.LocalAddr()) != nil {
|
|
|
|
return conn
|
|
|
|
}
|
|
|
|
connAddr := metadata.AddrPort()
|
|
|
|
if !connAddr.IsValid() {
|
|
|
|
return conn
|
|
|
|
}
|
2024-04-11 09:24:53 +08:00
|
|
|
port := connAddr.Port()
|
|
|
|
l.packetConnMap.Store(port, struct{}{})
|
2023-12-20 13:11:00 +08:00
|
|
|
return callback.NewCloseCallbackPacketConn(conn, func() {
|
2024-04-11 09:24:53 +08:00
|
|
|
l.packetConnMap.Delete(port)
|
2023-12-20 13:11:00 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-04-03 08:42:15 +08:00
|
|
|
func (l *Detector) CheckConn(metadata *C.Metadata) error {
|
|
|
|
connAddr := metadata.SourceAddrPort()
|
2023-12-20 13:11:00 +08:00
|
|
|
if !connAddr.IsValid() {
|
2024-04-03 08:42:15 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if _, ok := l.connMap.Load(connAddr); ok {
|
|
|
|
return fmt.Errorf("%w to: %s", ErrReject, metadata.RemoteAddress())
|
2023-12-20 13:11:00 +08:00
|
|
|
}
|
2024-04-03 08:42:15 +08:00
|
|
|
return nil
|
2023-12-20 13:11:00 +08:00
|
|
|
}
|
|
|
|
|
2024-04-03 08:42:15 +08:00
|
|
|
func (l *Detector) CheckPacketConn(metadata *C.Metadata) error {
|
|
|
|
connAddr := metadata.SourceAddrPort()
|
2023-12-20 13:11:00 +08:00
|
|
|
if !connAddr.IsValid() {
|
2024-04-03 08:42:15 +08:00
|
|
|
return nil
|
|
|
|
}
|
2024-04-11 09:24:53 +08:00
|
|
|
|
|
|
|
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 {
|
2024-04-03 08:42:15 +08:00
|
|
|
return fmt.Errorf("%w to: %s", ErrReject, metadata.RemoteAddress())
|
2023-12-20 13:11:00 +08:00
|
|
|
}
|
2024-04-03 08:42:15 +08:00
|
|
|
return nil
|
2023-12-20 13:11:00 +08:00
|
|
|
}
|