Change: ipv6 logic
This commit is contained in:
parent
84ab3c5708
commit
216116e128
6 changed files with 104 additions and 53 deletions
|
@ -95,6 +95,8 @@ allow-lan: false
|
||||||
# "[aaaa::a8aa:ff:fe09:57d8]": bind a single IPv6 address
|
# "[aaaa::a8aa:ff:fe09:57d8]": bind a single IPv6 address
|
||||||
# bind-address: "*"
|
# bind-address: "*"
|
||||||
|
|
||||||
|
# ipv6: false # when ipv6 is false, each clash dial with ipv6, but it's not affect the response of the dns server, default is false
|
||||||
|
|
||||||
# rule / global / direct (default is rule)
|
# rule / global / direct (default is rule)
|
||||||
mode: rule
|
mode: rule
|
||||||
|
|
||||||
|
@ -133,7 +135,7 @@ experimental:
|
||||||
|
|
||||||
# dns:
|
# dns:
|
||||||
# enable: true # set true to enable dns (default is false)
|
# enable: true # set true to enable dns (default is false)
|
||||||
# ipv6: false # default is false
|
# ipv6: false # it only affect the dns server response, default is false
|
||||||
# listen: 0.0.0.0:53
|
# listen: 0.0.0.0:53
|
||||||
# # default-nameserver: # resolve dns nameserver host, should fill pure IP
|
# # default-nameserver: # resolve dns nameserver host, should fill pure IP
|
||||||
# # - 114.114.114.114
|
# # - 114.114.114.114
|
||||||
|
|
|
@ -12,13 +12,18 @@ var (
|
||||||
// DefaultResolver aim to resolve ip
|
// DefaultResolver aim to resolve ip
|
||||||
DefaultResolver Resolver
|
DefaultResolver Resolver
|
||||||
|
|
||||||
|
// DisableIPv6 means don't resolve ipv6 host
|
||||||
|
// default value is true
|
||||||
|
DisableIPv6 = true
|
||||||
|
|
||||||
// DefaultHosts aim to resolve hosts
|
// DefaultHosts aim to resolve hosts
|
||||||
DefaultHosts = trie.New()
|
DefaultHosts = trie.New()
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrIPNotFound = errors.New("couldn't find ip")
|
ErrIPNotFound = errors.New("couldn't find ip")
|
||||||
ErrIPVersion = errors.New("ip version error")
|
ErrIPVersion = errors.New("ip version error")
|
||||||
|
ErrIPv6Disabled = errors.New("ipv6 disabled")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Resolver interface {
|
type Resolver interface {
|
||||||
|
@ -63,6 +68,10 @@ func ResolveIPv4(host string) (net.IP, error) {
|
||||||
|
|
||||||
// ResolveIPv6 with a host, return ipv6
|
// ResolveIPv6 with a host, return ipv6
|
||||||
func ResolveIPv6(host string) (net.IP, error) {
|
func ResolveIPv6(host string) (net.IP, error) {
|
||||||
|
if DisableIPv6 {
|
||||||
|
return nil, ErrIPv6Disabled
|
||||||
|
}
|
||||||
|
|
||||||
if node := DefaultHosts.Search(host); node != nil {
|
if node := DefaultHosts.Search(host); node != nil {
|
||||||
if ip := node.Data.(net.IP).To16(); ip != nil {
|
if ip := node.Data.(net.IP).To16(); ip != nil {
|
||||||
return ip, nil
|
return ip, nil
|
||||||
|
@ -102,7 +111,12 @@ func ResolveIP(host string) (net.IP, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if DefaultResolver != nil {
|
if DefaultResolver != nil {
|
||||||
|
if DisableIPv6 {
|
||||||
|
return DefaultResolver.ResolveIPv4(host)
|
||||||
|
}
|
||||||
return DefaultResolver.ResolveIP(host)
|
return DefaultResolver.ResolveIP(host)
|
||||||
|
} else if DisableIPv6 {
|
||||||
|
return ResolveIPv4(host)
|
||||||
}
|
}
|
||||||
|
|
||||||
ip := net.ParseIP(host)
|
ip := net.ParseIP(host)
|
||||||
|
|
|
@ -25,18 +25,29 @@ import (
|
||||||
|
|
||||||
// General config
|
// General config
|
||||||
type General struct {
|
type General struct {
|
||||||
Port int `json:"port"`
|
Inbound
|
||||||
SocksPort int `json:"socks-port"`
|
Controller
|
||||||
RedirPort int `json:"redir-port"`
|
Mode T.TunnelMode `json:"mode"`
|
||||||
MixedPort int `json:"mixed-port"`
|
LogLevel log.LogLevel `json:"log-level"`
|
||||||
Authentication []string `json:"authentication"`
|
IPv6 bool `json:"ipv6"`
|
||||||
AllowLan bool `json:"allow-lan"`
|
}
|
||||||
BindAddress string `json:"bind-address"`
|
|
||||||
Mode T.TunnelMode `json:"mode"`
|
// Inbound
|
||||||
LogLevel log.LogLevel `json:"log-level"`
|
type Inbound struct {
|
||||||
ExternalController string `json:"-"`
|
Port int `json:"port"`
|
||||||
ExternalUI string `json:"-"`
|
SocksPort int `json:"socks-port"`
|
||||||
Secret string `json:"-"`
|
RedirPort int `json:"redir-port"`
|
||||||
|
MixedPort int `json:"mixed-port"`
|
||||||
|
Authentication []string `json:"authentication"`
|
||||||
|
AllowLan bool `json:"allow-lan"`
|
||||||
|
BindAddress string `json:"bind-address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller
|
||||||
|
type Controller struct {
|
||||||
|
ExternalController string `json:"-"`
|
||||||
|
ExternalUI string `json:"-"`
|
||||||
|
Secret string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNS config
|
// DNS config
|
||||||
|
@ -104,6 +115,7 @@ type RawConfig struct {
|
||||||
BindAddress string `yaml:"bind-address"`
|
BindAddress string `yaml:"bind-address"`
|
||||||
Mode T.TunnelMode `yaml:"mode"`
|
Mode T.TunnelMode `yaml:"mode"`
|
||||||
LogLevel log.LogLevel `yaml:"log-level"`
|
LogLevel log.LogLevel `yaml:"log-level"`
|
||||||
|
IPv6 bool `yaml:"ipv6"`
|
||||||
ExternalController string `yaml:"external-controller"`
|
ExternalController string `yaml:"external-controller"`
|
||||||
ExternalUI string `yaml:"external-ui"`
|
ExternalUI string `yaml:"external-ui"`
|
||||||
Secret string `yaml:"secret"`
|
Secret string `yaml:"secret"`
|
||||||
|
@ -216,18 +228,9 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseGeneral(cfg *RawConfig) (*General, error) {
|
func parseGeneral(cfg *RawConfig) (*General, error) {
|
||||||
port := cfg.Port
|
|
||||||
socksPort := cfg.SocksPort
|
|
||||||
redirPort := cfg.RedirPort
|
|
||||||
mixedPort := cfg.MixedPort
|
|
||||||
allowLan := cfg.AllowLan
|
|
||||||
bindAddress := cfg.BindAddress
|
|
||||||
externalController := cfg.ExternalController
|
|
||||||
externalUI := cfg.ExternalUI
|
externalUI := cfg.ExternalUI
|
||||||
secret := cfg.Secret
|
|
||||||
mode := cfg.Mode
|
|
||||||
logLevel := cfg.LogLevel
|
|
||||||
|
|
||||||
|
// checkout externalUI exist
|
||||||
if externalUI != "" {
|
if externalUI != "" {
|
||||||
externalUI = C.Path.Resolve(externalUI)
|
externalUI = C.Path.Resolve(externalUI)
|
||||||
|
|
||||||
|
@ -236,20 +239,24 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
general := &General{
|
return &General{
|
||||||
Port: port,
|
Inbound: Inbound{
|
||||||
SocksPort: socksPort,
|
Port: cfg.Port,
|
||||||
RedirPort: redirPort,
|
SocksPort: cfg.SocksPort,
|
||||||
MixedPort: mixedPort,
|
RedirPort: cfg.RedirPort,
|
||||||
AllowLan: allowLan,
|
MixedPort: cfg.MixedPort,
|
||||||
BindAddress: bindAddress,
|
AllowLan: cfg.AllowLan,
|
||||||
Mode: mode,
|
BindAddress: cfg.BindAddress,
|
||||||
LogLevel: logLevel,
|
},
|
||||||
ExternalController: externalController,
|
Controller: Controller{
|
||||||
ExternalUI: externalUI,
|
ExternalController: cfg.ExternalController,
|
||||||
Secret: secret,
|
ExternalUI: cfg.ExternalUI,
|
||||||
}
|
Secret: cfg.Secret,
|
||||||
return general, nil
|
},
|
||||||
|
Mode: cfg.Mode,
|
||||||
|
LogLevel: cfg.LogLevel,
|
||||||
|
IPv6: cfg.IPv6,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]provider.ProxyProvider, err error) {
|
func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[string]provider.ProxyProvider, err error) {
|
||||||
|
|
|
@ -58,9 +58,23 @@ func withFakeIP(fakePool *fakeip.Pool) middleware {
|
||||||
|
|
||||||
func withResolver(resolver *Resolver) handler {
|
func withResolver(resolver *Resolver) handler {
|
||||||
return func(w D.ResponseWriter, r *D.Msg) {
|
return func(w D.ResponseWriter, r *D.Msg) {
|
||||||
|
q := r.Question[0]
|
||||||
|
|
||||||
|
// return a empty AAAA msg when ipv6 disabled
|
||||||
|
if !resolver.ipv6 && q.Qtype == D.TypeAAAA {
|
||||||
|
msg := &D.Msg{}
|
||||||
|
msg.Answer = []D.RR{}
|
||||||
|
|
||||||
|
msg.SetRcode(r, D.RcodeSuccess)
|
||||||
|
msg.Authoritative = true
|
||||||
|
msg.RecursionAvailable = true
|
||||||
|
|
||||||
|
w.WriteMsg(msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
msg, err := resolver.Exchange(r)
|
msg, err := resolver.Exchange(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
q := r.Question[0]
|
|
||||||
log.Debugln("[DNS Server] Exchange %s failed: %v", q.String(), err)
|
log.Debugln("[DNS Server] Exchange %s failed: %v", q.String(), err)
|
||||||
D.HandleFailed(w, r)
|
D.HandleFailed(w, r)
|
||||||
return
|
return
|
||||||
|
|
|
@ -43,6 +43,7 @@ func ReCreateServer(addr string, resolver *Resolver) error {
|
||||||
|
|
||||||
if server.Server != nil {
|
if server.Server != nil {
|
||||||
server.Shutdown()
|
server.Shutdown()
|
||||||
|
server = &Server{}
|
||||||
address = ""
|
address = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/adapters/provider"
|
"github.com/Dreamacro/clash/adapters/provider"
|
||||||
"github.com/Dreamacro/clash/component/auth"
|
"github.com/Dreamacro/clash/component/auth"
|
||||||
|
@ -20,6 +21,10 @@ import (
|
||||||
"github.com/Dreamacro/clash/tunnel"
|
"github.com/Dreamacro/clash/tunnel"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mux sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
// forward compatibility before 1.0
|
// forward compatibility before 1.0
|
||||||
func readRawConfig(path string) ([]byte, error) {
|
func readRawConfig(path string) ([]byte, error) {
|
||||||
data, err := ioutil.ReadFile(path)
|
data, err := ioutil.ReadFile(path)
|
||||||
|
@ -77,10 +82,11 @@ func ParseWithBytes(buf []byte) (*config.Config, error) {
|
||||||
|
|
||||||
// ApplyConfig dispatch configure to all parts
|
// ApplyConfig dispatch configure to all parts
|
||||||
func ApplyConfig(cfg *config.Config, force bool) {
|
func ApplyConfig(cfg *config.Config, force bool) {
|
||||||
|
mux.Lock()
|
||||||
|
defer mux.Unlock()
|
||||||
|
|
||||||
updateUsers(cfg.Users)
|
updateUsers(cfg.Users)
|
||||||
if force {
|
updateGeneral(cfg.General, force)
|
||||||
updateGeneral(cfg.General)
|
|
||||||
}
|
|
||||||
updateProxies(cfg.Proxies, cfg.Providers)
|
updateProxies(cfg.Proxies, cfg.Providers)
|
||||||
updateRules(cfg.Rules)
|
updateRules(cfg.Rules)
|
||||||
updateDNS(cfg.DNS)
|
updateDNS(cfg.DNS)
|
||||||
|
@ -96,15 +102,17 @@ func GetGeneral() *config.General {
|
||||||
}
|
}
|
||||||
|
|
||||||
general := &config.General{
|
general := &config.General{
|
||||||
Port: ports.Port,
|
Inbound: config.Inbound{
|
||||||
SocksPort: ports.SocksPort,
|
Port: ports.Port,
|
||||||
RedirPort: ports.RedirPort,
|
SocksPort: ports.SocksPort,
|
||||||
MixedPort: ports.MixedPort,
|
RedirPort: ports.RedirPort,
|
||||||
Authentication: authenticator,
|
MixedPort: ports.MixedPort,
|
||||||
AllowLan: P.AllowLan(),
|
Authentication: authenticator,
|
||||||
BindAddress: P.BindAddress(),
|
AllowLan: P.AllowLan(),
|
||||||
Mode: tunnel.Mode(),
|
BindAddress: P.BindAddress(),
|
||||||
LogLevel: log.Level(),
|
},
|
||||||
|
Mode: tunnel.Mode(),
|
||||||
|
LogLevel: log.Level(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return general
|
return general
|
||||||
|
@ -166,9 +174,14 @@ func updateRules(rules []C.Rule) {
|
||||||
tunnel.UpdateRules(rules)
|
tunnel.UpdateRules(rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateGeneral(general *config.General) {
|
func updateGeneral(general *config.General, force bool) {
|
||||||
log.SetLevel(general.LogLevel)
|
log.SetLevel(general.LogLevel)
|
||||||
tunnel.SetMode(general.Mode)
|
tunnel.SetMode(general.Mode)
|
||||||
|
resolver.DisableIPv6 = !general.IPv6
|
||||||
|
|
||||||
|
if !force {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
allowLan := general.AllowLan
|
allowLan := general.AllowLan
|
||||||
P.SetAllowLan(allowLan)
|
P.SetAllowLan(allowLan)
|
||||||
|
|
Loading…
Reference in a new issue