feat: add tls port for RESTful api and external controller

This commit is contained in:
Skyxim 2022-12-03 12:25:10 +08:00
parent cf5709aab1
commit 2fe271f19f
3 changed files with 53 additions and 5 deletions

View file

@ -80,6 +80,9 @@ type Controller struct {
ExternalController string `json:"-"` ExternalController string `json:"-"`
ExternalUI string `json:"-"` ExternalUI string `json:"-"`
Secret string `json:"-"` Secret string `json:"-"`
TLSPort int `json:"-"`
Cert string `json:"-"`
PrivateKey string `json:"-"`
} }
// DNS config // DNS config
@ -230,6 +233,9 @@ type Sniffer struct {
// Experimental config // Experimental config
type Experimental struct { type Experimental struct {
Fingerprints []string `yaml:"fingerprints"` Fingerprints []string `yaml:"fingerprints"`
TLSPort int `yaml:"tls-port,omitempty"`
Cert string `yaml:"cert,omitempty"`
PrivateKey string `yaml:"private-key,omitempty"`
} }
// Config is clash config manager // Config is clash config manager
@ -669,6 +675,9 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
ExternalController: cfg.ExternalController, ExternalController: cfg.ExternalController,
ExternalUI: cfg.ExternalUI, ExternalUI: cfg.ExternalUI,
Secret: cfg.Secret, Secret: cfg.Secret,
TLSPort: cfg.Experimental.TLSPort,
Cert: cfg.Experimental.Cert,
PrivateKey: cfg.Experimental.PrivateKey,
}, },
UnifiedDelay: cfg.UnifiedDelay, UnifiedDelay: cfg.UnifiedDelay,
Mode: cfg.Mode, Mode: cfg.Mode,

View file

@ -1,6 +1,8 @@
package hub package hub
import ( import (
"errors"
"github.com/Dreamacro/clash/config" "github.com/Dreamacro/clash/config"
"github.com/Dreamacro/clash/hub/executor" "github.com/Dreamacro/clash/hub/executor"
"github.com/Dreamacro/clash/hub/route" "github.com/Dreamacro/clash/hub/route"
@ -42,7 +44,12 @@ func Parse(options ...Option) error {
} }
if cfg.General.ExternalController != "" { if cfg.General.ExternalController != "" {
go route.Start(cfg.General.ExternalController, cfg.General.Secret) if cfg.General.TLSPort != 0 && (len(cfg.General.PrivateKey) == 0 || len(cfg.General.Cert) == 0) {
return errors.New("Must be provided certificates and keys, for tls controller")
}
go route.Start(cfg.General.ExternalController, cfg.General.Secret, cfg.General.TLSPort,
cfg.General.Cert, cfg.General.PrivateKey)
} }
executor.ApplyConfig(cfg, true) executor.ApplyConfig(cfg, true)

View file

@ -2,8 +2,11 @@ package route
import ( import (
"bytes" "bytes"
"crypto/tls"
"encoding/json" "encoding/json"
"net"
"net/http" "net/http"
"strconv"
"strings" "strings"
"time" "time"
@ -40,7 +43,7 @@ func SetUIPath(path string) {
uiPath = C.Path.Resolve(path) uiPath = C.Path.Resolve(path)
} }
func Start(addr string, secret string) { func Start(addr string, secret string, tlsPort int, cert string, privateKey string) {
if serverAddr != "" { if serverAddr != "" {
return return
} }
@ -49,18 +52,16 @@ func Start(addr string, secret string) {
serverSecret = secret serverSecret = secret
r := chi.NewRouter() r := chi.NewRouter()
corsM := cors.New(cors.Options{ corsM := cors.New(cors.Options{
AllowedOrigins: []string{"*"}, AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE"}, AllowedMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE"},
AllowedHeaders: []string{"Content-Type", "Authorization"}, AllowedHeaders: []string{"Content-Type", "Authorization"},
MaxAge: 300, MaxAge: 300,
}) })
r.Use()
r.Use(corsM.Handler) r.Use(corsM.Handler)
r.Group(func(r chi.Router) { r.Group(func(r chi.Router) {
r.Use(authentication) r.Use(authentication)
r.Get("/", hello) r.Get("/", hello)
r.Get("/logs", getLogs) r.Get("/logs", getLogs)
r.Get("/traffic", traffic) r.Get("/traffic", traffic)
@ -84,6 +85,34 @@ func Start(addr string, secret string) {
}) })
}) })
} }
if tlsPort >0 {
go func() {
if host, _, err := net.SplitHostPort(addr); err != nil {
log.Errorln("External controller tls serve error,%s", err)
} else {
l, err := inbound.Listen("tcp", net.JoinHostPort(host, strconv.Itoa(tlsPort)))
if err != nil {
log.Errorln("External controller tls listen error: %s", err)
return
}
serverAddr = l.Addr().String()
log.Infoln("RESTful API tls listening at: %s", serverAddr)
certificate, err := tls.X509KeyPair([]byte(cert), []byte(privateKey))
if err != nil {
log.Errorln("External controller tls sevre error,%s", err)
}
tlsServe := &http.Server{
Handler: r,
TLSConfig: &tls.Config{
Certificates: []tls.Certificate{certificate},
},
}
if err = tlsServe.ServeTLS(l, "", ""); err != nil {
log.Errorln("External controller tls serve error: %s", err)
}
}
}()
}
l, err := inbound.Listen("tcp", addr) l, err := inbound.Listen("tcp", addr)
if err != nil { if err != nil {
@ -92,9 +121,12 @@ func Start(addr string, secret string) {
} }
serverAddr = l.Addr().String() serverAddr = l.Addr().String()
log.Infoln("RESTful API listening at: %s", serverAddr) log.Infoln("RESTful API listening at: %s", serverAddr)
if err = http.Serve(l, r); err != nil { if err = http.Serve(l, r); err != nil {
log.Errorln("External controller serve error: %s", err) log.Errorln("External controller serve error: %s", err)
} }
} }
func authentication(next http.Handler) http.Handler { func authentication(next http.Handler) http.Handler {