diff --git a/config/config.go b/config/config.go index ce1e0fb7..358e055a 100644 --- a/config/config.go +++ b/config/config.go @@ -279,6 +279,8 @@ type RawTun struct { IncludeUIDRange []string `yaml:"include-uid-range" json:"include-uid-range,omitempty"` ExcludeUID []uint32 `yaml:"exclude-uid" json:"exclude-uid,omitempty"` ExcludeUIDRange []string `yaml:"exclude-uid-range" json:"exclude-uid-range,omitempty"` + ExcludePort []uint16 `yaml:"exclude-port" json:"exclude-port,omitempty"` + ExcludePortRange []string `yaml:"exclude-port-range" json:"exclude-port-range,omitempty"` IncludeAndroidUser []int `yaml:"include-android-user" json:"include-android-user,omitempty"` IncludePackage []string `yaml:"include-package" json:"include-package,omitempty"` ExcludePackage []string `yaml:"exclude-package" json:"exclude-package,omitempty"` @@ -1560,6 +1562,8 @@ func parseTun(rawTun RawTun, general *General) error { IncludeUIDRange: rawTun.IncludeUIDRange, ExcludeUID: rawTun.ExcludeUID, ExcludeUIDRange: rawTun.ExcludeUIDRange, + ExcludePort: rawTun.ExcludePort, + ExcludePortRange: rawTun.ExcludePortRange, IncludeAndroidUser: rawTun.IncludeAndroidUser, IncludePackage: rawTun.IncludePackage, ExcludePackage: rawTun.ExcludePackage, diff --git a/go.mod b/go.mod index f53dcb7b..d319be85 100644 --- a/go.mod +++ b/go.mod @@ -119,3 +119,5 @@ require ( ) replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20250228041610-d94509dc612a + +replace github.com/metacubex/sing-tun => github.com/okhowang/sing-tun v0.0.0-20250402060301-29507d93a82d diff --git a/go.sum b/go.sum index b0ae3b7d..dbc640cc 100644 --- a/go.sum +++ b/go.sum @@ -121,8 +121,6 @@ github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJ github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0= github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo= github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q= -github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04 h1:B211C+i/I8CWf4I/BaAV0mmkEHrDBJ0XR9EWxjPbFEg= -github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0= github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82 h1:zZp5uct9+/0Hb1jKGyqDjCU4/72t43rs7qOq3Rc9oU8= github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82/go.mod h1:nE7Mdzj/QUDwgRi/8BASPtsxtIFZTHA4Yst5GgwbGCQ= github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589 h1:Z6bNy0HLTjx6BKIkV48sV/yia/GP8Bnyb5JQuGgSGzg= @@ -140,6 +138,8 @@ github.com/mroth/weightedrand/v2 v2.1.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 h1:1102pQc2SEPp5+xrS26wEaeb26sZy6k9/ZXlZN+eXE4= github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7/go.mod h1:UqoUn6cHESlliMhOnKLWr+CBH+e3bazUPvFj1XZwAjs= +github.com/okhowang/sing-tun v0.0.0-20250402060301-29507d93a82d h1:3CesBf0y+UJYTOkY5+Abh/xknLygqxGolWFwDR8f2PM= +github.com/okhowang/sing-tun v0.0.0-20250402060301-29507d93a82d/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= diff --git a/listener/config/tun.go b/listener/config/tun.go index 3901bb1d..7d17f26a 100644 --- a/listener/config/tun.go +++ b/listener/config/tun.go @@ -53,6 +53,8 @@ type Tun struct { IncludeAndroidUser []int `yaml:"include-android-user" json:"include-android-user,omitempty"` IncludePackage []string `yaml:"include-package" json:"include-package,omitempty"` ExcludePackage []string `yaml:"exclude-package" json:"exclude-package,omitempty"` + ExcludePort []uint16 `yaml:"exclude-port" json:"exclude-port,omitempty"` + ExcludePortRange []string `yaml:"exclude-port-range" json:"exclude-port-range,omitempty"` EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint-independent-nat,omitempty"` UDPTimeout int64 `yaml:"udp-timeout" json:"udp-timeout,omitempty"` FileDescriptor int `yaml:"file-descriptor" json:"file-descriptor"` diff --git a/listener/sing_tun/server.go b/listener/sing_tun/server.go index 0ab5afee..ab9476b6 100644 --- a/listener/sing_tun/server.go +++ b/listener/sing_tun/server.go @@ -21,6 +21,7 @@ import ( LC "github.com/metacubex/mihomo/listener/config" "github.com/metacubex/mihomo/listener/sing" "github.com/metacubex/mihomo/log" + "golang.org/x/exp/constraints" tun "github.com/metacubex/sing-tun" "github.com/metacubex/sing-tun/control" @@ -211,6 +212,14 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis return nil, E.Cause(err, "parse exclude_uid_range") } } + excludePort := uidToRange(options.ExcludePort) + if len(options.ExcludePortRange) > 0 { + var err error + excludePort, err = parseRange(excludePort, options.ExcludePortRange) + if err != nil { + return nil, E.Cause(err, "parse exclude_port_range") + } + } var dnsAdds []netip.AddrPort @@ -339,6 +348,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis ExcludeInterface: options.ExcludeInterface, IncludeUID: includeUID, ExcludeUID: excludeUID, + ExcludePort: excludePort, IncludeAndroidUser: options.IncludeAndroidUser, IncludePackage: options.IncludePackage, ExcludePackage: options.ExcludePackage, @@ -566,13 +576,13 @@ func (d *cDialerInterfaceFinder) FindInterfaceName(destination netip.Addr) strin return "" } -func uidToRange(uidList []uint32) []ranges.Range[uint32] { - return common.Map(uidList, func(uid uint32) ranges.Range[uint32] { +func uidToRange[T constraints.Integer](uidList []T) []ranges.Range[T] { + return common.Map(uidList, func(uid T) ranges.Range[T] { return ranges.NewSingle(uid) }) } -func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges.Range[uint32], error) { +func parseRange[T constraints.Integer](uidRanges []ranges.Range[T], rangeList []string) ([]ranges.Range[T], error) { for _, uidRange := range rangeList { if !strings.Contains(uidRange, ":") { return nil, E.New("missing ':' in range: ", uidRange) @@ -593,7 +603,7 @@ func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges. if err != nil { return nil, E.Cause(err, "parse range end") } - uidRanges = append(uidRanges, ranges.New(uint32(start), uint32(end))) + uidRanges = append(uidRanges, ranges.New(T(start), T(end))) } return uidRanges, nil }