Skip to content

Commit

Permalink
chore: add route.ApplyConfig for CMFA
Browse files Browse the repository at this point in the history
  • Loading branch information
wwqgtxx committed Aug 31, 2024
1 parent f6164ac commit 15365f5
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 61 deletions.
16 changes: 1 addition & 15 deletions hub/hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"github.com/metacubex/mihomo/config"
"github.com/metacubex/mihomo/hub/executor"
"github.com/metacubex/mihomo/hub/route"
"github.com/metacubex/mihomo/log"
)

type Option func(*config.Config)
Expand Down Expand Up @@ -44,20 +43,7 @@ func Parse(options ...Option) error {
option(cfg)
}

if cfg.Controller.ExternalUI != "" {
route.SetUIPath(cfg.Controller.ExternalUI)
}

if cfg.Controller.ExternalController != "" {
go route.Start(cfg.Controller.ExternalController, cfg.Controller.ExternalControllerTLS,
cfg.Controller.Secret, cfg.TLS.Certificate, cfg.TLS.PrivateKey, cfg.Controller.ExternalDohServer,
cfg.General.LogLevel == log.DEBUG)
}

if cfg.Controller.ExternalControllerUnix != "" {
go route.StartUnix(cfg.Controller.ExternalControllerUnix, cfg.Controller.ExternalDohServer, cfg.General.LogLevel == log.DEBUG)
}

