2018-07-26 00:04:59 +08:00
package config
import (
2021-11-16 20:08:52 +08:00
"container/list"
2020-02-15 21:42:46 +08:00
"errors"
2018-07-26 00:04:59 +08:00
"fmt"
2022-04-23 09:36:11 +08:00
"github.com/Dreamacro/clash/listener/tun/ipstack/commons"
2018-12-05 21:13:29 +08:00
"net"
2022-03-12 02:16:13 +08:00
"net/netip"
2018-12-05 21:13:29 +08:00
"net/url"
2018-07-26 00:04:59 +08:00
"os"
2021-11-17 16:03:47 +08:00
"runtime"
2022-04-21 22:06:08 +08:00
"strconv"
2018-07-26 00:04:59 +08:00
"strings"
2022-02-05 02:42:49 +08:00
"time"
2018-07-26 00:04:59 +08:00
2022-04-21 22:06:08 +08:00
"github.com/Dreamacro/clash/common/utils"
R "github.com/Dreamacro/clash/rule"
RP "github.com/Dreamacro/clash/rule/provider"
2021-06-10 14:05:56 +08:00
"github.com/Dreamacro/clash/adapter"
"github.com/Dreamacro/clash/adapter/outbound"
"github.com/Dreamacro/clash/adapter/outboundgroup"
"github.com/Dreamacro/clash/adapter/provider"
2019-06-27 17:04:25 +08:00
"github.com/Dreamacro/clash/component/auth"
2022-03-09 05:08:35 +08:00
"github.com/Dreamacro/clash/component/dialer"
2019-05-03 00:05:14 +08:00
"github.com/Dreamacro/clash/component/fakeip"
2021-11-17 16:03:47 +08:00
"github.com/Dreamacro/clash/component/geodata"
"github.com/Dreamacro/clash/component/geodata/router"
2020-05-28 12:13:05 +08:00
"github.com/Dreamacro/clash/component/trie"
2018-07-26 00:04:59 +08:00
C "github.com/Dreamacro/clash/constant"
2021-07-04 20:32:59 +08:00
providerTypes "github.com/Dreamacro/clash/constant/provider"
2018-12-05 21:13:29 +08:00
"github.com/Dreamacro/clash/dns"
2018-11-21 13:47:46 +08:00
"github.com/Dreamacro/clash/log"
T "github.com/Dreamacro/clash/tunnel"
2022-03-17 12:26:43 +08:00
"gopkg.in/yaml.v2"
2018-07-26 00:04:59 +08:00
)
2018-08-12 02:23:46 +08:00
// General config
type General struct {
2020-06-18 18:11:02 +08:00
Inbound
Controller
2022-02-05 00:51:06 +08:00
Mode T . TunnelMode ` json:"mode" `
UnifiedDelay bool
LogLevel log . LogLevel ` json:"log-level" `
IPv6 bool ` json:"ipv6" `
Interface string ` json:"-" `
2022-03-16 00:43:08 +08:00
RoutingMark int ` json:"-" `
GeodataMode bool ` json:"geodata-mode" `
2022-02-05 00:51:06 +08:00
GeodataLoader string ` json:"geodata-loader" `
2022-04-23 00:27:22 +08:00
TCPConcurrent bool ` json:"tcp-concurrent" `
2020-06-18 18:11:02 +08:00
}
2022-03-15 02:55:06 +08:00
// Inbound config
2020-06-18 18:11:02 +08:00
type Inbound struct {
Port int ` json:"port" `
SocksPort int ` json:"socks-port" `
RedirPort int ` json:"redir-port" `
2020-11-09 10:46:10 +08:00
TProxyPort int ` json:"tproxy-port" `
2020-06-18 18:11:02 +08:00
MixedPort int ` json:"mixed-port" `
Authentication [ ] string ` json:"authentication" `
AllowLan bool ` json:"allow-lan" `
BindAddress string ` json:"bind-address" `
}
2022-03-15 02:55:06 +08:00
// Controller config
2020-06-18 18:11:02 +08:00
type Controller struct {
ExternalController string ` json:"-" `
ExternalUI string ` json:"-" `
Secret string ` json:"-" `
2018-08-12 02:23:46 +08:00
}
2018-12-05 21:13:29 +08:00
// DNS config
type DNS struct {
2022-03-28 00:44:13 +08:00
Enable bool ` yaml:"enable" `
IPv6 bool ` yaml:"ipv6" `
NameServer [ ] dns . NameServer ` yaml:"nameserver" `
Fallback [ ] dns . NameServer ` yaml:"fallback" `
FallbackFilter FallbackFilter ` yaml:"fallback-filter" `
Listen string ` yaml:"listen" `
EnhancedMode C . DNSMode ` yaml:"enhanced-mode" `
DefaultNameserver [ ] dns . NameServer ` yaml:"default-nameserver" `
FakeIPRange * fakeip . Pool
2022-04-11 06:28:42 +08:00
Hosts * trie . DomainTrie [ netip . Addr ]
2022-03-28 00:44:13 +08:00
NameServerPolicy map [ string ] dns . NameServer
ProxyServerNameserver [ ] dns . NameServer
2019-09-15 13:36:45 +08:00
}
// FallbackFilter config
type FallbackFilter struct {
2021-11-17 16:03:47 +08:00
GeoIP bool ` yaml:"geoip" `
GeoIPCode string ` yaml:"geoip-code" `
2022-04-20 01:52:51 +08:00
IPCIDR [ ] * netip . Prefix ` yaml:"ipcidr" `
2021-11-17 16:03:47 +08:00
Domain [ ] string ` yaml:"domain" `
GeoSite [ ] * router . DomainMatcher ` yaml:"geosite" `
2018-10-02 15:26:36 +08:00
}
2021-11-16 20:08:52 +08:00
var (
GroupsList = list . New ( )
ProxiesList = list . New ( )
ParsingProxiesCallback func ( groupsList * list . List , proxiesList * list . List )
)
2021-02-18 23:41:50 +08:00
// Profile config
type Profile struct {
StoreSelected bool ` yaml:"store-selected" `
2021-11-08 20:48:29 +08:00
StoreFakeIP bool ` yaml:"store-fake-ip" `
2021-02-18 23:41:50 +08:00
}
2021-11-17 16:03:47 +08:00
// Tun config
type Tun struct {
2022-04-23 23:42:42 +08:00
Enable bool ` yaml:"enable" json:"enable" `
Device string ` yaml:"device" json:"device" `
Stack C . TUNStack ` yaml:"stack" json:"stack" `
DNSHijack [ ] netip . AddrPort ` yaml:"dns-hijack" json:"dns-hijack" `
AutoRoute bool ` yaml:"auto-route" json:"auto-route" `
AutoDetectInterface bool ` yaml:"auto-detect-interface" json:"auto-detect-interface" `
2021-11-17 16:03:47 +08:00
}
2022-03-22 05:38:42 +08:00
// IPTables config
type IPTables struct {
2022-03-23 11:04:43 +08:00
Enable bool ` yaml:"enable" json:"enable" `
InboundInterface string ` yaml:"inbound-interface" json:"inbound-interface" `
Bypass [ ] string ` yaml:"bypass" json:"bypass" `
2022-03-22 05:38:42 +08:00
}
2022-04-09 22:30:36 +08:00
type Sniffer struct {
2022-04-17 20:02:13 +08:00
Enable bool
Force bool
Sniffers [ ] C . SnifferType
Reverses * trie . DomainTrie [ bool ]
ForceDomain * trie . DomainTrie [ bool ]
SkipSNI * trie . DomainTrie [ bool ]
2022-04-21 22:06:08 +08:00
Ports * [ ] utils . Range [ uint16 ]
2022-04-09 22:30:36 +08:00
}
2019-04-24 12:02:52 +08:00
// Experimental config
2020-06-27 14:19:31 +08:00
type Experimental struct { }
2019-04-24 12:02:52 +08:00
2021-11-26 00:57:33 +08:00
// Config is clash config manager
2018-07-26 00:04:59 +08:00
type Config struct {
2021-11-17 16:03:47 +08:00
General * General
Tun * Tun
2022-03-23 10:18:08 +08:00
IPTables * IPTables
2021-11-17 16:03:47 +08:00
DNS * DNS
Experimental * Experimental
2022-04-11 06:28:42 +08:00
Hosts * trie . DomainTrie [ netip . Addr ]
2021-11-17 16:03:47 +08:00
Profile * Profile
Rules [ ] C . Rule
Users [ ] auth . AuthUser
Proxies map [ string ] C . Proxy
Providers map [ string ] providerTypes . ProxyProvider
2021-12-02 22:56:17 +08:00
RuleProviders map [ string ] * providerTypes . RuleProvider
2022-04-09 22:30:36 +08:00
Sniffer * Sniffer
2018-07-26 00:04:59 +08:00
}
2020-01-11 00:22:34 +08:00
type RawDNS struct {
2022-03-28 00:44:13 +08:00
Enable bool ` yaml:"enable" `
IPv6 bool ` yaml:"ipv6" `
UseHosts bool ` yaml:"use-hosts" `
NameServer [ ] string ` yaml:"nameserver" `
Fallback [ ] string ` yaml:"fallback" `
FallbackFilter RawFallbackFilter ` yaml:"fallback-filter" `
Listen string ` yaml:"listen" `
EnhancedMode C . DNSMode ` yaml:"enhanced-mode" `
FakeIPRange string ` yaml:"fake-ip-range" `
FakeIPFilter [ ] string ` yaml:"fake-ip-filter" `
DefaultNameserver [ ] string ` yaml:"default-nameserver" `
NameServerPolicy map [ string ] string ` yaml:"nameserver-policy" `
ProxyServerNameserver [ ] string ` yaml:"proxy-server-nameserver" `
2019-09-15 13:36:45 +08:00
}
2020-01-11 00:22:34 +08:00
type RawFallbackFilter struct {
2021-08-25 15:15:13 +08:00
GeoIP bool ` yaml:"geoip" `
GeoIPCode string ` yaml:"geoip-code" `
IPCIDR [ ] string ` yaml:"ipcidr" `
Domain [ ] string ` yaml:"domain" `
2021-11-17 16:03:47 +08:00
GeoSite [ ] string ` yaml:"geosite" `
2018-12-05 21:13:29 +08:00
}
2022-03-09 05:08:35 +08:00
type RawTun struct {
2022-04-07 21:36:19 +08:00
Enable bool ` yaml:"enable" json:"enable" `
Device string ` yaml:"device" json:"device" `
Stack C . TUNStack ` yaml:"stack" json:"stack" `
DNSHijack [ ] string ` yaml:"dns-hijack" json:"dns-hijack" `
AutoRoute bool ` yaml:"auto-route" json:"auto-route" `
AutoDetectInterface bool ` yaml:"auto-detect-interface" `
2022-03-09 05:08:35 +08:00
}
2020-01-11 00:22:34 +08:00
type RawConfig struct {
2018-12-05 21:13:29 +08:00
Port int ` yaml:"port" `
SocksPort int ` yaml:"socks-port" `
RedirPort int ` yaml:"redir-port" `
2020-11-09 10:46:10 +08:00
TProxyPort int ` yaml:"tproxy-port" `
2020-05-12 11:29:53 +08:00
MixedPort int ` yaml:"mixed-port" `
2019-06-27 17:04:25 +08:00
Authentication [ ] string ` yaml:"authentication" `
2018-12-05 21:13:29 +08:00
AllowLan bool ` yaml:"allow-lan" `
2019-08-08 13:45:07 +08:00
BindAddress string ` yaml:"bind-address" `
2020-02-15 21:42:46 +08:00
Mode T . TunnelMode ` yaml:"mode" `
2021-12-26 21:20:41 +08:00
UnifiedDelay bool ` yaml:"unified-delay" `
2018-12-05 21:13:29 +08:00
LogLevel log . LogLevel ` yaml:"log-level" `
2020-06-18 18:11:02 +08:00
IPv6 bool ` yaml:"ipv6" `
2018-12-05 21:13:29 +08:00
ExternalController string ` yaml:"external-controller" `
2018-12-20 01:29:13 +08:00
ExternalUI string ` yaml:"external-ui" `
2018-12-05 21:13:29 +08:00
Secret string ` yaml:"secret" `
2020-06-27 14:19:31 +08:00
Interface string ` yaml:"interface-name" `
2022-03-16 00:43:08 +08:00
RoutingMark int ` yaml:"routing-mark" `
GeodataMode bool ` yaml:"geodata-mode" `
2022-02-05 00:51:06 +08:00
GeodataLoader string ` yaml:"geodata-loader" `
2022-04-23 00:45:43 +08:00
TCPConcurrent bool ` yaml:"tcp-concurrent" json:"tcp-concurrent" `
2018-12-05 21:13:29 +08:00
2022-04-09 22:30:36 +08:00
Sniffer SnifferRaw ` yaml:"sniffer" `
2022-03-16 12:10:13 +08:00
ProxyProvider map [ string ] map [ string ] any ` yaml:"proxy-providers" `
2022-03-17 17:41:02 +08:00
RuleProvider map [ string ] map [ string ] any ` yaml:"rule-providers" `
2022-03-16 12:10:13 +08:00
Hosts map [ string ] string ` yaml:"hosts" `
DNS RawDNS ` yaml:"dns" `
2022-03-16 20:16:30 +08:00
Tun RawTun ` yaml:"tun" `
2022-03-22 05:38:42 +08:00
IPTables IPTables ` yaml:"iptables" `
2022-03-16 12:10:13 +08:00
Experimental Experimental ` yaml:"experimental" `
Profile Profile ` yaml:"profile" `
Proxy [ ] map [ string ] any ` yaml:"proxies" `
ProxyGroup [ ] map [ string ] any ` yaml:"proxy-groups" `
Rule [ ] string ` yaml:"rules" `
2018-12-05 21:13:29 +08:00
}
2022-04-09 22:30:36 +08:00
type SnifferRaw struct {
2022-04-17 20:02:13 +08:00
Enable bool ` yaml:"enable" json:"enable" `
Sniffing [ ] string ` yaml:"sniffing" json:"sniffing" `
Force bool ` yaml:"force" json:"force" `
Reverse [ ] string ` yaml:"reverses" json:"reverses" `
ForceDomain [ ] string ` yaml:"force-domain" json:"force-domain" `
SkipSNI [ ] string ` yaml:"skip-sni" json:"skip-sni" `
2022-04-21 22:06:08 +08:00
Ports [ ] string ` yaml:"port-whitelist" json:"port-whitelist" `
2022-04-09 22:30:36 +08:00
}
2019-12-01 13:22:47 +08:00
// Parse config
func Parse ( buf [ ] byte ) ( * Config , error ) {
2020-01-11 00:22:34 +08:00
rawCfg , err := UnmarshalRawConfig ( buf )
if err != nil {
return nil , err
}
return ParseRawConfig ( rawCfg )
}
2018-10-14 21:22:58 +08:00
2020-01-11 00:22:34 +08:00
func UnmarshalRawConfig ( buf [ ] byte ) ( * RawConfig , error ) {
2021-02-18 23:41:50 +08:00
// config with default value
2020-01-11 00:22:34 +08:00
rawCfg := & RawConfig {
2019-06-27 17:04:25 +08:00
AllowLan : false ,
2019-08-08 13:45:07 +08:00
BindAddress : "*" ,
2019-06-27 17:04:25 +08:00
Mode : T . Rule ,
2022-03-16 17:29:09 +08:00
GeodataMode : C . GeodataMode ,
2022-02-05 00:51:06 +08:00
GeodataLoader : "memconservative" ,
2021-12-26 21:20:41 +08:00
UnifiedDelay : false ,
2019-06-27 17:04:25 +08:00
Authentication : [ ] string { } ,
LogLevel : log . INFO ,
2019-09-11 17:00:55 +08:00
Hosts : map [ string ] string { } ,
2019-06-27 17:04:25 +08:00
Rule : [ ] string { } ,
2022-03-16 12:10:13 +08:00
Proxy : [ ] map [ string ] any { } ,
ProxyGroup : [ ] map [ string ] any { } ,
2022-04-23 00:27:22 +08:00
TCPConcurrent : false ,
2022-03-17 17:41:02 +08:00
Tun : RawTun {
2022-04-07 21:36:19 +08:00
Enable : false ,
Device : "" ,
AutoDetectInterface : true ,
Stack : C . TunGvisor ,
DNSHijack : [ ] string { "0.0.0.0:53" } , // default hijack all dns query
AutoRoute : true ,
2022-03-17 17:41:02 +08:00
} ,
2022-03-22 05:38:42 +08:00
IPTables : IPTables {
Enable : false ,
InboundInterface : "lo" ,
2022-03-23 11:04:43 +08:00
Bypass : [ ] string { } ,
2022-03-22 05:38:42 +08:00
} ,
2020-01-11 00:22:34 +08:00
DNS : RawDNS {
2022-03-09 05:08:35 +08:00
Enable : false ,
UseHosts : true ,
EnhancedMode : C . DNSMapping ,
FakeIPRange : "198.18.0.1/16" ,
2020-01-11 00:22:34 +08:00
FallbackFilter : RawFallbackFilter {
2021-08-25 15:15:13 +08:00
GeoIP : true ,
GeoIPCode : "CN" ,
IPCIDR : [ ] string { } ,
2021-11-17 16:03:47 +08:00
GeoSite : [ ] string { } ,
2019-09-15 13:36:45 +08:00
} ,
2020-02-15 21:42:46 +08:00
DefaultNameserver : [ ] string {
"114.114.114.114" ,
2021-11-17 16:03:47 +08:00
"223.5.5.5" ,
2022-01-05 00:33:42 +08:00
"8.8.8.8" ,
"1.0.0.1" ,
} ,
NameServer : [ ] string {
2022-03-09 05:08:35 +08:00
"https://doh.pub/dns-query" ,
"tls://223.5.5.5:853" ,
2022-01-05 00:33:42 +08:00
} ,
FakeIPFilter : [ ] string {
"dns.msftnsci.com" ,
"www.msftnsci.com" ,
"www.msftconnecttest.com" ,
2020-02-15 21:42:46 +08:00
} ,
2018-12-05 21:52:31 +08:00
} ,
2022-04-09 22:30:36 +08:00
Sniffer : SnifferRaw {
2022-04-17 20:02:13 +08:00
Enable : false ,
Force : false ,
Sniffing : [ ] string { } ,
Reverse : [ ] string { } ,
ForceDomain : [ ] string { } ,
SkipSNI : [ ] string { } ,
2022-04-21 22:06:08 +08:00
Ports : [ ] string { } ,
2022-04-09 22:30:36 +08:00
} ,
2021-02-18 23:41:50 +08:00
Profile : Profile {
StoreSelected : true ,
} ,
2018-10-02 15:26:36 +08:00
}
2020-01-11 00:22:34 +08:00
2021-09-13 23:43:28 +08:00
if err := yaml . Unmarshal ( buf , rawCfg ) ; err != nil {
2018-11-21 13:47:46 +08:00
return nil , err
2018-07-26 00:04:59 +08:00
}
2019-12-01 13:22:47 +08:00
2020-01-11 00:22:34 +08:00
return rawCfg , nil
}
func ParseRawConfig ( rawCfg * RawConfig ) ( * Config , error ) {
config := & Config { }
2022-02-06 01:59:35 +08:00
log . Infoln ( "Start initial configuration in progress" ) //Segment finished in xxm
startTime := time . Now ( )
2019-04-24 12:02:52 +08:00
config . Experimental = & rawCfg . Experimental
2021-02-18 23:41:50 +08:00
config . Profile = & rawCfg . Profile
2022-03-22 05:38:42 +08:00
config . IPTables = & rawCfg . IPTables
2018-07-26 00:04:59 +08:00
2018-11-21 13:47:46 +08:00
general , err := parseGeneral ( rawCfg )
if err != nil {
return nil , err
2018-07-26 00:04:59 +08:00
}
2018-11-21 13:47:46 +08:00
config . General = general
2022-01-05 00:33:42 +08:00
2022-03-09 05:08:35 +08:00
tunCfg , err := parseTun ( rawCfg . Tun , config . General )
if err != nil {
return nil , err
}
config . Tun = tunCfg
dialer . DefaultInterface . Store ( config . General . Interface )
2018-07-26 00:04:59 +08:00
2019-12-08 12:17:24 +08:00
proxies , providers , err := parseProxies ( rawCfg )
2018-11-21 13:47:46 +08:00
if err != nil {
return nil , err
2018-07-26 00:04:59 +08:00
}
2018-11-21 13:47:46 +08:00
config . Proxies = proxies
2019-12-08 12:17:24 +08:00
config . Providers = providers
2018-07-26 00:04:59 +08:00
2021-11-17 16:03:47 +08:00
rules , ruleProviders , err := parseRules ( rawCfg , proxies )
2018-07-26 00:04:59 +08:00
if err != nil {
2018-11-21 13:47:46 +08:00
return nil , err
2018-07-26 00:04:59 +08:00
}
2018-11-21 13:47:46 +08:00
config . Rules = rules
2021-11-17 16:03:47 +08:00
config . RuleProviders = ruleProviders
2018-07-26 00:04:59 +08:00
2020-08-11 10:28:17 +08:00
hosts , err := parseHosts ( rawCfg )
2018-12-05 21:13:29 +08:00
if err != nil {
return nil , err
}
2020-08-11 10:28:17 +08:00
config . Hosts = hosts
2018-12-05 21:13:29 +08:00
2021-11-17 16:03:47 +08:00
dnsCfg , err := parseDNS ( rawCfg , hosts , rules )
2019-09-11 17:00:55 +08:00
if err != nil {
return nil , err
}
2020-08-11 10:28:17 +08:00
config . DNS = dnsCfg
2019-09-11 17:00:55 +08:00
2019-06-27 17:04:25 +08:00
config . Users = parseAuthentication ( rawCfg . Authentication )
2020-01-11 00:22:34 +08:00
2022-04-09 22:30:36 +08:00
config . Sniffer , err = parseSniffer ( rawCfg . Sniffer )
if err != nil {
return nil , err
}
2022-02-06 01:59:35 +08:00
elapsedTime := time . Since ( startTime ) / time . Millisecond // duration in ms
log . Infoln ( "Initial configuration complete, total time: %dms" , elapsedTime ) //Segment finished in xxm
2018-11-21 13:47:46 +08:00
return config , nil
2018-07-26 00:04:59 +08:00
}
2020-01-11 00:22:34 +08:00
func parseGeneral ( cfg * RawConfig ) ( * General , error ) {
2018-12-20 01:29:13 +08:00
externalUI := cfg . ExternalUI
2022-02-05 02:42:49 +08:00
geodata . SetLoader ( cfg . GeodataLoader )
2020-06-18 18:11:02 +08:00
// checkout externalUI exist
2018-12-21 10:55:21 +08:00
if externalUI != "" {
2020-01-30 17:03:11 +08:00
externalUI = C . Path . Resolve ( externalUI )
2018-12-21 10:55:21 +08:00
if _ , err := os . Stat ( externalUI ) ; os . IsNotExist ( err ) {
return nil , fmt . Errorf ( "external-ui: %s not exist" , externalUI )
}
2018-12-20 01:29:13 +08:00
}
2020-06-18 18:11:02 +08:00
return & General {
Inbound : Inbound {
Port : cfg . Port ,
SocksPort : cfg . SocksPort ,
RedirPort : cfg . RedirPort ,
2020-11-09 10:46:10 +08:00
TProxyPort : cfg . TProxyPort ,
2020-06-18 18:11:02 +08:00
MixedPort : cfg . MixedPort ,
AllowLan : cfg . AllowLan ,
BindAddress : cfg . BindAddress ,
} ,
Controller : Controller {
ExternalController : cfg . ExternalController ,
ExternalUI : cfg . ExternalUI ,
Secret : cfg . Secret ,
} ,
2022-02-05 02:42:49 +08:00
UnifiedDelay : cfg . UnifiedDelay ,
Mode : cfg . Mode ,
LogLevel : cfg . LogLevel ,
IPv6 : cfg . IPv6 ,
Interface : cfg . Interface ,
2022-03-16 00:43:08 +08:00
RoutingMark : cfg . RoutingMark ,
GeodataMode : cfg . GeodataMode ,
2022-02-05 02:42:49 +08:00
GeodataLoader : cfg . GeodataLoader ,
2022-04-23 00:27:22 +08:00
TCPConcurrent : cfg . TCPConcurrent ,
2020-06-18 18:11:02 +08:00
} , nil
2018-07-26 00:04:59 +08:00
}
2021-07-04 20:32:59 +08:00
func parseProxies ( cfg * RawConfig ) ( proxies map [ string ] C . Proxy , providersMap map [ string ] providerTypes . ProxyProvider , err error ) {
2019-12-08 12:17:24 +08:00
proxies = make ( map [ string ] C . Proxy )
2021-07-04 20:32:59 +08:00
providersMap = make ( map [ string ] providerTypes . ProxyProvider )
2018-10-02 15:26:36 +08:00
proxiesConfig := cfg . Proxy
groupsConfig := cfg . ProxyGroup
2019-12-08 12:17:24 +08:00
providersConfig := cfg . ProxyProvider
2018-10-02 15:26:36 +08:00
2022-03-15 02:55:06 +08:00
var proxyList [ ] string
2022-03-17 17:41:02 +08:00
_proxiesList := list . New ( )
_groupsList := list . New ( )
2022-03-15 02:55:06 +08:00
2021-06-10 14:05:56 +08:00
proxies [ "DIRECT" ] = adapter . NewProxy ( outbound . NewDirect ( ) )
proxies [ "REJECT" ] = adapter . NewProxy ( outbound . NewReject ( ) )
2022-01-18 21:09:36 +08:00
proxies [ "COMPATIBLE" ] = adapter . NewProxy ( outbound . NewCompatible ( ) )
2022-03-27 23:44:51 +08:00
proxies [ "PASS" ] = adapter . NewProxy ( outbound . NewPass ( ) )
2019-05-15 14:40:14 +08:00
proxyList = append ( proxyList , "DIRECT" , "REJECT" )
2018-07-26 00:04:59 +08:00
// parse proxy
2018-10-02 15:26:36 +08:00
for idx , mapping := range proxiesConfig {
2021-06-10 14:05:56 +08:00
proxy , err := adapter . ParseProxy ( mapping )
2018-10-02 15:26:36 +08:00
if err != nil {
2020-08-25 22:19:59 +08:00
return nil , nil , fmt . Errorf ( "proxy %d: %w" , idx , err )
2018-10-27 12:57:56 +08:00
}
if _ , exist := proxies [ proxy . Name ( ) ] ; exist {
2020-08-25 22:19:59 +08:00
return nil , nil , fmt . Errorf ( "proxy %s is the duplicate name" , proxy . Name ( ) )
2018-10-02 15:26:36 +08:00
}
2019-12-08 12:17:24 +08:00
proxies [ proxy . Name ( ) ] = proxy
2019-05-15 14:40:14 +08:00
proxyList = append ( proxyList , proxy . Name ( ) )
2021-11-16 20:08:52 +08:00
_proxiesList . PushBack ( mapping )
2018-07-26 00:04:59 +08:00
}
2020-04-08 15:49:12 +08:00
// keep the original order of ProxyGroups in config file
2019-08-28 23:44:32 +08:00
for idx , mapping := range groupsConfig {
groupName , existName := mapping [ "name" ] . ( string )
if ! existName {
2020-08-25 22:19:59 +08:00
return nil , nil , fmt . Errorf ( "proxy group %d: missing name" , idx )
2019-08-28 23:44:32 +08:00
}
proxyList = append ( proxyList , groupName )
2021-11-16 20:08:52 +08:00
_groupsList . PushBack ( mapping )
2019-08-28 23:44:32 +08:00
}
// check if any loop exists and sort the ProxyGroups
2019-12-08 12:17:24 +08:00
if err := proxyGroupsDagSort ( groupsConfig ) ; err != nil {
return nil , nil , err
2019-08-12 10:11:44 +08:00
}
2019-08-28 23:44:32 +08:00
2019-12-08 12:17:24 +08:00
// parse and initial providers
for name , mapping := range providersConfig {
if name == provider . ReservedName {
return nil , nil , fmt . Errorf ( "can not defined a provider called `%s`" , provider . ReservedName )
2018-10-02 15:26:36 +08:00
}
2019-12-08 12:17:24 +08:00
pd , err := provider . ParseProxyProvider ( name , mapping )
if err != nil {
2020-06-01 00:39:41 +08:00
return nil , nil , fmt . Errorf ( "parse proxy provider %s error: %w" , name , err )
2018-10-02 15:26:36 +08:00
}
2019-12-08 12:17:24 +08:00
providersMap [ name ] = pd
}
2019-02-15 14:25:20 +08:00
2019-12-08 12:17:24 +08:00
// parse proxy group
for idx , mapping := range groupsConfig {
group , err := outboundgroup . ParseProxyGroup ( mapping , proxies , providersMap )
2018-10-02 15:26:36 +08:00
if err != nil {
2020-08-25 22:19:59 +08:00
return nil , nil , fmt . Errorf ( "proxy group[%d]: %w" , idx , err )
2018-07-26 00:04:59 +08:00
}
2019-12-08 12:17:24 +08:00
groupName := group . Name ( )
if _ , exist := proxies [ groupName ] ; exist {
2020-08-25 22:19:59 +08:00
return nil , nil , fmt . Errorf ( "proxy group %s: the duplicate name" , groupName )
2019-12-08 12:17:24 +08:00
}
2021-06-10 14:05:56 +08:00
proxies [ groupName ] = adapter . NewProxy ( group )
2018-07-26 00:04:59 +08:00
}
2022-03-15 02:55:06 +08:00
var ps [ ] C . Proxy
2019-05-15 14:40:14 +08:00
for _ , v := range proxyList {
2022-03-27 23:44:51 +08:00
if proxies [ v ] . Type ( ) == C . Pass {
continue
}
2019-05-15 14:40:14 +08:00
ps = append ( ps , proxies [ v ] )
2018-10-18 23:24:04 +08:00
}
2020-11-19 00:53:22 +08:00
hc := provider . NewHealthCheck ( ps , "" , 0 , true )
2020-01-11 21:02:55 +08:00
pd , _ := provider . NewCompatibleProvider ( provider . ReservedName , ps , hc )
2019-12-08 12:17:24 +08:00
providersMap [ provider . ReservedName ] = pd
2018-10-18 23:24:04 +08:00
2020-11-13 21:48:52 +08:00
global := outboundgroup . NewSelector (
& outboundgroup . GroupCommonOption {
Name : "GLOBAL" ,
} ,
2021-07-04 20:32:59 +08:00
[ ] providerTypes . ProxyProvider { pd } ,
2020-11-13 21:48:52 +08:00
)
2021-06-10 14:05:56 +08:00
proxies [ "GLOBAL" ] = adapter . NewProxy ( global )
2021-11-16 20:08:52 +08:00
ProxiesList = _proxiesList
GroupsList = _groupsList
if ParsingProxiesCallback != nil {
// refresh tray menu
go ParsingProxiesCallback ( GroupsList , ProxiesList )
}
2019-12-08 12:17:24 +08:00
return proxies , providersMap , nil
2018-07-26 00:04:59 +08:00
}
2021-12-02 22:56:17 +08:00
func parseRules ( cfg * RawConfig , proxies map [ string ] C . Proxy ) ( [ ] C . Rule , map [ string ] * providerTypes . RuleProvider , error ) {
ruleProviders := map [ string ] * providerTypes . RuleProvider { }
2022-02-06 01:59:35 +08:00
log . Infoln ( "Geodata Loader mode: %s" , geodata . LoaderName ( ) )
2021-12-02 22:56:17 +08:00
// parse rule provider
for name , mapping := range cfg . RuleProvider {
2022-01-22 22:10:45 +08:00
rp , err := RP . ParseRuleProvider ( name , mapping )
2021-12-02 22:56:17 +08:00
if err != nil {
return nil , nil , err
}
ruleProviders [ name ] = & rp
2022-01-22 22:10:45 +08:00
RP . SetRuleProvider ( rp )
2021-12-02 22:56:17 +08:00
}
2022-01-05 00:33:42 +08:00
var rules [ ] C . Rule
2018-10-02 15:26:36 +08:00
rulesConfig := cfg . Rule
2021-11-17 16:03:47 +08:00
mode := cfg . Mode
2018-07-26 00:04:59 +08:00
// parse rules
2018-11-21 18:21:24 +08:00
for idx , line := range rulesConfig {
rule := trimArr ( strings . Split ( line , "," ) )
var (
2021-11-17 16:03:47 +08:00
payload string
target string
2022-01-05 00:33:42 +08:00
params [ ] string
2021-11-17 16:03:47 +08:00
ruleName = strings . ToUpper ( rule [ 0 ] )
2018-11-21 18:21:24 +08:00
)
2021-11-17 16:03:47 +08:00
if mode == T . Script && ruleName != "GEOSITE" {
continue
}
2022-03-17 17:41:02 +08:00
l := len ( rule )
2022-03-15 02:55:06 +08:00
2022-01-22 22:10:45 +08:00
if ruleName == "NOT" || ruleName == "OR" || ruleName == "AND" {
2022-03-17 17:41:02 +08:00
target = rule [ l - 1 ]
payload = strings . Join ( rule [ 1 : l - 1 ] , "," )
2022-01-22 22:10:45 +08:00
} else {
2022-03-17 17:41:02 +08:00
if l < 2 {
2022-03-17 23:24:07 +08:00
return nil , nil , fmt . Errorf ( "rules[%d] [%s] error: format invalid" , idx , line )
2022-03-17 17:41:02 +08:00
}
if l < 4 {
rule = append ( rule , make ( [ ] string , 4 - l ) ... )
}
if ruleName == "MATCH" {
l = 2
}
if l >= 3 {
l = 3
2022-01-22 22:10:45 +08:00
payload = rule [ 1 ]
2022-03-17 17:41:02 +08:00
}
target = rule [ l - 1 ]
params = rule [ l : ]
2018-07-26 00:04:59 +08:00
}
2018-11-21 18:21:24 +08:00
2022-04-11 06:28:42 +08:00
if _ , ok := proxies [ target ] ; ! ok {
2021-11-17 16:03:47 +08:00
return nil , nil , fmt . Errorf ( "rules[%d] [%s] error: proxy [%s] not found" , idx , line , target )
2019-06-20 11:03:50 +08:00
}
2019-10-28 00:02:23 +08:00
params = trimArr ( params )
2019-03-30 14:11:59 +08:00
2022-01-23 18:27:44 +08:00
if ruleName == "GEOSITE" {
2022-02-06 04:41:34 +08:00
if err := initGeoSite ( ) ; err != nil {
2022-03-18 01:25:59 +08:00
return nil , nil , fmt . Errorf ( "can't initial GeoSite: %s" , err )
2022-01-23 18:27:44 +08:00
}
2022-03-16 22:55:18 +08:00
initMode = false
2022-01-23 18:27:44 +08:00
}
2021-11-17 16:03:47 +08:00
parsed , parseErr := R . ParseRule ( ruleName , payload , target , params )
2019-10-28 00:02:23 +08:00
if parseErr != nil {
2021-11-17 16:03:47 +08:00
return nil , nil , fmt . Errorf ( "rules[%d] [%s] error: %s" , idx , line , parseErr . Error ( ) )
}
2022-04-11 06:28:42 +08:00
rules = append ( rules , parsed )
2021-11-17 16:03:47 +08:00
}
2022-02-06 01:59:35 +08:00
2021-11-17 16:03:47 +08:00
runtime . GC ( )
2019-03-30 14:11:59 +08:00
2021-11-17 16:03:47 +08:00
return rules , ruleProviders , nil
2018-07-26 00:04:59 +08:00
}
2018-12-05 21:13:29 +08:00
2022-04-11 06:28:42 +08:00
func parseHosts ( cfg * RawConfig ) ( * trie . DomainTrie [ netip . Addr ] , error ) {
tree := trie . New [ netip . Addr ] ( )
2020-06-07 17:25:51 +08:00
// add default hosts
2022-04-11 06:28:42 +08:00
if err := tree . Insert ( "localhost" , netip . AddrFrom4 ( [ 4 ] byte { 127 , 0 , 0 , 1 } ) ) ; err != nil {
2020-09-20 15:53:27 +08:00
log . Errorln ( "insert localhost to host error: %s" , err . Error ( ) )
2020-06-07 17:25:51 +08:00
}
2019-09-11 17:00:55 +08:00
if len ( cfg . Hosts ) != 0 {
for domain , ipStr := range cfg . Hosts {
2022-04-11 06:28:42 +08:00
ip , err := netip . ParseAddr ( ipStr )
if err != nil {
2019-09-11 17:00:55 +08:00
return nil , fmt . Errorf ( "%s is not a valid IP" , ipStr )
}
2022-03-15 02:55:06 +08:00
_ = tree . Insert ( domain , ip )
2019-09-11 17:00:55 +08:00
}
}
return tree , nil
}
2020-02-17 22:13:15 +08:00
func hostWithDefaultPort ( host string , defPort string ) ( string , error ) {
2018-12-05 21:13:29 +08:00
if ! strings . Contains ( host , ":" ) {
host += ":"
}
hostname , port , err := net . SplitHostPort ( host )
if err != nil {
2020-02-17 22:13:15 +08:00
return "" , err
2018-12-05 21:13:29 +08:00
}
if port == "" {
port = defPort
}
2020-02-17 22:13:15 +08:00
return net . JoinHostPort ( hostname , port ) , nil
2018-12-05 21:13:29 +08:00
}
func parseNameServer ( servers [ ] string ) ( [ ] dns . NameServer , error ) {
2022-03-15 02:55:06 +08:00
var nameservers [ ] dns . NameServer
2018-12-05 21:13:29 +08:00
for idx , server := range servers {
// parse without scheme .e.g 8.8.8.8:53
2019-03-01 00:52:30 +08:00
if ! strings . Contains ( server , "://" ) {
server = "udp://" + server
2018-12-05 21:13:29 +08:00
}
u , err := url . Parse ( server )
if err != nil {
return nil , fmt . Errorf ( "DNS NameServer[%d] format error: %s" , idx , err . Error ( ) )
}
2020-02-17 22:13:15 +08:00
var addr , dnsNetType string
2019-03-01 00:52:30 +08:00
switch u . Scheme {
case "udp" :
2020-02-17 22:13:15 +08:00
addr , err = hostWithDefaultPort ( u . Host , "53" )
2019-03-01 00:52:30 +08:00
dnsNetType = "" // UDP
case "tcp" :
2020-02-17 22:13:15 +08:00
addr , err = hostWithDefaultPort ( u . Host , "53" )
2019-03-01 00:52:30 +08:00
dnsNetType = "tcp" // TCP
case "tls" :
2020-02-17 22:13:15 +08:00
addr , err = hostWithDefaultPort ( u . Host , "853" )
2019-03-01 00:52:30 +08:00
dnsNetType = "tcp-tls" // DNS over TLS
2019-06-28 12:29:08 +08:00
case "https" :
clearURL := url . URL { Scheme : "https" , Host : u . Host , Path : u . Path }
2020-02-15 21:42:46 +08:00
addr = clearURL . String ( )
2019-06-28 12:29:08 +08:00
dnsNetType = "https" // DNS over HTTPS
2021-09-06 23:07:34 +08:00
case "dhcp" :
addr = u . Host
dnsNetType = "dhcp" // UDP from DHCP
2022-01-27 12:25:53 +08:00
case "quic" :
addr , err = hostWithDefaultPort ( u . Host , "784" )
dnsNetType = "quic" // DNS over QUIC
2019-03-01 00:52:30 +08:00
default :
2018-12-05 21:13:29 +08:00
return nil , fmt . Errorf ( "DNS NameServer[%d] unsupport scheme: %s" , idx , u . Scheme )
}
2019-06-28 12:29:08 +08:00
2019-03-01 00:52:30 +08:00
if err != nil {
return nil , fmt . Errorf ( "DNS NameServer[%d] format error: %s" , idx , err . Error ( ) )
}
2018-12-05 21:13:29 +08:00
nameservers = append (
nameservers ,
dns . NameServer {
2021-11-17 16:03:47 +08:00
Net : dnsNetType ,
Addr : addr ,
ProxyAdapter : u . Fragment ,
2022-03-12 02:16:13 +08:00
Interface : dialer . DefaultInterface . Load ( ) ,
2018-12-05 21:13:29 +08:00
} ,
)
}
return nameservers , nil
}
2021-05-19 11:17:35 +08:00
func parseNameServerPolicy ( nsPolicy map [ string ] string ) ( map [ string ] dns . NameServer , error ) {
policy := map [ string ] dns . NameServer { }
for domain , server := range nsPolicy {
nameservers , err := parseNameServer ( [ ] string { server } )
if err != nil {
return nil , err
}
if _ , valid := trie . ValidAndSplitDomain ( domain ) ; ! valid {
return nil , fmt . Errorf ( "DNS ResoverRule invalid domain: %s" , domain )
}
policy [ domain ] = nameservers [ 0 ]
}
return policy , nil
}
2022-04-20 01:52:51 +08:00
func parseFallbackIPCIDR ( ips [ ] string ) ( [ ] * netip . Prefix , error ) {
var ipNets [ ] * netip . Prefix
2019-09-15 13:36:45 +08:00
for idx , ip := range ips {
2022-04-20 01:52:51 +08:00
ipnet , err := netip . ParsePrefix ( ip )
2019-09-15 13:36:45 +08:00
if err != nil {
return nil , fmt . Errorf ( "DNS FallbackIP[%d] format error: %s" , idx , err . Error ( ) )
}
2022-04-20 01:52:51 +08:00
ipNets = append ( ipNets , & ipnet )
2019-09-15 13:36:45 +08:00
}
return ipNets , nil
}
2021-11-17 16:03:47 +08:00
func parseFallbackGeoSite ( countries [ ] string , rules [ ] C . Rule ) ( [ ] * router . DomainMatcher , error ) {
2022-01-05 00:33:42 +08:00
var sites [ ] * router . DomainMatcher
2022-01-11 22:17:24 +08:00
if len ( countries ) > 0 {
2022-02-06 04:41:34 +08:00
if err := initGeoSite ( ) ; err != nil {
2022-03-18 01:25:59 +08:00
return nil , fmt . Errorf ( "can't initial GeoSite: %s" , err )
2022-01-11 22:17:24 +08:00
}
}
2021-11-17 16:03:47 +08:00
for _ , country := range countries {
found := false
for _ , rule := range rules {
if rule . RuleType ( ) == C . GEOSITE {
if strings . EqualFold ( country , rule . Payload ( ) ) {
found = true
sites = append ( sites , rule . ( C . RuleGeoSite ) . GetDomainMatcher ( ) )
log . Infoln ( "Start initial GeoSite dns fallback filter from rule `%s`" , country )
}
}
}
if ! found {
matcher , recordsCount , err := geodata . LoadGeoSiteMatcher ( country )
if err != nil {
return nil , err
}
sites = append ( sites , matcher )
log . Infoln ( "Start initial GeoSite dns fallback filter `%s`, records: %d" , country , recordsCount )
}
}
runtime . GC ( )
return sites , nil
}
2022-04-11 06:28:42 +08:00
func parseDNS ( rawCfg * RawConfig , hosts * trie . DomainTrie [ netip . Addr ] , rules [ ] C . Rule ) ( * DNS , error ) {
2021-10-11 20:48:58 +08:00
cfg := rawCfg . DNS
2018-12-05 21:13:29 +08:00
if cfg . Enable && len ( cfg . NameServer ) == 0 {
2020-08-25 22:19:59 +08:00
return nil , fmt . Errorf ( "if DNS configuration is turned on, NameServer cannot be empty" )
2018-12-05 21:13:29 +08:00
}
dnsCfg := & DNS {
Enable : cfg . Enable ,
Listen : cfg . Listen ,
2019-06-29 00:58:59 +08:00
IPv6 : cfg . IPv6 ,
2018-12-05 21:13:29 +08:00
EnhancedMode : cfg . EnhancedMode ,
2019-09-15 13:36:45 +08:00
FallbackFilter : FallbackFilter {
2022-04-20 01:52:51 +08:00
IPCIDR : [ ] * netip . Prefix { } ,
2021-11-17 16:03:47 +08:00
GeoSite : [ ] * router . DomainMatcher { } ,
2019-09-15 13:36:45 +08:00
} ,
2018-12-05 21:13:29 +08:00
}
2019-03-01 00:52:30 +08:00
var err error
if dnsCfg . NameServer , err = parseNameServer ( cfg . NameServer ) ; err != nil {
return nil , err
2018-12-05 21:13:29 +08:00
}
2019-03-01 00:52:30 +08:00
if dnsCfg . Fallback , err = parseNameServer ( cfg . Fallback ) ; err != nil {
return nil , err
2018-12-05 21:13:29 +08:00
}
2021-05-19 11:17:35 +08:00
if dnsCfg . NameServerPolicy , err = parseNameServerPolicy ( cfg . NameServerPolicy ) ; err != nil {
return nil , err
}
2022-03-28 00:44:13 +08:00
if dnsCfg . ProxyServerNameserver , err = parseNameServer ( cfg . ProxyServerNameserver ) ; err != nil {
return nil , err
}
2020-02-15 21:42:46 +08:00
if len ( cfg . DefaultNameserver ) == 0 {
return nil , errors . New ( "default nameserver should have at least one nameserver" )
}
if dnsCfg . DefaultNameserver , err = parseNameServer ( cfg . DefaultNameserver ) ; err != nil {
return nil , err
}
// check default nameserver is pure ip addr
for _ , ns := range dnsCfg . DefaultNameserver {
2020-02-17 22:13:15 +08:00
host , _ , err := net . SplitHostPort ( ns . Addr )
if err != nil || net . ParseIP ( host ) == nil {
2022-04-03 19:14:21 +08:00
u , err := url . Parse ( ns . Addr )
if err != nil || net . ParseIP ( u . Host ) == nil {
return nil , errors . New ( "default nameserver should be pure IP" )
}
2020-02-15 21:42:46 +08:00
}
}
2021-10-18 21:08:27 +08:00
if cfg . EnhancedMode == C . DNSFakeIP {
2022-04-12 00:31:04 +08:00
ipnet , err := netip . ParsePrefix ( cfg . FakeIPRange )
2019-05-03 00:05:14 +08:00
if err != nil {
return nil , err
}
2019-12-28 00:10:06 +08:00
2022-04-11 06:28:42 +08:00
var host * trie . DomainTrie [ bool ]
2019-12-28 00:10:06 +08:00
// fake ip skip host filter
if len ( cfg . FakeIPFilter ) != 0 {
2022-04-11 06:28:42 +08:00
host = trie . New [ bool ] ( )
2019-12-28 00:10:06 +08:00
for _ , domain := range cfg . FakeIPFilter {
2022-03-15 02:55:06 +08:00
_ = host . Insert ( domain , true )
2021-11-17 16:03:47 +08:00
}
}
if len ( dnsCfg . Fallback ) != 0 {
if host == nil {
2022-04-11 06:28:42 +08:00
host = trie . New [ bool ] ( )
2021-11-17 16:03:47 +08:00
}
for _ , fb := range dnsCfg . Fallback {
if net . ParseIP ( fb . Addr ) != nil {
continue
}
2022-01-05 00:33:42 +08:00
_ = host . Insert ( fb . Addr , true )
2019-12-28 00:10:06 +08:00
}
}
2021-10-11 20:48:58 +08:00
pool , err := fakeip . New ( fakeip . Options {
2022-04-12 00:31:04 +08:00
IPNet : & ipnet ,
2021-10-11 20:48:58 +08:00
Size : 1000 ,
Host : host ,
Persistence : rawCfg . Profile . StoreFakeIP ,
} )
2019-05-03 00:05:14 +08:00
if err != nil {
return nil , err
}
dnsCfg . FakeIPRange = pool
}
2021-11-17 16:03:47 +08:00
if len ( cfg . Fallback ) != 0 {
dnsCfg . FallbackFilter . GeoIP = cfg . FallbackFilter . GeoIP
dnsCfg . FallbackFilter . GeoIPCode = cfg . FallbackFilter . GeoIPCode
if fallbackip , err := parseFallbackIPCIDR ( cfg . FallbackFilter . IPCIDR ) ; err == nil {
dnsCfg . FallbackFilter . IPCIDR = fallbackip
}
dnsCfg . FallbackFilter . Domain = cfg . FallbackFilter . Domain
fallbackGeoSite , err := parseFallbackGeoSite ( cfg . FallbackFilter . GeoSite , rules )
if err != nil {
return nil , fmt . Errorf ( "load GeoSite dns fallback filter error, %w" , err )
}
dnsCfg . FallbackFilter . GeoSite = fallbackGeoSite
2019-09-15 13:36:45 +08:00
}
2020-08-11 10:28:17 +08:00
if cfg . UseHosts {
dnsCfg . Hosts = hosts
}
2018-12-05 21:13:29 +08:00
return dnsCfg , nil
}
2019-06-27 17:04:25 +08:00
func parseAuthentication ( rawRecords [ ] string ) [ ] auth . AuthUser {
2022-03-28 16:36:34 +08:00
var users [ ] auth . AuthUser
2019-06-27 17:04:25 +08:00
for _ , line := range rawRecords {
2022-03-16 12:10:13 +08:00
if user , pass , found := strings . Cut ( line , ":" ) ; found {
users = append ( users , auth . AuthUser { User : user , Pass : pass } )
2019-06-27 17:04:25 +08:00
}
}
return users
}
2021-11-17 16:03:47 +08:00
2022-03-09 05:08:35 +08:00
func parseTun ( rawTun RawTun , general * General ) ( * Tun , error ) {
2022-04-07 21:36:19 +08:00
if rawTun . Enable && rawTun . AutoDetectInterface {
2022-03-09 05:08:35 +08:00
autoDetectInterfaceName , err := commons . GetAutoDetectInterface ( )
2022-04-20 22:00:05 +08:00
if err != nil {
2022-03-18 17:41:06 +08:00
log . Warnln ( "Can not find auto detect interface.[%s]" , err )
} else {
log . Warnln ( "Auto detect interface: %s" , autoDetectInterfaceName )
2022-03-09 05:08:35 +08:00
}
general . Interface = autoDetectInterfaceName
}
2022-03-12 02:16:13 +08:00
var dnsHijack [ ] netip . AddrPort
2022-03-15 02:55:06 +08:00
for _ , d := range rawTun . DNSHijack {
if _ , after , ok := strings . Cut ( d , "://" ) ; ok {
d = after
2022-03-09 05:08:35 +08:00
}
2022-04-22 13:30:04 +08:00
d = strings . Replace ( d , "any" , "0.0.0.0" , 1 )
2022-03-15 02:55:06 +08:00
addrPort , err := netip . ParseAddrPort ( d )
2022-03-12 02:16:13 +08:00
if err != nil {
return nil , fmt . Errorf ( "parse dns-hijack url error: %w" , err )
2022-03-09 05:08:35 +08:00
}
2022-03-12 02:16:13 +08:00
dnsHijack = append ( dnsHijack , addrPort )
2022-03-09 05:08:35 +08:00
}
return & Tun {
2022-04-23 23:42:42 +08:00
Enable : rawTun . Enable ,
Device : rawTun . Device ,
Stack : rawTun . Stack ,
DNSHijack : dnsHijack ,
AutoRoute : rawTun . AutoRoute ,
AutoDetectInterface : rawTun . AutoDetectInterface ,
2022-03-09 05:08:35 +08:00
} , nil
}
2022-04-09 22:30:36 +08:00
func parseSniffer ( snifferRaw SnifferRaw ) ( * Sniffer , error ) {
sniffer := & Sniffer {
Enable : snifferRaw . Enable ,
Force : snifferRaw . Force ,
}
2022-04-23 09:36:11 +08:00
var ports [ ] utils . Range [ uint16 ]
2022-04-21 22:06:08 +08:00
if len ( snifferRaw . Ports ) == 0 {
ports = append ( ports , * utils . NewRange [ uint16 ] ( 0 , 65535 ) )
} else {
for _ , portRange := range snifferRaw . Ports {
portRaws := strings . Split ( portRange , "-" )
2022-04-23 09:36:11 +08:00
p , err := strconv . ParseUint ( portRaws [ 0 ] , 10 , 16 )
if err != nil {
return nil , fmt . Errorf ( "%s format error" , portRange )
}
2022-04-21 22:06:08 +08:00
2022-04-23 09:36:11 +08:00
start := uint16 ( p )
if len ( portRaws ) > 1 {
p , err = strconv . ParseUint ( portRaws [ 1 ] , 10 , 16 )
2022-04-21 22:06:08 +08:00
if err != nil {
return nil , fmt . Errorf ( "%s format error" , portRange )
}
end := uint16 ( p )
ports = append ( ports , * utils . NewRange ( start , end ) )
2022-04-23 09:36:11 +08:00
} else {
ports = append ( ports , * utils . NewRange ( start , start ) )
2022-04-21 22:06:08 +08:00
}
}
}
sniffer . Ports = & ports
2022-04-09 22:30:36 +08:00
loadSniffer := make ( map [ C . SnifferType ] struct { } )
for _ , snifferName := range snifferRaw . Sniffing {
find := false
for _ , snifferType := range C . SnifferList {
if snifferType . String ( ) == strings . ToUpper ( snifferName ) {
find = true
loadSniffer [ snifferType ] = struct { } { }
}
}
if ! find {
return nil , fmt . Errorf ( "not find the sniffer[%s]" , snifferName )
}
}
for st := range loadSniffer {
sniffer . Sniffers = append ( sniffer . Sniffers , st )
}
2022-04-17 20:02:13 +08:00
sniffer . ForceDomain = trie . New [ bool ] ( )
for _ , domain := range snifferRaw . ForceDomain {
err := sniffer . ForceDomain . Insert ( domain , true )
2022-04-16 08:21:31 +08:00
if err != nil {
2022-04-17 20:02:13 +08:00
return nil , fmt . Errorf ( "error domian[%s] in force-domain, error:%v" , domain , err )
}
}
sniffer . SkipSNI = trie . New [ bool ] ( )
2022-04-17 21:17:21 +08:00
for _ , domain := range snifferRaw . SkipSNI {
2022-04-17 20:02:13 +08:00
err := sniffer . SkipSNI . Insert ( domain , true )
if err != nil {
return nil , fmt . Errorf ( "error domian[%s] in force-domain, error:%v" , domain , err )
}
}
// Compatibility, remove it when release
if strings . Contains ( C . Version , "alpha" ) || strings . Contains ( C . Version , "develop" ) || strings . Contains ( C . Version , "1.10.0" ) {
2022-04-17 20:03:53 +08:00
log . Warnln ( "Sniffer param force and reverses deprecated, will be removed in the release version, see https://github.com/MetaCubeX/Clash.Meta/commit/48a01adb7a4f38974b9d9639f931d0d245aebf28" )
2022-04-17 20:02:13 +08:00
if snifferRaw . Force {
// match all domain
sniffer . ForceDomain . Insert ( "+" , true )
for _ , domain := range snifferRaw . Reverse {
err := sniffer . SkipSNI . Insert ( domain , true )
if err != nil {
return nil , fmt . Errorf ( "error domian[%s], error:%v" , domain , err )
}
}
} else {
for _ , domain := range snifferRaw . Reverse {
err := sniffer . ForceDomain . Insert ( domain , true )
if err != nil {
return nil , fmt . Errorf ( "error domian[%s], error:%v" , domain , err )
}
}
2022-04-16 08:21:31 +08:00
}
}
2022-04-09 22:30:36 +08:00
return sniffer , nil
}