feat: add linsters

This commit is contained in:
Skyxim
2022-12-04 13:37:14 +08:00
parent ba884c29bd
commit 4f75201a98
49 changed files with 1018 additions and 306 deletions

View File

@ -15,9 +15,11 @@ import (
"time"
"github.com/Dreamacro/clash/common/utils"
"github.com/Dreamacro/clash/listener/sing_tun"
"github.com/Dreamacro/clash/listener/tunnel"
R "github.com/Dreamacro/clash/rules"
RP "github.com/Dreamacro/clash/rules/provider"
L "github.com/Dreamacro/clash/listener"
"github.com/Dreamacro/clash/adapter"
"github.com/Dreamacro/clash/adapter/outbound"
"github.com/Dreamacro/clash/adapter/outboundgroup"
@ -30,13 +32,11 @@ import (
"github.com/Dreamacro/clash/component/trie"
C "github.com/Dreamacro/clash/constant"
providerTypes "github.com/Dreamacro/clash/constant/provider"
"github.com/Dreamacro/clash/constant/sniffer"
snifferTypes "github.com/Dreamacro/clash/constant/sniffer"
"github.com/Dreamacro/clash/dns"
"github.com/Dreamacro/clash/log"
T "github.com/Dreamacro/clash/tunnel"
"github.com/samber/lo"
"gopkg.in/yaml.v3"
)
@ -149,11 +149,11 @@ type Tun struct {
RedirectToTun []string `yaml:"-" json:"-"`
MTU uint32 `yaml:"mtu" json:"mtu,omitempty"`
Inet4Address []ListenPrefix `yaml:"inet4-address" json:"inet4-address,omitempty"`
Inet6Address []ListenPrefix `yaml:"inet6-address" json:"inet6-address,omitempty"`
Inet4Address []sing_tun.ListenPrefix `yaml:"inet4-address" json:"inet4-address,omitempty"`
Inet6Address []sing_tun.ListenPrefix `yaml:"inet6-address" json:"inet6-address,omitempty"`
StrictRoute bool `yaml:"strict-route" json:"strict-route,omitempty"`
Inet4RouteAddress []ListenPrefix `yaml:"inet4-route-address" json:"inet4-route-address,omitempty"`
Inet6RouteAddress []ListenPrefix `yaml:"inet6-route-address" json:"inet6-route-address,omitempty"`
Inet4RouteAddress []sing_tun.ListenPrefix `yaml:"inet4-route-address" json:"inet4-route-address,omitempty"`
Inet6RouteAddress []sing_tun.ListenPrefix `yaml:"inet6-route-address" json:"inet6-route-address,omitempty"`
IncludeUID []uint32 `yaml:"include-uid" json:"include-uid,omitempty"`
IncludeUIDRange []string `yaml:"include-uid-range" json:"include-uid-range,omitempty"`
ExcludeUID []uint32 `yaml:"exclude-uid" json:"exclude-uid,omitempty"`
@ -165,56 +165,6 @@ type Tun struct {
UDPTimeout int64 `yaml:"udp-timeout" json:"udp-timeout,omitempty"`
}
type ListenPrefix netip.Prefix
func (p ListenPrefix) MarshalJSON() ([]byte, error) {
prefix := netip.Prefix(p)
if !prefix.IsValid() {
return json.Marshal(nil)
}
return json.Marshal(prefix.String())
}
func (p ListenPrefix) MarshalYAML() (interface{}, error) {
prefix := netip.Prefix(p)
if !prefix.IsValid() {
return nil, nil
}
return prefix.String(), nil
}
func (p *ListenPrefix) UnmarshalJSON(bytes []byte) error {
var value string
err := json.Unmarshal(bytes, &value)
if err != nil {
return err
}
prefix, err := netip.ParsePrefix(value)
if err != nil {
return err
}
*p = ListenPrefix(prefix)
return nil
}
func (p *ListenPrefix) UnmarshalYAML(node *yaml.Node) error {
var value string
err := node.Decode(&value)
if err != nil {
return err
}
prefix, err := netip.ParsePrefix(value)
if err != nil {
return err
}
*p = ListenPrefix(prefix)
return nil
}
func (p ListenPrefix) Build() netip.Prefix {
return netip.Prefix(p)
}
// IPTables config
type IPTables struct {
Enable bool `yaml:"enable" json:"enable"`
@ -224,7 +174,7 @@ type IPTables struct {
type Sniffer struct {
Enable bool
Sniffers []sniffer.Type
Sniffers []snifferTypes.Type
Reverses *trie.DomainTrie[struct{}]
ForceDomain *trie.DomainTrie[struct{}]
SkipDomain *trie.DomainTrie[struct{}]
@ -233,7 +183,6 @@ type Sniffer struct {
ParsePureIp bool
}
// Experimental config
type Experimental struct {
Fingerprints []string `yaml:"fingerprints"`
@ -248,12 +197,13 @@ type Config struct {
Hosts *trie.DomainTrie[netip.Addr]
Profile *Profile
Rules []C.Rule
SubRules *map[string][]C.Rule
SubRules map[string][]C.Rule
Users []auth.AuthUser
Proxies map[string]C.Proxy
Listeners map[string]C.NewListener
Providers map[string]providerTypes.ProxyProvider
RuleProviders map[string]providerTypes.RuleProvider
Tunnels []Tunnel
Tunnels []tunnel.Tunnel
Sniffer *Sniffer
TLS *TLS
}
@ -294,10 +244,10 @@ type RawTun struct {
MTU uint32 `yaml:"mtu" json:"mtu,omitempty"`
//Inet4Address []ListenPrefix `yaml:"inet4-address" json:"inet4_address,omitempty"`
Inet6Address []ListenPrefix `yaml:"inet6-address" json:"inet6_address,omitempty"`
Inet6Address []sing_tun.ListenPrefix `yaml:"inet6-address" json:"inet6_address,omitempty"`
StrictRoute bool `yaml:"strict-route" json:"strict_route,omitempty"`
Inet4RouteAddress []ListenPrefix `yaml:"inet4_route_address" json:"inet4_route_address,omitempty"`
Inet6RouteAddress []ListenPrefix `yaml:"inet6_route_address" json:"inet6_route_address,omitempty"`
Inet4RouteAddress []sing_tun.ListenPrefix `yaml:"inet4_route_address" json:"inet4_route_address,omitempty"`
Inet6RouteAddress []sing_tun.ListenPrefix `yaml:"inet6_route_address" json:"inet6_route_address,omitempty"`
IncludeUID []uint32 `yaml:"include-uid" json:"include_uid,omitempty"`
IncludeUIDRange []string `yaml:"include-uid-range" json:"include_uid_range,omitempty"`
ExcludeUID []uint32 `yaml:"exclude-uid" json:"exclude_uid,omitempty"`
@ -322,65 +272,6 @@ type RawTuicServer struct {
MaxUdpRelayPacketSize int `yaml:"max-udp-relay-packet-size" json:"max-udp-relay-packet-size,omitempty"`
}
type tunnel struct {
Network []string `yaml:"network"`
Address string `yaml:"address"`
Target string `yaml:"target"`
Proxy string `yaml:"proxy"`
}
type Tunnel tunnel
// UnmarshalYAML implements yaml.Unmarshaler
func (t *Tunnel) UnmarshalYAML(unmarshal func(any) error) error {
var tp string
if err := unmarshal(&tp); err != nil {
var inner tunnel
if err := unmarshal(&inner); err != nil {
return err
}
*t = Tunnel(inner)
return nil
}
// parse udp/tcp,address,target,proxy
parts := lo.Map(strings.Split(tp, ","), func(s string, _ int) string {
return strings.TrimSpace(s)
})
if len(parts) != 3 && len(parts) != 4 {
return fmt.Errorf("invalid tunnel config %s", tp)
}
network := strings.Split(parts[0], "/")
// validate network
for _, n := range network {
switch n {
case "tcp", "udp":
default:
return fmt.Errorf("invalid tunnel network %s", n)
}
}
// validate address and target
address := parts[1]
target := parts[2]
for _, addr := range []string{address, target} {
if _, _, err := net.SplitHostPort(addr); err != nil {
return fmt.Errorf("invalid tunnel target or address %s", addr)
}
}
*t = Tunnel(tunnel{
Network: network,
Address: address,
Target: target,
})
if len(parts) == 4 {
t.Proxy = parts[3]
}
return nil
}
type RawConfig struct {
Port int `yaml:"port"`
@ -404,7 +295,7 @@ type RawConfig struct {
Secret string `yaml:"secret"`
Interface string `yaml:"interface-name"`
RoutingMark int `yaml:"routing-mark"`
Tunnels []Tunnel `yaml:"tunnels"`
Tunnels []tunnel.Tunnel `yaml:"tunnels"`
GeodataMode bool `yaml:"geodata-mode"`
GeodataLoader string `yaml:"geodata-loader"`
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
@ -426,7 +317,8 @@ type RawConfig struct {
ProxyGroup []map[string]any `yaml:"proxy-groups"`
Rule []string `yaml:"rules"`
SubRules map[string][]string `yaml:"sub-rules"`
RawTLS TLS `yaml:"tls"`
RawTLS TLS `yaml:"tls"`
Listeners []map[string]any `yaml:"listeners"`
}
type RawGeoXUrl struct {
@ -492,7 +384,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
DNSHijack: []string{"0.0.0.0:53"}, // default hijack all dns query
AutoRoute: true,
AutoDetectInterface: true,
Inet6Address: []ListenPrefix{ListenPrefix(netip.MustParsePrefix("fdfe:dcba:9876::1/126"))},
Inet6Address: []sing_tun.ListenPrefix{sing_tun.ListenPrefix(netip.MustParsePrefix("fdfe:dcba:9876::1/126"))},
},
TuicServer: RawTuicServer{
Enable: false,
@ -576,7 +468,7 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
config.Experimental = &rawCfg.Experimental
config.Profile = &rawCfg.Profile
config.IPTables = &rawCfg.IPTables
config.TLS=&rawCfg.RawTLS
config.TLS = &rawCfg.RawTLS
general, err := parseGeneral(rawCfg)
if err != nil {
@ -585,7 +477,6 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
config.General = general
dialer.DefaultInterface.Store(config.General.Interface)
proxies, providers, err := parseProxies(rawCfg)
if err != nil {
return nil, err
@ -593,6 +484,12 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
config.Proxies = proxies
config.Providers = providers
listener, err := parseListeners(rawCfg)
if err != nil {
return nil, err
}
config.Listeners = listener
subRules, ruleProviders, err := parseSubRules(rawCfg, proxies)
if err != nil {
return nil, err
@ -645,7 +542,6 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
return nil, err
}
elapsedTime := time.Since(startTime) / time.Millisecond // duration in ms
log.Infoln("Initial configuration complete, total time: %dms", elapsedTime) //Segment finished in xxm
@ -677,9 +573,9 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
InboundTfo: cfg.InboundTfo,
},
Controller: Controller{
ExternalController: cfg.ExternalController,
ExternalUI: cfg.ExternalUI,
Secret: cfg.Secret,
ExternalController: cfg.ExternalController,
ExternalUI: cfg.ExternalUI,
Secret: cfg.Secret,
ExternalControllerTLS: cfg.ExternalControllerTLS,
},
UnifiedDelay: cfg.UnifiedDelay,
@ -799,9 +695,27 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
return proxies, providersMap, nil
}
func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy) (subRules *map[string][]C.Rule, ruleProviders map[string]providerTypes.RuleProvider, err error) {
func parseListeners(cfg *RawConfig) (listeners map[string]C.NewListener, err error) {
listeners = make(map[string]C.NewListener)
for index, mapping := range cfg.Listeners {
listener, err := L.ParseListener(mapping)
if err != nil {
return nil, fmt.Errorf("proxy %d: %w", index, err)
}
if _, exist := mapping[listener.Name()]; exist {
return nil, fmt.Errorf("listener %s is the duplicate name", listener.Name())
}
listeners[listener.Name()] = listener
}
return
}
func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy) (subRules map[string][]C.Rule, ruleProviders map[string]providerTypes.RuleProvider, err error) {
ruleProviders = map[string]providerTypes.RuleProvider{}
subRules = &map[string][]C.Rule{}
subRules = map[string][]C.Rule{}
log.Infoln("Geodata Loader mode: %s", geodata.LoaderName())
// parse rule provider
for name, mapping := range cfg.RuleProvider {
@ -815,6 +729,9 @@ func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy) (subRules *map[st
}
for name, rawRules := range cfg.SubRules {
if len(name) == 0 {
return nil, nil, fmt.Errorf("sub-rule name is empty")
}
var rules []C.Rule
for idx, line := range rawRules {
rawRule := trimArr(strings.Split(line, ","))
@ -860,7 +777,7 @@ func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy) (subRules *map[st
rules = append(rules, parsed)
}
(*subRules)[name] = rules
subRules[name] = rules
}
if err = verifySubRule(subRules); err != nil {
@ -870,8 +787,8 @@ func parseSubRules(cfg *RawConfig, proxies map[string]C.Proxy) (subRules *map[st
return
}
func verifySubRule(subRules *map[string][]C.Rule) error {
for name := range *subRules {
func verifySubRule(subRules map[string][]C.Rule) error {
for name := range subRules {
err := verifySubRuleCircularReferences(name, subRules, []string{})
if err != nil {
return err
@ -880,7 +797,7 @@ func verifySubRule(subRules *map[string][]C.Rule) error {
return nil
}
func verifySubRuleCircularReferences(n string, subRules *map[string][]C.Rule, arr []string) error {
func verifySubRuleCircularReferences(n string, subRules map[string][]C.Rule, arr []string) error {
isInArray := func(v string, array []string) bool {
for _, c := range array {
if v == c {
@ -891,9 +808,9 @@ func verifySubRuleCircularReferences(n string, subRules *map[string][]C.Rule, ar
}
arr = append(arr, n)
for i, rule := range (*subRules)[n] {
for i, rule := range subRules[n] {
if rule.RuleType() == C.SubRules {
if _, ok := (*subRules)[rule.Adapter()]; !ok {
if _, ok := subRules[rule.Adapter()]; !ok {
return fmt.Errorf("sub-rule[%d:%s] error: [%s] not found", i, n, rule.Adapter())
}
if isInArray(rule.Adapter(), arr) {
@ -909,7 +826,7 @@ func verifySubRuleCircularReferences(n string, subRules *map[string][]C.Rule, ar
return nil
}
func parseRules(cfg *RawConfig, proxies map[string]C.Proxy, subRules *map[string][]C.Rule) ([]C.Rule, error) {
func parseRules(cfg *RawConfig, proxies map[string]C.Proxy, subRules map[string][]C.Rule) ([]C.Rule, error) {
var rules []C.Rule
rulesConfig := cfg.Rule
@ -948,7 +865,7 @@ func parseRules(cfg *RawConfig, proxies map[string]C.Proxy, subRules *map[string
if _, ok := proxies[target]; !ok {
if ruleName != "SUB-RULE" {
return nil, fmt.Errorf("rules[%d] [%s] error: proxy [%s] not found", idx, line, target)
} else if _, ok = (*subRules)[target]; !ok {
} else if _, ok = subRules[target]; !ok {
return nil, fmt.Errorf("rules[%d] [%s] error: sub-rule [%s] not found", idx, line, target)
}
}
@ -1315,7 +1232,7 @@ func parseTun(rawTun RawTun, general *General) error {
RedirectToTun: rawTun.RedirectToTun,
MTU: rawTun.MTU,
Inet4Address: []ListenPrefix{ListenPrefix(tunAddressPrefix)},
Inet4Address: []sing_tun.ListenPrefix{sing_tun.ListenPrefix(tunAddressPrefix)},
Inet6Address: rawTun.Inet6Address,
StrictRoute: rawTun.StrictRoute,
Inet4RouteAddress: rawTun.Inet4RouteAddress,