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

@ -77,12 +77,10 @@ type Inbound struct {
// Controller config // Controller config
type Controller struct { type Controller struct {
ExternalController string `json:"-"` ExternalController string `json:"-"`
ExternalUI string `json:"-"` ExternalControllerTLS string `json:"-"`
Secret string `json:"-"` ExternalUI string `json:"-"`
TLSPort int `json:"-"` Secret string `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 {
@ -381,31 +383,32 @@ func (t *Tunnel) UnmarshalYAML(unmarshal func(any) error) error {
} }
type RawConfig struct { type RawConfig struct {
Port int `yaml:"port"` Port int `yaml:"port"`
SocksPort int `yaml:"socks-port"` SocksPort int `yaml:"socks-port"`
RedirPort int `yaml:"redir-port"` RedirPort int `yaml:"redir-port"`
TProxyPort int `yaml:"tproxy-port"` TProxyPort int `yaml:"tproxy-port"`
MixedPort int `yaml:"mixed-port"` MixedPort int `yaml:"mixed-port"`
ShadowSocksConfig string `yaml:"ss-config"` ShadowSocksConfig string `yaml:"ss-config"`
VmessConfig string `yaml:"vmess-config"` VmessConfig string `yaml:"vmess-config"`
InboundTfo bool `yaml:"inbound-tfo"` InboundTfo bool `yaml:"inbound-tfo"`
Authentication []string `yaml:"authentication"` Authentication []string `yaml:"authentication"`
AllowLan bool `yaml:"allow-lan"` AllowLan bool `yaml:"allow-lan"`
BindAddress string `yaml:"bind-address"` BindAddress string `yaml:"bind-address"`
Mode T.TunnelMode `yaml:"mode"` Mode T.TunnelMode `yaml:"mode"`
UnifiedDelay bool `yaml:"unified-delay"` UnifiedDelay bool `yaml:"unified-delay"`
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"`
ExternalUI string `yaml:"external-ui"` ExternalControllerTLS string `yaml:"external-controller-tls"`
Secret string `yaml:"secret"` ExternalUI string `yaml:"external-ui"`
Interface string `yaml:"interface-name"` Secret string `yaml:"secret"`
RoutingMark int `yaml:"routing-mark"` Interface string `yaml:"interface-name"`
Tunnels []Tunnel `yaml:"tunnels"` RoutingMark int `yaml:"routing-mark"`
GeodataMode bool `yaml:"geodata-mode"` Tunnels []Tunnel `yaml:"tunnels"`
GeodataLoader string `yaml:"geodata-loader"` GeodataMode bool `yaml:"geodata-mode"`
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"` GeodataLoader string `yaml:"geodata-loader"`
EnableProcess bool `yaml:"enable-process" json:"enable-process"` TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
EnableProcess bool `yaml:"enable-process" json:"enable-process"`
Sniffer RawSniffer `yaml:"sniffer"` Sniffer RawSniffer `yaml:"sniffer"`
ProxyProvider map[string]map[string]any `yaml:"proxy-providers"` ProxyProvider map[string]map[string]any `yaml:"proxy-providers"`
@ -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,28 +51,28 @@ 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
# include_uid_range: # 限制被路由的的用户范围 # include_uid_range: # 限制被路由的的用户范围
# - 1000-99999 # - 1000-99999
# exclude_uid: # 排除路由的的用户 # exclude_uid: # 排除路由的的用户
#- 1000 #- 1000
# exclude_uid_range: # 排除路由的的用户范围 # exclude_uid_range: # 排除路由的的用户范围
# - 1000-99999 # - 1000-99999
# Android 用户和应用规则仅在 Android 下被支持 # Android 用户和应用规则仅在 Android 下被支持
# 并且需要 auto_route # 并且需要 auto_route
# include_android_user: # 限制被路由的 Android 用户 # include_android_user: # 限制被路由的 Android 用户
# - 0 # - 0
# - 10 # - 10
# include_package: # 限制被路由的 Android 应用包名 # include_package: # 限制被路由的 Android 应用包名
# - com.android.chrome # - com.android.chrome
# exclude_package: # 排除被路由的 Android 应用包名 # exclude_package: # 排除被路由的 Android 应用包名
# - com.android.captiveportallogin # - com.android.captiveportallogin
#ebpf配置 #ebpf配置
ebpf: ebpf:
@ -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,31 +84,31 @@ 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) if err != nil {
} else { log.Errorln("External controller tls listen error: %s", err)
l, err := inbound.Listen("tcp", net.JoinHostPort(host, strconv.Itoa(tlsPort))) return
if err != nil { }
log.Errorln("External controller tls listen error: %s", err)
return l, err := inbound.Listen("tcp", tlsAddr)
} if err != nil {
serverAddr = l.Addr().String() log.Errorln("External controller tls listen error: %s", err)
log.Infoln("RESTful API tls listening at: %s", serverAddr) return
certificate, err := tls.X509KeyPair([]byte(cert), []byte(privateKey)) }
if err != nil {
log.Errorln("External controller tls sevre error,%s", err) serverAddr = l.Addr().String()
} log.Infoln("RESTful API tls listening at: %s", serverAddr)
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 {