Meow
2026-05-02 09:54:34 +08:00
committed by RPRX
parent 7ab0a3ccb7
commit 4e87f59628
26 changed files with 538 additions and 225 deletions
+1 -1
View File
@@ -84,7 +84,7 @@ func (c *DNSOutboundConfig) Build() (proto.Message, error) {
if c.Rules != nil {
return nil, errors.New("legacy nonIPQuery and blockTypes cannot be mixed with rules")
}
errors.PrintDeprecatedFeatureWarning(`"nonIPQuery" and "blockTypes" in DNS outbound`, `"rules"`)
errors.PrintDeprecatedFeatureWarning(`"nonIPQuery" and "blockTypes"`, `"rules"`)
rules, err := c.buildLegacyDNSPolicy()
if err != nil {
return nil, err
+64 -15
View File
@@ -1,6 +1,7 @@
package conf
import (
"context"
"encoding/base64"
"encoding/hex"
"net"
@@ -8,7 +9,7 @@ import (
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/geodata"
v2net "github.com/xtls/xray-core/common/net"
xnet "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/proxy/freedom"
"github.com/xtls/xray-core/transport/internet"
@@ -16,15 +17,16 @@ import (
)
type FreedomConfig struct {
TargetStrategy string `json:"targetStrategy"`
DomainStrategy string `json:"domainStrategy"`
Redirect string `json:"redirect"`
UserLevel uint32 `json:"userLevel"`
Fragment *Fragment `json:"fragment"`
Noise *Noise `json:"noise"`
Noises []*Noise `json:"noises"`
ProxyProtocol uint32 `json:"proxyProtocol"`
IPsBlocked *StringList `json:"ipsBlocked"`
TargetStrategy string `json:"targetStrategy"`
DomainStrategy string `json:"domainStrategy"`
Redirect string `json:"redirect"`
UserLevel uint32 `json:"userLevel"`
Fragment *Fragment `json:"fragment"`
Noise *Noise `json:"noise"`
Noises []*Noise `json:"noises"`
ProxyProtocol uint32 `json:"proxyProtocol"`
IPsBlocked *StringList `json:"ipsBlocked"`
FinalRules []*FreedomFinalRuleConfig `json:"finalRules"`
}
type Fragment struct {
@@ -41,8 +43,20 @@ type Noise struct {
ApplyTo string `json:"applyTo"`
}
type FreedomFinalRuleConfig struct {
Action string `json:"action"`
Network *NetworkList `json:"network"`
Port *PortList `json:"port"`
IP *StringList `json:"ip"`
}
// Build implements Buildable
func (c *FreedomConfig) Build() (proto.Message, error) {
if c.IPsBlocked != nil {
// todo: remove legacy
errors.LogWarning(context.Background(), `The feature "ipsBlocked" has been removed and migrated to "finalRules". Please update your config(s) according to release note and documentation.`)
}
config := new(freedom.Config)
targetStrategy := c.TargetStrategy
if targetStrategy == "" {
@@ -142,12 +156,13 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
}
config.UserLevel = c.UserLevel
if len(c.Redirect) > 0 {
host, portStr, err := net.SplitHostPort(c.Redirect)
if err != nil {
return nil, errors.New("invalid redirect address: ", c.Redirect, ": ", err).Base(err)
}
port, err := v2net.PortFromString(portStr)
port, err := xnet.PortFromString(portStr)
if err != nil {
return nil, errors.New("invalid redirect port: ", c.Redirect, ": ", err).Base(err)
}
@@ -158,19 +173,22 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
}
if len(host) > 0 {
config.DestinationOverride.Server.Address = v2net.NewIPOrDomain(v2net.ParseAddress(host))
config.DestinationOverride.Server.Address = xnet.NewIPOrDomain(xnet.ParseAddress(host))
}
}
if c.ProxyProtocol > 0 && c.ProxyProtocol <= 2 {
config.ProxyProtocol = c.ProxyProtocol
}
if c.IPsBlocked != nil {
rules, err := geodata.ParseIPRules(*c.IPsBlocked)
for _, r := range c.FinalRules {
rule, err := r.Build()
if err != nil {
return nil, err
}
config.IpsBlocked = &freedom.IPRules{Rules: rules}
config.FinalRules = append(config.FinalRules, rule)
}
return config, nil
}
@@ -229,3 +247,34 @@ func ParseNoise(noise *Noise) (*freedom.Noise, error) {
}
return NConfig, nil
}
func (c *FreedomFinalRuleConfig) Build() (*freedom.FinalRuleConfig, error) {
rule := &freedom.FinalRuleConfig{}
switch strings.ToLower(c.Action) {
case "allow":
rule.Action = freedom.RuleAction_Allow
case "block":
rule.Action = freedom.RuleAction_Block
default:
return nil, errors.New("unknown action: ", c.Action)
}
if c.Network != nil {
rule.Networks = c.Network.Build()
}
if c.Port != nil {
rule.PortList = c.Port.Build()
}
if c.IP != nil {
rules, err := geodata.ParseIPRules(*c.IP)
if err != nil {
return nil, err
}
rule.Ip = rules
}
return rule, nil
}
+55
View File
@@ -3,6 +3,7 @@ package conf_test
import (
"testing"
"github.com/xtls/xray-core/common/geodata"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
. "github.com/xtls/xray-core/infra/conf"
@@ -38,5 +39,59 @@ func TestFreedomConfig(t *testing.T) {
UserLevel: 1,
},
},
{
Input: `{
"finalRules": [{
"action": "block",
"network": "tcp,udp",
"port": "53,443",
"ip": ["10.0.0.0/8", "2001:db8::/32"]
}, {
"action": "allow",
"network": ["udp"]
}]
}`,
Parser: loadJSON(creator),
Output: &freedom.Config{
FinalRules: []*freedom.FinalRuleConfig{
{
Action: freedom.RuleAction_Block,
Networks: []net.Network{net.Network_TCP, net.Network_UDP},
PortList: &net.PortList{
Range: []*net.PortRange{
{From: 53, To: 53},
{From: 443, To: 443},
},
},
Ip: []*geodata.IPRule{
{
Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDRRule{
Cidr: &geodata.CIDR{
Ip: []byte{10, 0, 0, 0},
Prefix: 8,
},
},
},
},
{
Value: &geodata.IPRule_Custom{
Custom: &geodata.CIDRRule{
Cidr: &geodata.CIDR{
Ip: net.ParseAddress("2001:db8::").IP(),
Prefix: 32,
},
},
},
},
},
},
{
Action: freedom.RuleAction_Allow,
Networks: []net.Network{net.Network_UDP},
},
},
},
},
})
}