route.ApplyConfig(cfg)
executor.ApplyConfig(cfg, true)
return nil
}
131 changes: 86 additions & 45 deletions hub/route/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import (
"github.com/metacubex/mihomo/adapter/inbound"
CN "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/common/utils"
"github.com/metacubex/mihomo/config"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/constant/features"
"github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/tunnel/statistic"

Expand All @@ -30,10 +32,11 @@ import (
)

var (
serverSecret = ""
serverAddr = ""

uiPath = ""

httpServer *http.Server
tlsServer *http.Server
unixServer *http.Server
)

type Traffic struct {
Expand All @@ -46,11 +49,33 @@ type Memory struct {
OSLimit uint64 `json:"oslimit"` // maybe we need it in the future
}

func ApplyConfig(cfg *config.Config) {
if features.CMFA && strings.HasSuffix(cfg.Controller.ExternalController, ":0") {
// CMFA have set its default override value to end with ":0" for security.
// so we direct return at here
return
}

if cfg.Controller.ExternalUI != "" {
SetUIPath(cfg.Controller.ExternalUI)
}

if cfg.Controller.ExternalController != "" {
go Start(cfg.Controller.ExternalController, cfg.Controller.ExternalControllerTLS,
cfg.Controller.Secret, cfg.TLS.Certificate, cfg.TLS.PrivateKey, cfg.Controller.ExternalDohServer,
cfg.General.LogLevel == log.DEBUG)
}

if cfg.Controller.ExternalControllerUnix != "" {
go StartUnix(cfg.Controller.ExternalControllerUnix, cfg.Controller.ExternalDohServer, cfg.General.LogLevel == log.DEBUG)
}
}

func SetUIPath(path string) {
uiPath = C.Path.Resolve(path)
}

func router(isDebug bool, withAuth bool, dohServer string) *chi.Mux {
func router(isDebug bool, secret string, dohServer string) *chi.Mux {
r := chi.NewRouter()
corsM := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
Expand All @@ -72,8 +97,8 @@ func router(isDebug bool, withAuth bool, dohServer string) *chi.Mux {
}())
}
r.Group(func(r chi.Router) {
if withAuth {
r.Use(authentication)
if secret != "" {
r.Use(authentication(secret))
}
r.Get("/", hello)
r.Get("/logs", getLogs)
Expand Down Expand Up @@ -113,13 +138,18 @@ func router(isDebug bool, withAuth bool, dohServer string) *chi.Mux {

func Start(addr string, tlsAddr string, secret string,
certificate, privateKey string, dohServer string, isDebug bool) {
if serverAddr != "" {
return
// first stop existing server
if httpServer != nil {
_ = httpServer.Close()
httpServer = nil
}

serverAddr = addr
serverSecret = secret
if tlsServer != nil {
_ = tlsServer.Close()
tlsServer = nil
}

// handle tlsAddr
if len(tlsAddr) > 0 {
go func() {
c, err := CN.ParseCert(certificate, privateKey, C.Path)
Expand All @@ -134,35 +164,46 @@ func Start(addr string, tlsAddr string, secret string,
return
}

serverAddr = l.Addr().String()
log.Infoln("RESTful API tls listening at: %s", serverAddr)
tlsServe := &http.Server{
Handler: router(isDebug, true, dohServer),
log.Infoln("RESTful API tls listening at: %s", l.Addr().String())
server := &http.Server{
Handler: router(isDebug, secret, dohServer),
TLSConfig: &tls.Config{
Certificates: []tls.Certificate{c},
},
}
if err = tlsServe.ServeTLS(l, "", ""); err != nil {
if err = server.ServeTLS(l, "", ""); err != nil {
log.Errorln("External controller tls serve error: %s", err)
}
tlsServer = server
}()
}

// handle addr
l, err := inbound.Listen("tcp", addr)
if err != nil {
log.Errorln("External controller listen error: %s", err)
return
}
serverAddr = l.Addr().String()
log.Infoln("RESTful API listening at: %s", serverAddr)
log.Infoln("RESTful API listening at: %s", l.Addr().String())

if err = http.Serve(l, router(isDebug, true, dohServer)); err != nil {
server := &http.Server{
Handler: router(isDebug, secret, dohServer),
}
if err = server.Serve(l); err != nil {
log.Errorln("External controller serve error: %s", err)
}
httpServer = server

}

func StartUnix(addr string, dohServer string, isDebug bool) {
// first stop existing server
if unixServer != nil {
_ = unixServer.Close()
unixServer = nil
}

// handle addr
addr = C.Path.Resolve(addr)

dir := filepath.Dir(addr)
Expand All @@ -187,12 +228,15 @@ func StartUnix(addr string, dohServer string, isDebug bool) {
log.Errorln("External controller unix listen error: %s", err)
return
}
serverAddr = l.Addr().String()
log.Infoln("RESTful API unix listening at: %s", serverAddr)
log.Infoln("RESTful API unix listening at: %s", l.Addr().String())

if err = http.Serve(l, router(isDebug, false, dohServer)); err != nil {
server := &http.Server{
Handler: router(isDebug, "", dohServer),
}
if err = server.Serve(l); err != nil {
log.Errorln("External controller unix serve error: %s", err)
}
unixServer = server
}

func setPrivateNetworkAccess(next http.Handler) http.Handler {
Expand All @@ -210,38 +254,35 @@ func safeEuqal(a, b string) bool {
return subtle.ConstantTimeCompare(aBuf, bBuf) == 1
}

func authentication(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
if serverSecret == "" {
next.ServeHTTP(w, r)
return
}
func authentication(secret string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
// Browser websocket not support custom header
if r.Header.Get("Upgrade") == "websocket" && r.URL.Query().Get("token") != "" {
token := r.URL.Query().Get("token")
if !safeEuqal(token, secret) {
render.Status(r, http.StatusUnauthorized)
render.JSON(w, r, ErrUnauthorized)
return
}
next.ServeHTTP(w, r)
return
}

// Browser websocket not support custom header
if r.Header.Get("Upgrade") == "websocket" && r.URL.Query().Get("token") != "" {
token := r.URL.Query().Get("token")
if !safeEuqal(token, serverSecret) {
header := r.Header.Get("Authorization")
bearer, token, found := strings.Cut(header, " ")

hasInvalidHeader := bearer != "Bearer"
hasInvalidSecret := !found || !safeEuqal(token, secret)
if hasInvalidHeader || hasInvalidSecret {
render.Status(r, http.StatusUnauthorized)
render.JSON(w, r, ErrUnauthorized)
return
}
next.ServeHTTP(w, r)
return
}

header := r.Header.Get("Authorization")
bearer, token, found := strings.Cut(header, " ")

hasInvalidHeader := bearer != "Bearer"
hasInvalidSecret := !found || !safeEuqal(token, serverSecret)
if hasInvalidHeader || hasInvalidSecret {
render.Status(r, http.StatusUnauthorized)
render.JSON(w, r, ErrUnauthorized)
return
}
next.ServeHTTP(w, r)
return http.HandlerFunc(fn)
}
return http.HandlerFunc(fn)
}

func hello(w http.ResponseWriter, r *http.Request) {
Expand Down
2 changes: 2 additions & 0 deletions listener/sing_tun/server_android.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build android && !cmfa

package sing_tun

import (
Expand Down
2 changes: 1 addition & 1 deletion listener/sing_tun/server_notandroid.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !android
//go:build !android || cmfa

package sing_tun

Expand Down

0 comments on commit 15365f5

Please sign in to comment.