refactor: adjust config

This commit is contained in:
Skyxim 2022-12-03 14:14:15 +08:00
parent 2fe271f19f
commit ba884c29bd
5 changed files with 110 additions and 92 deletions

18
common/net/tls.go Normal file
View File

@ -0,0 +1,18 @@
package net
import (
"crypto/tls"
"fmt"
)
func ParseCert(certificate,privateKey string) (tls.Certificate, error) {
cert, painTextErr := tls.X509KeyPair([]byte(certificate), []byte(privateKey))
if painTextErr == nil {
return cert, nil
}
cert, loadErr := tls.LoadX509KeyPair(certificate, privateKey)
if loadErr != nil {
return tls.Certificate{}, fmt.Errorf("parse certificate failed,maybe format error:%s, or path error: %s", painTextErr.Error(), loadErr.Error())
}
return cert, nil
}

View File

@ -78,11 +78,9 @@ type Inbound struct {
// Controller config // Controller config
type Controller struct { type Controller struct {
ExternalController string `json:"-"` ExternalController string `json:"-"`
ExternalControllerTLS 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
@ -130,6 +128,11 @@ type TuicServer struct {
MaxUdpRelayPacketSize int `yaml:"max-udp-relay-packet-size" json:"max-udp-relay-packet-size,omitempty"` MaxUdpRelayPacketSize int `yaml:"max-udp-relay-packet-size" json:"max-udp-relay-packet-size,omitempty"`
} }
type TLS struct {
Certificate string `yaml:"certificate"`
PrivateKey string `yaml:"private-key"`
}
func (t TuicServer) String() string { func (t TuicServer) String() string {
b, _ := json.Marshal(t) b, _ := json.Marshal(t)
return string(b) return string(b)
@ -230,12 +233,10 @@ type Sniffer struct {
ParsePureIp bool ParsePureIp bool
} }
// 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
@ -254,6 +255,7 @@ type Config struct {
RuleProviders map[string]providerTypes.RuleProvider RuleProviders map[string]providerTypes.RuleProvider
Tunnels []Tunnel Tunnels []Tunnel
Sniffer *Sniffer Sniffer *Sniffer
TLS *TLS
} }
type RawDNS struct { type RawDNS struct {
@ -397,6 +399,7 @@ type RawConfig struct {
LogLevel log.LogLevel `yaml:"log-level"` LogLevel log.LogLevel `yaml:"log-level"`
IPv6 bool `yaml:"ipv6"` IPv6 bool `yaml:"ipv6"`
ExternalController string `yaml:"external-controller"` ExternalController string `yaml:"external-controller"`
ExternalControllerTLS string `yaml:"external-controller-tls"`
ExternalUI string `yaml:"external-ui"` ExternalUI string `yaml:"external-ui"`
Secret string `yaml:"secret"` Secret string `yaml:"secret"`
Interface string `yaml:"interface-name"` Interface string `yaml:"interface-name"`
@ -423,6 +426,7 @@ type RawConfig struct {
ProxyGroup []map[string]any `yaml:"proxy-groups"` ProxyGroup []map[string]any `yaml:"proxy-groups"`
Rule []string `yaml:"rules"` Rule []string `yaml:"rules"`
SubRules map[string][]string `yaml:"sub-rules"` SubRules map[string][]string `yaml:"sub-rules"`
RawTLS TLS `yaml:"tls"`
} }
type RawGeoXUrl struct { type RawGeoXUrl struct {
@ -572,6 +576,7 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
config.Experimental = &rawCfg.Experimental config.Experimental = &rawCfg.Experimental
config.Profile = &rawCfg.Profile config.Profile = &rawCfg.Profile
config.IPTables = &rawCfg.IPTables config.IPTables = &rawCfg.IPTables
config.TLS=&rawCfg.RawTLS
general, err := parseGeneral(rawCfg) general, err := parseGeneral(rawCfg)
if err != nil { if err != nil {
@ -640,6 +645,7 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
return nil, err return nil, err
} }
elapsedTime := time.Since(startTime) / time.Millisecond // duration in ms elapsedTime := time.Since(startTime) / time.Millisecond // duration in ms
log.Infoln("Initial configuration complete, total time: %dms", elapsedTime) //Segment finished in xxm log.Infoln("Initial configuration complete, total time: %dms", elapsedTime) //Segment finished in xxm
@ -652,7 +658,6 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
// checkout externalUI exist // checkout externalUI exist
if externalUI != "" { if externalUI != "" {
externalUI = C.Path.Resolve(externalUI) externalUI = C.Path.Resolve(externalUI)
if _, err := os.Stat(externalUI); os.IsNotExist(err) { if _, err := os.Stat(externalUI); os.IsNotExist(err) {
return nil, fmt.Errorf("external-ui: %s not exist", externalUI) return nil, fmt.Errorf("external-ui: %s not exist", externalUI)
} }
@ -675,9 +680,7 @@ 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, ExternalControllerTLS: cfg.ExternalControllerTLS,
Cert: cfg.Experimental.Cert,
PrivateKey: cfg.Experimental.PrivateKey,
}, },
UnifiedDelay: cfg.UnifiedDelay, UnifiedDelay: cfg.UnifiedDelay,
Mode: cfg.Mode, Mode: cfg.Mode,

View File

@ -16,7 +16,7 @@ log-level: debug # 日志等级 silent/error/warning/info/debug
ipv6: true # 开启 IPv6 总开关,关闭阻断所有 IPv6 链接和屏蔽 DNS 请求 AAAA 记录 ipv6: true # 开启 IPv6 总开关,关闭阻断所有 IPv6 链接和屏蔽 DNS 请求 AAAA 记录
external-controller: 0.0.0.0:9093 # RESTful API 监听地址 external-controller: 0.0.0.0:9093 # RESTful API 监听地址
external-controller-tls: 0.0.0.0:9443 # RESTful API HTTPS 监听地址,需要配置 tls 部分配置文件
# secret: "123456" # `Authorization: Bearer ${secret}` # secret: "123456" # `Authorization: Bearer ${secret}`
# tcp-concurrent: true # TCP并发连接所有IP, 将使用最快握手的TCP # tcp-concurrent: true # TCP并发连接所有IP, 将使用最快握手的TCP
@ -51,8 +51,8 @@ tun:
- 0.0.0.0/1 - 0.0.0.0/1
- 128.0.0.0/1 - 128.0.0.0/1
inet6_route_address: # 启用 auto_route 时使用自定义路由而不是默认路由 inet6_route_address: # 启用 auto_route 时使用自定义路由而不是默认路由
- '::/1' - "::/1"
- '8000::/1' - "8000::/1"
# endpoint_independent_nat: false # 启用独立于端点的 NAT # endpoint_independent_nat: false # 启用独立于端点的 NAT
# include_uid: # UID 规则仅在 Linux 下被支持,并且需要 auto_route # include_uid: # UID 规则仅在 Linux 下被支持,并且需要 auto_route
# - 0 # - 0
@ -219,7 +219,8 @@ proxies:
server: server server: server
port: 443 port: 443
cipher: chacha20-ietf-poly1305 cipher: chacha20-ietf-poly1305
password: "password" password:
"password"
# udp: true # udp: true
# udp-over-tcp: false # udp-over-tcp: false
# ip-version: ipv4 # 设置节点使用 IP 版本可选dualipv4ipv6ipv4-preferipv6-prefer。默认使用 dual # ip-version: ipv4 # 设置节点使用 IP 版本可选dualipv4ipv6ipv4-preferipv6-prefer。默认使用 dual
@ -657,3 +658,7 @@ sub-rules:
- IP-CIDR,1.1.1.1/32,REJECT - IP-CIDR,1.1.1.1/32,REJECT
- IP-CIDR,8.8.8.8/32,ss1 - IP-CIDR,8.8.8.8/32,ss1
- DOMAIN,dns.alidns.com,REJECT - DOMAIN,dns.alidns.com,REJECT
tls:
certificate: string # 证书 PEM 格式,或者 证书的路径
private-key: string # 证书对应的私钥 PEM 格式,或者私钥路径

View File

@ -1,8 +1,6 @@
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"
@ -44,12 +42,8 @@ func Parse(options ...Option) error {
} }
if cfg.General.ExternalController != "" { if cfg.General.ExternalController != "" {
if cfg.General.TLSPort != 0 && (len(cfg.General.PrivateKey) == 0 || len(cfg.General.Cert) == 0) { go route.Start(cfg.General.ExternalController,cfg.General.ExternalControllerTLS,
return errors.New("Must be provided certificates and keys, for tls controller") cfg.General.Secret,cfg.TLS.Certificate,cfg.TLS.PrivateKey)
}
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

@ -4,15 +4,14 @@ import (
"bytes" "bytes"
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"net"
"net/http" "net/http"
"strconv"
"strings" "strings"
"time" "time"
"github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/adapter/inbound"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/log"
CN "github.com/Dreamacro/clash/common/net"
"github.com/Dreamacro/clash/tunnel/statistic" "github.com/Dreamacro/clash/tunnel/statistic"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
@ -43,7 +42,8 @@ func SetUIPath(path string) {
uiPath = C.Path.Resolve(path) uiPath = C.Path.Resolve(path)
} }
func Start(addr string, secret string, tlsPort int, cert string, privateKey string) { func Start(addr string, tlsAddr string, secret string,
certificat, privateKey string) {
if serverAddr != "" { if serverAddr != "" {
return return
} }
@ -58,7 +58,6 @@ func Start(addr string, secret string, tlsPort int, cert string, privateKey stri
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)
@ -85,32 +84,32 @@ func Start(addr string, secret string, tlsPort int, cert string, privateKey stri
}) })
}) })
} }
if tlsPort >0 {
if len(tlsAddr) > 0 {
go func() { go func() {
if host, _, err := net.SplitHostPort(addr); err != nil { c, err := CN.ParseCert(certificat, privateKey)
log.Errorln("External controller tls serve error,%s", err)
} else {
l, err := inbound.Listen("tcp", net.JoinHostPort(host, strconv.Itoa(tlsPort)))
if err != nil { if err != nil {
log.Errorln("External controller tls listen error: %s", err) log.Errorln("External controller tls listen error: %s", err)
return return
} }
l, err := inbound.Listen("tcp", tlsAddr)
if err != nil {
log.Errorln("External controller tls listen error: %s", err)
return
}
serverAddr = l.Addr().String() serverAddr = l.Addr().String()
log.Infoln("RESTful API tls listening at: %s", serverAddr) 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{ tlsServe := &http.Server{
Handler: r, Handler: r,
TLSConfig: &tls.Config{ TLSConfig: &tls.Config{
Certificates: []tls.Certificate{certificate}, Certificates: []tls.Certificate{c},
}, },
} }
if err = tlsServe.ServeTLS(l, "", ""); err != nil { if err = tlsServe.ServeTLS(l, "", ""); err != nil {
log.Errorln("External controller tls serve error: %s", err) log.Errorln("External controller tls serve error: %s", err)
} }
}
}() }()
} }
@ -126,7 +125,6 @@ func Start(addr string, secret string, tlsPort int, cert string, privateKey stri
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 {