mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-11 17:47:20 +10:00
Add package_name_regex route, DNS and headless rule item
This commit is contained in:
@@ -82,6 +82,11 @@ func compileRuleSet(sourcePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func downgradeRuleSetVersion(version uint8, options option.PlainRuleSet) uint8 {
|
func downgradeRuleSetVersion(version uint8, options option.PlainRuleSet) uint8 {
|
||||||
|
if version == C.RuleSetVersion5 && !rule.HasHeadlessRule(options.Rules, func(rule option.DefaultHeadlessRule) bool {
|
||||||
|
return len(rule.PackageNameRegex) > 0
|
||||||
|
}) {
|
||||||
|
version = C.RuleSetVersion4
|
||||||
|
}
|
||||||
if version == C.RuleSetVersion4 && !rule.HasHeadlessRule(options.Rules, func(rule option.DefaultHeadlessRule) bool {
|
if version == C.RuleSetVersion4 && !rule.HasHeadlessRule(options.Rules, func(rule option.DefaultHeadlessRule) bool {
|
||||||
return rule.NetworkInterfaceAddress != nil && rule.NetworkInterfaceAddress.Size() > 0 ||
|
return rule.NetworkInterfaceAddress != nil && rule.NetworkInterfaceAddress.Size() > 0 ||
|
||||||
len(rule.DefaultInterfaceAddress) > 0
|
len(rule.DefaultInterfaceAddress) > 0
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ const (
|
|||||||
ruleItemNetworkIsConstrained
|
ruleItemNetworkIsConstrained
|
||||||
ruleItemNetworkInterfaceAddress
|
ruleItemNetworkInterfaceAddress
|
||||||
ruleItemDefaultInterfaceAddress
|
ruleItemDefaultInterfaceAddress
|
||||||
|
ruleItemPackageNameRegex
|
||||||
ruleItemFinal uint8 = 0xFF
|
ruleItemFinal uint8 = 0xFF
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -215,6 +216,8 @@ func readDefaultRule(reader varbin.Reader, recover bool) (rule option.DefaultHea
|
|||||||
rule.ProcessPathRegex, err = readRuleItemString(reader)
|
rule.ProcessPathRegex, err = readRuleItemString(reader)
|
||||||
case ruleItemPackageName:
|
case ruleItemPackageName:
|
||||||
rule.PackageName, err = readRuleItemString(reader)
|
rule.PackageName, err = readRuleItemString(reader)
|
||||||
|
case ruleItemPackageNameRegex:
|
||||||
|
rule.PackageNameRegex, err = readRuleItemString(reader)
|
||||||
case ruleItemWIFISSID:
|
case ruleItemWIFISSID:
|
||||||
rule.WIFISSID, err = readRuleItemString(reader)
|
rule.WIFISSID, err = readRuleItemString(reader)
|
||||||
case ruleItemWIFIBSSID:
|
case ruleItemWIFIBSSID:
|
||||||
@@ -394,6 +397,15 @@ func writeDefaultRule(writer varbin.Writer, rule option.DefaultHeadlessRule, gen
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(rule.PackageNameRegex) > 0 {
|
||||||
|
if generateVersion < C.RuleSetVersion5 {
|
||||||
|
return E.New("`package_name_regex` rule item is only supported in version 5 or later")
|
||||||
|
}
|
||||||
|
err = writeRuleItemString(writer, ruleItemPackageNameRegex, rule.PackageNameRegex)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
if len(rule.NetworkType) > 0 {
|
if len(rule.NetworkType) > 0 {
|
||||||
if generateVersion < C.RuleSetVersion3 {
|
if generateVersion < C.RuleSetVersion3 {
|
||||||
return E.New("`network_type` rule item is only supported in version 3 or later")
|
return E.New("`network_type` rule item is only supported in version 3 or later")
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ const (
|
|||||||
RuleSetVersion2
|
RuleSetVersion2
|
||||||
RuleSetVersion3
|
RuleSetVersion3
|
||||||
RuleSetVersion4
|
RuleSetVersion4
|
||||||
RuleSetVersionCurrent = RuleSetVersion4
|
RuleSetVersion5
|
||||||
|
RuleSetVersionCurrent = RuleSetVersion5
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ SFA provides an unprivileged TUN implementation through Android VpnService.
|
|||||||
| `process_path` | :material-close: | No permission |
|
| `process_path` | :material-close: | No permission |
|
||||||
| `process_path_regex` | :material-close: | No permission |
|
| `process_path_regex` | :material-close: | No permission |
|
||||||
| `package_name` | :material-check: | / |
|
| `package_name` | :material-check: | / |
|
||||||
|
| `package_name_regex` | :material-check: | / |
|
||||||
| `user` | :material-close: | Use `package_name` instead |
|
| `user` | :material-close: | Use `package_name` instead |
|
||||||
| `user_id` | :material-close: | Use `package_name` instead |
|
| `user_id` | :material-close: | Use `package_name` instead |
|
||||||
| `wifi_ssid` | :material-check: | Fine location permission required |
|
| `wifi_ssid` | :material-check: | Fine location permission required |
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ SFI/SFM/SFT provides an unprivileged TUN implementation through NetworkExtension
|
|||||||
| `process_path` | :material-close: | No permission |
|
| `process_path` | :material-close: | No permission |
|
||||||
| `process_path_regex` | :material-close: | No permission |
|
| `process_path_regex` | :material-close: | No permission |
|
||||||
| `package_name` | :material-close: | / |
|
| `package_name` | :material-close: | / |
|
||||||
|
| `package_name_regex` | :material-close: | / |
|
||||||
| `user` | :material-close: | No permission |
|
| `user` | :material-close: | No permission |
|
||||||
| `user_id` | :material-close: | No permission |
|
| `user_id` | :material-close: | No permission |
|
||||||
| `wifi_ssid` | :material-alert: | Only supported on iOS |
|
| `wifi_ssid` | :material-alert: | Only supported on iOS |
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ icon: material/alert-decagram
|
|||||||
:material-plus: [response_rcode](#response_rcode)
|
:material-plus: [response_rcode](#response_rcode)
|
||||||
:material-plus: [response_answer](#response_answer)
|
:material-plus: [response_answer](#response_answer)
|
||||||
:material-plus: [response_ns](#response_ns)
|
:material-plus: [response_ns](#response_ns)
|
||||||
:material-plus: [response_extra](#response_extra)
|
:material-plus: [response_extra](#response_extra)
|
||||||
|
:material-plus: [package_name_regex](#package_name_regex)
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.13.0"
|
!!! quote "Changes in sing-box 1.13.0"
|
||||||
|
|
||||||
@@ -129,6 +130,9 @@ icon: material/alert-decagram
|
|||||||
"package_name": [
|
"package_name": [
|
||||||
"com.termux"
|
"com.termux"
|
||||||
],
|
],
|
||||||
|
"package_name_regex": [
|
||||||
|
"^com\\.termux.*"
|
||||||
|
],
|
||||||
"user": [
|
"user": [
|
||||||
"sekai"
|
"sekai"
|
||||||
],
|
],
|
||||||
@@ -347,6 +351,12 @@ Match process path using regular expression.
|
|||||||
|
|
||||||
Match android package name.
|
Match android package name.
|
||||||
|
|
||||||
|
#### package_name_regex
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.14.0"
|
||||||
|
|
||||||
|
Match android package name using regular expression.
|
||||||
|
|
||||||
#### user
|
#### user
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ icon: material/alert-decagram
|
|||||||
:material-plus: [response_rcode](#response_rcode)
|
:material-plus: [response_rcode](#response_rcode)
|
||||||
:material-plus: [response_answer](#response_answer)
|
:material-plus: [response_answer](#response_answer)
|
||||||
:material-plus: [response_ns](#response_ns)
|
:material-plus: [response_ns](#response_ns)
|
||||||
:material-plus: [response_extra](#response_extra)
|
:material-plus: [response_extra](#response_extra)
|
||||||
|
:material-plus: [package_name_regex](#package_name_regex)
|
||||||
|
|
||||||
!!! quote "sing-box 1.13.0 中的更改"
|
!!! quote "sing-box 1.13.0 中的更改"
|
||||||
|
|
||||||
@@ -129,6 +130,9 @@ icon: material/alert-decagram
|
|||||||
"package_name": [
|
"package_name": [
|
||||||
"com.termux"
|
"com.termux"
|
||||||
],
|
],
|
||||||
|
"package_name_regex": [
|
||||||
|
"^com\\.termux.*"
|
||||||
|
],
|
||||||
"user": [
|
"user": [
|
||||||
"sekai"
|
"sekai"
|
||||||
],
|
],
|
||||||
@@ -347,6 +351,12 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
|
|||||||
|
|
||||||
匹配 Android 应用包名。
|
匹配 Android 应用包名。
|
||||||
|
|
||||||
|
#### package_name_regex
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.14.0 起"
|
||||||
|
|
||||||
|
使用正则表达式匹配 Android 应用包名。
|
||||||
|
|
||||||
#### user
|
#### user
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ icon: material/new-box
|
|||||||
!!! quote "Changes in sing-box 1.14.0"
|
!!! quote "Changes in sing-box 1.14.0"
|
||||||
|
|
||||||
:material-plus: [source_mac_address](#source_mac_address)
|
:material-plus: [source_mac_address](#source_mac_address)
|
||||||
:material-plus: [source_hostname](#source_hostname)
|
:material-plus: [source_hostname](#source_hostname)
|
||||||
|
:material-plus: [package_name_regex](#package_name_regex)
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.13.0"
|
!!! quote "Changes in sing-box 1.13.0"
|
||||||
|
|
||||||
@@ -129,6 +130,9 @@ icon: material/new-box
|
|||||||
"package_name": [
|
"package_name": [
|
||||||
"com.termux"
|
"com.termux"
|
||||||
],
|
],
|
||||||
|
"package_name_regex": [
|
||||||
|
"^com\\.termux.*"
|
||||||
|
],
|
||||||
"user": [
|
"user": [
|
||||||
"sekai"
|
"sekai"
|
||||||
],
|
],
|
||||||
@@ -354,6 +358,12 @@ Match process path using regular expression.
|
|||||||
|
|
||||||
Match android package name.
|
Match android package name.
|
||||||
|
|
||||||
|
#### package_name_regex
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.14.0"
|
||||||
|
|
||||||
|
Match android package name using regular expression.
|
||||||
|
|
||||||
#### user
|
#### user
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ icon: material/new-box
|
|||||||
!!! quote "sing-box 1.14.0 中的更改"
|
!!! quote "sing-box 1.14.0 中的更改"
|
||||||
|
|
||||||
:material-plus: [source_mac_address](#source_mac_address)
|
:material-plus: [source_mac_address](#source_mac_address)
|
||||||
:material-plus: [source_hostname](#source_hostname)
|
:material-plus: [source_hostname](#source_hostname)
|
||||||
|
:material-plus: [package_name_regex](#package_name_regex)
|
||||||
|
|
||||||
!!! quote "sing-box 1.13.0 中的更改"
|
!!! quote "sing-box 1.13.0 中的更改"
|
||||||
|
|
||||||
@@ -127,6 +128,9 @@ icon: material/new-box
|
|||||||
"package_name": [
|
"package_name": [
|
||||||
"com.termux"
|
"com.termux"
|
||||||
],
|
],
|
||||||
|
"package_name_regex": [
|
||||||
|
"^com\\.termux.*"
|
||||||
|
],
|
||||||
"user": [
|
"user": [
|
||||||
"sekai"
|
"sekai"
|
||||||
],
|
],
|
||||||
@@ -352,6 +356,12 @@ icon: material/new-box
|
|||||||
|
|
||||||
匹配 Android 应用包名。
|
匹配 Android 应用包名。
|
||||||
|
|
||||||
|
#### package_name_regex
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.14.0 起"
|
||||||
|
|
||||||
|
使用正则表达式匹配 Android 应用包名。
|
||||||
|
|
||||||
#### user
|
#### user
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.14.0"
|
||||||
|
|
||||||
|
:material-plus: [package_name_regex](#package_name_regex)
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.13.0"
|
!!! quote "Changes in sing-box 1.13.0"
|
||||||
|
|
||||||
:material-plus: [network_interface_address](#network_interface_address)
|
:material-plus: [network_interface_address](#network_interface_address)
|
||||||
@@ -78,6 +82,9 @@ icon: material/new-box
|
|||||||
"package_name": [
|
"package_name": [
|
||||||
"com.termux"
|
"com.termux"
|
||||||
],
|
],
|
||||||
|
"package_name_regex": [
|
||||||
|
"^com\\.termux.*"
|
||||||
|
],
|
||||||
"network_type": [
|
"network_type": [
|
||||||
"wifi"
|
"wifi"
|
||||||
],
|
],
|
||||||
@@ -205,6 +212,12 @@ Match process path using regular expression.
|
|||||||
|
|
||||||
Match android package name.
|
Match android package name.
|
||||||
|
|
||||||
|
#### package_name_regex
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.14.0"
|
||||||
|
|
||||||
|
Match android package name using regular expression.
|
||||||
|
|
||||||
#### network_type
|
#### network_type
|
||||||
|
|
||||||
!!! question "Since sing-box 1.11.0"
|
!!! question "Since sing-box 1.11.0"
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.14.0 中的更改"
|
||||||
|
|
||||||
|
:material-plus: [package_name_regex](#package_name_regex)
|
||||||
|
|
||||||
!!! quote "sing-box 1.13.0 中的更改"
|
!!! quote "sing-box 1.13.0 中的更改"
|
||||||
|
|
||||||
:material-plus: [network_interface_address](#network_interface_address)
|
:material-plus: [network_interface_address](#network_interface_address)
|
||||||
@@ -78,6 +82,9 @@ icon: material/new-box
|
|||||||
"package_name": [
|
"package_name": [
|
||||||
"com.termux"
|
"com.termux"
|
||||||
],
|
],
|
||||||
|
"package_name_regex": [
|
||||||
|
"^com\\.termux.*"
|
||||||
|
],
|
||||||
"network_type": [
|
"network_type": [
|
||||||
"wifi"
|
"wifi"
|
||||||
],
|
],
|
||||||
@@ -201,6 +208,12 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
|
|||||||
|
|
||||||
匹配 Android 应用包名。
|
匹配 Android 应用包名。
|
||||||
|
|
||||||
|
#### package_name_regex
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.14.0 起"
|
||||||
|
|
||||||
|
使用正则表达式匹配 Android 应用包名。
|
||||||
|
|
||||||
#### network_type
|
#### network_type
|
||||||
|
|
||||||
!!! question "自 sing-box 1.11.0 起"
|
!!! question "自 sing-box 1.11.0 起"
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.14.0"
|
||||||
|
|
||||||
|
:material-plus: version `5`
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.13.0"
|
!!! quote "Changes in sing-box 1.13.0"
|
||||||
|
|
||||||
:material-plus: version `4`
|
:material-plus: version `4`
|
||||||
@@ -41,6 +45,7 @@ Version of rule-set.
|
|||||||
* 2: sing-box 1.10.0: Optimized memory usages of `domain_suffix` rules in binary rule-sets.
|
* 2: sing-box 1.10.0: Optimized memory usages of `domain_suffix` rules in binary rule-sets.
|
||||||
* 3: sing-box 1.11.0: Added `network_type`, `network_is_expensive` and `network_is_constrainted` rule items.
|
* 3: sing-box 1.11.0: Added `network_type`, `network_is_expensive` and `network_is_constrainted` rule items.
|
||||||
* 4: sing-box 1.13.0: Added `network_interface_address` and `default_interface_address` rule items.
|
* 4: sing-box 1.13.0: Added `network_interface_address` and `default_interface_address` rule items.
|
||||||
|
* 5: sing-box 1.14.0: Added `package_name_regex` rule item.
|
||||||
|
|
||||||
#### rules
|
#### rules
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.14.0 中的更改"
|
||||||
|
|
||||||
|
:material-plus: version `5`
|
||||||
|
|
||||||
!!! quote "sing-box 1.13.0 中的更改"
|
!!! quote "sing-box 1.13.0 中的更改"
|
||||||
|
|
||||||
:material-plus: version `4`
|
:material-plus: version `4`
|
||||||
@@ -41,6 +45,7 @@ icon: material/new-box
|
|||||||
* 2: sing-box 1.10.0: 优化了二进制规则集中 `domain_suffix` 规则的内存使用。
|
* 2: sing-box 1.10.0: 优化了二进制规则集中 `domain_suffix` 规则的内存使用。
|
||||||
* 3: sing-box 1.11.0: 添加了 `network_type`、 `network_is_expensive` 和 `network_is_constrainted` 规则项。
|
* 3: sing-box 1.11.0: 添加了 `network_type`、 `network_is_expensive` 和 `network_is_constrainted` 规则项。
|
||||||
* 4: sing-box 1.13.0: 添加了 `network_interface_address` 和 `default_interface_address` 规则项。
|
* 4: sing-box 1.13.0: 添加了 `network_interface_address` 和 `default_interface_address` 规则项。
|
||||||
|
* 5: sing-box 1.14.0: 添加了 `package_name_regex` 规则项。
|
||||||
|
|
||||||
#### rules
|
#### rules
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ type RawDefaultRule struct {
|
|||||||
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
||||||
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
||||||
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
||||||
|
PackageNameRegex badoption.Listable[string] `json:"package_name_regex,omitempty"`
|
||||||
User badoption.Listable[string] `json:"user,omitempty"`
|
User badoption.Listable[string] `json:"user,omitempty"`
|
||||||
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
|
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
|
||||||
ClashMode string `json:"clash_mode,omitempty"`
|
ClashMode string `json:"clash_mode,omitempty"`
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ type RawDefaultDNSRule struct {
|
|||||||
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
||||||
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
||||||
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
||||||
|
PackageNameRegex badoption.Listable[string] `json:"package_name_regex,omitempty"`
|
||||||
User badoption.Listable[string] `json:"user,omitempty"`
|
User badoption.Listable[string] `json:"user,omitempty"`
|
||||||
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
|
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
|
||||||
Outbound badoption.Listable[string] `json:"outbound,omitempty"`
|
Outbound badoption.Listable[string] `json:"outbound,omitempty"`
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ type DefaultHeadlessRule struct {
|
|||||||
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
||||||
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
||||||
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
||||||
|
PackageNameRegex badoption.Listable[string] `json:"package_name_regex,omitempty"`
|
||||||
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
||||||
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
|
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
|
||||||
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
|
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
|
||||||
@@ -243,7 +244,7 @@ type PlainRuleSetCompat _PlainRuleSetCompat
|
|||||||
func (r PlainRuleSetCompat) MarshalJSON() ([]byte, error) {
|
func (r PlainRuleSetCompat) MarshalJSON() ([]byte, error) {
|
||||||
var v any
|
var v any
|
||||||
switch r.Version {
|
switch r.Version {
|
||||||
case C.RuleSetVersion1, C.RuleSetVersion2, C.RuleSetVersion3, C.RuleSetVersion4:
|
case C.RuleSetVersion1, C.RuleSetVersion2, C.RuleSetVersion3, C.RuleSetVersion4, C.RuleSetVersion5:
|
||||||
v = r.Options
|
v = r.Options
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown rule-set version: ", r.Version)
|
return nil, E.New("unknown rule-set version: ", r.Version)
|
||||||
@@ -258,7 +259,7 @@ func (r *PlainRuleSetCompat) UnmarshalJSON(bytes []byte) error {
|
|||||||
}
|
}
|
||||||
var v any
|
var v any
|
||||||
switch r.Version {
|
switch r.Version {
|
||||||
case C.RuleSetVersion1, C.RuleSetVersion2, C.RuleSetVersion3, C.RuleSetVersion4:
|
case C.RuleSetVersion1, C.RuleSetVersion2, C.RuleSetVersion3, C.RuleSetVersion4, C.RuleSetVersion5:
|
||||||
v = &r.Options
|
v = &r.Options
|
||||||
case 0:
|
case 0:
|
||||||
return E.New("missing rule-set version")
|
return E.New("missing rule-set version")
|
||||||
@@ -275,7 +276,7 @@ func (r *PlainRuleSetCompat) UnmarshalJSON(bytes []byte) error {
|
|||||||
|
|
||||||
func (r PlainRuleSetCompat) Upgrade() (PlainRuleSet, error) {
|
func (r PlainRuleSetCompat) Upgrade() (PlainRuleSet, error) {
|
||||||
switch r.Version {
|
switch r.Version {
|
||||||
case C.RuleSetVersion1, C.RuleSetVersion2, C.RuleSetVersion3, C.RuleSetVersion4:
|
case C.RuleSetVersion1, C.RuleSetVersion2, C.RuleSetVersion3, C.RuleSetVersion4, C.RuleSetVersion5:
|
||||||
default:
|
default:
|
||||||
return PlainRuleSet{}, E.New("unknown rule-set version: " + F.ToString(r.Version))
|
return PlainRuleSet{}, E.New("unknown rule-set version: " + F.ToString(r.Version))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,6 +209,14 @@ func NewDefaultRule(ctx context.Context, logger log.ContextLogger, options optio
|
|||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
if len(options.PackageNameRegex) > 0 {
|
||||||
|
item, err := NewPackageNameRegexItem(options.PackageNameRegex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "package_name_regex")
|
||||||
|
}
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
if len(options.User) > 0 {
|
if len(options.User) > 0 {
|
||||||
item := NewUserItem(options.User)
|
item := NewUserItem(options.User)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
|
|||||||
@@ -251,6 +251,14 @@ func NewDefaultDNSRule(ctx context.Context, logger log.ContextLogger, options op
|
|||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
if len(options.PackageNameRegex) > 0 {
|
||||||
|
item, err := NewPackageNameRegexItem(options.PackageNameRegex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "package_name_regex")
|
||||||
|
}
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
if len(options.User) > 0 {
|
if len(options.User) > 0 {
|
||||||
item := NewUserItem(options.User)
|
item := NewUserItem(options.User)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
|
|||||||
@@ -153,6 +153,14 @@ func NewDefaultHeadlessRule(ctx context.Context, options option.DefaultHeadlessR
|
|||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
if len(options.PackageNameRegex) > 0 {
|
||||||
|
item, err := NewPackageNameRegexItem(options.PackageNameRegex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "package_name_regex")
|
||||||
|
}
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
if networkManager != nil {
|
if networkManager != nil {
|
||||||
if len(options.NetworkType) > 0 {
|
if len(options.NetworkType) > 0 {
|
||||||
item := NewNetworkTypeItem(networkManager, common.Map(options.NetworkType, option.InterfaceType.Build))
|
item := NewNetworkTypeItem(networkManager, common.Map(options.NetworkType, option.InterfaceType.Build))
|
||||||
|
|||||||
56
route/rule/rule_item_package_name_regex.go
Normal file
56
route/rule/rule_item_package_name_regex.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package rule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
F "github.com/sagernet/sing/common/format"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ RuleItem = (*PackageNameRegexItem)(nil)
|
||||||
|
|
||||||
|
type PackageNameRegexItem struct {
|
||||||
|
matchers []*regexp.Regexp
|
||||||
|
description string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPackageNameRegexItem(expressions []string) (*PackageNameRegexItem, error) {
|
||||||
|
matchers := make([]*regexp.Regexp, 0, len(expressions))
|
||||||
|
for i, regex := range expressions {
|
||||||
|
matcher, err := regexp.Compile(regex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "parse expression ", i)
|
||||||
|
}
|
||||||
|
matchers = append(matchers, matcher)
|
||||||
|
}
|
||||||
|
description := "package_name_regex="
|
||||||
|
eLen := len(expressions)
|
||||||
|
if eLen == 1 {
|
||||||
|
description += expressions[0]
|
||||||
|
} else if eLen > 3 {
|
||||||
|
description += F.ToString("[", strings.Join(expressions[:3], " "), "]")
|
||||||
|
} else {
|
||||||
|
description += F.ToString("[", strings.Join(expressions, " "), "]")
|
||||||
|
}
|
||||||
|
return &PackageNameRegexItem{matchers, description}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PackageNameRegexItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
|
if metadata.ProcessInfo == nil || len(metadata.ProcessInfo.AndroidPackageNames) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, matcher := range r.matchers {
|
||||||
|
for _, packageName := range metadata.ProcessInfo.AndroidPackageNames {
|
||||||
|
if matcher.MatchString(packageName) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PackageNameRegexItem) String() string {
|
||||||
|
return r.description
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@ func HasHeadlessRule(rules []option.HeadlessRule, cond func(rule option.DefaultH
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isProcessHeadlessRule(rule option.DefaultHeadlessRule) bool {
|
func isProcessHeadlessRule(rule option.DefaultHeadlessRule) bool {
|
||||||
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.ProcessPathRegex) > 0 || len(rule.PackageName) > 0
|
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.ProcessPathRegex) > 0 || len(rule.PackageName) > 0 || len(rule.PackageNameRegex) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func isWIFIHeadlessRule(rule option.DefaultHeadlessRule) bool {
|
func isWIFIHeadlessRule(rule option.DefaultHeadlessRule) bool {
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ func hasDNSRule(rules []option.DNSRule, cond func(rule option.DefaultDNSRule) bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isProcessRule(rule option.DefaultRule) bool {
|
func isProcessRule(rule option.DefaultRule) bool {
|
||||||
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.ProcessPathRegex) > 0 || len(rule.PackageName) > 0 || len(rule.User) > 0 || len(rule.UserID) > 0
|
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.ProcessPathRegex) > 0 || len(rule.PackageName) > 0 || len(rule.PackageNameRegex) > 0 || len(rule.User) > 0 || len(rule.UserID) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func isProcessDNSRule(rule option.DefaultDNSRule) bool {
|
func isProcessDNSRule(rule option.DefaultDNSRule) bool {
|
||||||
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.ProcessPathRegex) > 0 || len(rule.PackageName) > 0 || len(rule.User) > 0 || len(rule.UserID) > 0
|
return len(rule.ProcessName) > 0 || len(rule.ProcessPath) > 0 || len(rule.ProcessPathRegex) > 0 || len(rule.PackageName) > 0 || len(rule.PackageNameRegex) > 0 || len(rule.User) > 0 || len(rule.UserID) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func isNeighborRule(rule option.DefaultRule) bool {
|
func isNeighborRule(rule option.DefaultRule) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user