mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-15 22:10:26 +00:00
Routing: Add localOS that directly matches runtime.GOOS (#6553)
https://github.com/XTLS/Xray-core/pull/6553#issuecomment-5262686006
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -393,3 +394,22 @@ func (m *ProcessNameMatcher) Apply(ctx routing.Context) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LocalOSMatcher matches the operating system Xray itself is running on. That never
|
||||||
|
// changes while Xray is running, so the result is resolved when the rule is built.
|
||||||
|
type LocalOSMatcher struct {
|
||||||
|
matched bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLocalOSMatcher(names []string) *LocalOSMatcher {
|
||||||
|
return &LocalOSMatcher{
|
||||||
|
matched: slices.ContainsFunc(names, func(name string) bool {
|
||||||
|
return strings.EqualFold(name, runtime.GOOS)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply implements Condition.
|
||||||
|
func (m *LocalOSMatcher) Apply(_ routing.Context) bool {
|
||||||
|
return m.matched
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package router_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/router"
|
. "github.com/xtls/xray-core/app/router"
|
||||||
@@ -343,6 +345,31 @@ func TestChinaSites(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLocalOSRule(t *testing.T) {
|
||||||
|
otherOS := "plan9"
|
||||||
|
if runtime.GOOS == otherOS {
|
||||||
|
otherOS = "linux"
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
localOS []string
|
||||||
|
output bool
|
||||||
|
}{
|
||||||
|
{localOS: []string{runtime.GOOS}, output: true},
|
||||||
|
{localOS: []string{otherOS}, output: false},
|
||||||
|
{localOS: []string{otherOS, runtime.GOOS}, output: true},
|
||||||
|
{localOS: []string{strings.ToUpper(runtime.GOOS)}, output: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range cases {
|
||||||
|
cond, err := (&RoutingRule{LocalOs: test.localOS}).BuildCondition()
|
||||||
|
common.Must(err)
|
||||||
|
if got := cond.Apply(withBackground()); got != test.output {
|
||||||
|
t.Errorf("for localOS %v on %s: expected %v, got %v", test.localOS, runtime.GOOS, test.output, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkMphDomainMatcher(b *testing.B) {
|
func BenchmarkMphDomainMatcher(b *testing.B) {
|
||||||
b.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
b.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
rules, err := geodata.ParseDomainRules([]string{"geosite:cn"}, geodata.Domain_Substr)
|
rules, err := geodata.ParseDomainRules([]string{"geosite:cn"}, geodata.Domain_Substr)
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ func (r *Rule) Apply(ctx routing.Context) bool {
|
|||||||
func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
||||||
conds := NewConditionChan()
|
conds := NewConditionChan()
|
||||||
|
|
||||||
|
if len(rr.LocalOs) > 0 {
|
||||||
|
conds.Add(NewLocalOSMatcher(rr.LocalOs))
|
||||||
|
}
|
||||||
|
|
||||||
if len(rr.InboundTag) > 0 {
|
if len(rr.InboundTag) > 0 {
|
||||||
conds.Add(NewInboundTagMatcher(rr.InboundTag))
|
conds.Add(NewInboundTagMatcher(rr.InboundTag))
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-4
@@ -107,8 +107,10 @@ type RoutingRule struct {
|
|||||||
VlessRouteList *net.PortList `protobuf:"bytes,20,opt,name=vless_route_list,json=vlessRouteList,proto3" json:"vless_route_list,omitempty"`
|
VlessRouteList *net.PortList `protobuf:"bytes,20,opt,name=vless_route_list,json=vlessRouteList,proto3" json:"vless_route_list,omitempty"`
|
||||||
Process []string `protobuf:"bytes,21,rep,name=process,proto3" json:"process,omitempty"`
|
Process []string `protobuf:"bytes,21,rep,name=process,proto3" json:"process,omitempty"`
|
||||||
Webhook *WebhookConfig `protobuf:"bytes,22,opt,name=webhook,proto3" json:"webhook,omitempty"`
|
Webhook *WebhookConfig `protobuf:"bytes,22,opt,name=webhook,proto3" json:"webhook,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
// List of operating systems for matching the one Xray itself is running on.
|
||||||
sizeCache protoimpl.SizeCache
|
LocalOs []string `protobuf:"bytes,23,rep,name=local_os,json=localOs,proto3" json:"local_os,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) Reset() {
|
func (x *RoutingRule) Reset() {
|
||||||
@@ -278,6 +280,13 @@ func (x *RoutingRule) GetWebhook() *WebhookConfig {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *RoutingRule) GetLocalOs() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.LocalOs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type isRoutingRule_TargetTag interface {
|
type isRoutingRule_TargetTag interface {
|
||||||
isRoutingRule_TargetTag()
|
isRoutingRule_TargetTag()
|
||||||
}
|
}
|
||||||
@@ -637,7 +646,7 @@ var File_app_router_config_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
const file_app_router_config_proto_rawDesc = "" +
|
const file_app_router_config_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x17app/router/config.proto\x12\x0fxray.app.router\x1a!common/serial/typed_message.proto\x1a\x15common/net/port.proto\x1a\x18common/net/network.proto\x1a\x1bcommon/geodata/geodat.proto\"\xc1\a\n" +
|
"\x17app/router/config.proto\x12\x0fxray.app.router\x1a!common/serial/typed_message.proto\x1a\x15common/net/port.proto\x1a\x18common/net/network.proto\x1a\x1bcommon/geodata/geodat.proto\"\xdc\a\n" +
|
||||||
"\vRoutingRule\x12\x12\n" +
|
"\vRoutingRule\x12\x12\n" +
|
||||||
"\x03tag\x18\x01 \x01(\tH\x00R\x03tag\x12%\n" +
|
"\x03tag\x18\x01 \x01(\tH\x00R\x03tag\x12%\n" +
|
||||||
"\rbalancing_tag\x18\f \x01(\tH\x00R\fbalancingTag\x12\x19\n" +
|
"\rbalancing_tag\x18\f \x01(\tH\x00R\fbalancingTag\x12\x19\n" +
|
||||||
@@ -661,7 +670,8 @@ const file_app_router_config_proto_rawDesc = "" +
|
|||||||
"\x0flocal_port_list\x18\x12 \x01(\v2\x19.xray.common.net.PortListR\rlocalPortList\x12C\n" +
|
"\x0flocal_port_list\x18\x12 \x01(\v2\x19.xray.common.net.PortListR\rlocalPortList\x12C\n" +
|
||||||
"\x10vless_route_list\x18\x14 \x01(\v2\x19.xray.common.net.PortListR\x0evlessRouteList\x12\x18\n" +
|
"\x10vless_route_list\x18\x14 \x01(\v2\x19.xray.common.net.PortListR\x0evlessRouteList\x12\x18\n" +
|
||||||
"\aprocess\x18\x15 \x03(\tR\aprocess\x128\n" +
|
"\aprocess\x18\x15 \x03(\tR\aprocess\x128\n" +
|
||||||
"\awebhook\x18\x16 \x01(\v2\x1e.xray.app.router.WebhookConfigR\awebhook\x1a=\n" +
|
"\awebhook\x18\x16 \x01(\v2\x1e.xray.app.router.WebhookConfigR\awebhook\x12\x19\n" +
|
||||||
|
"\blocal_os\x18\x17 \x03(\tR\alocalOs\x1a=\n" +
|
||||||
"\x0fAttributesEntry\x12\x10\n" +
|
"\x0fAttributesEntry\x12\x10\n" +
|
||||||
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
|
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
|
||||||
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\f\n" +
|
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\f\n" +
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ message RoutingRule {
|
|||||||
|
|
||||||
repeated string process = 21;
|
repeated string process = 21;
|
||||||
WebhookConfig webhook = 22;
|
WebhookConfig webhook = 22;
|
||||||
|
|
||||||
|
// List of operating systems for matching the one Xray itself is running on.
|
||||||
|
repeated string local_os = 23;
|
||||||
}
|
}
|
||||||
|
|
||||||
message WebhookConfig {
|
message WebhookConfig {
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
LocalIP *StringList `json:"localIP"`
|
LocalIP *StringList `json:"localIP"`
|
||||||
LocalPort *PortList `json:"localPort"`
|
LocalPort *PortList `json:"localPort"`
|
||||||
Process *StringList `json:"process"`
|
Process *StringList `json:"process"`
|
||||||
|
LocalOS *StringList `json:"localOS"`
|
||||||
Webhook *WebhookRuleConfig `json:"webhook"`
|
Webhook *WebhookRuleConfig `json:"webhook"`
|
||||||
}
|
}
|
||||||
rawFieldRule := new(RawFieldRule)
|
rawFieldRule := new(RawFieldRule)
|
||||||
@@ -261,6 +262,10 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
rule.Process = *rawFieldRule.Process
|
rule.Process = *rawFieldRule.Process
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rawFieldRule.LocalOS != nil && len(*rawFieldRule.LocalOS) > 0 {
|
||||||
|
rule.LocalOs = *rawFieldRule.LocalOS
|
||||||
|
}
|
||||||
|
|
||||||
if rawFieldRule.Webhook != nil && rawFieldRule.Webhook.URL != "" {
|
if rawFieldRule.Webhook != nil && rawFieldRule.Webhook.URL != "" {
|
||||||
rule.Webhook = &router.WebhookConfig{
|
rule.Webhook = &router.WebhookConfig{
|
||||||
Url: rawFieldRule.Webhook.URL,
|
Url: rawFieldRule.Webhook.URL,
|
||||||
|
|||||||
Reference in New Issue
Block a user