Compare commits

..
2 Commits
Author SHA1 Message Date
Fangliding 4d08386da3 simplify 2026-10-30 20:31:13 +08:00
Fangliding 0fdb276fb7 Disable default MPTCP listener 2026-10-30 04:13:11 +08:00
110 changed files with 313 additions and 719 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/commander/config.proto // source: app/commander/config.proto
package commander package commander
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/dispatcher/config.proto // source: app/dispatcher/config.proto
package dispatcher package dispatcher
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/dns/config.proto // source: app/dns/config.proto
package dns package dns
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/dns/fakedns/fakedns.proto // source: app/dns/fakedns/fakedns.proto
package fakedns package fakedns
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/geodata/config.proto // source: app/geodata/config.proto
package geodata package geodata
+1 -18
View File
@@ -1,8 +1,6 @@
package geodata package geodata
import ( import (
"bufio"
"compress/gzip"
"context" "context"
"crypto/tls" "crypto/tls"
go_errors "errors" go_errors "errors"
@@ -199,22 +197,7 @@ func (d *downloader) fetch(rawURL string, writer io.Writer) error {
return errors.New("geodata download exceeds 256 MiB") return errors.New("geodata download exceeds 256 MiB")
} }
br := bufio.NewReader(resp.Body) n, err := io.Copy(writer, io.LimitReader(resp.Body, maxDownloadSize+1))
header, err := br.Peek(2)
if err != nil && err != io.EOF {
return err
}
var body io.Reader = br
if len(header) == 2 && header[0] == 0x1f && header[1] == 0x8b {
zr, err := gzip.NewReader(br)
if err != nil {
return err
}
defer zr.Close()
body = zr
}
n, err := io.Copy(writer, io.LimitReader(body, maxDownloadSize+1))
if err != nil { if err != nil {
return err return err
} }
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/log/command/config.proto // source: app/log/command/config.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.6.2 // - protoc-gen-go-grpc v1.6.0
// - protoc (unknown) // - protoc v6.33.5
// source: app/log/command/config.proto // source: app/log/command/config.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/log/config.proto // source: app/log/config.proto
package log package log
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/metrics/config.proto // source: app/metrics/config.proto
package metrics package metrics
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/observatory/burst/config.proto // source: app/observatory/burst/config.proto
package burst package burst
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/observatory/command/command.proto // source: app/observatory/command/command.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.6.2 // - protoc-gen-go-grpc v1.6.0
// - protoc (unknown) // - protoc v6.33.5
// source: app/observatory/command/command.proto // source: app/observatory/command/command.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/observatory/config.proto // source: app/observatory/config.proto
package observatory package observatory
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/policy/config.proto // source: app/policy/config.proto
package policy package policy
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/proxyman/command/command.proto // source: app/proxyman/command/command.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.6.2 // - protoc-gen-go-grpc v1.6.0
// - protoc (unknown) // - protoc v6.33.5
// source: app/proxyman/command/command.proto // source: app/proxyman/command/command.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/proxyman/config.proto // source: app/proxyman/config.proto
package proxyman package proxyman
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/reverse/config.proto // source: app/reverse/config.proto
package reverse package reverse
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/router/command/command.proto // source: app/router/command/command.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.6.2 // - protoc-gen-go-grpc v1.6.0
// - protoc (unknown) // - protoc v6.33.5
// source: app/router/command/command.proto // source: app/router/command/command.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/router/config.proto // source: app/router/config.proto
package router package router
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/stats/command/command.proto // source: app/stats/command/command.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.6.2 // - protoc-gen-go-grpc v1.6.0
// - protoc (unknown) // - protoc v6.33.5
// source: app/stats/command/command.proto // source: app/stats/command/command.proto
package command package command
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/stats/config.proto // source: app/stats/config.proto
package stats package stats
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: app/version/config.proto // source: app/version/config.proto
package version package version
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/geodata/geodat.proto // source: common/geodata/geodat.proto
package geodata package geodata
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/log/log.proto // source: common/log/log.proto
package log package log
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/net/address.proto // source: common/net/address.proto
package net package net
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/net/destination.proto // source: common/net/destination.proto
package net package net
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/net/network.proto // source: common/net/network.proto
package net package net
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/net/port.proto // source: common/net/port.proto
package net package net
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/protocol/headers.proto // source: common/protocol/headers.proto
package protocol package protocol
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/protocol/server_spec.proto // source: common/protocol/server_spec.proto
package protocol package protocol
-4
View File
@@ -101,10 +101,6 @@ func ReadClientHello(data []byte, h *SniffHeader) error {
return errNotClientHello return errNotClientHello
} }
if nameType == 0 { if nameType == 0 {
// RFC 6066 requires a non-empty HostName.
if nameLen == 0 {
return errNotClientHello
}
// QUIC separated across packets // QUIC separated across packets
// May cause the serverName to be incomplete // May cause the serverName to be incomplete
b := byte(0) b := byte(0)
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/protocol/user.proto // source: common/protocol/user.proto
package protocol package protocol
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: common/serial/typed_message.proto // source: common/serial/typed_message.proto
package serial package serial
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: core/config.proto // source: core/config.proto
package core package core
+1 -1
View File
@@ -20,7 +20,7 @@ import (
var ( var (
Version_x byte = 26 Version_x byte = 26
Version_y byte = 10 Version_y byte = 10
Version_z byte = 31 Version_z byte = 29
) )
var ( var (
+2 -2
View File
@@ -33,7 +33,7 @@ require (
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb
golang.zx2c4.com/wireguard/windows v1.1.1 golang.zx2c4.com/wireguard/windows v1.1.1
google.golang.org/grpc v1.84.0 google.golang.org/grpc v1.84.0
google.golang.org/protobuf v1.36.12 google.golang.org/protobuf v1.36.11
h12.io/socks v1.0.3 h12.io/socks v1.0.3
layeh.com/gopher-luar v1.0.11 layeh.com/gopher-luar v1.0.11
lukechampine.com/blake3 v1.4.1 lukechampine.com/blake3 v1.4.1
@@ -59,7 +59,7 @@ require (
golang.org/x/text v0.43.0 // indirect golang.org/x/text v0.43.0 // indirect
golang.org/x/tools v0.51.0 // indirect golang.org/x/tools v0.51.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260706201446-f0a921348800 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260706201446-f0a921348800 // indirect
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.2 // indirect google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0 // indirect gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0 // indirect
) )
+4 -2
View File
@@ -154,8 +154,10 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20260706201446-f0a921348800 h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20260706201446-f0a921348800/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260706201446-f0a921348800/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0= google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0=
google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0= google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.2 h1:rgSNvqscFZ1JgV/4wH5GOsZFSFkR2Eua9As3KIr2LlM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.0 h1:6Al3kEFFP9VJhRz3DID6quisgPnTeZVr4lep9kkxdPA=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.2/go.mod h1:iMEtFwDlAhjDU9L5mY6U1XLwlIId/G3h+QcBHDIvrJ8= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.0/go.mod h1:QLvsjh0OIR0TYBeiu2bkWGTJBUNQ64st52iWj/yA93I=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-2
View File
@@ -293,7 +293,6 @@ type SplitHTTPConfig struct {
ServerMaxHeaderBytes int32 `json:"serverMaxHeaderBytes"` ServerMaxHeaderBytes int32 `json:"serverMaxHeaderBytes"`
Xmux XmuxConfig `json:"xmux"` Xmux XmuxConfig `json:"xmux"`
DownloadSettings *StreamConfig `json:"downloadSettings"` DownloadSettings *StreamConfig `json:"downloadSettings"`
H2Params json.RawMessage `json:"h2Params"`
Extra json.RawMessage `json:"extra"` Extra json.RawMessage `json:"extra"`
} }
@@ -496,7 +495,6 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
ServerMaxHeaderBytes: c.ServerMaxHeaderBytes, ServerMaxHeaderBytes: c.ServerMaxHeaderBytes,
SessionIDTable: c.SessionIDTable, SessionIDTable: c.SessionIDTable,
SessionIDLength: newRangeConfig(c.SessionIDLength), SessionIDLength: newRangeConfig(c.SessionIDLength),
H2Params: c.H2Params,
Xmux: &splithttp.XmuxConfig{ Xmux: &splithttp.XmuxConfig{
MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency), MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency),
MaxConnections: newRangeConfig(c.Xmux.MaxConnections), MaxConnections: newRangeConfig(c.Xmux.MaxConnections),
+15 -10
View File
@@ -6,7 +6,9 @@ import (
"math/big" "math/big"
"net" "net"
"runtime" "runtime"
"slices"
"strconv" "strconv"
"strings"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/proxy/tun" "github.com/xtls/xray-core/proxy/tun"
@@ -37,22 +39,25 @@ func (v *TunConfig) Build() (proto.Message, error) {
AutoSystemRoutingTable: v.AutoSystemRoutingTable, AutoSystemRoutingTable: v.AutoSystemRoutingTable,
AutoSystemDnsToGateway: v.AutoSystemDnsToGateway, AutoSystemDnsToGateway: v.AutoSystemDnsToGateway,
} }
leaks, err := tun.ExpandWfpBlockLeak(v.AutoSystemWfpBlockLeak) for _, leak := range v.AutoSystemWfpBlockLeak {
if err != nil { switch leak := strings.ToLower(leak); leak {
return nil, err case "dns", "misconfigtun":
config.AutoSystemWfpBlockLeak = append(config.AutoSystemWfpBlockLeak, leak)
default:
return nil, errors.New("unknown autoSystemWfpBlockLeak value: ", leak)
}
} }
config.AutoSystemWfpBlockLeak = leaks
// Each option needs other settings on the system it takes effect on: the // Each option needs other settings on the system it takes effect on: the
// filters go along with the routes of autoSystemRoutingTable, keeping the // filters go along with the routes of autoSystemRoutingTable, "dns" lets
// system's DNS inside the TUN needs DNS servers on it, and // DNS through the TUN only, and autoSystemDnsToGateway points the system
// autoSystemDnsToGateway points the system DNS at the gateway. // DNS at the gateway.
switch runtime.GOOS { switch runtime.GOOS {
case "windows": case "windows":
if len(leaks) > 0 && len(v.AutoSystemRoutingTable) == 0 { if len(config.AutoSystemWfpBlockLeak) > 0 && len(v.AutoSystemRoutingTable) == 0 {
return nil, errors.New("autoSystemWfpBlockLeak needs autoSystemRoutingTable to be set") return nil, errors.New("autoSystemWfpBlockLeak needs autoSystemRoutingTable to be set")
} }
if tun.BlocksSystemDNS(leaks) && len(v.DNS) == 0 { if slices.Contains(config.AutoSystemWfpBlockLeak, "dns") && len(v.DNS) == 0 {
return nil, errors.New(`autoSystemWfpBlockLeak "dns", "udp/53", "tcp/53" or "windnsclient" needs dns to be set`) return nil, errors.New(`autoSystemWfpBlockLeak "dns" needs dns to be set`)
} }
case "linux", "freebsd": case "linux", "freebsd":
if v.AutoSystemDnsToGateway && len(v.Gateway) == 0 { if v.AutoSystemDnsToGateway && len(v.Gateway) == 0 {
+8 -18
View File
@@ -29,17 +29,12 @@ func TestTunConfigAutoSystem(t *testing.T) {
{ {
Input: `{"name": "xray0", "dns": ["1.1.1.1"], "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["dns", "misconfigtun"]}`, Input: `{"name": "xray0", "dns": ["1.1.1.1"], "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["dns", "misconfigtun"]}`,
Parser: loadJSON(creator), Parser: loadJSON(creator),
Output: &tun.Config{Name: "xray0", Desc: "Wintun", MTU: 1500, DNS: []string{"1.1.1.1"}, AutoSystemRoutingTable: []string{"0.0.0.0/0"}, AutoOutboundsInterface: "auto", AutoSystemWfpBlockLeak: []string{"udp/53", "tcp/53", "windnsclient", "tcp/853", "udp/853", "misconfigtun"}}, Output: &tun.Config{Name: "xray0", Desc: "Wintun", MTU: 1500, DNS: []string{"1.1.1.1"}, AutoSystemRoutingTable: []string{"0.0.0.0/0"}, AutoOutboundsInterface: "auto", AutoSystemWfpBlockLeak: []string{"dns", "misconfigtun"}},
}, },
{ {
Input: `{"name": "xray0", "dns": ["1.1.1.1"], "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["DNS"]}`, Input: `{"name": "xray0", "dns": ["1.1.1.1"], "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["DNS"]}`,
Parser: loadJSON(creator), Parser: loadJSON(creator),
Output: &tun.Config{Name: "xray0", Desc: "Wintun", MTU: 1500, DNS: []string{"1.1.1.1"}, AutoSystemRoutingTable: []string{"0.0.0.0/0"}, AutoOutboundsInterface: "auto", AutoSystemWfpBlockLeak: []string{"udp/53", "tcp/53", "windnsclient", "tcp/853", "udp/853"}}, Output: &tun.Config{Name: "xray0", Desc: "Wintun", MTU: 1500, DNS: []string{"1.1.1.1"}, AutoSystemRoutingTable: []string{"0.0.0.0/0"}, AutoOutboundsInterface: "auto", AutoSystemWfpBlockLeak: []string{"dns"}},
},
{
Input: `{"name": "xray0", "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["TCP/853", "udp/853", "tcp/0853"]}`,
Parser: loadJSON(creator),
Output: &tun.Config{Name: "xray0", Desc: "Wintun", MTU: 1500, AutoSystemRoutingTable: []string{"0.0.0.0/0"}, AutoOutboundsInterface: "auto", AutoSystemWfpBlockLeak: []string{"tcp/853", "udp/853"}},
}, },
}) })
} }
@@ -54,9 +49,6 @@ func TestTunConfigAutoSystemNeeds(t *testing.T) {
{`{"name": "xray0", "autoSystemWfpBlockLeak": ["misconfigtun"]}`, []string{"windows"}}, {`{"name": "xray0", "autoSystemWfpBlockLeak": ["misconfigtun"]}`, []string{"windows"}},
{`{"name": "xray0", "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["misconfigtun"]}`, nil}, {`{"name": "xray0", "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["misconfigtun"]}`, nil},
{`{"name": "xray0", "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["dns"]}`, []string{"windows"}}, {`{"name": "xray0", "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["dns"]}`, []string{"windows"}},
{`{"name": "xray0", "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["udp/53"]}`, []string{"windows"}},
{`{"name": "xray0", "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["windnsclient"]}`, []string{"windows"}},
{`{"name": "xray0", "autoSystemRoutingTable": ["0.0.0.0/0"], "autoSystemWfpBlockLeak": ["tcp/853", "udp/853"]}`, nil},
{`{"name": "xray0", "autoSystemDnsToGateway": true}`, []string{"linux", "freebsd"}}, {`{"name": "xray0", "autoSystemDnsToGateway": true}`, []string{"linux", "freebsd"}},
} { } {
config := new(TunConfig) config := new(TunConfig)
@@ -70,13 +62,11 @@ func TestTunConfigAutoSystemNeeds(t *testing.T) {
} }
func TestTunConfigAutoSystemWfpBlockLeakUnknown(t *testing.T) { func TestTunConfigAutoSystemWfpBlockLeakUnknown(t *testing.T) {
for _, value := range []string{"ip", "tcp/0", "icmp/1"} { config := new(TunConfig)
config := new(TunConfig) if err := json.Unmarshal([]byte(`{"name": "xray0", "autoSystemWfpBlockLeak": ["dns", "ip"]}`), config); err != nil {
if err := json.Unmarshal([]byte(`{"name": "xray0", "autoSystemWfpBlockLeak": ["dns", "`+value+`"]}`), config); err != nil { t.Fatal(err)
t.Fatal(err) }
} if _, err := config.Build(); err == nil {
if _, err := config.Build(); err == nil { t.Error("an unknown autoSystemWfpBlockLeak value was accepted")
t.Errorf("autoSystemWfpBlockLeak value %q was accepted", value)
}
} }
} }
+20 -18
View File
@@ -117,7 +117,7 @@ func main() {
} }
var protoFiles []string var protoFiles []string
var existingPbFiles []string var pbCount int
err := filepath.WalkDir(pwd, func(path string, d fs.DirEntry, err error) error { err := filepath.WalkDir(pwd, func(path string, d fs.DirEntry, err error) error {
if err != nil || d.IsDir() { if err != nil || d.IsDir() {
return err return err
@@ -127,7 +127,7 @@ func main() {
protoFiles = append(protoFiles, filepath.ToSlash(rel)) protoFiles = append(protoFiles, filepath.ToSlash(rel))
} }
if strings.HasSuffix(d.Name(), ".pb.go") { if strings.HasSuffix(d.Name(), ".pb.go") {
existingPbFiles = append(existingPbFiles, path) pbCount++
} }
return nil return nil
}) })
@@ -135,6 +135,13 @@ func main() {
fmt.Println("Walk error:", err) fmt.Println("Walk error:", err)
os.Exit(1) os.Exit(1)
} }
if len(protoFiles) == 0 {
if isCheck && pbCount > 0 {
fmt.Fprintf(os.Stderr, "Found %d .pb.go files without any .proto files. Remove these orphaned files.\n", pbCount)
os.Exit(1)
}
return
}
compiler := protocompile.Compiler{ compiler := protocompile.Compiler{
Resolver: protocompile.WithStandardImports(&protocompile.SourceResolver{ Resolver: protocompile.WithStandardImports(&protocompile.SourceResolver{
@@ -156,8 +163,14 @@ func main() {
req := &pluginpb.CodeGeneratorRequest{ req := &pluginpb.CodeGeneratorRequest{
FileToGenerate: protoFiles, FileToGenerate: protoFiles,
Parameter: new("paths=source_relative"), Parameter: proto.String("paths=source_relative"),
ProtoFile: topoSort(fdList), ProtoFile: topoSort(fdList),
// TODO: replace with unknown in the future
CompilerVersion: &pluginpb.Version{
Major: proto.Int32(6),
Minor: proto.Int32(33),
Patch: proto.Int32(5),
},
} }
var diffCount int var diffCount int
@@ -210,22 +223,11 @@ func main() {
} }
} }
for _, path := range existingPbFiles {
if _, ok := generatedFiles[path]; !ok {
diffCount++
if isCheck {
fmt.Printf("Orphaned Protobuf file: %s\n", path)
} else {
fmt.Printf("Removing orphaned Protobuf file: %s\n", path)
if err := os.Remove(path); err != nil {
fmt.Fprintf(os.Stderr, "Error removing %s: %v\n", path, err)
os.Exit(1)
}
}
}
}
if isCheck { if isCheck {
if pbCount != len(generatedFiles) {
fmt.Printf("Protobuf file count mismatch: found %d, expected %d. Remove orphaned files and regenerate.\n", pbCount, len(generatedFiles))
diffCount++
}
if diffCount > 0 { if diffCount > 0 {
fmt.Println("Protobuf generated file problem(s) found.") fmt.Println("Protobuf generated file problem(s) found.")
fmt.Println("Please run 'go run ./infra/vprotogen' to regenerate them.") fmt.Println("Please run 'go run ./infra/vprotogen' to regenerate them.")
+11 -12
View File
@@ -47,19 +47,18 @@ func executeBalancerInfo(cmd *base.Command, args []string) {
conn, ctx, close := dialAPIServer() conn, ctx, close := dialAPIServer()
defer close() defer close()
client := routerService.NewRoutingServiceClient(conn) client := routerService.NewRoutingServiceClient(conn)
for _, tag := range unnamedArgs { r := &routerService.GetBalancerInfoRequest{Tag: unnamedArgs[0]}
r := &routerService.GetBalancerInfoRequest{Tag: tag} resp, err := client.GetBalancerInfo(ctx, r)
resp, err := client.GetBalancerInfo(ctx, r) if err != nil {
if err != nil { base.Fatalf("failed to get health information: %s", err)
base.Fatalf("failed to get health information: %s", err)
}
if apiJSON {
showJSONResponse(resp)
} else {
showBalancerInfo(resp.Balancer)
}
} }
if apiJSON {
showJSONResponse(resp)
return
}
showBalancerInfo(resp.Balancer)
} }
func showBalancerInfo(b *routerService.BalancerMsg) { func showBalancerInfo(b *routerService.BalancerMsg) {
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/blackhole/config.proto // source: proxy/blackhole/config.proto
package blackhole package blackhole
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/dns/config.proto // source: proxy/dns/config.proto
package dns package dns
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/dokodemo/config.proto // source: proxy/dokodemo/config.proto
package dokodemo package dokodemo
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/freedom/config.proto // source: proxy/freedom/config.proto
package freedom package freedom
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/http/config.proto // source: proxy/http/config.proto
package http package http
+2 -3
View File
@@ -312,9 +312,8 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
// Sometimes, server might send 1xx response to client // Sometimes, server might send 1xx response to client
// it should not be processed by http proxy handler, just forward it to client // it should not be processed by http proxy handler, just forward it to client
func readResponseAndHandle100Continue(r *bufio.Reader, req *http.Request, writer io.Writer) (*http.Response, error) { func readResponseAndHandle100Continue(r *bufio.Reader, req *http.Request, writer io.Writer) (*http.Response, error) {
// Wait for the HTTP/1.x status prefix before inspecting the buffered response. // have a little look of response
r.Peek(12) peekBytes, err := r.Peek(56)
peekBytes, err := r.Peek(min(56, r.Buffered()))
if err == nil || err == bufio.ErrBufferFull { if err == nil || err == bufio.ErrBufferFull {
str := string(peekBytes) str := string(peekBytes)
ResponseLine := strings.Split(str, "\r\n")[0] ResponseLine := strings.Split(str, "\r\n")[0]
+1 -2
View File
@@ -7,7 +7,6 @@ import (
"net/http" "net/http"
"strings" "strings"
"testing" "testing"
"testing/iotest"
) )
// A malformed upstream response containing a bare '\n' before the real // A malformed upstream response containing a bare '\n' before the real
@@ -30,7 +29,7 @@ func TestReadResponseAndHandle100ContinueDoesNotPanicOnEarlyNewline(t *testing.T
func TestReadResponseAndHandle100ContinueForwardsAndParsesFinalResponse(t *testing.T) { func TestReadResponseAndHandle100ContinueForwardsAndParsesFinalResponse(t *testing.T) {
payload := "HTTP/1.1 100 Continue\r\n\r\n" + payload := "HTTP/1.1 100 Continue\r\n\r\n" +
"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello" "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello"
r := bufio.NewReader(iotest.OneByteReader(bytes.NewReader([]byte(payload)))) r := bufio.NewReader(bytes.NewReader([]byte(payload)))
req, err := http.NewRequest("GET", "http://example.com/", nil) req, err := http.NewRequest("GET", "http://example.com/", nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/hysteria/account/config.proto // source: proxy/hysteria/account/config.proto
package account package account
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/hysteria/config.proto // source: proxy/hysteria/config.proto
package hysteria package hysteria
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/loopback/config.proto // source: proxy/loopback/config.proto
package loopback package loopback
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/masque/config.proto // source: proxy/masque/config.proto
package masque package masque
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/shadowsocks/config.proto // source: proxy/shadowsocks/config.proto
package shadowsocks package shadowsocks
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/shadowsocks_2022/config.proto // source: proxy/shadowsocks_2022/config.proto
package shadowsocks_2022 package shadowsocks_2022
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/socks/config.proto // source: proxy/socks/config.proto
package socks package socks
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/trojan/config.proto // source: proxy/trojan/config.proto
package trojan package trojan
+4 -15
View File
@@ -23,10 +23,6 @@ For more advanced routing policies or rules, OS level configuration can still ma
This keeps complex system level routing and rules in a single place of responsibility - the OS itself. \ This keeps complex system level routing and rules in a single place of responsibility - the OS itself. \
Examples of how to achieve this on a simple Linux system (Ubuntu with systemd-networkd) can be found at the end of this README. Examples of how to achieve this on a simple Linux system (Ubuntu with systemd-networkd) can be found at the end of this README.
Packets are handled by Xray-core's own lightweight TCP/IP stack, which replaced gVisor (XTLS/Xray-core#7130).
With `autoSystemRoutingTable`, Xray's own connections are kept out of the TUN through `autoOutboundsInterface` (then `"auto"` by default): each of their sockets is bound to another interface, the one named there, or with `"auto"` the one of the default route (Android needs the name). Linux and Android bind with `SO_BINDTODEVICE`, Windows with `IP_UNICAST_IF` and `IPV6_UNICAST_IF`, macOS and iOS with `IP_BOUND_IF` and `IPV6_BOUND_IF`, and FreeBSD switches them to another routing table (see [FreeBSD SUPPORT](#freebsd-support)). Connections to loopback addresses, TCP and UDP, stay unbound. If a socket cannot be bound, the connection fails rather than leave unbound, where it could loop back into the TUN (XTLS/Xray-core#7173).
### SYSTEM DNS ON LINUX AND FREEBSD (`autoSystemDnsToGateway`) ### SYSTEM DNS ON LINUX AND FREEBSD (`autoSystemDnsToGateway`)
On Linux and FreeBSD, setting `autoSystemDnsToGateway` to `true` lets the inbound point the system resolver at the tun interface, so name lookups resolve through Xray instead of going out over the physical link. It is off by default, and it exists only on those two systems. This section describes Linux; the FreeBSD differences follow in [SYSTEM DNS ON FREEBSD](#system-dns-on-freebsd). On Linux and FreeBSD, setting `autoSystemDnsToGateway` to `true` lets the inbound point the system resolver at the tun interface, so name lookups resolve through Xray instead of going out over the physical link. It is off by default, and it exists only on those two systems. This section describes Linux; the FreeBSD differences follow in [SYSTEM DNS ON FREEBSD](#system-dns-on-freebsd).
@@ -219,16 +215,12 @@ All in all systemd-networkd and its derivatives (like netplan or NetworkManager)
Windows version of the same functionality is implemented through Wintun library. \ Windows version of the same functionality is implemented through Wintun library. \
To make it start, wintun.dll specific for your Windows/arch must be present next to Xray.exe binary. To make it start, wintun.dll specific for your Windows/arch must be present next to Xray.exe binary.
After the start network adapter with the name you chose in the config will be created in the system, and exist while Xray is running. A Wintun adapter that already has that name is reused. After the start network adapter with the name you chose in the config will be created in the system, and exist while Xray is running.
With IPv6 disabled system-wide (the `DisabledComponents` registry value), the adapter has no IPv6, and the TUN starts with IPv4 only, unless `gateway` or `autoSystemRoutingTable` has IPv6 entries, which then keep it from starting.
When `dns` is set, those servers are applied to the adapter. Windows is kept from registering the TUN's addresses in DNS, and its DNS cache is flushed when the TUN starts and stops. When `dns` is set, those servers are applied to the adapter. Windows is kept from registering the TUN's addresses in DNS, and its DNS cache is flushed when the TUN starts and stops.
With `autoSystemWfpBlockLeak`, which needs `autoSystemRoutingTable` (the config is rejected otherwise), Xray also adds Windows Filtering Platform filters that keep traffic of every program but Xray itself from leaving outside the TUN, each kind chosen by a value in the list, e.g. `"autoSystemWfpBlockLeak": ["dns", "misconfigtun"]`: With `autoSystemWfpBlockLeak`, which needs `autoSystemRoutingTable` (the config is rejected otherwise), Xray also adds Windows Filtering Platform filters that keep two kinds of traffic of every program but Xray itself from leaving outside the TUN, each chosen by a value in the list, e.g. `"autoSystemWfpBlockLeak": ["dns", "misconfigtun"]`:
- `"tcp/<port>"`, `"udp/<port>"`: connections to that TCP or UDP port only go through the TUN, e.g. `"tcp/853"`. - `"dns"` (needs `dns`, the config is rejected otherwise): DNS (port 53) only goes through the TUN. Windows keeps sending name queries to the DNS servers of the other interfaces as well, out through those interfaces whatever the routes say, and other programs reach a resolver on the local network (e.g. `192.168.1.1` handed out by DHCP) through its more specific LAN route instead of the TUN. On Windows 11 and Server 2022 and later, where those queries may also go over HTTPS or TLS, Windows' DNS Client service cannot connect outside the TUN at all, except for name resolution on the local network (LLMNR, mDNS). The `dns` servers therefore have to lie within `gateway` or `autoSystemRoutingTable` (a warning is logged otherwise), and DNS servers that should be reached directly belong in Xray's own `dns` settings.
- `"windnsclient"`: Windows' DNS Client service cannot connect outside the TUN at all, except for name resolution on the local network (LLMNR, mDNS). On Windows 11 and Server 2022 and later, it may send name queries over HTTPS or TLS, to any port. Earlier versions only query port 53, so there it does nothing.
- `"dns"`: stands for `"udp/53"`, `"tcp/53"`, `"windnsclient"`, `"tcp/853"` (DNS over TLS) and `"udp/853"` (DNS over QUIC). Windows keeps sending name queries to the DNS servers of the other interfaces as well, out through those interfaces whatever the routes say, and other programs reach a resolver on the local network (e.g. `192.168.1.1` handed out by DHCP) through its more specific LAN route instead of the TUN. Keeping the system's DNS inside the TUN like this, with `"dns"`, `"udp/53"`, `"tcp/53"` or `"windnsclient"`, needs `dns` (the config is rejected otherwise). The `dns` servers then have to lie within `gateway` or `autoSystemRoutingTable` (a warning is logged otherwise), and DNS servers that should be reached directly belong in Xray's own `dns` settings.
- `"misconfigtun"`: an IP version without routes in `autoSystemRoutingTable`, IPv4 or IPv6, is blocked entirely, in both directions, as it would bypass the TUN. Only loopback and what Windows itself needs on the local link (DHCP, and for IPv6 neighbor and multicast listener discovery) remain allowed. An address of that version in `gateway` is not needed: without one, Windows gives the TUN link-local addresses itself, an IPv6 one at once and an IPv4 one from `169.254.0.0/16` after some seconds (until then, IPv4 routed to the TUN is unreachable), and what is routed to the TUN goes through it with those. - `"misconfigtun"`: an IP version without routes in `autoSystemRoutingTable`, IPv4 or IPv6, is blocked entirely, in both directions, as it would bypass the TUN. Only loopback and what Windows itself needs on the local link (DHCP, and for IPv6 neighbor and multicast listener discovery) remain allowed. An address of that version in `gateway` is not needed: without one, Windows gives the TUN link-local addresses itself, an IPv6 one at once and an IPv4 one from `169.254.0.0/16` after some seconds (until then, IPv4 routed to the TUN is unreachable), and what is routed to the TUN goes through it with those.
With the filters in place, Xray's own connections out also get past Windows Firewall's block rules (other firewalls may still block them), while connections to Xray's inbounds stay subject to them. With the filters in place, Xray's own connections out also get past Windows Firewall's block rules (other firewalls may still block them), while connections to Xray's inbounds stay subject to them.
@@ -241,8 +233,6 @@ If the filters cannot be added, Xray does not start. They are removed when Xray
`autoOutboundsInterface` (the default with `autoSystemRoutingTable`) keeps Xray's own connections out of the TUN by binding them to another interface, which Windows only honors while that interface has weak host send and forwarding off for the IP versions routed to the TUN. Otherwise, Windows sends them into the TUN, from that interface's address, and they stall. While the TUN runs, Xray therefore turns weak host send off on that interface, and on again when it stops or another interface takes over. Forwarding cannot be turned off this way, as Mobile Hotspot and Internet Connection Sharing need it, so a warning is logged while it is on. Having the hotspot share the TUN instead of that interface (Settings, Mobile hotspot, Share my internet connection from) moves forwarding to the TUN, where it does no harm, and sends the hotspot's devices through Xray as well. `autoOutboundsInterface` (the default with `autoSystemRoutingTable`) keeps Xray's own connections out of the TUN by binding them to another interface, which Windows only honors while that interface has weak host send and forwarding off for the IP versions routed to the TUN. Otherwise, Windows sends them into the TUN, from that interface's address, and they stall. While the TUN runs, Xray therefore turns weak host send off on that interface, and on again when it stops or another interface takes over. Forwarding cannot be turned off this way, as Mobile Hotspot and Internet Connection Sharing need it, so a warning is logged while it is on. Having the hotspot share the TUN instead of that interface (Settings, Mobile hotspot, Share my internet connection from) moves forwarding to the TUN, where it does no harm, and sends the hotspot's devices through Xray as well.
An outbound interface with only IPv4 or only IPv6 works as well: a UDP socket opened for both IP versions, which such an interface cannot be bound to, is opened again for the destination's version only, and IPv6 TCP is bound for IPv6 alone, so connections of the missing version fail rather than leave through another interface (XTLS/Xray-core#7214).
You can give the adapter ip address manually, you can live Windows to give it autogenerated ip address (which take few seconds), it doesn't matter, the traffic going _through_ the interface will be forwarded into the app for proxying. \ You can give the adapter ip address manually, you can live Windows to give it autogenerated ip address (which take few seconds), it doesn't matter, the traffic going _through_ the interface will be forwarded into the app for proxying. \
Minimal configuration that will work for local machine is routing passing the traffic on-link through the interface. Minimal configuration that will work for local machine is routing passing the traffic on-link through the interface.
You will need the interface id for that, unfortunately it is going to change with every Xray start due to implementation ambiguity between Xray and wintun driver. You will need the interface id for that, unfortunately it is going to change with every Xray start due to implementation ambiguity between Xray and wintun driver.
@@ -317,7 +307,6 @@ sudo route add -inet6 -host 2606:4700:4700::1111 -iface utun10
sudo route add -inet6 -host 2606:4700:4700::1001 -iface utun10 sudo route add -inet6 -host 2606:4700:4700::1001 -iface utun10
``` ```
Alternatively, configure `autoSystemRoutingTable` and Xray will add and remove those system routes while it is running. Alternatively, configure `autoSystemRoutingTable` and Xray will add and remove those system routes while it is running.
Xray's own connections are then kept out of the TUN through `autoOutboundsInterface`: an IPv4 socket is bound with `IP_BOUND_IF`, an IPv6 or dual-stack one with `IPV6_BOUND_IF`, which covers the IPv4 traffic of a dual-stack socket as well, since macOS rejects `IP_BOUND_IF` on IPv6 sockets (XTLS/Xray-core#7230).
Important to remember that everything written above about Linux routing concept, also apply to Mac OS X. If you simply route default route through utun interface, that will result network loop and immediate network failure. Important to remember that everything written above about Linux routing concept, also apply to Mac OS X. If you simply route default route through utun interface, that will result network loop and immediate network failure.
## ANDROID SUPPORT ## ANDROID SUPPORT
@@ -349,7 +338,7 @@ let tunFd = ((0 ... 1024).first { (_ fd: Int32) -> Bool in var len = socklen_t(b
}! }!
``` ```
Set the environment variable `xray.tun.fd` (or `XRAY_TUN_FD`) to the fd number before starting Xray. This can be done from Swift/Objective-C or by exposing a Go function via gomobile bindings. Xray works on a duplicate of the fd and closes only that, so the fd itself stays NetworkExtension's (XTLS/Xray-core#6883). Set the environment variable `xray.tun.fd` (or `XRAY_TUN_FD`) to the fd number before starting Xray. This can be done from Swift/Objective-C or by exposing a Go function via gomobile bindings.
Build using gomobile for iOS framework integration: Build using gomobile for iOS framework integration:
``` ```
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/tun/config.proto // source: proxy/tun/config.proto
package tun package tun
+22 -23
View File
@@ -247,31 +247,30 @@ startOver:
} }
// With autoSystemWfpBlockLeak, once the system routes lead to the TUN, // With autoSystemWfpBlockLeak, once the system routes lead to the TUN,
// keep connections to the ports given ("dns" stands for those of DNS), // keep DNS ("dns", if dns is set), and an IP version no route of which
// Windows' DNS Client service, and an IP version no route of which leads // leads to the TUN ("misconfigtun"), from leaving through the other
// to the TUN ("misconfigtun"), from leaving through the other interfaces. // interfaces. Addresses do not matter: without one of a version in
// Addresses do not matter: without one of a version in gateway, Windows // gateway, Windows gives the TUN a link-local one.
// gives the TUN a link-local one. leaks := t.options.AutoSystemWfpBlockLeak
leaks, err := ExpandWfpBlockLeak(t.options.AutoSystemWfpBlockLeak) blockDNS := slices.Contains(leaks, "dns") && len(dns) > 0
if err != nil { blockIPv4 := slices.Contains(leaks, "misconfigtun") && !route4
return err blockIPv6 := slices.Contains(leaks, "misconfigtun") && !route6
} if (route4 || route6) && (blockDNS || blockIPv4 || blockIPv6) {
block := newLeakFilters(leaks, route4, route6) if t.wfp, err = blockLeaks(t.luid, blockDNS, blockIPv4, blockIPv6); err != nil {
if route4 || route6 { var blocked []string
if slices.Contains(leaks, "windnsclient") && !block.dnsClient { for _, b := range []struct {
errors.LogInfo(context.Background(), "[tun] windnsclient skipped: before Windows 11 and Server 2022, the DNS Client service only queries port 53") on bool
} what string
if block.systemDNS() && len(dns) == 0 { }{{blockDNS, "DNS"}, {blockIPv4, "IPv4"}, {blockIPv6, "IPv6"}} {
return errors.New("keeping the system's DNS inside the TUN needs dns to be set") if b.on {
} blocked = append(blocked, b.what)
} }
if blocked := block.String(); (route4 || route6) && blocked != "" { }
if t.wfp, err = blockLeaks(t.luid, block); err != nil {
// Rather no TUN than a leaking one. // Rather no TUN than a leaking one.
return errors.New("unable to block ", blocked, " outside the TUN (remove autoSystemWfpBlockLeak to run without)").Base(err) return errors.New("unable to block ", strings.Join(blocked, " and "), " outside the TUN (remove autoSystemWfpBlockLeak to run without)").Base(err)
} }
errors.LogInfo(context.Background(), "[tun] blocked outside the TUN: ", blocked) errors.LogInfo(context.Background(), "[tun] outside the TUN, blocked DNS: ", blockDNS, ", blocked IPv4: ", blockIPv4, ", blocked IPv6: ", blockIPv6)
if block.systemDNS() { if blockDNS {
covered := slices.Clone(addresses) covered := slices.Clone(addresses)
for _, route := range routesData { for _, route := range routesData {
covered = append(covered, route.Destination) covered = append(covered, route.Destination)
+40 -105
View File
@@ -7,7 +7,6 @@ import (
"os" "os"
"runtime" "runtime"
"slices" "slices"
"strings"
"unsafe" "unsafe"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -171,79 +170,19 @@ func condition(field *windows.GUID, typ uint32, value uintptr) fwpmFilterConditi
} }
} }
// leakFilters is what blockLeaks keeps from leaving outside the TUN.
type leakFilters struct {
ports []leakPort // connections to these ports
dnsClient bool // Windows' DNS Client service
ipv4, ipv6 bool // an IP version altogether
}
// newLeakFilters turns expanded autoSystemWfpBlockLeak values into the filters
// for a TUN that the routes of route4 (IPv4) and route6 (IPv6) lead to.
func newLeakFilters(leaks []string, route4, route6 bool) leakFilters {
var block leakFilters
for _, leak := range leaks {
switch leak {
case "windnsclient":
block.dnsClient = dnsClientUsesAnyPort()
case "misconfigtun":
block.ipv4, block.ipv6 = !route4, !route6
default:
if port, ok := parseLeakPort(leak); ok {
block.ports = append(block.ports, port)
}
}
}
return block
}
// String lists what block keeps inside the TUN, or is empty for nothing.
func (block leakFilters) String() string {
var blocked []string
for _, port := range block.ports {
blocked = append(blocked, port.String())
}
for _, b := range []struct {
on bool
what string
}{{block.dnsClient, "windnsclient"}, {block.ipv4, "IPv4"}, {block.ipv6, "IPv6"}} {
if b.on {
blocked = append(blocked, b.what)
}
}
return strings.Join(blocked, ", ")
}
// systemDNS tells whether block keeps the system's DNS inside the TUN.
func (block leakFilters) systemDNS() bool {
return block.dnsClient || slices.ContainsFunc(block.ports, func(port leakPort) bool { return port.port == 53 })
}
// dnsClientUsesAnyPort tells whether Windows' DNS Client service may send its
// queries over HTTPS or TLS, and so to any port, which it does since Windows 11
// and Server 2022 (build 20348). Earlier versions only query port 53, and may
// run the service in one process with others, which its filters would catch
// as well.
func dnsClientUsesAnyPort() bool {
_, _, build := windows.RtlGetNtVersionNumbers()
return build >= 20348
}
// blockLeaks keeps traffic from leaving through interfaces other than tun, // blockLeaks keeps traffic from leaving through interfaces other than tun,
// for every program but Xray itself, whose outbounds (DNS included) use the // for every program but Xray itself, whose outbounds (DNS included) use the
// other interfaces on purpose: // other interfaces on purpose:
// //
// - ports: connections to these TCP or UDP ports may only go through the // - dns: DNS (port 53) may only go through the TUN. Windows sends a name
// TUN, those of DNS (53), DNS over TLS (TCP 853) and DNS over QUIC (UDP // query to the DNS servers of all interfaces, not only to those of the TUN:
// 853) with "dns". Windows sends a name query to the DNS servers of all // to the first server of each interface, then to all of them when no answer
// interfaces, not only to those of the TUN: to the first server of each // arrives within a second or two. It sends the queries for the servers of
// interface, then to all of them when no answer arrives within a second or // an interface out through that interface, whatever the routes say, and
// two. It sends the queries for the servers of an interface out through // other programs reach an on-link resolver, like 192.168.1.1 from DHCP,
// that interface, whatever the routes say, and other programs reach an // through its LAN route, which is more specific than the TUN's default
// on-link resolver, like 192.168.1.1 from DHCP, through its LAN route, // route. Since Windows 11 and Server 2022, Windows may also send its
// which is more specific than the TUN's default route. // queries over HTTPS or TLS, so there its DNS Client service may not
// - dnsClient: since Windows 11 and Server 2022, Windows may also send its
// queries over HTTPS or TLS, to any port, so its DNS Client service may not
// connect outside the TUN at all, except for name resolution on the local // connect outside the TUN at all, except for name resolution on the local
// link (mDNS, LLMNR). // link (mDNS, LLMNR).
// - ipv4, ipv6: no IPv4, or no IPv6, at all, in either direction, for a TUN // - ipv4, ipv6: no IPv4, or no IPv6, at all, in either direction, for a TUN
@@ -257,7 +196,7 @@ func dnsClientUsesAnyPort() bool {
// //
// The filters live in a dynamic WFP session: closing the returned engine handle // The filters live in a dynamic WFP session: closing the returned engine handle
// with closeWFPEngine deletes them, and so does Windows when the process dies. // with closeWFPEngine deletes them, and so does Windows when the process dies.
func blockLeaks(tun winipcfg.LUID, block leakFilters) (windows.Handle, error) { func blockLeaks(tun winipcfg.LUID, dns, ipv4, ipv6 bool) (windows.Handle, error) {
engine, err := openWFPEngine() engine, err := openWFPEngine()
if err != nil { if err != nil {
return 0, err return 0, err
@@ -266,7 +205,7 @@ func blockLeaks(tun winipcfg.LUID, block leakFilters) (windows.Handle, error) {
closeWFPEngine(engine) closeWFPEngine(engine)
return 0, errors.New("FwpmTransactionBegin0 failed").Base(err) return 0, errors.New("FwpmTransactionBegin0 failed").Base(err)
} }
err = addLeakFilters(engine, tun, block) err = addLeakFilters(engine, tun, dns, ipv4, ipv6)
if err == nil { if err == nil {
if err = fwpmResult(procFwpmTransactionCommit0.Call(uintptr(engine))); err != nil { if err = fwpmResult(procFwpmTransactionCommit0.Call(uintptr(engine))); err != nil {
err = errors.New("FwpmTransactionCommit0 failed").Base(err) err = errors.New("FwpmTransactionCommit0 failed").Base(err)
@@ -303,7 +242,7 @@ func closeWFPEngine(engine windows.Handle) {
// addLeakFilters adds the filters of blockLeaks in a sublayer of their own. // addLeakFilters adds the filters of blockLeaks in a sublayer of their own.
// blockLeaks runs it in a transaction, so that they take effect all at once. // blockLeaks runs it in a transaction, so that they take effect all at once.
func addLeakFilters(engine windows.Handle, tun winipcfg.LUID, block leakFilters) error { func addLeakFilters(engine windows.Handle, tun winipcfg.LUID, dns, ipv4, ipv6 bool) error {
exe, err := os.Executable() exe, err := os.Executable()
if err != nil { if err != nil {
return err return err
@@ -346,55 +285,51 @@ func addLeakFilters(engine windows.Handle, tun winipcfg.LUID, block leakFilters)
// hard permit. Connections from outside to Xray get an ordinary one, so // hard permit. Connections from outside to Xray get an ordinary one, so
// that firewalls keep guarding its inbounds. // that firewalls keep guarding its inbounds.
self := condition(&fwpmConditionALEAppID, fwpByteBlobType, uintptr(unsafe.Pointer(appID))) self := condition(&fwpmConditionALEAppID, fwpByteBlobType, uintptr(unsafe.Pointer(appID)))
// A connection goes through the TUN when its local address is the TUN's, dns53 := condition(&fwpmConditionIPRemotePort, fwpUint16, 53)
// and it also leaves, or arrives, through the TUN. The local address alone // DNS goes through the TUN when its local address is the TUN's, and it
// also leaves, or arrives, through the TUN. The local address alone
// decides by default, but with weak host sending or receiving enabled, // decides by default, but with weak host sending or receiving enabled,
// packets of the TUN's address can use other interfaces. (The next hop, // packets of the TUN's address can use other interfaces. (The next hop,
// the interface replies would leave by, is not known for arriving ones.) // the interface replies would leave by, is not known for arriving ones.)
onTUN := func(field *windows.GUID) fwpmFilterCondition0 { onTUN := func(field *windows.GUID) fwpmFilterCondition0 {
return condition(field, fwpUint64, uintptr(unsafe.Pointer(tunLUID))) return condition(field, fwpUint64, uintptr(unsafe.Pointer(tunLUID)))
} }
out := []fwpmFilterCondition0{dns53, onTUN(&fwpmConditionIPLocalInterface), onTUN(&fwpmConditionIPNexthopInterface)}
in := []fwpmFilterCondition0{dns53, onTUN(&fwpmConditionIPLocalInterface), onTUN(&fwpmConditionIPArrivalInterface)}
for _, layer := range []struct { for _, layer := range []struct {
key *windows.GUID key *windows.GUID
selfFlags uint32 selfFlags uint32
via *windows.GUID // the interface that has to be the TUN as well throughTUN []fwpmFilterCondition0
}{ }{
{&fwpmLayerALEAuthConnectV4, fwpmFilterFlagClearActionRight, &fwpmConditionIPNexthopInterface}, {&fwpmLayerALEAuthConnectV4, fwpmFilterFlagClearActionRight, out},
{&fwpmLayerALEAuthRecvAcceptV4, 0, &fwpmConditionIPArrivalInterface}, {&fwpmLayerALEAuthRecvAcceptV4, 0, in},
{&fwpmLayerALEAuthConnectV6, fwpmFilterFlagClearActionRight, &fwpmConditionIPNexthopInterface}, {&fwpmLayerALEAuthConnectV6, fwpmFilterFlagClearActionRight, out},
{&fwpmLayerALEAuthRecvAcceptV6, 0, &fwpmConditionIPArrivalInterface}, {&fwpmLayerALEAuthRecvAcceptV6, 0, in},
} { } {
if err := add(layer.key, "permit Xray", layer.selfFlags, fwpActionPermit, 4, self); err != nil { if err := add(layer.key, "permit Xray", layer.selfFlags, fwpActionPermit, 4, self); err != nil {
return err return err
} }
for _, port := range block.ports { if dns {
protocol := uintptr(windows.IPPROTO_UDP) if err := add(layer.key, "permit DNS through the TUN", 0, fwpActionPermit, 3, layer.throughTUN...); err != nil {
if port.tcp {
protocol = windows.IPPROTO_TCP
}
toPort := []fwpmFilterCondition0{
condition(&fwpmConditionIPProtocol, fwpUint8, protocol),
condition(&fwpmConditionIPRemotePort, fwpUint16, uintptr(port.port)),
}
throughTUN := slices.Concat(toPort, []fwpmFilterCondition0{onTUN(&fwpmConditionIPLocalInterface), onTUN(layer.via)})
if err := add(layer.key, "permit "+port.String()+" through the TUN", 0, fwpActionPermit, 3, throughTUN...); err != nil {
return err return err
} }
if err := add(layer.key, "block "+port.String(), 0, fwpActionBlock, 2, toPort...); err != nil { if err := add(layer.key, "block DNS", 0, fwpActionBlock, 2, dns53); err != nil {
return err return err
} }
} }
} }
// Since Windows 11 and Server 2022, the DNS Client service may also send // Since Windows 11 and Server 2022 (build 20348), the DNS Client service
// the queries for an interface's servers over HTTPS or TLS, out through // may also send the queries for an interface's servers over HTTPS or TLS,
// that interface and to any port. So there it may only connect through // out through that interface and to any port. So there it may only
// the TUN, except for mDNS and LLMNR, which stay on the local link (over // connect through the TUN, except for mDNS and LLMNR, which stay on the
// an IP version only while it is not blocked altogether). Like Windows // local link (over an IP version only while it is not blocked altogether).
// Firewall's rules for it, the filters recognize the service by its SID, // Earlier versions only query port 53, and may run the service in one
// process with others, which the filters would catch as well. Like
// Windows Firewall's rules for it, they recognize the service by its SID,
// which Windows puts in the token of its process: the security descriptor // which Windows puts in the token of its process: the security descriptor
// grants that SID the right to match (FWP_ACTRL_MATCH_FILTER, CC in SDDL). // grants that SID the right to match (FWP_ACTRL_MATCH_FILTER, CC in SDDL).
if block.dnsClient { if _, _, build := windows.RtlGetNtVersionNumbers(); dns && build >= 20348 {
sd, err := windows.SecurityDescriptorFromString("O:SYG:SYD:(A;;CCRC;;;" + dnsClientSID + ")") sd, err := windows.SecurityDescriptorFromString("O:SYG:SYD:(A;;CCRC;;;" + dnsClientSID + ")")
if err != nil { if err != nil {
return err return err
@@ -408,8 +343,8 @@ func addLeakFilters(engine windows.Handle, tun winipcfg.LUID, block leakFilters)
key *windows.GUID key *windows.GUID
localLink bool localLink bool
}{ }{
{&fwpmLayerALEAuthConnectV4, !block.ipv4}, {&fwpmLayerALEAuthConnectV4, !ipv4},
{&fwpmLayerALEAuthConnectV6, !block.ipv6}, {&fwpmLayerALEAuthConnectV6, !ipv6},
} { } {
if err := add(layer.key, "permit the DNS Client service through the TUN", 0, fwpActionPermit, 3, dnsClient, onTUN(&fwpmConditionIPLocalInterface), onTUN(&fwpmConditionIPNexthopInterface)); err != nil { if err := add(layer.key, "permit the DNS Client service through the TUN", 0, fwpActionPermit, 3, dnsClient, onTUN(&fwpmConditionIPLocalInterface), onTUN(&fwpmConditionIPNexthopInterface)); err != nil {
return err return err
@@ -432,7 +367,7 @@ func addLeakFilters(engine windows.Handle, tun winipcfg.LUID, block leakFilters)
matchType: fwpMatchFlagsAllSet, matchType: fwpMatchFlagsAllSet,
conditionValue: fwpValue0{typ: fwpUint32, value: fwpConditionFlagIsLoopback}, conditionValue: fwpValue0{typ: fwpUint32, value: fwpConditionFlagIsLoopback},
} }
if block.ipv4 { if ipv4 {
// DHCP keeps the addresses of the other interfaces, which Xray's own // DHCP keeps the addresses of the other interfaces, which Xray's own
// connections use. // connections use.
dhcp := []fwpmFilterCondition0{ dhcp := []fwpmFilterCondition0{
@@ -452,7 +387,7 @@ func addLeakFilters(engine windows.Handle, tun winipcfg.LUID, block leakFilters)
} }
} }
} }
if block.ipv6 { if ipv6 {
// Neighbor and multicast listener discovery, ICMPv6 130-137 and 143, // Neighbor and multicast listener discovery, ICMPv6 130-137 and 143,
// whose type and code sit where the local and remote port are. // whose type and code sit where the local and remote port are.
discovery := []fwpmFilterCondition0{condition(&fwpmConditionIPProtocol, fwpUint8, windows.IPPROTO_ICMPV6)} discovery := []fwpmFilterCondition0{condition(&fwpmConditionIPProtocol, fwpUint8, windows.IPPROTO_ICMPV6)}
+1 -28
View File
@@ -114,38 +114,11 @@ func TestLeakFiltersAccepted(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
leaks, err := ExpandWfpBlockLeak([]string{"dns", "misconfigtun", "tcp/443"}) if err := addLeakFilters(engine, loopback, true, true, true); err != nil {
if err != nil {
t.Fatal(err)
}
block := newLeakFilters(leaks, false, false)
block.dnsClient = true // whatever the Windows version
if err := addLeakFilters(engine, loopback, block); err != nil {
skipUnlessElevated(err) skipUnlessElevated(err)
} }
} }
func TestNewLeakFilters(t *testing.T) {
leaks, err := ExpandWfpBlockLeak([]string{"dns", "misconfigtun"})
if err != nil {
t.Fatal(err)
}
block := newLeakFilters(leaks, true, false)
want := "udp/53, tcp/53, tcp/853, udp/853, IPv6"
if dnsClientUsesAnyPort() {
want = "udp/53, tcp/53, tcp/853, udp/853, windnsclient, IPv6"
}
if got := block.String(); got != want {
t.Errorf("String() = %q, want %q", got, want)
}
if !block.systemDNS() {
t.Error("systemDNS() = false with dns")
}
if block := newLeakFilters([]string{"tcp/853", "udp/853", "misconfigtun"}, true, true); block.String() != "tcp/853, udp/853" || block.systemDNS() {
t.Errorf("tcp/853, udp/853: %q, systemDNS() = %v", block.String(), block.systemDNS())
}
}
func TestDNSClientSID(t *testing.T) { func TestDNSClientSID(t *testing.T) {
sid, _, _, err := windows.LookupSID("", `NT SERVICE\Dnscache`) sid, _, _, err := windows.LookupSID("", `NT SERVICE\Dnscache`)
if err != nil { if err != nil {
-79
View File
@@ -1,79 +0,0 @@
package tun
import (
"slices"
"strconv"
"strings"
"github.com/xtls/xray-core/common/errors"
)
// dnsLeaks is what "dns" in autoSystemWfpBlockLeak stands for: DNS over UDP and
// TCP, Windows' DNS Client service, which may also use other protocols and
// ports, DNS over TLS, and DNS over QUIC.
var dnsLeaks = []string{"udp/53", "tcp/53", "windnsclient", "tcp/853", "udp/853"}
// leakPort is a "tcp/<port>" or "udp/<port>" value of autoSystemWfpBlockLeak:
// connections to that port may only go through the TUN.
type leakPort struct {
tcp bool
port uint16
}
func (p leakPort) String() string {
if p.tcp {
return "tcp/" + strconv.Itoa(int(p.port))
}
return "udp/" + strconv.Itoa(int(p.port))
}
// parseLeakPort parses a lower case "tcp/<port>" or "udp/<port>" value.
func parseLeakPort(value string) (leakPort, bool) {
protocol, port, ok := strings.Cut(value, "/")
if !ok || protocol != "tcp" && protocol != "udp" {
return leakPort{}, false
}
n, err := strconv.ParseUint(port, 10, 16)
if err != nil || n == 0 {
return leakPort{}, false
}
return leakPort{tcp: protocol == "tcp", port: uint16(n)}, true
}
// ExpandWfpBlockLeak checks the values of autoSystemWfpBlockLeak and returns
// them in lower case, in order and without duplicates, with "dns" replaced by
// what it stands for.
func ExpandWfpBlockLeak(values []string) ([]string, error) {
var leaks []string
add := func(leak string) {
if !slices.Contains(leaks, leak) {
leaks = append(leaks, leak)
}
}
for _, value := range values {
switch value = strings.ToLower(value); value {
case "dns":
for _, leak := range dnsLeaks {
add(leak)
}
case "windnsclient", "misconfigtun":
add(value)
default:
port, ok := parseLeakPort(value)
if !ok {
return nil, errors.New("unknown autoSystemWfpBlockLeak value: ", value)
}
add(port.String())
}
}
return leaks, nil
}
// BlocksSystemDNS tells whether expanded autoSystemWfpBlockLeak values keep the
// system's DNS (port 53, or Windows' DNS Client service) inside the TUN, which
// then needs DNS servers of its own.
func BlocksSystemDNS(leaks []string) bool {
return slices.ContainsFunc(leaks, func(leak string) bool {
return leak == "udp/53" || leak == "tcp/53" || leak == "windnsclient"
})
}
-40
View File
@@ -1,40 +0,0 @@
package tun
import (
"slices"
"testing"
)
func TestExpandWfpBlockLeak(t *testing.T) {
for _, c := range []struct {
values []string
leaks []string
systemDNS bool
}{
{nil, nil, false},
{[]string{"dns"}, []string{"udp/53", "tcp/53", "windnsclient", "tcp/853", "udp/853"}, true},
{[]string{"DNS", "MisconfigTUN"}, []string{"udp/53", "tcp/53", "windnsclient", "tcp/853", "udp/853", "misconfigtun"}, true},
{[]string{"tcp/853", "dns", "TCP/0853"}, []string{"tcp/853", "udp/53", "tcp/53", "windnsclient", "udp/853"}, true},
{[]string{"tcp/853", "udp/853", "misconfigtun"}, []string{"tcp/853", "udp/853", "misconfigtun"}, false},
{[]string{"udp/65535", "tcp/1"}, []string{"udp/65535", "tcp/1"}, false},
{[]string{"tcp/53"}, []string{"tcp/53"}, true},
{[]string{"windnsclient"}, []string{"windnsclient"}, true},
} {
leaks, err := ExpandWfpBlockLeak(c.values)
if err != nil {
t.Errorf("%v: %v", c.values, err)
continue
}
if !slices.Equal(leaks, c.leaks) {
t.Errorf("%v: got %v, want %v", c.values, leaks, c.leaks)
}
if got := BlocksSystemDNS(leaks); got != c.systemDNS {
t.Errorf("%v: BlocksSystemDNS() = %v", c.values, got)
}
}
for _, value := range []string{"", "ip", "tcp", "tcp/", "tcp/0", "udp/65536", "tcp/-1", "tcp/+53", "tcp/53/1", "udp/abc", "icmp/1", "tcp:53", " dns"} {
if _, err := ExpandWfpBlockLeak([]string{value}); err == nil {
t.Errorf("%q was accepted", value)
}
}
}
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/vless/account.proto // source: proxy/vless/account.proto
package vless package vless
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/vless/encoding/addons.proto // source: proxy/vless/encoding/addons.proto
package encoding package encoding
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/vless/inbound/config.proto // source: proxy/vless/inbound/config.proto
package inbound package inbound
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/vless/outbound/config.proto // source: proxy/vless/outbound/config.proto
package outbound package outbound
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/vmess/account.proto // source: proxy/vmess/account.proto
package vmess package vmess
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/vmess/inbound/config.proto // source: proxy/vmess/inbound/config.proto
package inbound package inbound
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/vmess/outbound/config.proto // source: proxy/vmess/outbound/config.proto
package outbound package outbound
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: proxy/wireguard/config.proto // source: proxy/wireguard/config.proto
package wireguard package wireguard
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/config.proto // source: transport/internet/config.proto
package internet package internet
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/filter/config.proto // source: transport/internet/finalmask/filter/config.proto
package filter package filter
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/fragment/config.proto // source: transport/internet/finalmask/fragment/config.proto
package fragment package fragment
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/header/custom/config.proto // source: transport/internet/finalmask/header/custom/config.proto
package custom package custom
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/mkcp/aes128gcm/config.proto // source: transport/internet/finalmask/mkcp/aes128gcm/config.proto
package aes128gcm package aes128gcm
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/mkcp/header/config.proto // source: transport/internet/finalmask/mkcp/header/config.proto
package header package header
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/mkcp/original/config.proto // source: transport/internet/finalmask/mkcp/original/config.proto
package original package original
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/noise/config.proto // source: transport/internet/finalmask/noise/config.proto
package noise package noise
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/realm/config.proto // source: transport/internet/finalmask/realm/config.proto
package realm package realm
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/salamander/config.proto // source: transport/internet/finalmask/salamander/config.proto
package salamander package salamander
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/sudoku/config.proto // source: transport/internet/finalmask/sudoku/config.proto
package sudoku package sudoku
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/udphop/config.proto // source: transport/internet/finalmask/udphop/config.proto
package udphop package udphop
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/xdns/config.proto // source: transport/internet/finalmask/xdns/config.proto
package xdns package xdns
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/xicmp/config.proto // source: transport/internet/finalmask/xicmp/config.proto
package xicmp package xicmp
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/finalmask/xmc/config.proto // source: transport/internet/finalmask/xmc/config.proto
package xmc package xmc
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/grpc/config.proto // source: transport/internet/grpc/config.proto
package grpc package grpc
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/grpc/encoding/stream.proto // source: transport/internet/grpc/encoding/stream.proto
package encoding package encoding
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.6.2 // - protoc-gen-go-grpc v1.6.0
// - protoc (unknown) // - protoc v6.33.5
// source: transport/internet/grpc/encoding/stream.proto // source: transport/internet/grpc/encoding/stream.proto
package encoding package encoding
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/headers/http/config.proto // source: transport/internet/headers/http/config.proto
package http package http
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/headers/noop/config.proto // source: transport/internet/headers/noop/config.proto
package noop package noop
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/httpupgrade/config.proto // source: transport/internet/httpupgrade/config.proto
package httpupgrade package httpupgrade
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/hysteria/config.proto // source: transport/internet/hysteria/config.proto
package hysteria package hysteria
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/kcp/config.proto // source: transport/internet/kcp/config.proto
package kcp package kcp
+2 -2
View File
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.12 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc v6.33.5
// source: transport/internet/masque/config.proto // source: transport/internet/masque/config.proto
package masque package masque

Some files were not shown because too many files have changed in this diff Show More