diff --git a/server/README.md b/server/README.md index 3e4f316..5435b9c 100644 --- a/server/README.md +++ b/server/README.md @@ -28,6 +28,7 @@ The configuration file path is `/etc/kvm/server.yaml`. ```yaml # Network Settings proto: http # Access protocol. Can be changed to `https` only when certificates are configured. Default is `http` +host: "" # The listening address for the HTTP/HTTPS service. If left empty, all network interfaces will be bound port: http: 80 # The listening port for the HTTP service. Default is `80` https: 443 # The listening port for the HTTPS service (effective when HTTPS is enabled). Default is `443` diff --git a/server/README_JA.md b/server/README_JA.md index 55a6f40..92ad8c2 100644 --- a/server/README_JA.md +++ b/server/README_JA.md @@ -27,6 +27,7 @@ server ```yaml proto: http +host: "" port: http: 80 https: 443 diff --git a/server/README_ZH.md b/server/README_ZH.md index ed26a0a..94b82c3 100644 --- a/server/README_ZH.md +++ b/server/README_ZH.md @@ -26,6 +26,7 @@ server ```yaml # 网络设置 proto: http # 访问协议,默认为 `http`,仅当配置了证书时支持改为 `https` +host: "" port: http: 80 # HTTP 服务的监听端口,默认为 `80` https: 443 # HTTPS 服务的监听端口(启用 https 协议时生效),默认为 `443` diff --git a/server/config/default.go b/server/config/default.go index 987c317..2208e9c 100644 --- a/server/config/default.go +++ b/server/config/default.go @@ -2,6 +2,7 @@ package config var defaultConfig = &Config{ Proto: "http", + Host: "", Port: Port{ Http: 80, Https: 443, diff --git a/server/config/types.go b/server/config/types.go index 40df073..902ffa5 100644 --- a/server/config/types.go +++ b/server/config/types.go @@ -2,6 +2,7 @@ package config type Config struct { Proto string `yaml:"proto"` + Host string `yaml:"host"` Port Port `yaml:"port"` Cert Cert `yaml:"cert"` Logger Logger `yaml:"logger"` diff --git a/server/main.go b/server/main.go index f4f3200..b1940db 100644 --- a/server/main.go +++ b/server/main.go @@ -3,8 +3,10 @@ package main import ( "fmt" "log" + "net" "os" "os/signal" + "strconv" "syscall" "time" @@ -71,12 +73,13 @@ func run() { router.Init(r) - httpAddr := fmt.Sprintf(":%d", conf.Port.Http) - httpsAddr := fmt.Sprintf(":%d", conf.Port.Https) + httpAddr := listenAddr(conf.Host, strconv.Itoa(conf.Port.Http)) if conf.Proto == "https" { + httpsPortStr := strconv.Itoa(conf.Port.Https) + go func() { - err := r.RunTLS(httpsAddr, conf.Cert.Crt, conf.Cert.Key) + err := r.RunTLS(listenAddr(conf.Host, httpsPortStr), conf.Cert.Crt, conf.Cert.Key) if err != nil { panic("start https server failed") } @@ -84,7 +87,7 @@ func run() { if err := middleware.ListenAndServeLoopbackHTTPRedirect( httpAddr, - httpsAddr, + httpsPortStr, r, router.LoopbackHTTPAllowedPaths()..., ); err != nil { @@ -100,3 +103,10 @@ func run() { func dispose() { common.GetKvmVision().Close() } + +func listenAddr(host string, port string) string { + if host == "" { + return fmt.Sprintf(":%s", port) + } + return net.JoinHostPort(host, port) +} diff --git a/server/middleware/loopback_http.go b/server/middleware/loopback_http.go index 2ffe0ba..48dc55d 100644 --- a/server/middleware/loopback_http.go +++ b/server/middleware/loopback_http.go @@ -10,7 +10,7 @@ import ( ) func ListenAndServeLoopbackHTTPRedirect( - httpPort string, + httpAddr string, httpsPort string, handler http.Handler, allowedPaths ...string, @@ -23,7 +23,7 @@ func ListenAndServeLoopbackHTTPRedirect( allowlist[path] = struct{}{} } - return http.ListenAndServe(httpPort, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + return http.ListenAndServe(httpAddr, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if isLoopbackAllowedPath(req, allowlist) { if hasValidLoopbackHTTPToken(req) { handler.ServeHTTP(w, req) @@ -35,16 +35,18 @@ func ListenAndServeLoopbackHTTPRedirect( } host := req.Host - if strings.Contains(host, httpPort) { - host = strings.Split(host, httpPort)[0] + if h, _, err := net.SplitHostPort(host); err == nil { + host = h } - targetURL := "https://" + host + req.URL.String() - if httpsPort != ":443" { - targetURL = "https://" + host + httpsPort + req.URL.String() + if strings.Contains(host, ":") { + host = "[" + host + "]" + } + if httpsPort != "443" { + host += ":" + httpsPort } - http.Redirect(w, req, targetURL, http.StatusTemporaryRedirect) + http.Redirect(w, req, "https://"+host+req.URL.RequestURI(), http.StatusTemporaryRedirect) })) }