add dns patch
This commit is contained in:
21 files changed
+272
-100
No files matched your search
@@ -95,6 +95,8 @@ class LogcatService : Service(), CoroutineScope by MainScope(), IInterface {
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
logChannel.close()
|
||||
|
||||
cancel()
|
||||
|
||||
stopForeground(true)
|
||||
@@ -231,7 +233,7 @@ class LogcatService : Service(), CoroutineScope by MainScope(), IInterface {
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setColor(getColor(R.color.colorAccentService))
|
||||
.setContentTitle(getString(R.string.clash_logcat))
|
||||
.setContentText(getString(R.string.capturing_clash_log))
|
||||
.setContentText(getString(R.string.running))
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(
|
||||
this,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="70dp"
|
||||
android:layout_height="90dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<View
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<string name="cancel">Cancel</string>
|
||||
|
||||
<string name="clash_logcat">Clash Logcat</string>
|
||||
<string name="capturing_clash_log">Capturing clash core log</string>
|
||||
<string name="capturing_clash_log">Capturing logs</string>
|
||||
<string name="history">History</string>
|
||||
<string name="enabled">Enabled</string>
|
||||
<string name="log_viewer">Log Viewer</string>
|
||||
|
||||
@@ -16,9 +16,9 @@ func QueryGeneral() *TunnelGeneral {
|
||||
result := &TunnelGeneral{}
|
||||
|
||||
g := executor.GetGeneral()
|
||||
t := tunnel.Instance()
|
||||
m := tunnel.Mode()
|
||||
|
||||
result.Mode = t.Mode().String()
|
||||
result.Mode = m.String()
|
||||
result.HTTPPort = g.Port
|
||||
result.SocksPort = g.SocksPort
|
||||
result.RedirectPort = g.RedirPort
|
||||
@@ -29,10 +29,10 @@ func QueryGeneral() *TunnelGeneral {
|
||||
func SetProxyMode(mode string) {
|
||||
switch mode {
|
||||
case "Direct":
|
||||
tunnel.Instance().SetMode(tunnel.Direct)
|
||||
tunnel.SetMode(tunnel.Direct)
|
||||
case "Global":
|
||||
tunnel.Instance().SetMode(tunnel.Global)
|
||||
tunnel.SetMode(tunnel.Global)
|
||||
case "Rule":
|
||||
tunnel.Instance().SetMode(tunnel.Rule)
|
||||
tunnel.SetMode(tunnel.Rule)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,27 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/kr328/cfa/profile"
|
||||
)
|
||||
|
||||
func ResetDnsAppend(dns string) {
|
||||
if len(dns) == 0 {
|
||||
profile.NameServersAppend = make([]string, 0)
|
||||
} else {
|
||||
profile.NameServersAppend = strings.Split(dns, ",")
|
||||
}
|
||||
}
|
||||
|
||||
func SetDnsOverrideEnabled(enabled bool) {
|
||||
if enabled {
|
||||
profile.DnsPatch = profile.OptionalDnsPatch
|
||||
} else {
|
||||
profile.DnsPatch = nil
|
||||
}
|
||||
}
|
||||
|
||||
func LoadProfileFile(path, baseDir string, callback DoneCallback) {
|
||||
go func() {
|
||||
call(profile.LoadFromFile(path, baseDir), callback)
|
||||
|
||||
@@ -51,7 +51,7 @@ func StartUrlTest(group string, callback DoneCallback) {
|
||||
go func() {
|
||||
defer callback.Done()
|
||||
|
||||
p := tunnel.Instance().Proxies()[group]
|
||||
p := tunnel.Proxies()[group]
|
||||
|
||||
pa, ok := p.(*outbound.Proxy)
|
||||
if !ok {
|
||||
@@ -88,7 +88,7 @@ func StartUrlTest(group string, callback DoneCallback) {
|
||||
}
|
||||
|
||||
func QueryAllProxyGroups(collection ProxyGroupCollection) {
|
||||
ps := tunnel.Instance().Proxies()
|
||||
ps := tunnel.Proxies()
|
||||
|
||||
for _, p := range ps {
|
||||
pa, ok := p.(*outbound.Proxy)
|
||||
@@ -144,7 +144,7 @@ func QueryAllProxyGroups(collection ProxyGroupCollection) {
|
||||
}
|
||||
|
||||
func SetSelectedProxy(name, proxy string) bool {
|
||||
p := tunnel.Instance().Proxies()[name]
|
||||
p := tunnel.Proxies()[name]
|
||||
if p == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,15 +1,43 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
"github.com/kr328/cfa/tun"
|
||||
)
|
||||
|
||||
type TunCallback interface {
|
||||
OnCreateSocket(fd int)
|
||||
OnStop()
|
||||
}
|
||||
|
||||
var callback TunCallback
|
||||
|
||||
func init() {
|
||||
dialer.DialerHook = onNewDialer
|
||||
dialer.ListenConfigHook = onNewListenConfig
|
||||
}
|
||||
|
||||
func onNewDialer(dialer *net.Dialer) {
|
||||
dialer.Control = onNewSocket
|
||||
}
|
||||
|
||||
func onNewListenConfig(listen *net.ListenConfig) {
|
||||
listen.Control = onNewSocket
|
||||
}
|
||||
|
||||
func onNewSocket(network, address string, c syscall.RawConn) error {
|
||||
if cb := callback; cb != nil {
|
||||
c.Control(func(fd uintptr) {
|
||||
cb.OnCreateSocket(int(fd))
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartTunDevice(fd, mtu int, dns string, cb TunCallback) error {
|
||||
callback = cb
|
||||
|
||||
|
||||
Submodule core/src/main/golang/clash updated: 1de786635c...e0e7605d1a.
@@ -19,6 +19,8 @@ github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=
|
||||
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/chi v4.0.3+incompatible h1:gakN3pDJnzZN5jqFV2TEdF66rTfKeITyR8qu6ekICEY=
|
||||
github.com/go-chi/chi v4.0.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/cors v1.0.0 h1:e6x8k7uWbUwYs+aXDoiUzeQFT6l0cygBYyNhD7/1Tg0=
|
||||
github.com/go-chi/cors v1.0.0/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I=
|
||||
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
|
||||
@@ -50,6 +52,8 @@ github.com/miekg/dns v1.1.24 h1:6G8Eop/HM8hpagajbn0rFQvAKZWiiCa8P6N2I07+wwI=
|
||||
github.com/miekg/dns v1.1.24/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU=
|
||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
|
||||
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/oschwald/geoip2-golang v1.2.1 h1:3iz+jmeJc6fuCyWeKgtXSXu7+zvkxJbHFXkMT5FVebU=
|
||||
github.com/oschwald/geoip2-golang v1.2.1/go.mod h1:0LTTzix/Ao1uMvOhAV4iLU0Lz7eCrP94qZWBTDKf0iE=
|
||||
github.com/oschwald/geoip2-golang v1.3.0 h1:D+Hsdos1NARPbzZ2aInUHZL+dApIzo8E0ErJVsWcku8=
|
||||
@@ -85,6 +89,8 @@ golang.org/x/crypto v0.0.0-20191128160524-b544559bb6d1 h1:anGSYQpPhQwXlwsu5wmfq0
|
||||
golang.org/x/crypto v0.0.0-20191128160524-b544559bb6d1/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 h1:Sy5bstxEqwwbYs6n0/pBuxKENqOeZUgD45Gp3Q3pqLg=
|
||||
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
@@ -95,6 +101,7 @@ golang.org/x/mobile v0.0.0-20191210151939-1a1fef82734d h1:LlA9R5JFi974qK4gm9FRK1
|
||||
golang.org/x/mobile v0.0.0-20191210151939-1a1fef82734d/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
|
||||
golang.org/x/mod v0.1.0 h1:sfUMP1Gu8qASkorDVjnMuvgJzwFbTZSeXFiGBYAVdl4=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -108,6 +115,8 @@ golang.org/x/net v0.0.0-20191207000613-e7e4b65ae663 h1:Dd5RoEW+yQi+9DMybroBctIdy
|
||||
golang.org/x/net v0.0.0-20191207000613-e7e4b65ae663/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||
@@ -133,8 +142,10 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190909214602-067311248421 h1:NmmWqJbt02YJHmp4A4gBXvsXXIzzixjzE1y6PKUyIjk=
|
||||
golang.org/x/tools v0.0.0-20190909214602-067311248421/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/eapache/channels.v1 v1.1.0 h1:5bGAyKKvyCTWjSj7mhefG6Lc68VyN4MH1v8/7OoeeB4=
|
||||
@@ -143,3 +154,5 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -26,7 +26,7 @@ var client = &http.Client{
|
||||
|
||||
client, server := net.Pipe()
|
||||
|
||||
tunnel.Instance().Add(inbound.NewSocket(socks5.ParseAddr(address), server, constant.HTTP, constant.TCP))
|
||||
tunnel.Add(inbound.NewSocket(socks5.ParseAddr(address), server, constant.HTTP, constant.TCP))
|
||||
|
||||
go func() {
|
||||
if ctx == nil || ctx.Done() == nil {
|
||||
|
||||
@@ -3,9 +3,7 @@ package profile
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
|
||||
"github.com/Dreamacro/clash/component/fakeip"
|
||||
"github.com/Dreamacro/clash/config"
|
||||
"github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/dns"
|
||||
@@ -34,6 +32,31 @@ Rule:
|
||||
- 'MATCH,DIRECT'
|
||||
`
|
||||
|
||||
func init() {
|
||||
defaultNameServers := []string{
|
||||
"223.5.5.5",
|
||||
"119.29.29.29",
|
||||
"1.1.1.1",
|
||||
"208.67.222.222",
|
||||
}
|
||||
|
||||
OptionalDnsPatch = &config.RawDNS{
|
||||
Enable: true,
|
||||
IPv6: true,
|
||||
NameServer: defaultNameServers,
|
||||
Fallback: []string{},
|
||||
FallbackFilter: config.RawFallbackFilter{
|
||||
GeoIP: false,
|
||||
IPCIDR: []string{},
|
||||
},
|
||||
Listen: ":0",
|
||||
EnhancedMode: dns.FAKEIP,
|
||||
FakeIPRange: "198.18.0.0/16",
|
||||
FakeIPFilter: []string{},
|
||||
DefaultNameserver: defaultNameServers,
|
||||
}
|
||||
}
|
||||
|
||||
// LoadDefault - load default configure
|
||||
func LoadDefault() {
|
||||
defaultC, err := parseConfig([]byte(defaultConfig), constant.Path.HomeDir())
|
||||
@@ -42,6 +65,9 @@ func LoadDefault() {
|
||||
return
|
||||
}
|
||||
|
||||
DnsPatch = nil
|
||||
NameServersAppend = make([]string, 0)
|
||||
|
||||
executor.ApplyConfig(defaultC, true)
|
||||
|
||||
tun.ResetDnsRedirect()
|
||||
@@ -59,50 +85,12 @@ func LoadFromFile(path, baseDir string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ns := range cfg.DNS.NameServer {
|
||||
log.Infoln("DNS: %s", ns.Addr)
|
||||
}
|
||||
|
||||
executor.ApplyConfig(cfg, true)
|
||||
|
||||
if dns.DefaultResolver == nil && cfg.DNS.Enable {
|
||||
c := cfg.DNS
|
||||
|
||||
r := dns.New(dns.Config{
|
||||
Main: c.NameServer,
|
||||
Fallback: c.Fallback,
|
||||
IPv6: c.IPv6,
|
||||
EnhancedMode: c.EnhancedMode,
|
||||
Pool: c.FakeIPRange,
|
||||
FallbackFilter: dns.FallbackFilter{
|
||||
GeoIP: c.FallbackFilter.GeoIP,
|
||||
IPCIDR: c.FallbackFilter.IPCIDR,
|
||||
},
|
||||
})
|
||||
|
||||
dns.DefaultResolver = r
|
||||
}
|
||||
|
||||
if dns.DefaultResolver == nil {
|
||||
_, ipnet, _ := net.ParseCIDR("198.18.0.1/16")
|
||||
pool, _ := fakeip.New(ipnet, 1000, nil)
|
||||
|
||||
var defaultDNSResolver = dns.New(dns.Config{
|
||||
Main: []dns.NameServer{
|
||||
dns.NameServer{Net: "tcp", Addr: "1.1.1.1:53"},
|
||||
dns.NameServer{Net: "tcp", Addr: "208.67.222.222:53"},
|
||||
dns.NameServer{Net: "", Addr: "119.29.29.29:53"},
|
||||
dns.NameServer{Net: "", Addr: "223.5.5.5:53"},
|
||||
},
|
||||
Fallback: make([]dns.NameServer, 0),
|
||||
IPv6: false,
|
||||
EnhancedMode: dns.FAKEIP,
|
||||
Pool: pool,
|
||||
FallbackFilter: dns.FallbackFilter{
|
||||
GeoIP: false,
|
||||
IPCIDR: make([]*net.IPNet, 0),
|
||||
},
|
||||
})
|
||||
|
||||
dns.DefaultResolver = defaultDNSResolver
|
||||
}
|
||||
|
||||
tun.ResetDnsRedirect()
|
||||
|
||||
log.Infoln("Profile " + path + " loaded")
|
||||
@@ -120,5 +108,14 @@ func parseConfig(data []byte, baseDir string) (*config.Config, error) {
|
||||
raw.ExternalController = ""
|
||||
raw.Rule = append([]string{fmt.Sprintf("IP-CIDR,%s,REJECT", tunAddress)}, raw.Rule...)
|
||||
|
||||
return config.ParseRawConfig(raw, baseDir)
|
||||
patchRawConfig(raw)
|
||||
|
||||
cfg, err := config.ParseRawConfig(raw, baseDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
patchConfig(cfg)
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"github.com/Dreamacro/clash/component/fakeip"
|
||||
"github.com/Dreamacro/clash/config"
|
||||
)
|
||||
|
||||
var (
|
||||
OptionalDnsPatch *config.RawDNS
|
||||
DnsPatch *config.RawDNS
|
||||
NameServersAppend []string
|
||||
|
||||
cachedPool *fakeip.Pool
|
||||
)
|
||||
|
||||
func patchRawConfig(rawConfig *config.RawConfig) {
|
||||
if d := DnsPatch; d != nil {
|
||||
rawConfig.DNS = *d
|
||||
} else if d := OptionalDnsPatch; d != nil {
|
||||
if !rawConfig.DNS.Enable {
|
||||
rawConfig.DNS = *d
|
||||
}
|
||||
}
|
||||
|
||||
if append := NameServersAppend; len(append) > 0 {
|
||||
d := &rawConfig.DNS
|
||||
nameservers := make([]string, len(append)+len(d.NameServer))
|
||||
copy(nameservers, append)
|
||||
copy(nameservers[len(append):], d.NameServer)
|
||||
|
||||
d.NameServer = nameservers
|
||||
}
|
||||
}
|
||||
|
||||
func patchConfig(config *config.Config) {
|
||||
if config.DNS.FakeIPRange != nil {
|
||||
if c := cachedPool; c != nil {
|
||||
if config.DNS.FakeIPRange.Gateway().String() == c.Gateway().String() {
|
||||
config.DNS.FakeIPRange = c
|
||||
}
|
||||
} else {
|
||||
cachedPool = config.DNS.FakeIPRange
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/Dreamacro/clash/dns"
|
||||
"github.com/Dreamacro/clash/component/resolver"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"github.com/Dreamacro/clash/proxy/tun"
|
||||
)
|
||||
@@ -56,5 +56,5 @@ func ResetDnsRedirect() {
|
||||
return
|
||||
}
|
||||
|
||||
(*tunInstance).ReCreateDNSServer(dns.DefaultResolver, dnsAddress)
|
||||
(*tunInstance).ReCreateDNSServer(resolver.DefaultResolver, dnsAddress)
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.github.kr328.clash.core
|
||||
|
||||
import android.content.Context
|
||||
import bridge.Bridge
|
||||
import bridge.TunCallback
|
||||
import com.github.kr328.clash.core.event.EventStream
|
||||
import com.github.kr328.clash.core.event.LogEvent
|
||||
import com.github.kr328.clash.core.model.General
|
||||
@@ -47,15 +48,31 @@ object Clash {
|
||||
fd: Int,
|
||||
mtu: Int,
|
||||
dns: String,
|
||||
onStop: () -> Unit
|
||||
onNewSocket: (Int) -> Boolean,
|
||||
onTunStop: () -> Unit
|
||||
) {
|
||||
Bridge.startTunDevice(fd.toLong(), mtu.toLong(), dns, onStop)
|
||||
Bridge.startTunDevice(fd.toLong(), mtu.toLong(), dns, object: TunCallback {
|
||||
override fun onCreateSocket(fd: Long) {
|
||||
onNewSocket(fd.toInt())
|
||||
}
|
||||
override fun onStop() {
|
||||
onTunStop()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun stopTunDevice() {
|
||||
Bridge.stopTunDevice()
|
||||
}
|
||||
|
||||
fun appendDns(dns: List<String>) {
|
||||
Bridge.resetDnsAppend(dns.joinToString(","))
|
||||
}
|
||||
|
||||
fun setDnsOverrideEnabled(enabled: Boolean) {
|
||||
Bridge.setDnsOverrideEnabled(enabled)
|
||||
}
|
||||
|
||||
fun loadProfile(path: File, baseDir: File): CompletableDeferred<Unit> {
|
||||
return DoneCallbackImpl().apply {
|
||||
Bridge.loadProfileFile(path.absolutePath, baseDir.absolutePath, this)
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.os.PowerManager
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.github.kr328.clash.core.Clash
|
||||
import com.github.kr328.clash.core.utils.Log
|
||||
import com.github.kr328.clash.core.utils.asBytesString
|
||||
import com.github.kr328.clash.core.utils.asSpeedString
|
||||
import kotlinx.coroutines.*
|
||||
@@ -105,10 +106,17 @@ class ClashNotification(private val context: ClashService, enableRefresh: Boolea
|
||||
|
||||
private fun startTicker(): Job {
|
||||
return launch {
|
||||
while (isActive) {
|
||||
tickerChannel.send(Unit)
|
||||
Log.d("Clash Notification Started")
|
||||
|
||||
delay(1000)
|
||||
try {
|
||||
while (isActive) {
|
||||
tickerChannel.send(Unit)
|
||||
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
Log.d("Clash Notification Stopped")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class ClashService : BaseService() {
|
||||
private var stopReason: String? = null
|
||||
private val reloadChannel = Channel<Unit>(Channel.CONFLATED)
|
||||
private val settings: Settings by lazy { Settings(ClashManager(this, this)) }
|
||||
private val profileObserver = object : BroadcastReceiver() {
|
||||
private val reloadReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
if (intent?.`package` != packageName)
|
||||
return
|
||||
@@ -64,7 +64,10 @@ class ClashService : BaseService() {
|
||||
if (startVpn)
|
||||
startService(TunService::class.intent)
|
||||
|
||||
registerReceiver(profileObserver, IntentFilter(Intents.INTENT_ACTION_PROFILE_CHANGED))
|
||||
registerReceiver(reloadReceiver, IntentFilter().apply {
|
||||
addAction(Intents.INTENT_ACTION_PROFILE_CHANGED)
|
||||
addAction(Intents.INTENT_ACTION_NETWORK_CHANGED)
|
||||
})
|
||||
|
||||
reloadChannel.offer(Unit)
|
||||
|
||||
@@ -85,7 +88,7 @@ class ClashService : BaseService() {
|
||||
|
||||
broadcastClashStopped(this, stopReason)
|
||||
|
||||
unregisterReceiver(profileObserver)
|
||||
unregisterReceiver(reloadReceiver)
|
||||
|
||||
isServiceRunning = false
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ object Intents {
|
||||
"${BuildConfig.LIBRARY_PACKAGE_NAME}.intent.action.profile.setup"
|
||||
const val INTENT_ACTION_PROFILE_LOADED =
|
||||
"${BuildConfig.LIBRARY_PACKAGE_NAME}.intent.action.profile.loaded"
|
||||
const val INTENT_ACTION_NETWORK_CHANGED =
|
||||
"${BuildConfig.LIBRARY_PACKAGE_NAME}.intent.action.network.changed"
|
||||
|
||||
const val INTENT_EXTRA_CLASH_STOP_REASON =
|
||||
"${BuildConfig.LIBRARY_PACKAGE_NAME}.intent.extra.clash.stop.reason"
|
||||
|
||||
@@ -11,6 +11,8 @@ class Settings(private val clashManager: IClashManager) {
|
||||
val ACCESS_CONTROL_PACKAGES = PackageListSetting("access_control_packages", emptyList())
|
||||
val DNS_HIJACKING = BooleanSetting("dns_hijacking", true)
|
||||
val NOTIFICATION_REFRESH = BooleanSetting("notification_refresh", true)
|
||||
val AUTO_ADD_SYSTEM_DNS = BooleanSetting("auto_add_system_dns", true)
|
||||
val OVERRIDE_DNS = BooleanSetting("override_dns", true)
|
||||
}
|
||||
|
||||
fun put(key: String, value: String) {
|
||||
|
||||
@@ -5,7 +5,10 @@ import android.os.Build
|
||||
import com.github.kr328.clash.core.Clash
|
||||
import com.github.kr328.clash.core.utils.Log
|
||||
import com.github.kr328.clash.service.net.DefaultNetworkChannel
|
||||
import com.github.kr328.clash.service.util.broadcastNetworkChanged
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.broadcast
|
||||
import java.net.InetAddress
|
||||
|
||||
class TunService : VpnService(), CoroutineScope by MainScope() {
|
||||
companion object {
|
||||
@@ -40,9 +43,9 @@ class TunService : VpnService(), CoroutineScope by MainScope() {
|
||||
|
||||
Log.i("TunService.startTun ${fd.fd}")
|
||||
|
||||
Clash.startTunDevice(fd.fd, VPN_MTU, dnsAddress) {
|
||||
stopSelf()
|
||||
}
|
||||
Clash.setDnsOverrideEnabled(settings.get(Settings.OVERRIDE_DNS))
|
||||
|
||||
Clash.startTunDevice(fd.fd, VPN_MTU, dnsAddress, this::protect, this::stopSelf)
|
||||
|
||||
fd.close()
|
||||
}
|
||||
@@ -64,7 +67,24 @@ class TunService : VpnService(), CoroutineScope by MainScope() {
|
||||
}
|
||||
|
||||
while (isActive) {
|
||||
setUnderlyingNetworks(defaultNetworkChannel.receive()?.let { arrayOf(it) })
|
||||
val d = defaultNetworkChannel.receive()
|
||||
|
||||
if ( d == null ) {
|
||||
setUnderlyingNetworks(null)
|
||||
continue
|
||||
}
|
||||
|
||||
setUnderlyingNetworks(arrayOf(d.first))
|
||||
|
||||
if ( settings.get(Settings.AUTO_ADD_SYSTEM_DNS) ) {
|
||||
withContext(Dispatchers.Default) {
|
||||
Clash.appendDns(d.second.dnsServers
|
||||
.map(InetAddress::getHostName)
|
||||
.filter(String::isNotBlank))
|
||||
}
|
||||
}
|
||||
|
||||
broadcastNetworkChanged(this@TunService)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,12 +127,10 @@ class TunService : VpnService(), CoroutineScope by MainScope() {
|
||||
addDisallowedApplication(app)
|
||||
}
|
||||
}
|
||||
addDisallowedApplication(packageName)
|
||||
}
|
||||
Settings.ACCESS_CONTROL_MODE_WHITELIST -> {
|
||||
for (app in settings.get(Settings.ACCESS_CONTROL_PACKAGES).toSet() -
|
||||
resources.getStringArray(R.array.default_disallow_application) -
|
||||
setOf(packageName)) {
|
||||
resources.getStringArray(R.array.default_disallow_application)) {
|
||||
runCatching {
|
||||
addAllowedApplication(app)
|
||||
}.onFailure {
|
||||
@@ -129,7 +147,6 @@ class TunService : VpnService(), CoroutineScope by MainScope() {
|
||||
Log.w("Package $app not found")
|
||||
}
|
||||
}
|
||||
addDisallowedApplication(packageName)
|
||||
}
|
||||
else -> throw IllegalArgumentException("Invalid mode")
|
||||
}
|
||||
|
||||
@@ -2,40 +2,37 @@
|
||||
package com.github.kr328.clash.service.net
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkRequest
|
||||
import com.github.kr328.clash.core.utils.Log
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import android.net.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
|
||||
class DefaultNetworkChannel(val context: Context, scope: CoroutineScope) :
|
||||
CoroutineScope by scope, Channel<Network?> by Channel(Channel.CONFLATED) {
|
||||
CoroutineScope by scope, Channel<Pair<Network, LinkProperties>?> by Channel(Channel.CONFLATED) {
|
||||
private var currentNetwork: Network? = null
|
||||
private val detectDelayLock = Mutex()
|
||||
private val connectivity = context.getSystemService(ConnectivityManager::class.java)!!
|
||||
private val callback = object : ConnectivityManager.NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
launch {
|
||||
send(rebuildNetworkList())
|
||||
}
|
||||
sendDefaultNetwork(true)
|
||||
}
|
||||
|
||||
override fun onLost(network: Network) {
|
||||
launch {
|
||||
send(rebuildNetworkList())
|
||||
}
|
||||
sendDefaultNetwork(true)
|
||||
}
|
||||
|
||||
override fun onCapabilitiesChanged(
|
||||
network: Network,
|
||||
networkCapabilities: NetworkCapabilities
|
||||
) {
|
||||
launch {
|
||||
send(rebuildNetworkList())
|
||||
}
|
||||
if ( network == currentNetwork &&
|
||||
!networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) )
|
||||
sendDefaultNetwork(true)
|
||||
}
|
||||
|
||||
override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
|
||||
if ( network == currentNetwork )
|
||||
sendDefaultNetwork(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +44,30 @@ class DefaultNetworkChannel(val context: Context, scope: CoroutineScope) :
|
||||
connectivity.unregisterNetworkCallback(callback)
|
||||
}
|
||||
|
||||
private suspend fun rebuildNetworkList(): Network? = withContext(Dispatchers.Default) {
|
||||
private fun sendDefaultNetwork(ignoreSameNetwork: Boolean) {
|
||||
if (detectDelayLock.tryLock()) {
|
||||
launch {
|
||||
delay(1000)
|
||||
|
||||
val network = detectDefaultNetwork()
|
||||
if ( ignoreSameNetwork && network == currentNetwork )
|
||||
return@launch
|
||||
|
||||
currentNetwork = network
|
||||
|
||||
val linkProperties = network?.let { connectivity.getLinkProperties(it) }
|
||||
|
||||
if ( network != null && linkProperties != null )
|
||||
send(network to linkProperties)
|
||||
else
|
||||
send(null)
|
||||
|
||||
detectDelayLock.unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun detectDefaultNetwork(): Network? = withContext(Dispatchers.Default) {
|
||||
return@withContext try {
|
||||
connectivity.allNetworks
|
||||
.asSequence()
|
||||
@@ -71,10 +91,6 @@ class DefaultNetworkChannel(val context: Context, scope: CoroutineScope) :
|
||||
else
|
||||
0
|
||||
}
|
||||
.map {
|
||||
Log.i("Network ${it.first}")
|
||||
it
|
||||
}
|
||||
.map {
|
||||
it.second
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ fun broadcastProfileLoaded(context: Context, profileEntity: ClashProfileEntity)
|
||||
context.sendBroadcastSelf(intent)
|
||||
}
|
||||
|
||||
fun broadcastNetworkChanged(context: Context) {
|
||||
context.sendBroadcastSelf(Intent(Intents.INTENT_ACTION_NETWORK_CHANGED))
|
||||
}
|
||||
|
||||
fun broadcastClashStarted(context: Context) {
|
||||
context.sendBroadcastSelf(Intent(Intents.INTENT_ACTION_CLASH_STARTED))
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user