chore: try to let tun's restful patch api work
This commit is contained in:
parent
9a5c0a4b6d
commit
e20d01a679
4 changed files with 172 additions and 36 deletions
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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{}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue