chore: try to let tun's restful patch api work

This commit is contained in:
wwqgtxx 2022-11-04 08:52:30 +08:00
parent 9a5c0a4b6d
commit e20d01a679
4 changed files with 172 additions and 36 deletions

View file

@ -213,7 +213,6 @@ type Experimental struct {
// Config is clash config manager
type Config struct {
General *General
Tun *Tun
IPTables *IPTables
DNS *DNS
Experimental *Experimental
@ -496,11 +495,10 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) {
}
config.DNS = dnsCfg
tunCfg, err := parseTun(rawCfg.Tun, config.General, dnsCfg)
err = parseTun(rawCfg.Tun, config.General, dnsCfg)
if err != nil {
return nil, err
}
config.Tun = tunCfg
config.Users = parseAuthentication(rawCfg.Authentication)
@ -1126,7 +1124,7 @@ func parseAuthentication(rawRecords []string) []auth.AuthUser {
return users
}
func parseTun(rawTun RawTun, general *General, dnsCfg *DNS) (*Tun, error) {
func parseTun(rawTun RawTun, general *General, dnsCfg *DNS) error {
var dnsHijack []netip.AddrPort
for _, d := range rawTun.DNSHijack {
@ -1136,7 +1134,7 @@ func parseTun(rawTun RawTun, general *General, dnsCfg *DNS) (*Tun, error) {
d = strings.Replace(d, "any", "0.0.0.0", 1)
addrPort, err := netip.ParseAddrPort(d)
if err != nil {
return nil, fmt.Errorf("parse dns-hijack url error: %w", err)
return fmt.Errorf("parse dns-hijack url error: %w", err)
}
dnsHijack = append(dnsHijack, addrPort)
@ -1150,7 +1148,7 @@ func parseTun(rawTun RawTun, general *General, dnsCfg *DNS) (*Tun, error) {
}
tunAddressPrefix = netip.PrefixFrom(tunAddressPrefix.Addr(), 30)
return &Tun{
general.Tun = Tun{
Enable: rawTun.Enable,
Device: rawTun.Device,
Stack: rawTun.Stack,
@ -1174,7 +1172,9 @@ func parseTun(rawTun RawTun, general *General, dnsCfg *DNS) (*Tun, error) {
ExcludePackage: rawTun.ExcludePackage,
EndpointIndependentNat: rawTun.EndpointIndependentNat,
UDPTimeout: rawTun.UDPTimeout,
}, nil
}
return nil
}
func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) {

View file

@ -86,7 +86,7 @@ func ApplyConfig(cfg *config.Config, force bool) {
loadRuleProvider(cfg.RuleProviders)
updateGeneral(cfg.General, force)
updateIPTables(cfg)
updateTun(cfg.Tun)
updateTun(cfg.General)
updateExperimental(cfg)
log.SetLevel(cfg.General.LogLevel)
@ -258,12 +258,12 @@ func loadProxyProvider(proxyProviders map[string]provider.ProxyProvider) {
wg.Wait()
}
func updateTun(tun *config.Tun) {
if tun == nil {
func updateTun(general *config.General) {
if general == nil {
return
}
P.ReCreateTun(*tun, tunnel.TCPIn(), tunnel.UDPIn())
P.ReCreateRedirToTun(tun.RedirectToTun)
P.ReCreateTun(general.Tun, tunnel.TCPIn(), tunnel.UDPIn())
P.ReCreateRedirToTun(general.Tun.RedirectToTun)
}
func updateSniffer(sniffer *config.Sniffer) {
@ -403,7 +403,7 @@ func updateIPTables(cfg *config.Config) {
}
}()
if cfg.Tun.Enable {
if cfg.General.Tun.Enable {
err = fmt.Errorf("when tun is enabled, iptables cannot be set automatically")
return
}

View file

@ -1,14 +1,16 @@
package route
import (
"github.com/Dreamacro/clash/component/dialer"
"net/http"
"net/netip"
"path/filepath"
"sync"
"github.com/Dreamacro/clash/component/dialer"
"github.com/Dreamacro/clash/component/resolver"
"github.com/Dreamacro/clash/config"
"github.com/Dreamacro/clash/constant"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/hub/executor"
P "github.com/Dreamacro/clash/listener"
"github.com/Dreamacro/clash/log"
@ -38,7 +40,7 @@ type configSchema struct {
RedirPort *int `json:"redir-port"`
TProxyPort *int `json:"tproxy-port"`
MixedPort *int `json:"mixed-port"`
Tun *config.Tun `json:"tun"`
Tun *tunSchema `json:"tun"`
AllowLan *bool `json:"allow-lan"`
BindAddress *string `json:"bind-address"`
Mode *tunnel.TunnelMode `json:"mode"`
@ -49,6 +51,32 @@ type configSchema struct {
InterfaceName *string `json:"interface-name"`
}
type tunSchema struct {
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"`
//RedirectToTun []string `yaml:"-" json:"-"`
MTU *uint32 `yaml:"mtu" json:"mtu,omitempty"`
//Inet4Address *[]config.ListenPrefix `yaml:"inet4-address" json:"inet4_address,omitempty"`
Inet6Address *[]config.ListenPrefix `yaml:"inet6-address" json:"inet6_address,omitempty"`
StrictRoute *bool `yaml:"strict-route" json:"strict_route,omitempty"`
Inet4RouteAddress *[]config.ListenPrefix `yaml:"inet4_route_address" json:"inet4_route_address,omitempty"`
Inet6RouteAddress *[]config.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"`
ExcludeUIDRange *[]string `yaml:"exclude-uid-range" json:"exclude_uid_range,omitempty"`
IncludeAndroidUser *[]int `yaml:"include-android-user" json:"include_android_user,omitempty"`
IncludePackage *[]string `yaml:"include-package" json:"include_package,omitempty"`
ExcludePackage *[]string `yaml:"exclude-package" json:"exclude_package,omitempty"`
EndpointIndependentNat *bool `yaml:"endpoint-independent-nat" json:"endpoint_independent_nat,omitempty"`
UDPTimeout *int64 `yaml:"udp-timeout" json:"udp_timeout,omitempty"`
}
func getConfigs(w http.ResponseWriter, r *http.Request) {
general := executor.GetGeneral()
render.JSON(w, r, general)
@ -62,6 +90,64 @@ func pointerOrDefault(p *int, def int) int {
return def
}
func pointerOrDefaultTun(p *tunSchema, def config.Tun) config.Tun {
if p != nil {
def.Enable = p.Enable
if p.Device != nil {
def.Device = *p.Device
}
if p.Stack != nil {
def.Stack = *p.Stack
}
if p.DNSHijack != nil {
def.DNSHijack = *p.DNSHijack
}
if p.AutoRoute != nil {
def.AutoRoute = *p.AutoRoute
}
if p.AutoDetectInterface != nil {
def.AutoDetectInterface = *p.AutoDetectInterface
}
if p.MTU != nil {
def.MTU = *p.MTU
}
//if p.Inet4Address != nil {
// def.Inet4Address = *p.Inet4Address
//}
if p.Inet6Address != nil {
def.Inet6Address = *p.Inet6Address
}
if p.IncludeUID != nil {
def.IncludeUID = *p.IncludeUID
}
if p.IncludeUIDRange != nil {
def.IncludeUIDRange = *p.IncludeUIDRange
}
if p.ExcludeUID != nil {
def.ExcludeUID = *p.ExcludeUID
}
if p.ExcludeUIDRange != nil {
def.ExcludeUIDRange = *p.ExcludeUIDRange
}
if p.IncludeAndroidUser != nil {
def.IncludeAndroidUser = *p.IncludeAndroidUser
}
if p.IncludePackage != nil {
def.IncludePackage = *p.IncludePackage
}
if p.ExcludePackage != nil {
def.ExcludePackage = *p.ExcludePackage
}
if p.EndpointIndependentNat != nil {
def.EndpointIndependentNat = *p.EndpointIndependentNat
}
if p.UDPTimeout != nil {
def.UDPTimeout = *p.UDPTimeout
}
}
return def
}
func patchConfigs(w http.ResponseWriter, r *http.Request) {
general := &configSchema{}
if err := render.DecodeJSON(r.Body, general); err != nil {
@ -100,6 +186,7 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
P.ReCreateRedir(pointerOrDefault(general.RedirPort, ports.RedirPort), tcpIn, udpIn)
P.ReCreateTProxy(pointerOrDefault(general.TProxyPort, ports.TProxyPort), tcpIn, udpIn)
P.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tcpIn, udpIn)
P.ReCreateTun(pointerOrDefaultTun(general.Tun, P.LastTunConf), tcpIn, udpIn)
if general.Mode != nil {
tunnel.SetMode(*general.Mode)

View file

@ -52,7 +52,7 @@ var (
autoRedirMux sync.Mutex
tcMux sync.Mutex
lastTunConf config.Tun
LastTunConf config.Tun
)
type Ports struct {
@ -339,7 +339,7 @@ func ReCreateMixed(port int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.P
func ReCreateTun(tunConf config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) {
tunMux.Lock()
defer func() {
lastTunConf = tunConf
LastTunConf = tunConf
tunMux.Unlock()
}()
@ -351,7 +351,7 @@ func ReCreateTun(tunConf config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *i
}
}()
if !hasTunConfigChange(tunConf) {
if !hasTunConfigChange(&tunConf) {
if tunLister != nil {
tunLister.FlushDefaultInterface()
}
@ -512,34 +512,83 @@ func genAddr(host string, port int, allowLan bool) string {
return fmt.Sprintf("127.0.0.1:%d", port)
}
func hasTunConfigChange(tunConf config.Tun) bool {
if lastTunConf.Enable != tunConf.Enable ||
lastTunConf.Device != tunConf.Device ||
lastTunConf.Stack != tunConf.Stack ||
lastTunConf.AutoRoute != tunConf.AutoRoute ||
lastTunConf.AutoDetectInterface != tunConf.AutoDetectInterface {
func hasTunConfigChange(tunConf *config.Tun) bool {
if LastTunConf.Enable != tunConf.Enable ||
LastTunConf.Device != tunConf.Device ||
LastTunConf.Stack != tunConf.Stack ||
LastTunConf.AutoRoute != tunConf.AutoRoute ||
LastTunConf.AutoDetectInterface != tunConf.AutoDetectInterface ||
LastTunConf.MTU != tunConf.MTU ||
LastTunConf.StrictRoute != tunConf.StrictRoute ||
LastTunConf.EndpointIndependentNat != tunConf.EndpointIndependentNat ||
LastTunConf.UDPTimeout != tunConf.UDPTimeout {
return true
}
if len(lastTunConf.DNSHijack) != len(tunConf.DNSHijack) {
if len(LastTunConf.DNSHijack) != len(tunConf.DNSHijack) {
return true
}
sort.Slice(lastTunConf.DNSHijack, func(i, j int) bool {
return lastTunConf.DNSHijack[i].Addr().Less(lastTunConf.DNSHijack[j].Addr())
})
sort.Slice(tunConf.DNSHijack, func(i, j int) bool {
return tunConf.DNSHijack[i].Addr().Less(tunConf.DNSHijack[j].Addr())
})
for i, dns := range tunConf.DNSHijack {
if dns != lastTunConf.DNSHijack[i] {
return true
}
}
sort.Slice(tunConf.Inet4Address, func(i, j int) bool {
return tunConf.Inet4Address[i].Build().String() < tunConf.Inet4Address[j].Build().String()
})
if slices.Equal(tunConf.Inet4Address, lastTunConf.Inet4Address) && slices.Equal(tunConf.Inet6Address, lastTunConf.Inet6Address) {
sort.Slice(tunConf.Inet6Address, func(i, j int) bool {
return tunConf.Inet6Address[i].Build().String() < tunConf.Inet6Address[j].Build().String()
})
sort.Slice(tunConf.Inet4RouteAddress, func(i, j int) bool {
return tunConf.Inet4RouteAddress[i].Build().String() < tunConf.Inet4RouteAddress[j].Build().String()
})
sort.Slice(tunConf.Inet6RouteAddress, func(i, j int) bool {
return tunConf.Inet6RouteAddress[i].Build().String() < tunConf.Inet6RouteAddress[j].Build().String()
})
sort.Slice(tunConf.IncludeUID, func(i, j int) bool {
return tunConf.IncludeUID[i] < tunConf.IncludeUID[j]
})
sort.Slice(tunConf.IncludeUIDRange, func(i, j int) bool {
return tunConf.IncludeUIDRange[i] < tunConf.IncludeUIDRange[j]
})
sort.Slice(tunConf.ExcludeUID, func(i, j int) bool {
return tunConf.ExcludeUID[i] < tunConf.ExcludeUID[j]
})
sort.Slice(tunConf.ExcludeUIDRange, func(i, j int) bool {
return tunConf.ExcludeUIDRange[i] < tunConf.ExcludeUIDRange[j]
})
sort.Slice(tunConf.IncludeAndroidUser, func(i, j int) bool {
return tunConf.IncludeAndroidUser[i] < tunConf.IncludeAndroidUser[j]
})
sort.Slice(tunConf.IncludePackage, func(i, j int) bool {
return tunConf.IncludePackage[i] < tunConf.IncludePackage[j]
})
sort.Slice(tunConf.ExcludePackage, func(i, j int) bool {
return tunConf.ExcludePackage[i] < tunConf.ExcludePackage[j]
})
if !slices.Equal(tunConf.DNSHijack, LastTunConf.DNSHijack) ||
!slices.Equal(tunConf.Inet4Address, LastTunConf.Inet4Address) ||
!slices.Equal(tunConf.Inet6Address, LastTunConf.Inet6Address) ||
!slices.Equal(tunConf.Inet4RouteAddress, LastTunConf.Inet4RouteAddress) ||
!slices.Equal(tunConf.Inet6RouteAddress, LastTunConf.Inet6RouteAddress) ||
!slices.Equal(tunConf.IncludeUID, LastTunConf.IncludeUID) ||
!slices.Equal(tunConf.IncludeUIDRange, LastTunConf.IncludeUIDRange) ||
!slices.Equal(tunConf.ExcludeUID, LastTunConf.ExcludeUID) ||
!slices.Equal(tunConf.ExcludeUIDRange, LastTunConf.ExcludeUIDRange) ||
!slices.Equal(tunConf.IncludeAndroidUser, LastTunConf.IncludeAndroidUser) ||
!slices.Equal(tunConf.IncludePackage, LastTunConf.IncludePackage) ||
!slices.Equal(tunConf.ExcludePackage, LastTunConf.ExcludePackage) {
return true
}
@ -551,5 +600,5 @@ func Cleanup(wait bool) {
tunLister.Close()
tunLister = nil
}
lastTunConf = config.Tun{}
LastTunConf = config.Tun{}
}