mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-31 10:14:15 +00:00
fix(sub): don't leak loopback bind IP into link host
Some checks are pending
CI / go-test (push) Waiting to run
CI / govulncheck (push) Waiting to run
CI / frontend (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Release 3X-UI / build (386) (push) Waiting to run
Release 3X-UI / build (amd64) (push) Waiting to run
Release 3X-UI / build (arm64) (push) Waiting to run
Release 3X-UI / build (armv5) (push) Waiting to run
Release 3X-UI / build (armv6) (push) Waiting to run
Release 3X-UI / build (armv7) (push) Waiting to run
Release 3X-UI / build (s390x) (push) Waiting to run
Release 3X-UI / Build for Windows (push) Waiting to run
Some checks are pending
CI / go-test (push) Waiting to run
CI / govulncheck (push) Waiting to run
CI / frontend (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Release 3X-UI / build (386) (push) Waiting to run
Release 3X-UI / build (amd64) (push) Waiting to run
Release 3X-UI / build (arm64) (push) Waiting to run
Release 3X-UI / build (armv5) (push) Waiting to run
Release 3X-UI / build (armv6) (push) Waiting to run
Release 3X-UI / build (armv7) (push) Waiting to run
Release 3X-UI / build (s390x) (push) Waiting to run
Release 3X-UI / Build for Windows (push) Waiting to run
When the sub server is reached on a loopback/unspecified host (e.g. 127.0.0.2 from its Listen IP bind), the request host was used as the link address. Substitute the configured Subscription/Web Domain, or normalize loopback to localhost, so the sub link address matches the panel's Client Information.
This commit is contained in:
parent
234cce408b
commit
3f6fe1167d
2 changed files with 47 additions and 0 deletions
|
|
@ -52,10 +52,42 @@ func NewSubService(showInfo bool, remarkModel string) *SubService {
|
||||||
// freshly-loaded node map regardless of which sub flavour the client
|
// freshly-loaded node map regardless of which sub flavour the client
|
||||||
// hit.
|
// hit.
|
||||||
func (s *SubService) PrepareForRequest(host string) {
|
func (s *SubService) PrepareForRequest(host string) {
|
||||||
|
if !isRoutableHost(host) {
|
||||||
|
if d := s.configuredPublicHost(); d != "" {
|
||||||
|
host = d
|
||||||
|
} else if isLoopbackHost(host) {
|
||||||
|
host = "localhost"
|
||||||
|
}
|
||||||
|
}
|
||||||
s.address = host
|
s.address = host
|
||||||
s.loadNodes()
|
s.loadNodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SubService) configuredPublicHost() string {
|
||||||
|
if d, err := s.settingService.GetSubDomain(); err == nil && d != "" {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
if d, err := s.settingService.GetWebDomain(); err == nil && d != "" {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRoutableHost(host string) bool {
|
||||||
|
if host == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ip := net.ParseIP(strings.Trim(host, "[]")); ip != nil {
|
||||||
|
return !ip.IsLoopback() && !ip.IsUnspecified()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func isLoopbackHost(host string) bool {
|
||||||
|
ip := net.ParseIP(strings.Trim(host, "[]"))
|
||||||
|
return ip != nil && ip.IsLoopback()
|
||||||
|
}
|
||||||
|
|
||||||
// GetSubs retrieves subscription links for a given subscription ID and host.
|
// GetSubs retrieves subscription links for a given subscription ID and host.
|
||||||
func (s *SubService) GetSubs(subId string, host string) ([]string, []string, int64, xray.ClientTraffic, error) {
|
func (s *SubService) GetSubs(subId string, host string) ([]string, []string, int64, xray.ClientTraffic, error) {
|
||||||
s.PrepareForRequest(host)
|
s.PrepareForRequest(host)
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,21 @@ func TestFindClientIndex(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsRoutableHost(t *testing.T) {
|
||||||
|
routable := []string{"example.com", "sub.example.com", "10.0.0.1", "192.168.1.5", "1.2.3.4", "2001:db8::1"}
|
||||||
|
for _, v := range routable {
|
||||||
|
if !isRoutableHost(v) {
|
||||||
|
t.Fatalf("isRoutableHost(%q) = false, want true", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notRoutable := []string{"", "0.0.0.0", "::", "::0", "127.0.0.1", "127.0.0.2", "::1", "[::1]"}
|
||||||
|
for _, v := range notRoutable {
|
||||||
|
if isRoutableHost(v) {
|
||||||
|
t.Fatalf("isRoutableHost(%q) = true, want false", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUnmarshalStreamSettings(t *testing.T) {
|
func TestUnmarshalStreamSettings(t *testing.T) {
|
||||||
got := unmarshalStreamSettings(`{"network":"ws","wsSettings":{"path":"/api"}}`)
|
got := unmarshalStreamSettings(`{"network":"ws","wsSettings":{"path":"/api"}}`)
|
||||||
if got["network"] != "ws" {
|
if got["network"] != "ws" {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue