Quellcode durchsuchen

Independent `source_ip_is_private` and `ip_is_private` rules

世界 vor 1 Jahr
Ursprung
Commit
a21c5324fd
5 geänderte Dateien mit 93 neuen und 31 gelöschten Zeilen
  1. 2 0
      option/rule.go
  2. 32 31
      option/rule_dns.go
  3. 10 0
      route/rule_default.go
  4. 5 0
      route/rule_dns.go
  5. 44 0
      route/rule_item_ip_is_private.go

+ 2 - 0
option/rule.go

@@ -78,7 +78,9 @@ type DefaultRule struct {
 	SourceGeoIP              Listable[string] `json:"source_geoip,omitempty"`
 	GeoIP                    Listable[string] `json:"geoip,omitempty"`
 	SourceIPCIDR             Listable[string] `json:"source_ip_cidr,omitempty"`
+	SourceIPIsPrivate        bool             `json:"source_ip_is_private,omitempty"`
 	IPCIDR                   Listable[string] `json:"ip_cidr,omitempty"`
+	IPIsPrivate              bool             `json:"ip_is_private,omitempty"`
 	SourcePort               Listable[uint16] `json:"source_port,omitempty"`
 	SourcePortRange          Listable[string] `json:"source_port_range,omitempty"`
 	Port                     Listable[uint16] `json:"port,omitempty"`

+ 32 - 31
option/rule_dns.go

@@ -65,37 +65,38 @@ func (r DNSRule) IsValid() bool {
 }
 
 type DefaultDNSRule struct {
-	Inbound         Listable[string]       `json:"inbound,omitempty"`
-	IPVersion       int                    `json:"ip_version,omitempty"`
-	QueryType       Listable[DNSQueryType] `json:"query_type,omitempty"`
-	Network         Listable[string]       `json:"network,omitempty"`
-	AuthUser        Listable[string]       `json:"auth_user,omitempty"`
-	Protocol        Listable[string]       `json:"protocol,omitempty"`
-	Domain          Listable[string]       `json:"domain,omitempty"`
-	DomainSuffix    Listable[string]       `json:"domain_suffix,omitempty"`
-	DomainKeyword   Listable[string]       `json:"domain_keyword,omitempty"`
-	DomainRegex     Listable[string]       `json:"domain_regex,omitempty"`
-	Geosite         Listable[string]       `json:"geosite,omitempty"`
-	SourceGeoIP     Listable[string]       `json:"source_geoip,omitempty"`
-	SourceIPCIDR    Listable[string]       `json:"source_ip_cidr,omitempty"`
-	SourcePort      Listable[uint16]       `json:"source_port,omitempty"`
-	SourcePortRange Listable[string]       `json:"source_port_range,omitempty"`
-	Port            Listable[uint16]       `json:"port,omitempty"`
-	PortRange       Listable[string]       `json:"port_range,omitempty"`
-	ProcessName     Listable[string]       `json:"process_name,omitempty"`
-	ProcessPath     Listable[string]       `json:"process_path,omitempty"`
-	PackageName     Listable[string]       `json:"package_name,omitempty"`
-	User            Listable[string]       `json:"user,omitempty"`
-	UserID          Listable[int32]        `json:"user_id,omitempty"`
-	Outbound        Listable[string]       `json:"outbound,omitempty"`
-	ClashMode       string                 `json:"clash_mode,omitempty"`
-	WIFISSID        Listable[string]       `json:"wifi_ssid,omitempty"`
-	WIFIBSSID       Listable[string]       `json:"wifi_bssid,omitempty"`
-	RuleSet         Listable[string]       `json:"rule_set,omitempty"`
-	Invert          bool                   `json:"invert,omitempty"`
-	Server          string                 `json:"server,omitempty"`
-	DisableCache    bool                   `json:"disable_cache,omitempty"`
-	RewriteTTL      *uint32                `json:"rewrite_ttl,omitempty"`
+	Inbound           Listable[string]       `json:"inbound,omitempty"`
+	IPVersion         int                    `json:"ip_version,omitempty"`
+	QueryType         Listable[DNSQueryType] `json:"query_type,omitempty"`
+	Network           Listable[string]       `json:"network,omitempty"`
+	AuthUser          Listable[string]       `json:"auth_user,omitempty"`
+	Protocol          Listable[string]       `json:"protocol,omitempty"`
+	Domain            Listable[string]       `json:"domain,omitempty"`
+	DomainSuffix      Listable[string]       `json:"domain_suffix,omitempty"`
+	DomainKeyword     Listable[string]       `json:"domain_keyword,omitempty"`
+	DomainRegex       Listable[string]       `json:"domain_regex,omitempty"`
+	Geosite           Listable[string]       `json:"geosite,omitempty"`
+	SourceGeoIP       Listable[string]       `json:"source_geoip,omitempty"`
+	SourceIPCIDR      Listable[string]       `json:"source_ip_cidr,omitempty"`
+	SourceIPIsPrivate bool                   `json:"source_ip_is_private,omitempty"`
+	SourcePort        Listable[uint16]       `json:"source_port,omitempty"`
+	SourcePortRange   Listable[string]       `json:"source_port_range,omitempty"`
+	Port              Listable[uint16]       `json:"port,omitempty"`
+	PortRange         Listable[string]       `json:"port_range,omitempty"`
+	ProcessName       Listable[string]       `json:"process_name,omitempty"`
+	ProcessPath       Listable[string]       `json:"process_path,omitempty"`
+	PackageName       Listable[string]       `json:"package_name,omitempty"`
+	User              Listable[string]       `json:"user,omitempty"`
+	UserID            Listable[int32]        `json:"user_id,omitempty"`
+	Outbound          Listable[string]       `json:"outbound,omitempty"`
+	ClashMode         string                 `json:"clash_mode,omitempty"`
+	WIFISSID          Listable[string]       `json:"wifi_ssid,omitempty"`
+	WIFIBSSID         Listable[string]       `json:"wifi_bssid,omitempty"`
+	RuleSet           Listable[string]       `json:"rule_set,omitempty"`
+	Invert            bool                   `json:"invert,omitempty"`
+	Server            string                 `json:"server,omitempty"`
+	DisableCache      bool                   `json:"disable_cache,omitempty"`
+	RewriteTTL        *uint32                `json:"rewrite_ttl,omitempty"`
 }
 
 func (r DefaultDNSRule) IsValid() bool {

+ 10 - 0
route/rule_default.go

@@ -120,6 +120,11 @@ func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options opt
 		rule.sourceAddressItems = append(rule.sourceAddressItems, item)
 		rule.allItems = append(rule.allItems, item)
 	}
+	if options.SourceIPIsPrivate {
+		item := NewIPIsPrivateItem(true)
+		rule.sourceAddressItems = append(rule.sourceAddressItems, item)
+		rule.allItems = append(rule.allItems, item)
+	}
 	if len(options.IPCIDR) > 0 {
 		item, err := NewIPCIDRItem(false, options.IPCIDR)
 		if err != nil {
@@ -128,6 +133,11 @@ func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options opt
 		rule.destinationAddressItems = append(rule.destinationAddressItems, item)
 		rule.allItems = append(rule.allItems, item)
 	}
+	if options.IPIsPrivate {
+		item := NewIPIsPrivateItem(false)
+		rule.destinationAddressItems = append(rule.destinationAddressItems, item)
+		rule.allItems = append(rule.allItems, item)
+	}
 	if len(options.SourcePort) > 0 {
 		item := NewPortItem(true, options.SourcePort)
 		rule.sourcePortItems = append(rule.sourcePortItems, item)

+ 5 - 0
route/rule_dns.go

@@ -119,6 +119,11 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options
 		rule.sourceAddressItems = append(rule.sourceAddressItems, item)
 		rule.allItems = append(rule.allItems, item)
 	}
+	if options.SourceIPIsPrivate {
+		item := NewIPIsPrivateItem(true)
+		rule.sourceAddressItems = append(rule.sourceAddressItems, item)
+		rule.allItems = append(rule.allItems, item)
+	}
 	if len(options.SourcePort) > 0 {
 		item := NewPortItem(true, options.SourcePort)
 		rule.sourcePortItems = append(rule.sourcePortItems, item)

+ 44 - 0
route/rule_item_ip_is_private.go

@@ -0,0 +1,44 @@
+package route
+
+import (
+	"net/netip"
+
+	"github.com/sagernet/sing-box/adapter"
+	N "github.com/sagernet/sing/common/network"
+)
+
+var _ RuleItem = (*IPIsPrivateItem)(nil)
+
+type IPIsPrivateItem struct {
+	isSource bool
+}
+
+func NewIPIsPrivateItem(isSource bool) *IPIsPrivateItem {
+	return &IPIsPrivateItem{isSource}
+}
+
+func (r *IPIsPrivateItem) Match(metadata *adapter.InboundContext) bool {
+	var destination netip.Addr
+	if r.isSource {
+		destination = metadata.Source.Addr
+	} else {
+		destination = metadata.Destination.Addr
+	}
+	if destination.IsValid() && !N.IsPublicAddr(destination) {
+		return true
+	}
+	for _, destinationAddress := range metadata.DestinationAddresses {
+		if !N.IsPublicAddr(destinationAddress) {
+			return true
+		}
+	}
+	return false
+}
+
+func (r *IPIsPrivateItem) String() string {
+	if r.isSource {
+		return "source_ip_is_private=true"
+	} else {
+		return "ip_is_private=true"
+	}
+}