mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-11-05 18:07:00 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc1355d7e9 | ||
|
|
d9da576f68 |
@@ -9,8 +9,8 @@ ARG TARGETARCH
|
||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags "-s -w -buildid=" ./main
|
||||
|
||||
# Download geodat into a staging directory
|
||||
ADD https://raw.githubusercontent.com/XTLS/Xray-rules-dat/release/geoip/geoip-full.dat /tmp/geodat/geoip.dat
|
||||
ADD https://raw.githubusercontent.com/XTLS/Xray-rules-dat/release/geosite/geosite-expand.dat /tmp/geodat/geosite.dat
|
||||
ADD https://github.com/XTLS/Xray-rules-dat/releases/latest/download/geoip-full.dat /tmp/geodat/geoip.dat
|
||||
ADD https://github.com/XTLS/Xray-rules-dat/releases/latest/download/geosite-expand.dat /tmp/geodat/geosite.dat
|
||||
|
||||
RUN mkdir -p /tmp/empty
|
||||
|
||||
@@ -20,7 +20,7 @@ RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
|
||||
{
|
||||
"log": {
|
||||
"error": "/var/log/xray/error.log",
|
||||
"logLevel": "warning",
|
||||
"loglevel": "warning",
|
||||
"access": "none",
|
||||
"dnsLog": false
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ ARG TARGETARCH
|
||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags "-s -w -buildid=" ./main
|
||||
|
||||
# Download geodat into a staging directory
|
||||
ADD https://raw.githubusercontent.com/XTLS/Xray-rules-dat/release/geoip/geoip-full.dat /tmp/geodat/geoip.dat
|
||||
ADD https://raw.githubusercontent.com/XTLS/Xray-rules-dat/release/geosite/geosite-expand.dat /tmp/geodat/geosite.dat
|
||||
ADD https://github.com/XTLS/Xray-rules-dat/releases/latest/download/geoip-full.dat /tmp/geodat/geoip.dat
|
||||
ADD https://github.com/XTLS/Xray-rules-dat/releases/latest/download/geosite-expand.dat /tmp/geodat/geosite.dat
|
||||
|
||||
RUN mkdir -p /tmp/empty
|
||||
|
||||
@@ -20,7 +20,7 @@ RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
|
||||
{
|
||||
"log": {
|
||||
"error": "/var/log/xray/error.log",
|
||||
"logLevel": "warning",
|
||||
"loglevel": "warning",
|
||||
"access": "none",
|
||||
"dnsLog": false
|
||||
}
|
||||
|
||||
@@ -217,7 +217,6 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
||||
if ob.Target.Network == net.Network_UDP && ob.Target.Port == 443 {
|
||||
switch h.udp443 {
|
||||
case "reject":
|
||||
proxy.DropUDP(ctx, link.Reader)
|
||||
test(errors.New("XUDP rejected UDP/443 traffic"))
|
||||
return
|
||||
case "skip":
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ func (r *TimeoutWrapperReader) ReadMultiBufferTimeout(duration time.Duration) (M
|
||||
}
|
||||
return r.mb, r.err
|
||||
case <-timeout:
|
||||
return nil, ErrReadTimeout
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ func TestMarshalConfigJson(t *testing.T) {
|
||||
func getConfig() string {
|
||||
return `{
|
||||
"log": {
|
||||
"logLevel": "debug"
|
||||
"loglevel": "debug"
|
||||
},
|
||||
"stats": {},
|
||||
"policy": {
|
||||
|
||||
@@ -10,7 +10,7 @@ require (
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/klauspost/cpuid/v2 v2.4.2
|
||||
github.com/klauspost/cpuid/v2 v2.4.1
|
||||
github.com/libp2p/go-nat v1.0.1-0.20250821073202-01afc089f138
|
||||
github.com/miekg/dns v1.1.73
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
|
||||
@@ -35,8 +35,8 @@ github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI=
|
||||
github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
|
||||
github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA=
|
||||
github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
|
||||
github.com/klauspost/cpuid/v2 v2.4.2 h1:xRw7IZEsAgVCp6trS/DgWbTAqpixhmywgVgBjYGg1bQ=
|
||||
github.com/klauspost/cpuid/v2 v2.4.2/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
|
||||
github.com/klauspost/cpuid/v2 v2.4.1 h1:I9KxadAkvo+QjtcEE2f2tyfEvmIla/T0m+14PrZNl0U=
|
||||
github.com/klauspost/cpuid/v2 v2.4.1/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
|
||||
github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
|
||||
github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
|
||||
+3
-33
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/geodata"
|
||||
"github.com/xtls/xray-core/common/log"
|
||||
xnet "github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
"github.com/xtls/xray-core/proxy/freedom"
|
||||
@@ -49,8 +48,6 @@ type FreedomFinalRuleConfig struct {
|
||||
Network *NetworkList `json:"network"`
|
||||
Port *PortList `json:"port"`
|
||||
IP *StringList `json:"ip"`
|
||||
Delay *Int32Range `json:"delay"`
|
||||
LogLevel string `json:"logLevel"`
|
||||
BlockDelay *Int32Range `json:"blockDelay"`
|
||||
}
|
||||
|
||||
@@ -283,37 +280,10 @@ func (c *FreedomFinalRuleConfig) Build() (*freedom.FinalRuleConfig, error) {
|
||||
}
|
||||
|
||||
if c.BlockDelay != nil {
|
||||
errors.PrintDeprecatedFeatureWarning("finalRules.blockDelay", "finalRules.delay")
|
||||
c.Delay = c.BlockDelay
|
||||
}
|
||||
|
||||
if rule.Action != freedom.RuleAction_Block {
|
||||
if c.Delay != nil || c.LogLevel != "" {
|
||||
return nil, errors.New("delay and logLevel are only supported for block finalRules")
|
||||
rule.BlockDelay = &freedom.Range{
|
||||
Min: uint64(c.BlockDelay.From),
|
||||
Max: uint64(c.BlockDelay.To),
|
||||
}
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
if c.Delay != nil {
|
||||
rule.Delay = &freedom.Range{
|
||||
Min: uint64(c.Delay.From),
|
||||
Max: uint64(c.Delay.To),
|
||||
}
|
||||
}
|
||||
|
||||
switch strings.ToLower(c.LogLevel) {
|
||||
case "", "info":
|
||||
rule.LogLevel = log.Severity_Info.Enum()
|
||||
case "none":
|
||||
rule.LogLevel = log.Severity_Unknown.Enum()
|
||||
case "debug":
|
||||
rule.LogLevel = log.Severity_Debug.Enum()
|
||||
case "warning":
|
||||
rule.LogLevel = log.Severity_Warning.Enum()
|
||||
case "error":
|
||||
rule.LogLevel = log.Severity_Error.Enum()
|
||||
default:
|
||||
return nil, errors.New("unknown finalRules.logLevel: ", c.LogLevel)
|
||||
}
|
||||
|
||||
return rule, nil
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/xtls/xray-core/common/geodata"
|
||||
"github.com/xtls/xray-core/common/log"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
. "github.com/xtls/xray-core/infra/conf"
|
||||
@@ -47,8 +46,7 @@ func TestFreedomConfig(t *testing.T) {
|
||||
"network": "tcp,udp",
|
||||
"port": "53,443",
|
||||
"ip": ["10.0.0.0/8", "2001:db8::/32"],
|
||||
"delay": "30-60",
|
||||
"logLevel": "debug"
|
||||
"blockDelay": "30-60"
|
||||
}, {
|
||||
"action": "allow",
|
||||
"network": ["udp"]
|
||||
@@ -88,8 +86,10 @@ func TestFreedomConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Delay: &freedom.Range{Min: 30, Max: 60},
|
||||
LogLevel: log.Severity_Debug.Enum(),
|
||||
BlockDelay: &freedom.Range{
|
||||
Min: 30,
|
||||
Max: 60,
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: freedom.RuleAction_Allow,
|
||||
|
||||
+10
-1
@@ -2,6 +2,7 @@ package conf
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
"github.com/xtls/xray-core/app/geodata"
|
||||
@@ -19,11 +20,19 @@ func (c *GeodataAssetConfig) Build() (*geodata.Asset, error) {
|
||||
return nil, errors.New("invalid geodata asset url: ", c.URL).Base(err)
|
||||
}
|
||||
return &geodata.Asset{
|
||||
Url: c.URL,
|
||||
Url: migrateGeodataURL(c.URL),
|
||||
File: c.File,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func migrateGeodataURL(assetURL string) string {
|
||||
if strings.HasSuffix(assetURL, ".dat") && (strings.HasPrefix(strings.ToLower(assetURL), "https://raw.githubusercontent.com/xtls/xray-rules-dat/") || strings.HasPrefix(strings.ToLower(assetURL), "https://github.com/xtls/xray-rules-dat/")) {
|
||||
errors.PrintDeprecatedFeatureWarning(assetURL, assetURL+".gz")
|
||||
return assetURL + ".gz"
|
||||
}
|
||||
return assetURL
|
||||
}
|
||||
|
||||
func validateHTTPS(s string) error {
|
||||
u, err := url.ParseRequestURI(s)
|
||||
if err != nil {
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ func DefaultLogConfig() *log.Config {
|
||||
type LogConfig struct {
|
||||
AccessLog string `json:"access"`
|
||||
ErrorLog string `json:"error"`
|
||||
LogLevel string `json:"logLevel"`
|
||||
LogLevel string `json:"loglevel"`
|
||||
DNSLog bool `json:"dnsLog"`
|
||||
MaskAddress string `json:"maskAddress"`
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestLoaderError(t *testing.T) {
|
||||
"log": {
|
||||
// abcd
|
||||
0,
|
||||
"logLevel": "info"
|
||||
"loglevel": "info"
|
||||
}
|
||||
}`,
|
||||
Output: "line 4 char 6",
|
||||
@@ -27,7 +27,7 @@ func TestLoaderError(t *testing.T) {
|
||||
Input: `{
|
||||
"log": {
|
||||
// abcd
|
||||
"logLevel": "info",
|
||||
"loglevel": "info",
|
||||
}
|
||||
}`,
|
||||
Output: "line 5 char 5",
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestXrayConfig(t *testing.T) {
|
||||
Input: `{
|
||||
"log": {
|
||||
"access": "/var/log/xray/access.log",
|
||||
"logLevel": "error",
|
||||
"loglevel": "error",
|
||||
"error": "/var/log/xray/error.log"
|
||||
},
|
||||
"inbounds": [{
|
||||
|
||||
@@ -9,10 +9,11 @@ import (
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/dice"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/proxy"
|
||||
"github.com/xtls/xray-core/common/signal"
|
||||
"github.com/xtls/xray-core/transport"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
@@ -68,8 +69,14 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
}
|
||||
defer common.Interrupt(link.Writer)
|
||||
defer common.Interrupt(link.Reader)
|
||||
// wait to drain all the possible incoming UDP data
|
||||
if ob.Target.Network == net.Network_UDP {
|
||||
proxy.DropUDP(ctx, link.Reader)
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
timer := signal.CancelAfterInactivity(ctx, func() {
|
||||
cancel()
|
||||
}, time.Duration(30+dice.Roll(61))*time.Second)
|
||||
go buf.Copy(link.Reader, buf.Discard, buf.UpdateActivity(timer))
|
||||
<-ctx.Done()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand/v2"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/signal"
|
||||
)
|
||||
|
||||
// wait to drain all the possible incoming UDP data
|
||||
// because re-established QUIC UDP may bypass the sniffer
|
||||
func DropUDP(ctx context.Context, reader buf.Reader) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
timer := signal.CancelAfterInactivity(ctx, func() {
|
||||
cancel()
|
||||
}, time.Duration(30+rand.N(60))*time.Second)
|
||||
context.AfterFunc(ctx, func() {
|
||||
common.Interrupt(reader)
|
||||
})
|
||||
buf.Copy(reader, buf.Discard, buf.UpdateActivity(timer))
|
||||
}
|
||||
+20
-34
@@ -8,7 +8,6 @@ package freedom
|
||||
|
||||
import (
|
||||
geodata "github.com/xtls/xray-core/common/geodata"
|
||||
log "github.com/xtls/xray-core/common/log"
|
||||
net "github.com/xtls/xray-core/common/net"
|
||||
protocol "github.com/xtls/xray-core/common/protocol"
|
||||
internet "github.com/xtls/xray-core/transport/internet"
|
||||
@@ -358,8 +357,7 @@ type FinalRuleConfig struct {
|
||||
Networks []net.Network `protobuf:"varint,2,rep,packed,name=networks,proto3,enum=xray.common.net.Network" json:"networks,omitempty"`
|
||||
PortList *net.PortList `protobuf:"bytes,3,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
||||
Ip []*geodata.IPRule `protobuf:"bytes,4,rep,name=ip,proto3" json:"ip,omitempty"`
|
||||
Delay *Range `protobuf:"bytes,5,opt,name=delay,proto3" json:"delay,omitempty"`
|
||||
LogLevel *log.Severity `protobuf:"varint,6,opt,name=log_level,json=logLevel,proto3,enum=xray.common.log.Severity,oneof" json:"log_level,omitempty"`
|
||||
BlockDelay *Range `protobuf:"bytes,5,opt,name=block_delay,json=blockDelay,proto3" json:"block_delay,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -422,20 +420,13 @@ func (x *FinalRuleConfig) GetIp() []*geodata.IPRule {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FinalRuleConfig) GetDelay() *Range {
|
||||
func (x *FinalRuleConfig) GetBlockDelay() *Range {
|
||||
if x != nil {
|
||||
return x.Delay
|
||||
return x.BlockDelay
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FinalRuleConfig) GetLogLevel() log.Severity {
|
||||
if x != nil && x.LogLevel != nil {
|
||||
return *x.LogLevel
|
||||
}
|
||||
return log.Severity(0)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
DomainStrategy internet.DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
|
||||
@@ -532,7 +523,7 @@ var File_proxy_freedom_config_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_proxy_freedom_config_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x1aproxy/freedom/config.proto\x12\x12xray.proxy.freedom\x1a!common/protocol/server_spec.proto\x1a\x1ftransport/internet/config.proto\x1a\x15common/net/port.proto\x1a\x18common/net/network.proto\x1a\x1bcommon/geodata/geodat.proto\x1a\x14common/log/log.proto\"S\n" +
|
||||
"\x1aproxy/freedom/config.proto\x12\x12xray.proxy.freedom\x1a!common/protocol/server_spec.proto\x1a\x1ftransport/internet/config.proto\x1a\x15common/net/port.proto\x1a\x18common/net/network.proto\x1a\x1bcommon/geodata/geodat.proto\"S\n" +
|
||||
"\x13DestinationOverride\x12<\n" +
|
||||
"\x06server\x18\x01 \x01(\v2$.xray.common.protocol.ServerEndpointR\x06server\"\x98\x02\n" +
|
||||
"\bFragment\x12!\n" +
|
||||
@@ -558,16 +549,14 @@ const file_proxy_freedom_config_proto_rawDesc = "" +
|
||||
"\bapply_to\x18\x06 \x01(\tR\aapplyTo\"+\n" +
|
||||
"\x05Range\x12\x10\n" +
|
||||
"\x03min\x18\x01 \x01(\x04R\x03min\x12\x10\n" +
|
||||
"\x03max\x18\x02 \x01(\x04R\x03max\"\xe0\x02\n" +
|
||||
"\x03max\x18\x02 \x01(\x04R\x03max\"\xa0\x02\n" +
|
||||
"\x0fFinalRuleConfig\x126\n" +
|
||||
"\x06action\x18\x01 \x01(\x0e2\x1e.xray.proxy.freedom.RuleActionR\x06action\x124\n" +
|
||||
"\bnetworks\x18\x02 \x03(\x0e2\x18.xray.common.net.NetworkR\bnetworks\x126\n" +
|
||||
"\tport_list\x18\x03 \x01(\v2\x19.xray.common.net.PortListR\bportList\x12+\n" +
|
||||
"\x02ip\x18\x04 \x03(\v2\x1b.xray.common.geodata.IPRuleR\x02ip\x12/\n" +
|
||||
"\x05delay\x18\x05 \x01(\v2\x19.xray.proxy.freedom.RangeR\x05delay\x12;\n" +
|
||||
"\tlog_level\x18\x06 \x01(\x0e2\x19.xray.common.log.SeverityH\x00R\blogLevel\x88\x01\x01B\f\n" +
|
||||
"\n" +
|
||||
"_log_level\"\xaf\x03\n" +
|
||||
"\x02ip\x18\x04 \x03(\v2\x1b.xray.common.geodata.IPRuleR\x02ip\x12:\n" +
|
||||
"\vblock_delay\x18\x05 \x01(\v2\x19.xray.proxy.freedom.RangeR\n" +
|
||||
"blockDelay\"\xaf\x03\n" +
|
||||
"\x06Config\x12P\n" +
|
||||
"\x0fdomain_strategy\x18\x01 \x01(\x0e2'.xray.transport.internet.DomainStrategyR\x0edomainStrategy\x12Z\n" +
|
||||
"\x14destination_override\x18\x03 \x01(\v2'.xray.proxy.freedom.DestinationOverrideR\x13destinationOverride\x12\x1d\n" +
|
||||
@@ -610,8 +599,7 @@ var file_proxy_freedom_config_proto_goTypes = []any{
|
||||
(net.Network)(0), // 8: xray.common.net.Network
|
||||
(*net.PortList)(nil), // 9: xray.common.net.PortList
|
||||
(*geodata.IPRule)(nil), // 10: xray.common.geodata.IPRule
|
||||
(log.Severity)(0), // 11: xray.common.log.Severity
|
||||
(internet.DomainStrategy)(0), // 12: xray.transport.internet.DomainStrategy
|
||||
(internet.DomainStrategy)(0), // 11: xray.transport.internet.DomainStrategy
|
||||
}
|
||||
var file_proxy_freedom_config_proto_depIdxs = []int32{
|
||||
7, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint
|
||||
@@ -619,18 +607,17 @@ var file_proxy_freedom_config_proto_depIdxs = []int32{
|
||||
8, // 2: xray.proxy.freedom.FinalRuleConfig.networks:type_name -> xray.common.net.Network
|
||||
9, // 3: xray.proxy.freedom.FinalRuleConfig.port_list:type_name -> xray.common.net.PortList
|
||||
10, // 4: xray.proxy.freedom.FinalRuleConfig.ip:type_name -> xray.common.geodata.IPRule
|
||||
4, // 5: xray.proxy.freedom.FinalRuleConfig.delay:type_name -> xray.proxy.freedom.Range
|
||||
11, // 6: xray.proxy.freedom.FinalRuleConfig.log_level:type_name -> xray.common.log.Severity
|
||||
12, // 7: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||
1, // 8: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
|
||||
2, // 9: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
|
||||
3, // 10: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
|
||||
5, // 11: xray.proxy.freedom.Config.final_rules:type_name -> xray.proxy.freedom.FinalRuleConfig
|
||||
12, // [12:12] is the sub-list for method output_type
|
||||
12, // [12:12] is the sub-list for method input_type
|
||||
12, // [12:12] is the sub-list for extension type_name
|
||||
12, // [12:12] is the sub-list for extension extendee
|
||||
0, // [0:12] is the sub-list for field type_name
|
||||
4, // 5: xray.proxy.freedom.FinalRuleConfig.block_delay:type_name -> xray.proxy.freedom.Range
|
||||
11, // 6: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||
1, // 7: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
|
||||
2, // 8: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
|
||||
3, // 9: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
|
||||
5, // 10: xray.proxy.freedom.Config.final_rules:type_name -> xray.proxy.freedom.FinalRuleConfig
|
||||
11, // [11:11] is the sub-list for method output_type
|
||||
11, // [11:11] is the sub-list for method input_type
|
||||
11, // [11:11] is the sub-list for extension type_name
|
||||
11, // [11:11] is the sub-list for extension extendee
|
||||
0, // [0:11] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proxy_freedom_config_proto_init() }
|
||||
@@ -638,7 +625,6 @@ func file_proxy_freedom_config_proto_init() {
|
||||
if File_proxy_freedom_config_proto != nil {
|
||||
return
|
||||
}
|
||||
file_proxy_freedom_config_proto_msgTypes[4].OneofWrappers = []any{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
|
||||
@@ -11,7 +11,6 @@ import "transport/internet/config.proto";
|
||||
import "common/net/port.proto";
|
||||
import "common/net/network.proto";
|
||||
import "common/geodata/geodat.proto";
|
||||
import "common/log/log.proto";
|
||||
|
||||
message DestinationOverride {
|
||||
xray.common.protocol.ServerEndpoint server = 1;
|
||||
@@ -52,8 +51,7 @@ message FinalRuleConfig {
|
||||
repeated xray.common.net.Network networks = 2;
|
||||
xray.common.net.PortList port_list = 3;
|
||||
repeated xray.common.geodata.IPRule ip = 4;
|
||||
Range delay = 5;
|
||||
optional xray.common.log.Severity log_level = 6;
|
||||
Range block_delay = 5;
|
||||
}
|
||||
|
||||
message Config {
|
||||
|
||||
+20
-42
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/dice"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/geodata"
|
||||
"github.com/xtls/xray-core/common/log"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/platform"
|
||||
"github.com/xtls/xray-core/common/retry"
|
||||
@@ -73,26 +72,23 @@ func init() {
|
||||
}
|
||||
|
||||
defaultBlockPrivateRule = &FinalRule{
|
||||
action: RuleAction_Block,
|
||||
network: allNetworks,
|
||||
ip: geodata.GetPrivateIPMatcher(),
|
||||
logLevel: log.Severity_Warning.Enum(),
|
||||
action: RuleAction_Block,
|
||||
network: allNetworks,
|
||||
ip: geodata.GetPrivateIPMatcher(),
|
||||
}
|
||||
|
||||
defaultBlockAllRule = &FinalRule{
|
||||
action: RuleAction_Block,
|
||||
network: allNetworks,
|
||||
logLevel: log.Severity_Warning.Enum(),
|
||||
action: RuleAction_Block,
|
||||
network: allNetworks,
|
||||
}
|
||||
}
|
||||
|
||||
type FinalRule struct {
|
||||
action RuleAction
|
||||
network [8]bool
|
||||
port net.MemoryPortList
|
||||
ip geodata.IPMatcher
|
||||
delay *Range
|
||||
logLevel *log.Severity
|
||||
action RuleAction
|
||||
network [8]bool
|
||||
port net.MemoryPortList
|
||||
ip geodata.IPMatcher
|
||||
blockDelay *Range
|
||||
}
|
||||
|
||||
// Handler handles Freedom connections.
|
||||
@@ -106,9 +102,8 @@ type Handler struct {
|
||||
|
||||
func buildFinalRule(config *FinalRuleConfig) (*FinalRule, error) {
|
||||
rule := &FinalRule{
|
||||
action: config.GetAction(),
|
||||
delay: config.GetDelay(),
|
||||
logLevel: config.LogLevel,
|
||||
action: config.GetAction(),
|
||||
blockDelay: config.GetBlockDelay(),
|
||||
}
|
||||
|
||||
if len(config.Networks) == 0 {
|
||||
@@ -169,7 +164,7 @@ func getDefaultFinalRule(inbound *session.Inbound) *FinalRule {
|
||||
switch inbound.Name {
|
||||
case "vless-reverse":
|
||||
return defaultBlockAllRule
|
||||
case "vless", "vmess", "trojan", "hysteria", "wireguard", "masque":
|
||||
case "vless", "vmess", "trojan", "hysteria", "wireguard":
|
||||
return defaultBlockPrivateRule
|
||||
default:
|
||||
if strings.HasPrefix(inbound.Name, "shadowsocks") {
|
||||
@@ -217,12 +212,12 @@ func (h *Handler) policy() policy.Session {
|
||||
return p
|
||||
}
|
||||
|
||||
func (r *FinalRule) blockDuration() time.Duration {
|
||||
func (h *Handler) blockDelay(rule *FinalRule) time.Duration {
|
||||
min := uint64(30)
|
||||
max := uint64(90)
|
||||
if r.delay != nil {
|
||||
min = r.delay.Min
|
||||
max = r.delay.Max
|
||||
if rule.blockDelay != nil {
|
||||
min = rule.blockDelay.Min
|
||||
max = rule.blockDelay.Max
|
||||
}
|
||||
span := max - min
|
||||
if max < min {
|
||||
@@ -231,26 +226,9 @@ func (r *FinalRule) blockDuration() time.Duration {
|
||||
return time.Duration(min+uint64(dice.Roll(int(span+1)))) * time.Second
|
||||
}
|
||||
|
||||
func (r *FinalRule) log(ctx context.Context, msg ...interface{}) {
|
||||
level := log.Severity_Info
|
||||
if r.logLevel != nil {
|
||||
level = *r.logLevel
|
||||
}
|
||||
switch level {
|
||||
case log.Severity_Debug:
|
||||
errors.LogDebug(ctx, msg...)
|
||||
case log.Severity_Info:
|
||||
errors.LogInfo(ctx, msg...)
|
||||
case log.Severity_Warning:
|
||||
errors.LogWarning(ctx, msg...)
|
||||
case log.Severity_Error:
|
||||
errors.LogError(ctx, msg...)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) blackhole(ctx context.Context, input buf.Reader, output buf.Writer, rule *FinalRule, dest *net.Destination) error {
|
||||
delay := rule.blockDuration()
|
||||
rule.log(ctx, "target blocked by a finalrule: ", *dest, ", blackholing connection for ", delay)
|
||||
delay := h.blockDelay(rule)
|
||||
errors.LogInfo(ctx, "blocked target: ", *dest, ", blackholing connection for ", delay)
|
||||
defer common.Close(output)
|
||||
done := make(chan struct{})
|
||||
go func() { // a DispatchLink inbound's reader ignores Interrupt, so don't wait for this copy
|
||||
@@ -262,7 +240,7 @@ func (h *Handler) blackhole(ctx context.Context, input buf.Reader, output buf.Wr
|
||||
case <-time.After(delay):
|
||||
common.Interrupt(input)
|
||||
common.Interrupt(output)
|
||||
rule.log(ctx, "closed blackholed connection to blocked target: ", *dest)
|
||||
errors.LogInfo(ctx, "closed blackholed connection to blocked target: ", *dest)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -201,12 +201,6 @@ startOver:
|
||||
}
|
||||
err = t.luid.SetDNS(family, dns, nil)
|
||||
if err != nil {
|
||||
// Skip IPv6 the config does not ask for also when setting its DNS
|
||||
// servers fails, as reported on Windows 11 24H2 with IPv6 disabled
|
||||
// (Access is denied).
|
||||
if family == windows.AF_INET6 && !address6 && !route6 {
|
||||
continue
|
||||
}
|
||||
firstErr = errors.New("unable to set DNS").Base(err)
|
||||
if err == windows.ERROR_NOT_FOUND {
|
||||
goto startOver
|
||||
|
||||
@@ -254,7 +254,6 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
switch request.Command {
|
||||
case protocol.RequestCommandUDP:
|
||||
if !allowUDP443 && request.Port == 443 {
|
||||
proxy.DropUDP(ctx, link.Reader)
|
||||
return errors.New("XTLS rejected UDP/443 traffic")
|
||||
}
|
||||
case protocol.RequestCommandMux:
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
|
||||
type bind struct {
|
||||
ctx context.Context
|
||||
resolveFunc func(ctx context.Context, host string) (net.IP, error)
|
||||
resolveFunc func(host string) (net.IP, error)
|
||||
listenFunc func(ctx context.Context) (net.PacketConn, error)
|
||||
downFunc func() error
|
||||
reserved []byte
|
||||
@@ -143,11 +143,7 @@ func (b *bind) ParseEndpoint(s string) (conn.Endpoint, error) {
|
||||
if port < 0 || port > 65535 {
|
||||
return nil, errors.New("invalid port " + sport)
|
||||
}
|
||||
// up sets the connection's context right before it hands over the endpoint
|
||||
b.mu.Lock()
|
||||
ctx := b.ctx
|
||||
b.mu.Unlock()
|
||||
ip, err := b.resolveFunc(ctx, host)
|
||||
ip, err := b.resolveFunc(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -323,12 +323,12 @@ func (h *Handler) up(ctx context.Context) error {
|
||||
return h.dev.Up()
|
||||
}
|
||||
|
||||
func MakeResolveLocal(d dns.Client, streamSettings *internet.MemoryStreamConfig) func(ctx context.Context, host string) (net.IP, error) {
|
||||
return func(ctx context.Context, host string) (net.IP, error) {
|
||||
func MakeResolveLocal(d dns.Client, streamSettings *internet.MemoryStreamConfig) func(host string) (net.IP, error) {
|
||||
return func(host string) (net.IP, error) {
|
||||
if ip := net.ParseIP(host); ip != nil {
|
||||
return ip, nil
|
||||
}
|
||||
ips, err := lookupIPContext(ctx, d, host)
|
||||
ips, _, err := d.LookupIP(host, dns.IPOption{IPv4Enable: true, IPv6Enable: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -368,27 +368,6 @@ func MakeResolveLocal(d dns.Client, streamSettings *internet.MemoryStreamConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func lookupIPContext(ctx context.Context, d dns.Client, host string) ([]net.IP, error) {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
type result struct {
|
||||
ips []net.IP
|
||||
err error
|
||||
}
|
||||
done := make(chan result, 1)
|
||||
go func() {
|
||||
ips, _, err := d.LookupIP(host, dns.IPOption{IPv4Enable: true, IPv6Enable: true})
|
||||
done <- result{ips, err}
|
||||
}()
|
||||
select {
|
||||
case r := <-done:
|
||||
return r.ips, r.err
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
type UDPConnClient struct {
|
||||
net.PacketConn
|
||||
Dest *net.UDPAddr
|
||||
|
||||
@@ -661,7 +661,7 @@ func TestVlessRealityFingerprints(t *testing.T) {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// A blocked connection must close after finalRules.delay even while the client keeps it open and sends nothing.
|
||||
// A blocked connection must be closed after blockDelay even while the client keeps it open and sends nothing.
|
||||
func TestVlessBlockDelay(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
@@ -671,7 +671,7 @@ func TestVlessBlockDelay(t *testing.T) {
|
||||
defer tcpServer.Close()
|
||||
|
||||
for _, delay := range []uint64{0, 1} {
|
||||
t.Run(fmt.Sprint("delay=", delay), func(t *testing.T) {
|
||||
t.Run(fmt.Sprint("blockDelay=", delay), func(t *testing.T) {
|
||||
userID := protocol.NewID(uuid.New())
|
||||
serverPort := tcp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
@@ -697,8 +697,8 @@ func TestVlessBlockDelay(t *testing.T) {
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||
FinalRules: []*freedom.FinalRuleConfig{
|
||||
{
|
||||
Action: freedom.RuleAction_Block,
|
||||
Delay: &freedom.Range{Min: delay, Max: delay},
|
||||
Action: freedom.RuleAction_Block,
|
||||
BlockDelay: &freedom.Range{Min: delay, Max: delay},
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -726,15 +726,15 @@ func TestVlessBlockDelay(t *testing.T) {
|
||||
Port: dest.Port,
|
||||
}, &encoding.Addons{}))
|
||||
|
||||
blockDuration := time.Duration(delay) * time.Second
|
||||
common.Must(conn.SetReadDeadline(time.Now().Add(blockDuration + 5*time.Second)))
|
||||
blockDelay := time.Duration(delay) * time.Second
|
||||
common.Must(conn.SetReadDeadline(time.Now().Add(blockDelay + 5*time.Second)))
|
||||
_, err = io.Copy(io.Discard, conn)
|
||||
elapsed := time.Since(start)
|
||||
if err, ok := err.(net.Error); ok && err.Timeout() {
|
||||
t.Fatalf("connection is still open after %v", elapsed)
|
||||
}
|
||||
if elapsed < blockDuration {
|
||||
t.Fatalf("connection is closed after %v, before finalRules.delay", elapsed)
|
||||
if elapsed < blockDelay {
|
||||
t.Fatalf("connection is closed after %v, before blockDelay", elapsed)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
goerrors "errors"
|
||||
"io"
|
||||
mrand "math/rand"
|
||||
stdnet "net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -165,7 +164,7 @@ func (c *udpHopConn) recv(conn net.PacketConn) {
|
||||
n, addr, err := conn.ReadFrom(p)
|
||||
if err != nil {
|
||||
pool.Put(p[:cap(p)])
|
||||
if c.closed() || goerrors.Is(err, stdnet.ErrClosed) {
|
||||
if c.closed() {
|
||||
return
|
||||
}
|
||||
var netErr net.Error
|
||||
|
||||
Reference in New Issue
Block a user