Server Dashboard SSL Support (#2982)

This commit is contained in:
EMRE ÇELİK 2022-06-27 05:08:02 +03:00 committed by GitHub
parent c652b8ef07
commit 218b354f82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 28 deletions

View File

@ -477,6 +477,21 @@ dashboard_pwd = admin
Then visit `http://[server_addr]:7500` to see the dashboard, with username and password both being `admin`. Then visit `http://[server_addr]:7500` to see the dashboard, with username and password both being `admin`.
Additionally, you can use HTTPS port by using your domains wildcard or normal SSL certificate:
```ini
[common]
dashboard_port = 7500
# dashboard's username and password are both optional
dashboard_user = admin
dashboard_pwd = admin
dashboard_tls_mode = true
dashboard_tls_cert_file = server.crt
dashboard_tls_key_file = server.key
```
Then visit `https://[server_addr]:7500` to see the dashboard in secure HTTPS connection, with username and password both being `admin`.
![dashboard](/doc/pic/dashboard.png) ![dashboard](/doc/pic/dashboard.png)
### Admin UI ### Admin UI

View File

@ -37,31 +37,34 @@ var (
cfgFile string cfgFile string
showVersion bool showVersion bool
bindAddr string bindAddr string
bindPort int bindPort int
bindUDPPort int bindUDPPort int
kcpBindPort int kcpBindPort int
proxyBindAddr string proxyBindAddr string
vhostHTTPPort int vhostHTTPPort int
vhostHTTPSPort int vhostHTTPSPort int
vhostHTTPTimeout int64 vhostHTTPTimeout int64
dashboardAddr string dashboardAddr string
dashboardPort int dashboardPort int
dashboardUser string dashboardUser string
dashboardPwd string dashboardPwd string
enablePrometheus bool enablePrometheus bool
assetsDir string assetsDir string
logFile string logFile string
logLevel string logLevel string
logMaxDays int64 logMaxDays int64
disableLogColor bool disableLogColor bool
token string token string
subDomainHost string subDomainHost string
tcpMux bool tcpMux bool
allowPorts string allowPorts string
maxPoolCount int64 maxPoolCount int64
maxPortsPerClient int64 maxPortsPerClient int64
tlsOnly bool tlsOnly bool
dashboardTLSMode bool
dashboardTLSCertFile string
dashboardTLSKeyFile string
) )
func init() { func init() {
@ -91,6 +94,9 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&allowPorts, "allow_ports", "", "", "allow ports") rootCmd.PersistentFlags().StringVarP(&allowPorts, "allow_ports", "", "", "allow ports")
rootCmd.PersistentFlags().Int64VarP(&maxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client") rootCmd.PersistentFlags().Int64VarP(&maxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client")
rootCmd.PersistentFlags().BoolVarP(&tlsOnly, "tls_only", "", false, "frps tls only") rootCmd.PersistentFlags().BoolVarP(&tlsOnly, "tls_only", "", false, "frps tls only")
rootCmd.PersistentFlags().BoolVarP(&dashboardTLSMode, "dashboard_tls_mode", "", false, "dashboard tls mode")
rootCmd.PersistentFlags().StringVarP(&dashboardTLSCertFile, "dashboard_tls_cert_file", "", "", "dashboard tls cert file")
rootCmd.PersistentFlags().StringVarP(&dashboardTLSKeyFile, "dashboard_tls_key_file", "", "", "dashboard tls key file")
} }
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
@ -167,6 +173,9 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
cfg.DashboardUser = dashboardUser cfg.DashboardUser = dashboardUser
cfg.DashboardPwd = dashboardPwd cfg.DashboardPwd = dashboardPwd
cfg.EnablePrometheus = enablePrometheus cfg.EnablePrometheus = enablePrometheus
cfg.DashboardTLSCertFile = dashboardTLSCertFile
cfg.DashboardTLSKeyFile = dashboardTLSKeyFile
cfg.DashboardTLSMode = dashboardTLSMode
cfg.LogFile = logFile cfg.LogFile = logFile
cfg.LogLevel = logLevel cfg.LogLevel = logLevel
cfg.LogMaxDays = logMaxDays cfg.LogMaxDays = logMaxDays

View File

