Compare commits

...
20 Commits
Author SHA1 Message Date
kr328 51dab21f6f Chore: bump version 2021-06-13 14:19:00 +08:00
kr328 9e89b3a201 Chore: update clash core 2021-06-13 14:19:00 +08:00
kr328 1c1e2b9f3d Chore: update dependencies 2021-06-13 14:19:00 +08:00
kr328 e2e0238dcd Chore: update tun2socket 2021-06-13 14:19:00 +08:00
Tragic Life 9745e11da4 Chore: update zh-TW translate (#1063) 2021-06-13 12:38:33 +08:00
kr328 8ae7ccbfc9 Chore: add coroutine-android proguard rules 2021-06-13 12:32:34 +08:00
kr328 5a2229596a Chore: use coroutine-android instead of core 2021-06-13 12:32:10 +08:00
kr328 a463d94480 Chore: bump version 2021-06-13 04:22:53 +08:00
kr328 750abc8c71 Improve: enable system proxy by default 2021-06-13 04:22:15 +08:00
kr328 8375fbd8b3 Fix: add http timeout & disable keep-alive 2021-06-13 02:45:20 +08:00
kr328 394e406a36 Chore: update tun2socket 2021-06-13 02:35:35 +08:00
kr328 2645af0d4c Chore: update tun2socket 2021-05-29 19:56:21 +08:00
Kr328 48222c22c8 Fix: should close connection if match blocking list 2021-05-29 00:35:04 +08:00
kr328 d6a71267c6 Chore: bump version 2021-05-28 23:05:09 +08:00
Kr328 0f4a46188c Chore: remove verbose logs 2021-05-28 11:36:29 +08:00
Kr328 5917b90837 Feature: add block loopback connections 2021-05-28 11:32:21 +08:00
Kr328 a222e90d1f Chore: update kaidl 2021-05-28 10:52:41 +08:00
Kr328 3f60d713f8 Chore: update dependencies 2021-05-28 10:52:35 +08:00
Kr328 9cb8433f3b Chore: update tun2socket 2021-05-28 10:43:00 +08:00
Goooler 428ca53532 Chore: use "implementation" & remove "exclude" for buildSrc dependencies (#1034) 2021-05-28 10:37:23 +08:00
37 changed files with 290 additions and 214 deletions

No files matched your search

+5 -1
View File
@@ -26,6 +26,10 @@ android {
resValue("integer", "release_code", "$buildVersionCode")
}
packagingOptions {
exclude("DebugProbesKt.bin")
}
buildTypes {
named("release") {
isMinifyEnabled = true
@@ -121,7 +125,7 @@ dependencies {
premiumImplementation("com.microsoft.appcenter:appcenter-crashes:$appcenterVersion")
implementation(kotlin("stdlib-jdk7"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
implementation("androidx.core:core-ktx:$coreVersion")
implementation("androidx.activity:activity:$activityVersion")
implementation("androidx.appcompat:appcompat:$appcompatVersion")
+26
View File
@@ -31,3 +31,29 @@
public static void checkParameterIsNotNull(...);
public static void checkNotNullParameter(...);
}
# Kotlin Coroutine
# Allow R8 to optimize away the FastServiceLoader.
# Together with ServiceLoader optimization in R8
# this results in direct instantiation when loading Dispatchers.Main
-assumenosideeffects class kotlinx.coroutines.internal.MainDispatcherLoader {
boolean FAST_SERVICE_LOADER_ENABLED return false;
}
-assumenosideeffects class kotlinx.coroutines.internal.FastServiceLoaderKt {
boolean ANDROID_DETECTED return true;
}
-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}
# Disable support for "Missing Main Dispatcher", since we always have Android main dispatcher
-assumenosideeffects class kotlinx.coroutines.internal.MainDispatchersKt {
boolean SUPPORT_MISSING return false;
}
# Statically turn off all debugging facilities and assertions
-assumenosideeffects class kotlinx.coroutines.DebugKt {
boolean getASSERTIONS_ENABLED() return false;
boolean getDEBUG() return false;
boolean getRECOVER_STACK_TRACES() return false;
}
+5 -15
View File
@@ -1,5 +1,5 @@
plugins {
kotlin("jvm") version "1.5.0"
kotlin("jvm") version "1.5.10"
`java-gradle-plugin`
}
@@ -9,20 +9,10 @@ repositories {
}
dependencies {
implementation(kotlin("stdlib"))
compileOnly(gradleApi())
api(kotlin("gradle-plugin"))
api(kotlin("serialization"))
api("com.android.tools.build:gradle:4.2.1") {
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk8")
exclude("org.jetbrains.kotlin", "kotlin-stdlib-jdk7")
exclude("org.jetbrains.kotlin", "kotlin-reflect")
}
api("com.google.devtools.ksp:symbol-processing-gradle-plugin:1.5.0-1.0.0-alpha10") {
exclude("com.android.tools.build", "gradle")
}
implementation(kotlin("gradle-plugin"))
implementation(kotlin("serialization"))
implementation("com.android.tools.build:gradle:4.2.1")
implementation("com.google.devtools.ksp:symbol-processing-gradle-plugin:1.5.10-1.0.0-beta01")
}
gradlePlugin {
+2 -2
View File
@@ -1,7 +1,7 @@
import org.gradle.api.Project
const val buildVersionCode = 204005
const val buildVersionName = "2.4.5"
const val buildVersionCode = 204008
const val buildVersionName = "2.4.8"
const val buildMinSdkVersion = 21
const val buildTargetSdkVersion = 30
+2 -2
View File
@@ -4,10 +4,10 @@ const val roomVersion = "2.3.0"
const val coreVersion = "1.5.0"
const val appcompatVersion = "1.3.0"
const val muiltprocessVersion = "1.0.0"
const val appcenterVersion = "4.1.1"
const val appcenterVersion = "4.2.0"
const val serializationVersion = "1.2.1"
const val materialVersion = "1.3.0"
const val coordinatorlayoutVersion = "1.1.0"
const val recyclerviewVersion = "1.2.0"
const val recyclerviewVersion = "1.2.1"
const val fragmentVersion = "1.3.4"
const val viewpagerVersion = "1.0.0"
+1 -1
View File
@@ -41,7 +41,7 @@ dependencies {
implementation(kotlin("stdlib-jdk7"))
implementation("androidx.core:core-ktx:$coreVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
}
repositories {
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="receive_clash_broadcasts">接收 Clash 廣播</string>
<string name="receive_broadcasts_of_clash">接收來自 Clash 內部的廣播</string>
</resources>
+1 -1
View File
@@ -82,7 +82,7 @@ dependencies {
implementation(kotlin("stdlib-jdk7"))
implementation("androidx.core:core-ktx:$coreVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
}
+3 -3
View File
@@ -98,15 +98,15 @@ Java_com_github_kr328_clash_core_bridge_Bridge_nativeNotifyInstalledAppChanged(J
JNIEXPORT void JNICALL
Java_com_github_kr328_clash_core_bridge_Bridge_nativeStartTun(JNIEnv *env, jobject thiz,
jint fd, jint mtu,
jstring gateway, jstring dns,
jstring dns, jstring blocking,
jobject cb) {
TRACE_METHOD();
scoped_string _gateway = get_string(gateway);
scoped_string _blocking = get_string(blocking);
scoped_string _dns = get_string(dns);
jobject _interface = new_global(cb);
startTun(fd, mtu, _gateway, _dns, _interface);
startTun(fd, mtu, _dns, _blocking, _interface);
}
JNIEXPORT void JNICALL
+2 -3
View File
@@ -25,13 +25,12 @@ type Status struct {
var client = &http.Client{
Transport: &http.Transport{
// from http.DefaultTransport
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
DisableKeepAlives: true,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
DialContext: dialer.DefaultTunnelDialer,
},
Timeout: 60 * time.Second,
}
func openUrl(url string) (io.ReadCloser, error) {
+13 -1
View File
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"strings"
"time"
"github.com/Dreamacro/clash/log"
"github.com/dlclark/regexp2"
@@ -16,6 +17,11 @@ import (
"github.com/Dreamacro/clash/dns"
)
const (
defaultHealthCheckUrl = "https://www.gstatic.com/generate_204"
defaultHealthCheckInterval = time.Hour
)
var processors = []processor{
patchOverride,
patchGeneral,
@@ -88,7 +94,13 @@ func patchProviders(cfg *config.RawConfig, profileDir string) error {
func patchProxyGroup(cfg *config.RawConfig, _ string) error {
for _, g := range cfg.ProxyGroup {
g["lazy"] = false
if _, exist := g["url"]; !exist {
g["url"] = defaultHealthCheckUrl
}
if _, exist := g["interval"]; !exist {
g["interval"] = int(defaultHealthCheckInterval.Seconds())
}
}
return nil
+6 -4
View File
@@ -7,7 +7,7 @@ import (
"sync"
"time"
adapters "github.com/Dreamacro/clash/adapters/inbound"
"github.com/Dreamacro/clash/adapter/inbound"
"github.com/Dreamacro/clash/log"
"github.com/Dreamacro/clash/tunnel"
)
@@ -89,8 +89,10 @@ func (l *httpListener) handleConn(conn net.Conn) {
if err != nil || request.URL.Host == "" {
if err != nil {
log.Warnln("HTTP Connection closed: %s", err.Error())
} else {
log.Warnln("HTTP Connection closed: unknown host")
}
_ = conn.Close()
return
}
@@ -100,9 +102,9 @@ func (l *httpListener) handleConn(conn net.Conn) {
if err != nil {
return
}
tunnel.Add(adapters.NewHTTPS(request, conn))
tunnel.Add(inbound.NewHTTPS(request, conn))
return
}
tunnel.Add(adapters.NewHTTP(request, conn))
tunnel.Add(inbound.NewHTTP(request, conn))
}
+8 -3
View File
@@ -20,6 +20,7 @@ func (a *adapter) tcp() {
defer log.Infoln("[ATUN] TCP listener exited")
defer a.stack.Close()
accept:
for {
conn, err := a.stack.TCP().Accept()
if err != nil {
@@ -34,9 +35,13 @@ func (a *adapter) tcp() {
continue
}
// drop all connections connect to gateway
if a.gateway.Contains(tAddr.IP) {
continue
// drop all connections connect to blocking list
for _, b := range a.blocking {
if b.Contains(tAddr.IP) {
_ = conn.Close()
continue accept
}
}
metadata := &C.Metadata{
+29 -16
View File
@@ -3,6 +3,7 @@ package tun
import (
"net"
"os"
"strings"
"sync"
"syscall"
@@ -10,13 +11,13 @@ import (
)
type adapter struct {
device *os.File
stack tun2socket.Stack
gateway *net.IPNet
dns net.IP
mtu int
once sync.Once
stop func()
device *os.File
stack tun2socket.Stack
blocking []*net.IPNet
dns net.IP
mtu int
once sync.Once
stop func()
}
var lock sync.Mutex
@@ -27,7 +28,7 @@ func (a *adapter) close() {
_ = a.device.Close()
}
func Start(fd, mtu int, gateway, dns string, stop func()) error {
func Start(fd, mtu int, dns string, blocking string, stop func()) error {
lock.Lock()
defer lock.Unlock()
@@ -46,16 +47,28 @@ func Start(fd, mtu int, gateway, dns string, stop func()) error {
}
dn := net.ParseIP(dns)
_, gw, _ := net.ParseCIDR(gateway)
var blk []*net.IPNet
for _, b := range strings.Split(blocking, ";") {
_, n, err := net.ParseCIDR(b)
if err != nil {
device.Close()
return err
}
blk = append(blk, n)
}
instance = &adapter{
device: device,
stack: stack,
gateway: gw,
dns: dn,
mtu: mtu,
once: sync.Once{},
stop: stop,
device: device,
stack: stack,
blocking: blk,
dns: dn,
mtu: mtu,
once: sync.Once{},
stop: stop,
}
go instance.rx()
+8 -7
View File
@@ -7,7 +7,7 @@ import (
"github.com/Dreamacro/clash/transport/socks5"
"github.com/kr328/tun2socket"
adapters "github.com/Dreamacro/clash/adapters/inbound"
"github.com/Dreamacro/clash/adapter/inbound"
"github.com/Dreamacro/clash/common/pool"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/tunnel"
@@ -44,6 +44,7 @@ func (a *adapter) udp() {
defer log.Infoln("[ATUN] UDP receiver exited")
defer a.stack.Close()
read:
for {
buf := pool.Get(a.mtu)
@@ -60,11 +61,11 @@ func (a *adapter) udp() {
continue
}
// drop all packets send to gateway
if a.gateway.Contains(tAddr.IP) {
pool.Put(buf)
continue
// drop all packet send to blocking list
for _, b := range a.blocking {
if b.Contains(tAddr.IP) {
continue read
}
}
pkt := &packet{
@@ -73,7 +74,7 @@ func (a *adapter) udp() {
data: buf[:n],
}
adapter := adapters.NewPacket(socks5.ParseAddrToSocksAddr(tAddr), pkt, C.SOCKS)
adapter := inbound.NewPacket(socks5.ParseAddrToSocksAddr(tAddr), pkt, C.SOCKS)
tunnel.AddPacket(adapter)
}
+4 -4
View File
@@ -3,9 +3,9 @@ package tunnel
import (
"sync"
"github.com/Dreamacro/clash/adapters/outbound"
"github.com/Dreamacro/clash/adapters/outboundgroup"
"github.com/Dreamacro/clash/adapters/provider"
"github.com/Dreamacro/clash/adapter"
"github.com/Dreamacro/clash/adapter/outboundgroup"
"github.com/Dreamacro/clash/adapter/provider"
"github.com/Dreamacro/clash/log"
"github.com/Dreamacro/clash/tunnel"
)
@@ -19,7 +19,7 @@ func HealthCheck(name string) {
return
}
g, ok := p.(*outbound.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup)
g, ok := p.(*adapter.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup)
if !ok {
log.Warnln("Request health check for `%s`: invalid type %s", name, p.Type().String())
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"fmt"
"time"
"github.com/Dreamacro/clash/adapters/provider"
"github.com/Dreamacro/clash/adapter/provider"
"github.com/Dreamacro/clash/tunnel"
)
@@ -7,7 +7,7 @@ import (
"fmt"
"time"
"github.com/Dreamacro/clash/adapters/provider"
"github.com/Dreamacro/clash/adapter/provider"
"github.com/Dreamacro/clash/log"
"github.com/Dreamacro/clash/tunnel"
)
+8 -8
View File
@@ -4,11 +4,11 @@ import (
"sort"
"strings"
"github.com/Dreamacro/clash/adapter"
"github.com/dlclark/regexp2"
"github.com/Dreamacro/clash/adapters/outbound"
"github.com/Dreamacro/clash/adapters/outboundgroup"
"github.com/Dreamacro/clash/adapters/provider"
"github.com/Dreamacro/clash/adapter/outboundgroup"
"github.com/Dreamacro/clash/adapter/provider"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/log"
"github.com/Dreamacro/clash/tunnel"
@@ -60,7 +60,7 @@ func QueryProxyGroupNames(excludeNotSelectable bool) []string {
return []string{}
}
global := tunnel.Proxies()["GLOBAL"].(*outbound.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup)
global := tunnel.Proxies()["GLOBAL"].(*adapter.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup)
proxies := global.Providers()[0].Proxies()
result := make([]string, 0, len(proxies)+1)
@@ -69,7 +69,7 @@ func QueryProxyGroupNames(excludeNotSelectable bool) []string {
}
for _, p := range proxies {
if _, ok := p.(*outbound.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup); ok {
if _, ok := p.(*adapter.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup); ok {
if !excludeNotSelectable || p.Type() == C.Selector {
result = append(result, p.Name())
}
@@ -88,7 +88,7 @@ func QueryProxyGroup(name string, sortMode SortMode, uiSubtitlePattern *regexp2.
return nil
}
g, ok := p.(*outbound.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup)
g, ok := p.(*adapter.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup)
if !ok {
log.Warnln("Query group `%s`: invalid type %s", name, p.Type().String())
@@ -136,7 +136,7 @@ func PatchSelector(selector, name string) bool {
return false
}
g, ok := p.(*outbound.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup)
g, ok := p.(*adapter.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup)
if !ok {
log.Warnln("Patch selector `%s`: invalid type %s", selector, p.Type().String())
@@ -171,7 +171,7 @@ func collectProviders(providers []provider.ProxyProvider, uiSubtitlePattern *reg
subtitle := px.Type().String()
if uiSubtitlePattern != nil {
if _, ok := px.(*outbound.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup); !ok {
if _, ok := px.(*adapter.Proxy).ProxyAdapter.(outboundgroup.ProxyGroup); !ok {
runes := []rune(name)
match, err := uiSubtitlePattern.FindRunesMatch(runes)
if err == nil && match != nil {
+1 -1
View File
@@ -1,6 +1,6 @@
package tunnel
import "github.com/Dreamacro/clash/adapters/provider"
import "github.com/Dreamacro/clash/adapter/provider"
func Suspend(s bool) {
provider.Suspend(s)
@@ -61,12 +61,12 @@ object Clash {
fun startTun(
fd: Int,
mtu: Int,
gateway: String,
dns: String,
blocking: String,
markSocket: (Int) -> Boolean,
querySocketUid: (protocol: Int, source: InetSocketAddress, target: InetSocketAddress) -> Int
) {
Bridge.nativeStartTun(fd, mtu, gateway, dns, object : TunInterface {
Bridge.nativeStartTun(fd, mtu, dns, blocking, object : TunInterface {
override fun markSocket(fd: Int) {
markSocket(fd)
}
@@ -17,7 +17,7 @@ object Bridge {
external fun nativeQueryTrafficTotal(): Long
external fun nativeNotifyDnsChanged(dnsList: String)
external fun nativeNotifyInstalledAppChanged(uidList: String)
external fun nativeStartTun(fd: Int, mtu: Int, gateway: String, dns: String, cb: TunInterface)
external fun nativeStartTun(fd: Int, mtu: Int, dns: String, blocking: String, cb: TunInterface)
external fun nativeStopTun()
external fun nativeStartHttp(listenAt: String): String?
external fun nativeStopHttp()
+1 -1
View File
@@ -58,7 +58,7 @@ dependencies {
api(project(":service"))
implementation(kotlin("stdlib-jdk7"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
implementation("androidx.core:core-ktx:$coreVersion")
implementation("androidx.appcompat:appcompat:$appcompatVersion")
implementation("androidx.activity:activity:$activityVersion")
@@ -70,6 +70,13 @@ class NetworkSettingsDesign(
configure = vpnDependencies::add,
)
switch(
value = srvStore::blockLoopback,
title = R.string.block_loopback,
summary = R.string.block_loopback_summary,
configure = vpnDependencies::add,
)
if (Build.VERSION.SDK_INT >= 29) {
switch(
value = srvStore::systemProxy,
@@ -211,4 +211,6 @@
<string name="sources">源代碼</string>
<string name="clash_core">Clash 核心</string>
<string name="name_server_policy">Name Server 策略</string>
<string name="block_loopback">阻止本地迴環</string>
<string name="block_loopback_summary">阻止本地迴環連接</string>
</resources>
+110 -108
View File
@@ -1,95 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="access_control_packages_summary">為應用配置訪問權限</string>
<string name="access_control_packages_summary">為軟體設定訪問權限</string>
<string name="about">關於</string>
<string name="access_control_mode">訪問控制模式</string>
<string name="access_control_packages">訪問控制應用包列表</string>
<string name="append_system_dns">追加系統 DNS</string>
<string name="application_broken">應用損壞</string>
<string name="access_control_packages">訪問控制軟體套件清單</string>
<string name="append_system_dns">追加作業系統 DNS</string>
<string name="application_broken">軟體損毀</string>
<string name="application_name">Clash for Android</string>
<string name="auto_update">自動更新</string>
<string name="behavior">行為</string>
<string name="bypass_private_network">繞過私有網絡</string>
<string name="bypass_private_network_summary">繞過私有網絡地址</string>
<string name="bypass_private_network">繞過私有網路</string>
<string name="bypass_private_network_summary">繞過私有網路位址</string>
<string name="cancel">取消</string>
<string name="clash_logcat">Clash 日誌捕捉工具</string>
<string name="create_profile">創建配置</string>
<string name="dark_mode">暗黑模式</string>
<string name="default_">默認</string>
<string name="delay">延遲</string>
<string name="clash_logcat">Clash 日誌檔採集工具</string>
<string name="create_profile">建立設定檔</string>
<string name="dark_mode">深色模式</string>
<string name="default_">預設</string>
<string name="delay">延時</string>
<string name="delete">刪除</string>
<string name="delete_all_logs">刪除所有日誌</string>
<string name="delete_all_logs_warn">所有歷史日誌將丟失</string>
<string name="detail">詳情</string>
<string name="delete_all_logs">刪除所有日誌檔</string>
<string name="delete_all_logs_warn">所有歷史日誌檔將丟失</string>
<string name="detail">內容</string>
<string name="direct_mode">直連模式</string>
<string name="disabled">已禁用</string>
<string name="dns_hijacking">DNS 劫持</string>
<string name="dns_hijacking_summary">處理所有 DNS 數據包</string>
<string name="dns_hijacking_summary">處理所有 DNS 封包</string>
<string name="duplicate">複製</string>
<string name="edit">編輯</string>
<string name="empty_name">空名稱</string>
<string name="exit_without_save">退出而不保存</string>
<string name="empty_name">空白名稱</string>
<string name="exit_without_save">退出而不儲存</string>
<string name="exit_without_save_warning">所有變更將會丟失</string>
<string name="export">導出</string>
<string name="export">匯出</string>
<string name="external">外部</string>
<string name="file">文件</string>
<string name="file_exported">文件已導出</string>
<string name="file">檔案</string>
<string name="file_exported">檔案已匯出</string>
<string name="format_minutes">%d 分鐘</string>
<string name="format_profile_activated">%s 已激活</string>
<string name="format_profile_activated">%s 已啟用</string>
<string name="format_traffic_forwarded">%s 已轉發</string>
<string name="global_mode">全局模式</string>
<string name="global_mode">全域性模式</string>
<string name="history">歷史</string>
<string name="import_from_file">從文件導入</string>
<string name="import_from_url">從 URL 導入</string>
<string name="interface_">界面</string>
<string name="invalid_url">無效的 URL</string>
<string name="import_from_file">從檔案匯入</string>
<string name="import_from_url">從 URL 匯入</string>
<string name="interface_">介面</string>
<string name="invalid_url">無效 URL</string>
<string name="launch_name">Clash</string>
<string name="logcat">Logcat</string>
<string name="logs">日誌</string>
<string name="mode">模式</string>
<string name="name">名稱</string>
<string name="network">網絡</string>
<string name="new_profile">新配置</string>
<string name="not_selected">未選擇</string>
<string name="network">網路</string>
<string name="new_profile">新設定檔</string>
<string name="not_selected">未選取</string>
<string name="ok">確認</string>
<string name="profile">配置</string>
<string name="profile_name">配置名稱</string>
<string name="profiles">配置</string>
<string name="profile">設定檔</string>
<string name="profile_name">設定檔名稱</string>
<string name="profiles">設定檔</string>
<string name="properties">參數</string>
<string name="proxy">代理</string>
<string name="recently">近期</string>
<string name="route_system_traffic">自動路由系統流量</string>
<string name="routing_via_vpn_service">通過 VpnService 自動路由所有系統流量</string>
<string name="proxy">Proxy</string>
<string name="recently">最近</string>
<string name="route_system_traffic">自動轉發作業系統流量</string>
<string name="routing_via_vpn_service">通過 VpnService 自動轉發所有作業系統流量</string>
<string name="rule_mode">規則模式</string>
<string name="running">運行中</string>
<string name="settings">設置</string>
<string name="running">運作中</string>
<string name="settings">設定</string>
<string name="show_traffic">顯示流量</string>
<string name="show_traffic_summary">在通知中自動刷新流量</string>
<string name="allow_clash_auto_restart">允許 Clash 自動重啟</string>
<string name="auto_restart">自動重啟</string>
<string name="show_traffic_summary">在通知中自動重新整理流量</string>
<string name="allow_clash_auto_restart">允許 Clash 自動重新啟動</string>
<string name="auto_restart">自動重新啟動</string>
<string name="stopped">已停止</string>
<string name="help">幫助</string>
<string name="tap_to_start">點此啟動</string>
<string name="update">更新</string>
<string name="url">URL</string>
<string name="vpn_service_options">VpnService 選項</string>
<string name="options_unavailable">選項在 Clash 運行時不可用</string>
<string name="search">查找</string>
<string name="system_apps">系統應用</string>
<string name="options_unavailable">選項在 Clash 運作時不可用</string>
<string name="search">尋找</string>
<string name="system_apps">作業系統軟體</string>
<string name="update_time">更新時間</string>
<string name="package_name">應用包名稱</string>
<string name="package_name">軟體套件名稱</string>
<string name="install_time">安裝時間</string>
<string name="clash_for_android">Clash for Android</string>
<string name="feedback">反饋</string>
<string name="feedback">回饋</string>
<string name="github_issues">Github Issues</string>
<string name="tips_properties"><![CDATA[僅接受 <strong>Clash 配置文件</strong>(包含<strong>代理</strong>/<strong>規則</strong>)]]></string>
<string name="tips_properties"><![CDATA[僅接受 <strong>Clash 設定檔</strong>(包含<strong>Proxy</strong>/<strong>規則</strong>)]]></string>
<string name="loading">載入中</string>
<string name="tips_help"><![CDATA[Clash for Android 是一個<strong>免費軟件</strong>並且我們<strong>不</strong>為其提供任何服務, <strong>請務必不要反饋非應用自身引起的問題</strong>]]></string>
<string name="donate">捐贈</string>
<string name="allow_all_apps">允許所有應用</string>
<string name="allow_selected_apps">僅允許已選擇的應用</string>
<string name="deny_selected_apps">不允許已選擇的應用</string>
<string name="no_profile_selected">沒有選擇配置文件</string>
<string name="tips_help"><![CDATA[Clash for Android 是一個<strong>免費軟體</strong>並且我們<strong>不</strong>為其提供任何服務, <strong>請務必不要回報非軟體自身引起的問題</strong>]]></string>
<string name="donate">抖內</string>
<string name="allow_all_apps">允許所有軟體</string>
<string name="allow_selected_apps">僅允許已選取的軟體</string>
<string name="deny_selected_apps">不允許已選取的軟體</string>
<string name="no_profile_selected">沒有選取設定檔</string>
<string name="copied">已複製</string>
<string name="script_mode">腳本模式</string>
<string name="google_play">Google Play</string>
@@ -97,22 +97,22 @@
<string name="select_all">全選</string>
<string name="select_invert">反選</string>
<string name="select_none">清除</string>
<string name="app">應用</string>
<string name="follow_system_android_10">跟隨系統 (Android 10+)</string>
<string name="always_dark">總是暗黑模式</string>
<string name="always_light">總是明亮模式</string>
<string name="app">軟體</string>
<string name="follow_system_android_10">跟隨作業系統 (Android 10+)</string>
<string name="always_dark">總是深色模式</string>
<string name="always_light">總是淺色模式</string>
<string name="service">服務</string>
<string name="accept_http_content">僅接受 http(s) 和 content 類型</string>
<string name="at_least_15_minutes">至少 15 分鐘</string>
<string name="override">覆寫</string>
<string name="general">常規</string>
<string name="general">一般</string>
<string name="dns">DNS</string>
<string name="http_port">HTTP 端口</string>
<string name="socks_port">Socks 端口</string>
<string name="mixed_port">複合端口</string>
<string name="allow_lan">允許來自局域網的連接</string>
<string name="bind_address">監聽地址</string>
<string name="log_level">日誌級別</string>
<string name="http_port">HTTP 埠</string>
<string name="socks_port">Socks 埠</string>
<string name="mixed_port">複合埠</string>
<string name="allow_lan">允許來自區域網路的連結</string>
<string name="bind_address">監聽位址</string>
<string name="log_level">日誌檔級別</string>
<string name="ipv6">IPv6</string>
<string name="hosts">Hosts</string>
<string name="enabled">已啟用</string>
@@ -130,85 +130,87 @@
<string name="fakeip_filter">FakeIP 過濾器</string>
<string name="geoip_fallback">GeoIP Fallback</string>
<string name="ipcidr_fallback">IPCIDR Fallback</string>
<string name="use_built_in">使用內置</string>
<string name="use_built_in">使用內建</string>
<string name="mapping">Real-IP 至 域名映射</string>
<string name="fakeip">Fake-IP 至 域名映射</string>
<string name="sort">排序</string>
<string name="layout">佈局</string>
<string name="single">單列</string>
<string name="multiple">多列</string>
<string name="not_selectable">不可選擇</string>
<string name="single">單欄</string>
<string name="multiple">多欄</string>
<string name="not_selectable">不可選取</string>
<string name="providers">外部資源</string>
<string name="unavailable">不可用</string>
<string name="_new">新建</string>
<string name="_new">新增</string>
<string name="value">值</string>
<string name="listen">監聽</string>
<string name="files">文件</string>
<string name="browse_files">瀏覽文件</string>
<string name="browse_configuration_providers">瀏覽配置文件和外部資源</string>
<string name="rename">重命名</string>
<string name="file_name">文件名</string>
<string name="format_type_unsaved">%s (未保存)</string>
<string name="files">檔案</string>
<string name="browse_files">瀏覽檔案</string>
<string name="browse_configuration_providers">瀏覽設定檔和外部資源</string>
<string name="rename">重新命名</string>
<string name="file_name">檔名</string>
<string name="format_type_unsaved">%s (未儲存)</string>
<string name="format_minutes_ago">%d 分鐘前</string>
<string name="format_hours_ago">%d 小時前</string>
<string name="format_days_ago">%d 天前</string>
<string name="format_months_ago">%d 月前</string>
<string name="format_years_ago">%d 年前</string>
<string name="system_proxy">系統代理</string>
<string name="system_proxy_summary">為 VpnService 附加 HTTP 代理</string>
<string name="system_proxy">作業系統 Proxy</string>
<string name="system_proxy_summary">為 VpnService 附加 HTTP Proxy</string>
<string name="dont_modify">不修改</string>
<string name="redirect_port">Redirect 端口</string>
<string name="tproxy_port">TProxy 端口</string>
<string name="reset">重置</string>
<string name="redirect_port">Redirect 埠</string>
<string name="tproxy_port">TProxy 埠</string>
<string name="reset">重設</string>
<string name="use_hosts">使用 Hosts</string>
<string name="authentication">認證</string>
<string name="domain_fallback">域名 Fallback</string>
<string name="empty">置空</string>
<string name="import_from_clipboard">從剪切板導入</string>
<string name="export_to_clipboard">導出至剪切板</string>
<string name="import_from_clipboard">從剪貼簿匯入</string>
<string name="export_to_clipboard">匯出至剪貼簿</string>
<string name="auto_update_minutes">自動更新 (分鐘)</string>
<string name="profile_url">配置 URL</string>
<string name="profile_url">設定檔 URL</string>
<string name="should_not_be_blank">不能為空</string>
<string name="format_fetching_configuration">正在從 %s 下載配置文件</string>
<string name="format_fetching_configuration">正在從 %s 下載設定檔</string>
<string name="format_fetching_provider">正在下載外部資源 %s</string>
<string name="initializing">正在初始化</string>
<string name="verifying">正在校驗</string>
<string name="sideload_geoip">旁加載 GEOIP</string>
<string name="sideload_geoip_summary">外部 GEOIP 數據庫</string>
<string name="sideload_geoip">旁載入 GEOIP</string>
<string name="sideload_geoip_summary">外部 GEOIP 資料庫</string>
<string name="force_enable">強制啟用</string>
<string name="document">文檔</string>
<string name="document">文件</string>
<string name="clash_wiki">Clash Wiki</string>
<string name="invalid_file_name">非法的文件名稱</string>
<string name="reset_override_settings">重置覆寫設置</string>
<string name="reset_override_settings_message">所有的覆寫設置將會被擦除</string>
<string name="invalid_file_name">不規範檔案名稱</string>
<string name="reset_override_settings">重置覆寫設定</string>
<string name="reset_override_settings_message">所有的覆寫設定將會被抹除</string>
<string name="key">鍵</string>
<string name="more">更多</string>
<string name="save">保存</string>
<string name="delay_test">延遲測試</string>
<string name="save">儲存</string>
<string name="delay_test">延時測試</string>
<string name="format_provider_type">%1$s(%2$s)</string>
<string name="rule">規則</string>
<string name="http">HTTP</string>
<string name="compatible">兼容</string>
<string name="compatible">相容</string>
<string name="format_update_provider_failure">更新 %1$s: %2$s</string>
<string name="update_all">更新全部</string>
<string name="proxy_empty_tips">沒有可以顯示的組</string>
<string name="proxy_empty_tips">沒有可以顯示的分組</string>
<string name="reverse">反轉</string>
<string name="close">關閉</string>
<string name="keyword">關鍵詞</string>
<string name="invalid_log_file">無效的日誌文件</string>
<string name="application_crashed">應用崩潰</string>
<string name="application_broken_tips">應用缺少必要的運行組件,這通常由於下載不完整的 apk 導致。</string>
<string name="keyword">關鍵字</string>
<string name="invalid_log_file">無效的日誌檔</string>
<string name="application_crashed">軟體崩潰</string>
<string name="application_broken_tips">軟體缺少必要的運作元件,這通常是由於下載了不完整的 apk 而導致。</string>
<string name="reinstall">重新安裝</string>
<string name="github_releases">Github Releases</string>
<string name="unable_to_start_vpn">無法啟動 VPN 組件</string>
<string name="request_donate_tips">如果您覺得本應用對您有幫助歡迎在 [幫助] 中給予開發者一點捐贈</string>
<string name="request_donate">捐贈</string>
<string name="version_updated">應用已更新</string>
<string name="version_updated_tips">設置已被清除,舊的配置文件需要再次保存。</string>
<string name="active_unsaved_tips">配置文件需要在激活之前保存</string>
<string name="mode_switch_tips">僅在本次會話中有效</string>
<string name="import_">導入</string>
<string name="sources">源代碼</string>
<string name="unable_to_start_vpn">無法啟動 VPN 元件</string>
<string name="request_donate_tips">如果您覺得本軟體對您有幫助歡迎在 [幫助] 中給予開發者一點抖內</string>
<string name="request_donate">抖內</string>
<string name="version_updated">軟體已更新</string>
<string name="version_updated_tips">設定已被清除,舊版設定檔需要再次儲存。</string>
<string name="active_unsaved_tips">設定檔需要在啟用之前儲存</string>
<string name="mode_switch_tips">僅在本次工作階段中有效</string>
<string name="import_">匯入</string>
<string name="sources">原始碼</string>
<string name="clash_core">Clash 核心</string>
<string name="name_server_policy">Name Server 策略</string>
</resources>
<string name="block_loopback">阻止本地迴環</string>
<string name="block_loopback_summary">阻止本地迴環連結</string>
</resources>
@@ -211,4 +211,6 @@
<string name="sources">源代码</string>
<string name="clash_core">Clash 核心</string>
<string name="name_server_policy">Name Server 策略</string>
<string name="block_loopback">阻止本地回环</string>
<string name="block_loopback_summary">阻止本地回环连接</string>
</resources>
+2
View File
@@ -119,6 +119,8 @@
<string name="bypass_private_network_summary">Bypass private network addresses</string>
<string name="dns_hijacking">DNS Hijacking</string>
<string name="dns_hijacking_summary">Handle all dns packet</string>
<string name="block_loopback">Block Loopback</string>
<string name="block_loopback_summary">Block loopback connections</string>
<string name="system_proxy">System Proxy</string>
<string name="system_proxy_summary">Attach http proxy to VpnService</string>
<string name="access_control_mode">Access Control Mode</string>
+1 -1
Submodule kaidl updated: 963190ac8e...16da2e83b7.
+5 -2
View File
@@ -57,9 +57,12 @@ dependencies {
api(project(":core"))
api(project(":common"))
implementation(project(":kaidl:kaidl-runtime")) {
exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-core")
}
implementation(kotlin("stdlib-jdk7"))
implementation(project(":kaidl:kaidl-runtime"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
implementation("androidx.room:room-runtime:$roomVersion")
implementation("androidx.room:room-ktx:$roomVersion")
implementation("androidx.core:core-ktx:$coreVersion")
@@ -14,7 +14,6 @@ import com.github.kr328.clash.common.compat.pendingIntentFlags
import com.github.kr328.clash.common.constants.Components
import com.github.kr328.clash.common.constants.Intents
import com.github.kr328.clash.common.id.UndefinedIds
import com.github.kr328.clash.common.log.Log
import com.github.kr328.clash.common.util.setUUID
import com.github.kr328.clash.common.util.uuid
import com.github.kr328.clash.service.data.ImportedDao
@@ -148,17 +147,12 @@ class ProfileWorker : BaseService() {
NotificationManagerCompat.from(applicationContext)
.notify(id, notification)
Log.d("notify processing $name: id = $id")
try {
block()
} finally {
withContext(NonCancellable) {
NotificationManagerCompat.from(applicationContext)
.cancel(id)
Log.d("notify processed $name: id = $id")
}
}
}
@@ -190,8 +184,6 @@ class ProfileWorker : BaseService() {
NotificationManagerCompat.from(this)
.notify(id, notification)
Log.d("notify completed $name: id = $id")
}
private fun failed(uuid: UUID, name: String, reason: String) {
@@ -207,8 +199,6 @@ class ProfileWorker : BaseService() {
NotificationManagerCompat.from(this)
.notify(id, notification)
Log.d("notify failed $name: id = $id")
}
companion object {
@@ -216,11 +216,16 @@ class TunService : VpnService(), CoroutineScope by CoroutineScope(Dispatchers.De
}
}
val blocking = mutableListOf("$TUN_GATEWAY/$TUN_SUBNET_PREFIX")
if (store.blockLoopback) {
blocking.add(NET_SUBNET_LOOPBACK)
}
TunModule.TunDevice(
fd = establish()?.detachFd()
?: throw NullPointerException("Establish VPN rejected by system"),
mtu = TUN_MTU,
gateway = "$TUN_GATEWAY/$TUN_SUBNET_PREFIX",
blocking = blocking.joinToString(";"),
dns = if (store.dnsHijacking) NET_ANY else TUN_DNS,
)
}
@@ -234,5 +239,6 @@ class TunService : VpnService(), CoroutineScope by CoroutineScope(Dispatchers.De
private const val TUN_GATEWAY = "172.19.0.1"
private const val TUN_DNS = "172.19.0.2"
private const val NET_ANY = "0.0.0.0"
private const val NET_SUBNET_LOOPBACK = "127.0.0.0/8"
}
}
@@ -16,7 +16,7 @@ class TunModule(private val vpn: VpnService) : Module<Unit>(vpn) {
data class TunDevice(
val fd: Int,
val mtu: Int,
val gateway: String,
val blocking: String,
val dns: String,
)
@@ -57,8 +57,8 @@ class TunModule(private val vpn: VpnService) : Module<Unit>(vpn) {
Clash.startTun(
fd = device.fd,
mtu = device.mtu,
gateway = device.gateway,
dns = device.dns,
blocking = device.blocking,
markSocket = vpn::protect,
querySocketUid = this::queryUid
)
@@ -43,7 +43,12 @@ class ServiceStore(context: Context) {
var systemProxy by store.boolean(
key = "system_proxy",
defaultValue = false
defaultValue = true
)
var blockLoopback by store.boolean(
key = "block_loopback",
defaultValue = true
)
var dynamicNotification by store.boolean(
@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="clash_service_status_channel">Clash 狀態</string>
<string name="running">正在運行</string>
<string name="running">正在運作</string>
<string name="format_update_complete">更新 %s 成功</string>
<string name="format_update_failure">"更新 %1$s: %2$s "</string>
<string name="clash_for_android">Clash for Android</string>
<string name="profiles_and_providers">配置文件和外部資源</string>
<string name="configuration_yaml">配置文件.yaml</string>
<string name="profiles_and_providers">設定檔和外部資源</string>
<string name="configuration_yaml">設定檔.yaml</string>
<string name="provider_files">外部資源文件列表</string>
<string name="loading">載入中</string>
<string name="profile_process_status">配置文件處理狀態</string>
<string name="profile_process_status">設定檔處理狀態</string>
<string name="update_successfully">更新成功</string>
<string name="update_failure">更新失敗</string>
<string name="profile_updater">配置更新服務</string>
<string name="profile_updating">配置更新中</string>
<string name="profile_service_status">配置文件服務狀態</string>
<string name="profile_process_result">配置文件處理結果</string>
</resources>
<string name="profile_updater">設定檔更新服務</string>
<string name="profile_updating">設定檔更新中</string>
<string name="profile_service_status">設定檔服務狀態</string>
<string name="profile_process_result">設定檔處理結果</string>
</resources>