2018-11-21 05:47:46 +00:00
|
|
|
package executor
|
|
|
|
|
|
|
|
import (
|
2019-12-01 05:22:47 +00:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
2019-12-08 04:17:24 +00:00
|
|
|
"github.com/Dreamacro/clash/adapters/provider"
|
2019-06-27 09:04:25 +00:00
|
|
|
"github.com/Dreamacro/clash/component/auth"
|
2019-09-11 09:00:55 +00:00
|
|
|
trie "github.com/Dreamacro/clash/component/domain-trie"
|
2018-11-21 05:47:46 +00:00
|
|
|
"github.com/Dreamacro/clash/config"
|
|
|
|
C "github.com/Dreamacro/clash/constant"
|
2018-12-05 13:13:29 +00:00
|
|
|
"github.com/Dreamacro/clash/dns"
|
2018-11-21 05:47:46 +00:00
|
|
|
"github.com/Dreamacro/clash/log"
|
|
|
|
P "github.com/Dreamacro/clash/proxy"
|
2019-06-27 09:04:25 +00:00
|
|
|
authStore "github.com/Dreamacro/clash/proxy/auth"
|
2018-11-21 05:47:46 +00:00
|
|
|
T "github.com/Dreamacro/clash/tunnel"
|
|
|
|
)
|
|
|
|
|
2019-12-01 05:22:47 +00:00
|
|
|
// forward compatibility before 1.0
|
|
|
|
func readRawConfig(path string) ([]byte, error) {
|
|
|
|
data, err := ioutil.ReadFile(path)
|
|
|
|
if err == nil && len(data) != 0 {
|
|
|
|
return data, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if filepath.Ext(path) != ".yaml" {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
path = path[:len(path)-5] + ".yml"
|
|
|
|
if _, fallbackErr := os.Stat(path); fallbackErr == nil {
|
|
|
|
return ioutil.ReadFile(path)
|
|
|
|
}
|
|
|
|
|
|
|
|
return data, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func readConfig(path string) ([]byte, error) {
|
|
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
data, err := readRawConfig(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(data) == 0 {
|
|
|
|
return nil, fmt.Errorf("Configuration file %s is empty", path)
|
|
|
|
}
|
|
|
|
|
|
|
|
return data, err
|
|
|
|
}
|
|
|
|
|
2018-11-21 05:47:46 +00:00
|
|
|
// Parse config with default config path
|
|
|
|
func Parse() (*config.Config, error) {
|
|
|
|
return ParseWithPath(C.Path.Config())
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseWithPath parse config with custom config path
|
|
|
|
func ParseWithPath(path string) (*config.Config, error) {
|
2019-12-01 05:22:47 +00:00
|
|
|
buf, err := readConfig(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return config.Parse(buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse config with default config path
|
|
|
|
func ParseWithBytes(buf []byte) (*config.Config, error) {
|
|
|
|
return ParseWithPath(C.Path.Config())
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ApplyConfig dispatch configure to all parts
|
2018-11-30 09:42:40 +00:00
|
|
|
func ApplyConfig(cfg *config.Config, force bool) {
|
2019-06-27 09:04:25 +00:00
|
|
|
updateUsers(cfg.Users)
|
2018-11-30 09:42:40 +00:00
|
|
|
if force {
|
|
|
|
updateGeneral(cfg.General)
|
|
|
|
}
|
2019-12-08 04:17:24 +00:00
|
|
|
updateProxies(cfg.Proxies, cfg.Providers)
|
2018-11-21 05:47:46 +00:00
|
|
|
updateRules(cfg.Rules)
|
2018-12-05 13:13:29 +00:00
|
|
|
updateDNS(cfg.DNS)
|
2019-09-11 09:00:55 +00:00
|
|
|
updateHosts(cfg.Hosts)
|
2019-04-24 04:02:52 +00:00
|
|
|
updateExperimental(cfg.Experimental)
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func GetGeneral() *config.General {
|
|
|
|
ports := P.GetPorts()
|
2019-06-27 12:45:12 +00:00
|
|
|
authenticator := []string{}
|
|
|
|
if auth := authStore.Authenticator(); auth != nil {
|
|
|
|
authenticator = auth.Users()
|
|
|
|
}
|
|
|
|
|
|
|
|
general := &config.General{
|
2019-06-27 09:04:25 +00:00
|
|
|
Port: ports.Port,
|
|
|
|
SocksPort: ports.SocksPort,
|
|
|
|
RedirPort: ports.RedirPort,
|
2019-06-27 12:45:12 +00:00
|
|
|
Authentication: authenticator,
|
2019-06-27 09:04:25 +00:00
|
|
|
AllowLan: P.AllowLan(),
|
2019-08-08 05:45:07 +00:00
|
|
|
BindAddress: P.BindAddress(),
|
2019-06-27 09:04:25 +00:00
|
|
|
Mode: T.Instance().Mode(),
|
|
|
|
LogLevel: log.Level(),
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
2019-06-27 12:45:12 +00:00
|
|
|
|
|
|
|
return general
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
|
|
|
|
2019-04-24 04:02:52 +00:00
|
|
|
func updateExperimental(c *config.Experimental) {
|
|
|
|
T.Instance().UpdateExperimental(c.IgnoreResolveFail)
|
|
|
|
}
|
|
|
|
|
2018-12-05 13:13:29 +00:00
|
|
|
func updateDNS(c *config.DNS) {
|
|
|
|
if c.Enable == false {
|
2019-06-28 16:58:59 +00:00
|
|
|
dns.DefaultResolver = nil
|
2018-12-05 13:13:29 +00:00
|
|
|
dns.ReCreateServer("", nil)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
r := dns.New(dns.Config{
|
|
|
|
Main: c.NameServer,
|
|
|
|
Fallback: c.Fallback,
|
|
|
|
IPv6: c.IPv6,
|
|
|
|
EnhancedMode: c.EnhancedMode,
|
2019-05-02 16:05:14 +00:00
|
|
|
Pool: c.FakeIPRange,
|
2019-09-15 05:36:45 +00:00
|
|
|
FallbackFilter: dns.FallbackFilter{
|
|
|
|
GeoIP: c.FallbackFilter.GeoIP,
|
|
|
|
IPCIDR: c.FallbackFilter.IPCIDR,
|
|
|
|
},
|
2018-12-05 13:13:29 +00:00
|
|
|
})
|
2019-06-28 16:58:59 +00:00
|
|
|
dns.DefaultResolver = r
|
2019-01-06 06:31:42 +00:00
|
|
|
if err := dns.ReCreateServer(c.Listen, r); err != nil {
|
|
|
|
log.Errorln("Start DNS server error: %s", err.Error())
|
2019-02-02 13:37:36 +00:00
|
|
|
return
|
2019-01-06 06:31:42 +00:00
|
|
|
}
|
2019-06-28 16:58:59 +00:00
|
|
|
|
|
|
|
if c.Listen != "" {
|
|
|
|
log.Infoln("DNS server listening at: %s", c.Listen)
|
|
|
|
}
|
2018-12-05 13:13:29 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 09:00:55 +00:00
|
|
|
func updateHosts(tree *trie.Trie) {
|
|
|
|
dns.DefaultHosts = tree
|
|
|
|
}
|
|
|
|
|
2019-12-08 04:17:24 +00:00
|
|
|
func updateProxies(proxies map[string]C.Proxy, providers map[string]provider.ProxyProvider) {
|
2018-12-05 10:19:30 +00:00
|
|
|
tunnel := T.Instance()
|
2019-12-08 04:17:24 +00:00
|
|
|
oldProviders := tunnel.Providers()
|
2018-12-05 10:19:30 +00:00
|
|
|
|
2019-12-08 04:17:24 +00:00
|
|
|
// close providers goroutine
|
|
|
|
for _, provider := range oldProviders {
|
|
|
|
provider.Destroy()
|
2018-12-05 10:19:30 +00:00
|
|
|
}
|
|
|
|
|
2019-12-08 04:17:24 +00:00
|
|
|
tunnel.UpdateProxies(proxies, providers)
|
2018-11-21 05:47:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func updateRules(rules []C.Rule) {
|
|
|
|
T.Instance().UpdateRules(rules)
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateGeneral(general *config.General) {
|
2018-12-03 15:41:40 +00:00
|
|
|
log.SetLevel(general.LogLevel)
|
|
|
|
T.Instance().SetMode(general.Mode)
|
|
|
|
|
2018-11-21 05:47:46 +00:00
|
|
|
allowLan := general.AllowLan
|
|
|
|
P.SetAllowLan(allowLan)
|
2019-06-27 09:04:25 +00:00
|
|
|
|
2019-08-08 05:45:07 +00:00
|
|
|
bindAddress := general.BindAddress
|
|
|
|
P.SetBindAddress(bindAddress)
|
|
|
|
|
2018-11-21 05:47:46 +00:00
|
|
|
if err := P.ReCreateHTTP(general.Port); err != nil {
|
|
|
|
log.Errorln("Start HTTP server error: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := P.ReCreateSocks(general.SocksPort); err != nil {
|
|
|
|
log.Errorln("Start SOCKS5 server error: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := P.ReCreateRedir(general.RedirPort); err != nil {
|
|
|
|
log.Errorln("Start Redir server error: %s", err.Error())
|
|
|
|
}
|
|
|
|
}
|
2019-06-27 09:04:25 +00:00
|
|
|
|
|
|
|
func updateUsers(users []auth.AuthUser) {
|
|
|
|
authenticator := auth.NewAuthenticator(users)
|
|
|
|
authStore.SetAuthenticator(authenticator)
|
|
|
|
if authenticator != nil {
|
|
|
|
log.Infoln("Authentication of local server updated")
|
|
|
|
}
|
|
|
|
}
|