@ -43,6 +43,11 @@ dashboard_port = 7500
dashboard_user = admin dashboard_user = admin
dashboard_pwd = admin dashboard_pwd = admin
# dashboard TLS mode
dashboard_tls_mode = false
# dashboard_tls_cert_file = server.crt
# dashboard_tls_key_file = server.key
# enable_prometheus will export prometheus metrics on {dashboard_addr}:{dashboard_port} in /metrics api. # enable_prometheus will export prometheus metrics on {dashboard_addr}:{dashboard_port} in /metrics api.
enable_prometheus = true enable_prometheus = true

View File

@ -74,6 +74,17 @@ type ServerCommonConf struct {
// value is 0, the dashboard will not be started. By default, this value is // value is 0, the dashboard will not be started. By default, this value is
// 0. // 0.
DashboardPort int `ini:"dashboard_port" json:"dashboard_port" validate:"gte=0,lte=65535"` DashboardPort int `ini:"dashboard_port" json:"dashboard_port" validate:"gte=0,lte=65535"`
// DashboardTLSCertFile specifies the path of the cert file that the server will
// load. If "dashboard_tls_cert_file", "dashboard_tls_key_file" are valid, the server will use this
// supplied tls configuration.
DashboardTLSCertFile string `ini:"dashboard_tls_cert_file" json:"dashboard_tls_cert_file"`
// DashboardTLSKeyFile specifies the path of the secret key that the server will
// load. If "dashboard_tls_cert_file", "dashboard_tls_key_file" are valid, the server will use this
// supplied tls configuration.
DashboardTLSKeyFile string `ini:"dashboard_tls_key_file" json:"dashboard_tls_key_file"`
// DashboardTLSMode specifies the mode of the dashboard between HTTP or HTTPS modes. By
// default, this value is false, which is HTTP mode.
DashboardTLSMode bool `ini:"dashboard_tls_mode" json:"dashboard_tls_mode"`
// DashboardUser specifies the username that the dashboard will use for // DashboardUser specifies the username that the dashboard will use for
// login. // login.
DashboardUser string `ini:"dashboard_user" json:"dashboard_user"` DashboardUser string `ini:"dashboard_user" json:"dashboard_user"`
@ -297,6 +308,23 @@ func (cfg *ServerCommonConf) Complete() {
} }
func (cfg *ServerCommonConf) Validate() error { func (cfg *ServerCommonConf) Validate() error {
if cfg.DashboardTLSMode == false {
if cfg.DashboardTLSCertFile != "" {
fmt.Println("WARNING! dashboard_tls_cert_file is invalid when dashboard_tls_mode is false")
}
if cfg.DashboardTLSKeyFile != "" {
fmt.Println("WARNING! dashboard_tls_key_file is invalid when dashboard_tls_mode is false")
}
} else {
if cfg.DashboardTLSCertFile == "" {
return fmt.Errorf("ERROR! dashboard_tls_cert_file must be specified when dashboard_tls_mode is true")
}
if cfg.DashboardTLSKeyFile == "" {
return fmt.Errorf("ERROR! dashboard_tls_cert_file must be specified when dashboard_tls_mode is true")
}
}
return validator.New().Struct(cfg) return validator.New().Struct(cfg)
} }

View File

@ -15,6 +15,7 @@
package server package server
import ( import (
"crypto/tls"
"net" "net"
"net/http" "net/http"
"net/http/pprof" "net/http/pprof"
@ -76,14 +77,21 @@ func (svr *Service) RunDashboardServer(address string) (err error) {
ReadTimeout: httpServerReadTimeout, ReadTimeout: httpServerReadTimeout,
WriteTimeout: httpServerWriteTimeout, WriteTimeout: httpServerWriteTimeout,
} }
if address == "" || address == ":" {
address = ":http"
}
ln, err := net.Listen("tcp", address) ln, err := net.Listen("tcp", address)
if err != nil { if err != nil {
return err return err
} }
if svr.cfg.DashboardTLSMode {
cert, err := tls.LoadX509KeyPair(svr.cfg.DashboardTLSCertFile, svr.cfg.DashboardTLSKeyFile)
if err != nil {
return err
}
tlsCfg := &tls.Config{
Certificates: []tls.Certificate{cert},
}
ln = tls.NewListener(ln, tlsCfg)
}
go server.Serve(ln) go server.Serve(ln)
return return
} }