diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000000..f1bf5edd0f04 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,42 @@ +name: Bug report +description: "Submit Xray-core bug" +body: + - type: checkboxes + attributes: + label: Integrity requirements + description: |- + Please check all of the following options to prove that you have read and understood the requirements, otherwise this issue will be closed. + options: + - label: I confirm that I have read the documentation, understand the meaning of all the configuration items I wrote, and did not pile up seemingly useful options or default values. + required: true + - label: I searched issues and did not find any similar issues. + required: true + - type: textarea + attributes: + label: Version + description: Xray-core version + render: shell + - type: textarea + attributes: + label: Description + description: Please provide a detailed description of the bug. And information that you consider valuable. + validations: + required: true + - type: textarea + attributes: + label: Reproduction + description: |- + Provide method to reproduce the bug. + Please provide config that can reproduce the problem, including both the server and client, removing unnecessary inbounds, outbounds, route rules, and options. This cloud help us locate the problem if you really want to get help. + Do not paste a large exported config here. + Even if you are using a GUI/script/panel, please follow the above requirements. We do not have the energy or obligation to find the software and spend time reproducing according to the description. + validations: + required: true + - type: textarea + attributes: + label: log + description: |- + Set the log level to debug. + Please Restart Xray-core, and then follow the reproduction method to reduce irrelevant parts in log. + Remember to remove personal information such as UUID, IP. + render: shell \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report_zh.yml b/.github/ISSUE_TEMPLATE/bug_report_zh.yml new file mode 100644 index 000000000000..1a6e2b208a74 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report_zh.yml @@ -0,0 +1,42 @@ +name: bug反馈 +description: "提交 Xray-core bug" +body: + - type: checkboxes + attributes: + label: 完整性要求 + description: |- + 请勾选以下所有选项以证明您已经阅读并理解了以下要求,否则该 issue 将被关闭。 + options: + - label: 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。 + required: true + - label: 我搜索了issues,没有发现已提出的类似问题。 + required: true + - type: textarea + attributes: + label: 版本 + description: 使用的Xray-core版本 + render: shell + - type: textarea + attributes: + label: 描述 + description: 请提供错误的详细描述。以及你认为有价值的信息。 + validations: + required: true + - type: textarea + attributes: + label: 重现方式 + description: |- + 提供重现BUG方法。 + 请提供可以重现问题的配置文件,包括服务端和客户端,去掉无用的出入站、规则、选项,这可以帮助确定问题,如果你真的想得到帮助。 + 不要直接在这里黏贴一大段导出的 config 文件。 + 即使你在使用图形客户端/脚本/面板,也请遵照上述要求,我们没有精力也没有义务去找到项目再花时间按描述重新问题。 + validations: + required: true + - type: textarea + attributes: + label: 日志 + description: |- + 请先将日志等级设置为 debug. + 重启 Xray-core ,再按复现方式操作,尽量减少日志中的无关部分。 + 记得删除有关个人信息(如UUID与IP)的部分。 + render: shell \ No newline at end of file diff --git a/Makefile b/Makefile index f69a9b2b7507..0578fe6759e4 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,15 @@ NAME = xray VERSION=$(shell git describe --always --dirty) +export GOARCH ?= +export GOOS ?= + +ifdef GOARCH + ifeq ($(GOOS),darwin) + NAME:=$(NAME)-$(GOARCH) + endif +endif + LDFLAGS = -X github.com/xtls/xray-core/core.build=$(VERSION) -s -w -buildid= PARAMS = -trimpath -ldflags "$(LDFLAGS)" -v MAIN = ./main @@ -26,4 +35,4 @@ install: clean: go clean -v -i $(PWD) - rm -f xray xray.exe wxray.exe xray_softfloat \ No newline at end of file + rm -f xray xray.exe wxray.exe xray_softfloat diff --git a/app/router/config.pb.go b/app/router/config.pb.go index 23aba9113846..d0da6d141461 100644 --- a/app/router/config.pb.go +++ b/app/router/config.pb.go @@ -864,7 +864,7 @@ type StrategyLeastLoadConfig struct { Baselines []int64 `protobuf:"varint,3,rep,packed,name=baselines,proto3" json:"baselines,omitempty"` // expected nodes count to select Expected int32 `protobuf:"varint,4,opt,name=expected,proto3" json:"expected,omitempty"` - // max acceptable rtt, filter away high delay nodes. defalut 0 + // max acceptable rtt, filter away high delay nodes. default 0 MaxRTT int64 `protobuf:"varint,5,opt,name=maxRTT,proto3" json:"maxRTT,omitempty"` // acceptable failure rate Tolerance float32 `protobuf:"fixed32,6,opt,name=tolerance,proto3" json:"tolerance,omitempty"` diff --git a/app/router/config.proto b/app/router/config.proto index cff00fade4d3..fdd2e61d7fc7 100644 --- a/app/router/config.proto +++ b/app/router/config.proto @@ -147,7 +147,7 @@ message StrategyLeastLoadConfig { repeated int64 baselines = 3; // expected nodes count to select int32 expected = 4; - // max acceptable rtt, filter away high delay nodes. defalut 0 + // max acceptable rtt, filter away high delay nodes. default 0 int64 maxRTT = 5; // acceptable failure rate float tolerance = 6; diff --git a/core/config.go b/core/config.go index 1aa21f5f3c0f..1a5fa33f211b 100644 --- a/core/config.go +++ b/core/config.go @@ -24,7 +24,7 @@ type ConfigLoader func(input interface{}) (*Config, error) // ConfigBuilder is a builder to build core.Config from filenames and formats type ConfigBuilder func(files []string, formats []string) (*Config, error) -// ConfigMerger merge multiple json configs into on config +// ConfigsMerger merge multiple json configs into on config type ConfigsMerger func(files []string, formats []string) (string, error) var ( diff --git a/go.mod b/go.mod index 807dec1f1b32..e400e8f3621a 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,13 @@ module github.com/xtls/xray-core go 1.22 require ( + github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 + github.com/cloudflare/circl v1.3.7 github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 github.com/golang/mock v1.7.0-rc.1 github.com/google/go-cmp v0.6.0 github.com/gorilla/websocket v1.5.1 - github.com/miekg/dns v1.1.58 + github.com/miekg/dns v1.1.59 github.com/pelletier/go-toml v1.9.5 github.com/pires/go-proxyproto v0.7.0 github.com/quic-go/quic-go v0.42.0 @@ -34,7 +36,6 @@ require ( require ( github.com/andybalholm/brotli v1.1.0 // indirect - github.com/cloudflare/circl v1.3.7 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect github.com/francoispqt/gojay v1.2.13 // indirect diff --git a/go.sum b/go.sum index 64362f4ed2a2..dc99982a5e58 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1 dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJSGpevP+8Pk5bANX7fJacO2w04aqLiC5I= +github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= @@ -88,8 +90,8 @@ github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= -github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= +github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= +github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= diff --git a/infra/conf/router_strategy.go b/infra/conf/router_strategy.go index 58367b4a06c1..4d0f647adbc2 100644 --- a/infra/conf/router_strategy.go +++ b/infra/conf/router_strategy.go @@ -38,7 +38,7 @@ type strategyLeastLoadConfig struct { Baselines []duration.Duration `json:"baselines,omitempty"` // expected nodes count to select Expected int32 `json:"expected,omitempty"` - // max acceptable rtt, filter away high delay nodes. defalut 0 + // max acceptable rtt, filter away high delay nodes. default 0 MaxRTT duration.Duration `json:"maxRTT,omitempty"` // acceptable failure rate Tolerance float64 `json:"tolerance,omitempty"` diff --git a/main/commands/all/tls/ech.go b/main/commands/all/tls/ech.go new file mode 100644 index 000000000000..d4e17f9be3f1 --- /dev/null +++ b/main/commands/all/tls/ech.go @@ -0,0 +1,69 @@ +package tls + +import ( + "encoding/json" + "encoding/pem" + "os" + "strings" + + "github.com/OmarTariq612/goech" + "github.com/cloudflare/circl/hpke" + "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/main/commands/base" +) + +var cmdECH = &base.Command{ + UsageLine: `{{.Exec}} tls ech [--serverName (string)] [--json]`, + Short: `Generate TLS-ECH certificates`, + Long: ` +Generate TLS-ECH certificates. + +Set serverName to your custom string: {{.Exec}} tls ech --serverName (string) +Generate into json format: {{.Exec}} tls ech --json +`, // Enable PQ signature schemes: {{.Exec}} tls ech --pq-signature-schemes-enabled +} + +func init() { + cmdECH.Run = executeECH +} + +var input_pqSignatureSchemesEnabled = cmdECH.Flag.Bool("pqSignatureSchemesEnabled", false, "") +var input_serverName = cmdECH.Flag.String("serverName", "cloudflare-ech.com", "") +var input_json = cmdECH.Flag.Bool("json", false, "True == turn on json output") + +func executeECH(cmd *base.Command, args []string) { + var kem hpke.KEM + + if *input_pqSignatureSchemesEnabled { + kem = hpke.KEM_X25519_KYBER768_DRAFT00 + } else { + kem = hpke.KEM_X25519_HKDF_SHA256 + } + + echKeySet, err := goech.GenerateECHKeySet(0, *input_serverName, kem) + common.Must(err) + + configBuffer, _ := echKeySet.ECHConfig.MarshalBinary() + keyBuffer, _ := echKeySet.MarshalBinary() + + configPEM := string(pem.EncodeToMemory(&pem.Block{Type: "ECH CONFIGS", Bytes: configBuffer})) + keyPEM := string(pem.EncodeToMemory(&pem.Block{Type: "ECH KEYS", Bytes: keyBuffer})) + if *input_json { + jECHConfigs := map[string]interface{}{ + "configs": strings.Split(strings.TrimSpace(string(configPEM)), "\n"), + } + jECHKey := map[string]interface{}{ + "key": strings.Split(strings.TrimSpace(string(keyPEM)), "\n"), + } + + for _, i := range []map[string]interface{}{jECHConfigs, jECHKey} { + content, err := json.MarshalIndent(i, "", " ") + common.Must(err) + os.Stdout.Write(content) + os.Stdout.WriteString("\n") + } + } else { + os.Stdout.WriteString(configPEM) + os.Stdout.WriteString(keyPEM) + } +} diff --git a/main/commands/all/tls/tls.go b/main/commands/all/tls/tls.go index bf6533017d6e..a93da1c3baeb 100644 --- a/main/commands/all/tls/tls.go +++ b/main/commands/all/tls/tls.go @@ -14,5 +14,6 @@ var CmdTLS = &base.Command{ cmdCert, cmdPing, cmdCertChainHash, + cmdECH, }, } diff --git a/transport/internet/reality/reality.go b/transport/internet/reality/reality.go index f74d6bcfb6fd..c2d0dcd1fd72 100644 --- a/transport/internet/reality/reality.go +++ b/transport/internet/reality/reality.go @@ -232,6 +232,7 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati if resp, err = client.Do(req); err != nil { break } + defer resp.Body.Close() req.Header.Set("Referer", req.URL.String()) if body, err = io.ReadAll(resp.Body); err != nil { break diff --git a/transport/internet/websocket/hub.go b/transport/internet/websocket/hub.go index 8a860c30bf9d..60f07390012f 100644 --- a/transport/internet/websocket/hub.go +++ b/transport/internet/websocket/hub.go @@ -39,10 +39,12 @@ var upgrader = &websocket.Upgrader{ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) { if len(h.host) > 0 && request.Host != h.host { + newError("failed to validate host, request:", request.Host, ", config:", h.host).WriteToLog() writer.WriteHeader(http.StatusNotFound) return } if request.URL.Path != h.path { + newError("failed to validate path, request:", request.URL.Path, ", config:", h.path).WriteToLog() writer.WriteHeader(http.StatusNotFound) return }