mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-01-13 06:07:14 +08:00
Compare commits
1 Commits
domo-stat
...
replace-go
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e29201eb1 |
6
.github/workflows/release-win7.yml
vendored
6
.github/workflows/release-win7.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Restore Geodat Cache
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
key: xray-geodat-
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
||||
|
||||
- name: Restore Geodat Cache
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
key: xray-geodat-
|
||||
@@ -132,7 +132,7 @@ jobs:
|
||||
mv build_assets Xray-${{ env.ASSET_NAME }}
|
||||
|
||||
- name: Upload files to Artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: Xray-${{ env.ASSET_NAME }}
|
||||
path: |
|
||||
|
||||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Restore Geodat Cache
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
key: xray-geodat-
|
||||
@@ -207,7 +207,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Restore Geodat Cache
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
key: xray-geodat-
|
||||
@@ -238,7 +238,7 @@ jobs:
|
||||
mv build_assets Xray-${{ env.ASSET_NAME }}
|
||||
|
||||
- name: Upload files to Artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: Xray-${{ env.ASSET_NAME }}
|
||||
path: |
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Restore Geodat Cache
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
key: xray-geodat-
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
done
|
||||
|
||||
- name: Save Geodat Cache
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@v4
|
||||
if: ${{ steps.update.outputs.unhit }}
|
||||
with:
|
||||
path: resources
|
||||
|
||||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Restore Geodat Cache
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
key: xray-geodat-
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- name: Restore Geodat Cache
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
key: xray-geodat-
|
||||
|
||||
10
common/platform/ctlcmd/attr_other.go
Normal file
10
common/platform/ctlcmd/attr_other.go
Normal file
@@ -0,0 +1,10 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package ctlcmd
|
||||
|
||||
import "syscall"
|
||||
|
||||
func getSysProcAttr() *syscall.SysProcAttr {
|
||||
return nil
|
||||
}
|
||||
12
common/platform/ctlcmd/attr_windows.go
Normal file
12
common/platform/ctlcmd/attr_windows.go
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package ctlcmd
|
||||
|
||||
import "syscall"
|
||||
|
||||
func getSysProcAttr() *syscall.SysProcAttr {
|
||||
return &syscall.SysProcAttr{
|
||||
HideWindow: true,
|
||||
}
|
||||
}
|
||||
50
common/platform/ctlcmd/ctlcmd.go
Normal file
50
common/platform/ctlcmd/ctlcmd.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package ctlcmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/platform"
|
||||
)
|
||||
|
||||
func Run(args []string, input io.Reader) (buf.MultiBuffer, error) {
|
||||
xctl := platform.GetToolLocation("xctl")
|
||||
if _, err := os.Stat(xctl); err != nil {
|
||||
return nil, errors.New("xctl doesn't exist").Base(err)
|
||||
}
|
||||
|
||||
var errBuffer buf.MultiBufferContainer
|
||||
var outBuffer buf.MultiBufferContainer
|
||||
|
||||
cmd := exec.Command(xctl, args...)
|
||||
cmd.Stderr = &errBuffer
|
||||
cmd.Stdout = &outBuffer
|
||||
cmd.SysProcAttr = getSysProcAttr()
|
||||
if input != nil {
|
||||
cmd.Stdin = input
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, errors.New("failed to start xctl").Base(err)
|
||||
}
|
||||
|
||||
if err := cmd.Wait(); err != nil {
|
||||
msg := "failed to execute xctl"
|
||||
if errBuffer.Len() > 0 {
|
||||
msg += ": \n" + strings.TrimSpace(errBuffer.MultiBuffer.String())
|
||||
}
|
||||
return nil, errors.New(msg).Base(err)
|
||||
}
|
||||
|
||||
// log stderr, info message
|
||||
if !errBuffer.IsEmpty() {
|
||||
errors.LogInfo(context.Background(), "<xctl message> \n", strings.TrimSpace(errBuffer.MultiBuffer.String()))
|
||||
}
|
||||
|
||||
return outBuffer.MultiBuffer, nil
|
||||
}
|
||||
@@ -8,10 +8,19 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func ExpandEnv(s string) string {
|
||||
return os.ExpandEnv(s)
|
||||
}
|
||||
|
||||
func LineSeparator() string {
|
||||
return "\n"
|
||||
}
|
||||
|
||||
func GetToolLocation(file string) string {
|
||||
toolPath := NewEnvFlag(ToolLocation).GetValue(getExecutableDir)
|
||||
return filepath.Join(toolPath, file)
|
||||
}
|
||||
|
||||
// GetAssetLocation searches for `file` in the env dir, the executable dir, and certain locations
|
||||
func GetAssetLocation(file string) string {
|
||||
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
||||
|
||||
@@ -8,8 +8,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
PluginLocation = "xray.location.plugin"
|
||||
ConfigLocation = "xray.location.config"
|
||||
ConfdirLocation = "xray.location.confdir"
|
||||
ToolLocation = "xray.location.tool"
|
||||
AssetLocation = "xray.location.asset"
|
||||
CertLocation = "xray.location.cert"
|
||||
|
||||
@@ -77,6 +79,17 @@ func getExecutableDir() string {
|
||||
return filepath.Dir(exec)
|
||||
}
|
||||
|
||||
func getExecutableSubDir(dir string) func() string {
|
||||
return func() string {
|
||||
return filepath.Join(getExecutableDir(), dir)
|
||||
}
|
||||
}
|
||||
|
||||
func GetPluginDirectory() string {
|
||||
pluginDir := NewEnvFlag(PluginLocation).GetValue(getExecutableSubDir("plugins"))
|
||||
return pluginDir
|
||||
}
|
||||
|
||||
func GetConfigurationPath() string {
|
||||
configPath := NewEnvFlag(ConfigLocation).GetValue(getExecutableDir)
|
||||
return filepath.Join(configPath, "config.json")
|
||||
|
||||
@@ -5,10 +5,20 @@ package platform
|
||||
|
||||
import "path/filepath"
|
||||
|
||||
func ExpandEnv(s string) string {
|
||||
// TODO
|
||||
return s
|
||||
}
|
||||
|
||||
func LineSeparator() string {
|
||||
return "\r\n"
|
||||
}
|
||||
|
||||
func GetToolLocation(file string) string {
|
||||
toolPath := NewEnvFlag(ToolLocation).GetValue(getExecutableDir)
|
||||
return filepath.Join(toolPath, file+".exe")
|
||||
}
|
||||
|
||||
// GetAssetLocation searches for `file` in the env dir and the executable dir
|
||||
func GetAssetLocation(file string) string {
|
||||
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
||||
|
||||
@@ -64,7 +64,7 @@ func GetMergedConfig(args cmdarg.Arg) (string, error) {
|
||||
var files []*ConfigSource
|
||||
supported := []string{"json", "yaml", "toml"}
|
||||
for _, file := range args {
|
||||
format := GetFormat(file)
|
||||
format := getFormat(file)
|
||||
if slices.Contains(supported, format) {
|
||||
files = append(files, &ConfigSource{
|
||||
Name: file,
|
||||
@@ -98,7 +98,7 @@ func getExtension(filename string) string {
|
||||
return filename[idx+1:]
|
||||
}
|
||||
|
||||
func GetFormat(filename string) string {
|
||||
func getFormat(filename string) string {
|
||||
return GetFormatByExtension(getExtension(filename))
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func LoadConfig(formatName string, input interface{}) (*Config, error) {
|
||||
|
||||
if formatName == "auto" {
|
||||
if file != "stdin:" {
|
||||
f = GetFormat(file)
|
||||
f = getFormat(file)
|
||||
} else {
|
||||
f = "json"
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
var (
|
||||
Version_x byte = 25
|
||||
Version_y byte = 12
|
||||
Version_z byte = 8
|
||||
Version_z byte = 2
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
18
go.mod
18
go.mod
@@ -8,7 +8,7 @@ require (
|
||||
github.com/golang/mock v1.7.0-rc.1
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/miekg/dns v1.1.69
|
||||
github.com/miekg/dns v1.1.68
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pires/go-proxyproto v0.8.1
|
||||
github.com/quic-go/quic-go v0.57.1
|
||||
@@ -21,13 +21,13 @@ require (
|
||||
github.com/vishvananda/netlink v1.3.1
|
||||
github.com/xtls/reality v0.0.0-20251014195629-e4eec4520535
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
golang.org/x/crypto v0.46.0
|
||||
golang.org/x/net v0.48.0
|
||||
golang.org/x/sync v0.19.0
|
||||
golang.org/x/sys v0.39.0
|
||||
golang.org/x/crypto v0.44.0
|
||||
golang.org/x/net v0.47.0
|
||||
golang.org/x/sync v0.18.0
|
||||
golang.org/x/sys v0.38.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
google.golang.org/grpc v1.77.0
|
||||
google.golang.org/protobuf v1.36.11
|
||||
google.golang.org/protobuf v1.36.10
|
||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
|
||||
h12.io/socks v1.0.3
|
||||
lukechampine.com/blake3 v1.4.1
|
||||
@@ -46,10 +46,10 @@ require (
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||
github.com/vishvananda/netns v0.0.5 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
golang.org/x/tools v0.39.0 // indirect
|
||||
golang.org/x/tools v0.38.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
||||
36
go.sum
36
go.sum
@@ -38,8 +38,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/miekg/dns v1.1.69 h1:Kb7Y/1Jo+SG+a2GtfoFUfDkG//csdRPwRLkCsxDG9Sc=
|
||||
github.com/miekg/dns v1.1.69/go.mod h1:7OyjD9nEba5OkqQ/hB4fy3PIoxafSZJtducccIelz3g=
|
||||
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
||||
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
|
||||
@@ -95,20 +95,20 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
|
||||
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -116,21 +116,21 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
|
||||
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -144,8 +144,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
|
||||
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
|
||||
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.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
||||
@@ -3,6 +3,8 @@ package conf
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -45,6 +47,8 @@ var (
|
||||
"dns": func() interface{} { return new(DNSOutboundConfig) },
|
||||
"wireguard": func() interface{} { return &WireGuardConfig{IsClient: true} },
|
||||
}, "protocol", "settings")
|
||||
|
||||
ctllog = log.New(os.Stderr, "xctl> ", 0)
|
||||
)
|
||||
|
||||
type SniffingConfig struct {
|
||||
|
||||
@@ -3,6 +3,7 @@ package convert
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/xtls/xray-core/common/cmdarg"
|
||||
creflect "github.com/xtls/xray-core/common/reflect"
|
||||
@@ -60,7 +61,7 @@ func executeConvertConfigsToProtobuf(cmd *base.Command, args []string) {
|
||||
}
|
||||
|
||||
if len(optFile) > 0 {
|
||||
switch core.GetFormat(optFile){
|
||||
switch core.GetFormatByExtension(getFileExtension(optFile)){
|
||||
case "protobuf", "":
|
||||
fmt.Println("Output ProtoBuf file is ", optFile)
|
||||
default:
|
||||
@@ -105,3 +106,11 @@ func executeConvertConfigsToProtobuf(cmd *base.Command, args []string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getFileExtension(filename string) string {
|
||||
idx := strings.LastIndexByte(filename, '.')
|
||||
if idx == -1 {
|
||||
return ""
|
||||
}
|
||||
return filename[idx+1:]
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@ import (
|
||||
|
||||
type (
|
||||
configFileLoader func(string) (io.Reader, error)
|
||||
extconfigLoader func([]string, io.Reader) (io.Reader, error)
|
||||
)
|
||||
|
||||
var (
|
||||
EffectiveConfigFileLoader configFileLoader
|
||||
EffectiveExtConfigLoader extconfigLoader
|
||||
)
|
||||
|
||||
// LoadConfig reads from a path/url/stdin
|
||||
@@ -25,3 +27,13 @@ func LoadConfig(file string) (io.Reader, error) {
|
||||
}
|
||||
return EffectiveConfigFileLoader(file)
|
||||
}
|
||||
|
||||
// LoadExtConfig calls xctl to handle multiple config
|
||||
// the actual work also in external module
|
||||
func LoadExtConfig(files []string, reader io.Reader) (io.Reader, error) {
|
||||
if EffectiveExtConfigLoader == nil {
|
||||
return nil, errors.New("external config module not loaded").AtError()
|
||||
}
|
||||
|
||||
return EffectiveExtConfigLoader(files, reader)
|
||||
}
|
||||
|
||||
11
main/confloader/external/external.go
vendored
11
main/confloader/external/external.go
vendored
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/platform/ctlcmd"
|
||||
"github.com/xtls/xray-core/main/confloader"
|
||||
)
|
||||
|
||||
@@ -128,6 +129,16 @@ func FetchUnixSocketHTTPContent(target string) ([]byte, error) {
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func ExtConfigLoader(files []string, reader io.Reader) (io.Reader, error) {
|
||||
buf, err := ctlcmd.Run(append([]string{"convert"}, files...), reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return strings.NewReader(buf.String()), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
confloader.EffectiveConfigFileLoader = ConfigLoader
|
||||
confloader.EffectiveExtConfigLoader = ExtConfigLoader
|
||||
}
|
||||
|
||||
@@ -111,8 +111,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
|
||||
destinationOverridden = true
|
||||
}
|
||||
}
|
||||
iConn := stat.TryUnwrapStatsConn(conn)
|
||||
if tlsConn, ok := iConn.(tls.Interface); ok && !destinationOverridden {
|
||||
if tlsConn, ok := conn.(tls.Interface); ok && !destinationOverridden {
|
||||
if serverName := tlsConn.HandshakeContextServerName(ctx); serverName != "" {
|
||||
dest.Address = net.DomainAddress(serverName)
|
||||
destinationOverridden = true
|
||||
|
||||
@@ -296,7 +296,10 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iConn := stat.TryUnwrapStatsConn(rawConn)
|
||||
iConn := rawConn
|
||||
if statConn, ok := iConn.(*stat.CounterConnection); ok {
|
||||
iConn = statConn.Connection
|
||||
}
|
||||
|
||||
nextProto := ""
|
||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||
|
||||
@@ -248,7 +248,7 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
*withinPaddingBuffers = false
|
||||
*switchToDirectCopy = true
|
||||
} else {
|
||||
errors.LogDebug(w.ctx, "XtlsRead unknown command ", *currentCommand, buffer.Len())
|
||||
errors.LogInfo(w.ctx, "XtlsRead unknown command ", *currentCommand, buffer.Len())
|
||||
}
|
||||
}
|
||||
if w.trafficState.NumberOfPacketToFilter > 0 {
|
||||
@@ -269,9 +269,9 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
w.rawInput = nil
|
||||
|
||||
if inbound := session.InboundFromContext(w.ctx); inbound != nil && inbound.Conn != nil {
|
||||
// if w.isUplink && inbound.CanSpliceCopy == 2 { // TODO: enable uplink splice
|
||||
// inbound.CanSpliceCopy = 1
|
||||
// }
|
||||
if w.isUplink && inbound.CanSpliceCopy == 2 {
|
||||
inbound.CanSpliceCopy = 1
|
||||
}
|
||||
if !w.isUplink && w.ob != nil && w.ob.CanSpliceCopy == 2 { // ob need to be passed in due to context can have more than one ob
|
||||
w.ob.CanSpliceCopy = 1
|
||||
}
|
||||
@@ -334,9 +334,9 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
if !w.isUplink && inbound.CanSpliceCopy == 2 {
|
||||
inbound.CanSpliceCopy = 1
|
||||
}
|
||||
// if w.isUplink && w.ob != nil && w.ob.CanSpliceCopy == 2 { // TODO: enable uplink splice
|
||||
// w.ob.CanSpliceCopy = 1
|
||||
// }
|
||||
if w.isUplink && w.ob != nil && w.ob.CanSpliceCopy == 2 {
|
||||
w.ob.CanSpliceCopy = 1
|
||||
}
|
||||
}
|
||||
rawConn, _, writerCounter := UnwrapRawConn(w.conn)
|
||||
w.Writer = buf.NewWriter(rawConn)
|
||||
@@ -478,7 +478,7 @@ func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBu
|
||||
buffer[i] = nil
|
||||
}
|
||||
buffer = buffer[:0]
|
||||
errors.LogDebug(ctx, "ReshapeMultiBuffer ", toPrint)
|
||||
errors.LogInfo(ctx, "ReshapeMultiBuffer ", toPrint)
|
||||
return mb2
|
||||
}
|
||||
|
||||
@@ -517,7 +517,7 @@ func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, longPadding bool
|
||||
b = nil
|
||||
}
|
||||
newbuffer.Extend(paddingLen)
|
||||
errors.LogDebug(ctx, "XtlsPadding ", contentLen, " ", paddingLen, " ", command)
|
||||
errors.LogInfo(ctx, "XtlsPadding ", contentLen, " ", paddingLen, " ", command)
|
||||
return newbuffer
|
||||
}
|
||||
|
||||
@@ -564,7 +564,7 @@ func XtlsUnpadding(b *buf.Buffer, s *TrafficState, isUplink bool, ctx context.Co
|
||||
*remainingPadding = int32(data) << 8
|
||||
case 1:
|
||||
*remainingPadding = *remainingPadding | int32(data)
|
||||
errors.LogDebug(ctx, "Xtls Unpadding new block, content ", *remainingContent, " padding ", *remainingPadding, " command ", *currentCommand)
|
||||
errors.LogInfo(ctx, "Xtls Unpadding new block, content ", *remainingContent, " padding ", *remainingPadding, " command ", *currentCommand)
|
||||
}
|
||||
*remainingCommand--
|
||||
} else if *remainingContent > 0 {
|
||||
@@ -623,11 +623,11 @@ func XtlsFilterTls(buffer buf.MultiBuffer, trafficState *TrafficState, ctx conte
|
||||
cipherSuite := b.BytesRange(43+sessionIdLen+1, 43+sessionIdLen+3)
|
||||
trafficState.Cipher = uint16(cipherSuite[0])<<8 | uint16(cipherSuite[1])
|
||||
} else {
|
||||
errors.LogDebug(ctx, "XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", trafficState.RemainingServerHello)
|
||||
errors.LogInfo(ctx, "XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", trafficState.RemainingServerHello)
|
||||
}
|
||||
} else if bytes.Equal(TlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == TlsHandshakeTypeClientHello {
|
||||
trafficState.IsTLS = true
|
||||
errors.LogDebug(ctx, "XtlsFilterTls found tls client hello! ", buffer.Len())
|
||||
errors.LogInfo(ctx, "XtlsFilterTls found tls client hello! ", buffer.Len())
|
||||
}
|
||||
}
|
||||
if trafficState.RemainingServerHello > 0 {
|
||||
@@ -643,18 +643,18 @@ func XtlsFilterTls(buffer buf.MultiBuffer, trafficState *TrafficState, ctx conte
|
||||
} else if v != "TLS_AES_128_CCM_8_SHA256" {
|
||||
trafficState.EnableXtls = true
|
||||
}
|
||||
errors.LogDebug(ctx, "XtlsFilterTls found tls 1.3! ", b.Len(), " ", v)
|
||||
errors.LogInfo(ctx, "XtlsFilterTls found tls 1.3! ", b.Len(), " ", v)
|
||||
trafficState.NumberOfPacketToFilter = 0
|
||||
return
|
||||
} else if trafficState.RemainingServerHello <= 0 {
|
||||
errors.LogDebug(ctx, "XtlsFilterTls found tls 1.2! ", b.Len())
|
||||
errors.LogInfo(ctx, "XtlsFilterTls found tls 1.2! ", b.Len())
|
||||
trafficState.NumberOfPacketToFilter = 0
|
||||
return
|
||||
}
|
||||
errors.LogDebug(ctx, "XtlsFilterTls inconclusive server hello ", b.Len(), " ", trafficState.RemainingServerHello)
|
||||
errors.LogInfo(ctx, "XtlsFilterTls inconclusive server hello ", b.Len(), " ", trafficState.RemainingServerHello)
|
||||
}
|
||||
if trafficState.NumberOfPacketToFilter <= 0 {
|
||||
errors.LogDebug(ctx, "XtlsFilterTls stop filtering", buffer.Len())
|
||||
errors.LogInfo(ctx, "XtlsFilterTls stop filtering", buffer.Len())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -736,7 +736,7 @@ func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net
|
||||
}
|
||||
}
|
||||
if splice {
|
||||
errors.LogDebug(ctx, "CopyRawConn splice")
|
||||
errors.LogInfo(ctx, "CopyRawConn splice")
|
||||
statWriter, _ := writer.(*dispatcher.SizeStatWriter)
|
||||
//runtime.Gosched() // necessary
|
||||
time.Sleep(time.Millisecond) // without this, there will be a rare ssl error for freedom splice
|
||||
@@ -779,7 +779,7 @@ func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net
|
||||
}
|
||||
|
||||
func readV(ctx context.Context, reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, readCounter stats.Counter) error {
|
||||
errors.LogDebug(ctx, "CopyRawConn (maybe) readv")
|
||||
errors.LogInfo(ctx, "CopyRawConn (maybe) readv")
|
||||
if err := buf.Copy(reader, writer, buf.UpdateActivity(timer), buf.AddToStatCounter(readCounter)); err != nil {
|
||||
return errors.New("failed to process response").Base(err)
|
||||
}
|
||||
@@ -787,7 +787,10 @@ func readV(ctx context.Context, reader buf.Reader, writer buf.Writer, timer sign
|
||||
}
|
||||
|
||||
func IsRAWTransportWithoutSecurity(conn stat.Connection) bool {
|
||||
iConn := stat.TryUnwrapStatsConn(conn)
|
||||
iConn := conn
|
||||
if statConn, ok := iConn.(*stat.CounterConnection); ok {
|
||||
iConn = statConn.Connection
|
||||
}
|
||||
_, ok1 := iConn.(*proxyproto.Conn)
|
||||
_, ok2 := iConn.(*net.TCPConn)
|
||||
_, ok3 := iConn.(*internet.UnixConnWrapper)
|
||||
|
||||
@@ -147,7 +147,11 @@ func (s *Server) Network() []net.Network {
|
||||
|
||||
// Process implements proxy.Inbound.Process().
|
||||
func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
||||
iConn := stat.TryUnwrapStatsConn(conn)
|
||||
iConn := conn
|
||||
statConn, ok := iConn.(*stat.CounterConnection)
|
||||
if ok {
|
||||
iConn = statConn.Connection
|
||||
}
|
||||
|
||||
sessionPolicy := s.policyManager.ForLevel(0)
|
||||
if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
|
||||
|
||||
@@ -265,7 +265,10 @@ func (*Handler) Network() []net.Network {
|
||||
|
||||
// Process implements proxy.Inbound.Process().
|
||||
func (h *Handler) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
|
||||
iConn := stat.TryUnwrapStatsConn(connection)
|
||||
iConn := connection
|
||||
if statConn, ok := iConn.(*stat.CounterConnection); ok {
|
||||
iConn = statConn.Connection
|
||||
}
|
||||
|
||||
if h.decryption != nil {
|
||||
var err error
|
||||
|
||||
@@ -192,7 +192,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
|
||||
ob.Conn = conn // for Vision's pre-connect
|
||||
|
||||
iConn := stat.TryUnwrapStatsConn(conn)
|
||||
iConn := conn
|
||||
if statConn, ok := iConn.(*stat.CounterConnection); ok {
|
||||
iConn = statConn.Connection
|
||||
}
|
||||
target := ob.Target
|
||||
errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination.NetAddr())
|
||||
|
||||
|
||||
@@ -229,7 +229,10 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
return errors.New("unable to set read deadline").Base(err).AtWarning()
|
||||
}
|
||||
|
||||
iConn := stat.TryUnwrapStatsConn(connection)
|
||||
iConn := connection
|
||||
if statConn, ok := iConn.(*stat.CounterConnection); ok {
|
||||
iConn = statConn.Connection
|
||||
}
|
||||
_, isDrain := iConn.(*net.TCPConn)
|
||||
if !isDrain {
|
||||
_, isDrain = iConn.(*net.UnixConn)
|
||||
|
||||
@@ -300,14 +300,14 @@ func (h *Handler) createIPCRequest() string {
|
||||
errors.LogInfo(h.bind.ctx, "createIPCRequest use dialer dest ip: ", addr)
|
||||
} else {
|
||||
ips, _, err := h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
||||
IPv4Enable: h.conf.preferIP4(),
|
||||
IPv6Enable: h.conf.preferIP6(),
|
||||
IPv4Enable: h.hasIPv4 && h.conf.preferIP4(),
|
||||
IPv6Enable: h.hasIPv6 && h.conf.preferIP6(),
|
||||
})
|
||||
{ // Resolve fallback
|
||||
if (len(ips) == 0 || err != nil) && h.conf.hasFallback() {
|
||||
ips, _, err = h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
||||
IPv4Enable: h.conf.fallbackIP4(),
|
||||
IPv6Enable: h.conf.fallbackIP6(),
|
||||
IPv4Enable: h.hasIPv4 && h.conf.fallbackIP4(),
|
||||
IPv6Enable: h.hasIPv6 && h.conf.fallbackIP6(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,13 +32,3 @@ func (c *CounterConnection) Write(b []byte) (int, error) {
|
||||
}
|
||||
return nBytes, err
|
||||
}
|
||||
|
||||
func TryUnwrapStatsConn(conn net.Conn) net.Conn {
|
||||
if conn == nil {
|
||||
return conn
|
||||
}
|
||||
if conn, ok := conn.(*CounterConnection); ok {
|
||||
return conn.Connection
|
||||
}
|
||||
return conn
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user