Feature: add tunnels
This commit is contained in:
@ -22,6 +22,7 @@ import (
|
||||
R "github.com/Dreamacro/clash/rule"
|
||||
T "github.com/Dreamacro/clash/tunnel"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@ -98,6 +99,7 @@ type Config struct {
|
||||
Users []auth.AuthUser
|
||||
Proxies map[string]C.Proxy
|
||||
Providers map[string]providerTypes.ProxyProvider
|
||||
Tunnels []Tunnel
|
||||
}
|
||||
|
||||
type RawDNS struct {
|
||||
@ -122,6 +124,64 @@ type RawFallbackFilter struct {
|
||||
Domain []string `yaml:"domain"`
|
||||
}
|
||||
|
||||
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) != 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,
|
||||
Proxy: parts[3],
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
type RawConfig struct {
|
||||
Port int `yaml:"port"`
|
||||
SocksPort int `yaml:"socks-port"`
|
||||
@ -139,6 +199,7 @@ type RawConfig struct {
|
||||
Secret string `yaml:"secret"`
|
||||
Interface string `yaml:"interface-name"`
|
||||
RoutingMark int `yaml:"routing-mark"`
|
||||
Tunnels []Tunnel `yaml:"tunnels"`
|
||||
|
||||
ProxyProvider map[string]map[string]any `yaml:"proxy-providers"`
|
||||
Hosts map[string]string `yaml:"hosts"`
|
||||
@ -237,6 +298,14 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
||||
|
||||
config.Users = parseAuthentication(rawCfg.Authentication)
|
||||
|
||||
config.Tunnels = rawCfg.Tunnels
|
||||
// verify tunnels
|
||||
for _, t := range config.Tunnels {
|
||||
if _, ok := config.Proxies[t.Proxy]; !ok {
|
||||
return nil, fmt.Errorf("tunnel proxy %s not found", t.Proxy)
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user