Commit b78f4850 authored by Max Lv's avatar Max Lv

Merge branch 'develop' into beta

parents 890be544 a61b03c8
...@@ -17,10 +17,6 @@ ...@@ -17,10 +17,6 @@
path = mobile/src/main/jni/redsocks path = mobile/src/main/jni/redsocks
url = https://github.com/shadowsocks/redsocks.git url = https://github.com/shadowsocks/redsocks.git
branch = shadowsocks-android branch = shadowsocks-android
[submodule "mobile/src/main/jni/pdnsd"]
path = mobile/src/main/jni/pdnsd
url = https://github.com/shadowsocks/pdnsd.git
branch = shadowsocks-android
[submodule "mobile/src/main/jni/mbedtls"] [submodule "mobile/src/main/jni/mbedtls"]
path = mobile/src/main/jni/mbedtls path = mobile/src/main/jni/mbedtls
url = https://github.com/ARMmbed/mbedtls url = https://github.com/ARMmbed/mbedtls
......
...@@ -18,7 +18,7 @@ lazy val commonSettings = Seq( ...@@ -18,7 +18,7 @@ lazy val commonSettings = Seq(
typedResources := false typedResources := false
) )
val supportLibsVersion = "25.1.1" val supportLibsVersion = "25.2.0"
lazy val root = Project(id = "shadowsocks-android", base = file(".")) lazy val root = Project(id = "shadowsocks-android", base = file("."))
.settings(commonSettings) .settings(commonSettings)
.aggregate(plugin, mobile) .aggregate(plugin, mobile)
......
...@@ -2,8 +2,8 @@ enablePlugins(AndroidApp) ...@@ -2,8 +2,8 @@ enablePlugins(AndroidApp)
android.useSupportVectors android.useSupportVectors
name := "shadowsocks" name := "shadowsocks"
version := "4.0.4" version := "4.1.0"
versionCode := Some(179) versionCode := Some(180)
proguardOptions ++= proguardOptions ++=
"-keep class com.github.shadowsocks.JniHelper { *; }" :: "-keep class com.github.shadowsocks.JniHelper { *; }" ::
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -54,7 +54,14 @@ public class JniHelper { ...@@ -54,7 +54,14 @@ public class JniHelper {
? new ErrnoException("kill", errno) : new Exception("kill failed: " + errno); ? new ErrnoException("kill", errno) : new Exception("kill failed: " + errno);
} }
@Deprecated // Use Process.destroy() since API 24
public static int waitpidCompat(Process process) throws Exception {
if (Build.VERSION.SDK_INT >= 24) throw new UnsupportedOperationException("Never call this method in OpenJDK!");
return waitpid(process);
}
private static native int sigterm(Process process); private static native int sigterm(Process process);
private static native int waitpid(Process process);
public static native int sendFd(int fd, String path); public static native int sendFd(int fd, String path);
public static native void close(int fd); public static native void close(int fd);
} }
...@@ -239,23 +239,6 @@ LOCAL_CFLAGS := -O2 -std=gnu99 -DUSE_IPTABLES \ ...@@ -239,23 +239,6 @@ LOCAL_CFLAGS := -O2 -std=gnu99 -DUSE_IPTABLES \
include $(BUILD_SHARED_EXECUTABLE) include $(BUILD_SHARED_EXECUTABLE)
########################################################
## pdnsd
########################################################
include $(CLEAR_VARS)
PDNSD_SOURCES := $(wildcard $(LOCAL_PATH)/pdnsd/src/*.c)
LOCAL_MODULE := pdnsd
LOCAL_SRC_FILES := $(PDNSD_SOURCES:$(LOCAL_PATH)/%=%)
LOCAL_CFLAGS := -DANDROID -Wall -O2 -I$(LOCAL_PATH)/pdnsd \
-I$(LOCAL_PATH)/include/pdnsd -I$(LOCAL_PATH)/libancillary
LOCAL_STATIC_LIBRARIES := libancillary
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_EXECUTABLE)
######################################################## ########################################################
## shadowsocks-libev local ## shadowsocks-libev local
######################################################## ########################################################
...@@ -494,6 +477,17 @@ LOCAL_SRC_FILES := $(addprefix pcre/, $(libpcre_src_files)) ...@@ -494,6 +477,17 @@ LOCAL_SRC_FILES := $(addprefix pcre/, $(libpcre_src_files))
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
########################################################
## overture
########################################################
include $(CLEAR_VARS)
LOCAL_MODULE := overture
LOCAL_SRC_FILES := overture/$(TARGET_ARCH_ABI)/liboverture.so
include $(PREBUILT_SHARED_LIBRARY)
# Import cpufeatures # Import cpufeatures
$(call import-module,android/cpufeatures) $(call import-module,android/cpufeatures)
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/wait.h>
#include <ancillary.h> #include <ancillary.h>
#define LOGI(...) do { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); } while(0) #define LOGI(...) do { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); } while(0)
...@@ -41,6 +42,17 @@ jint Java_com_github_shadowsocks_jnihelper_sigterm(JNIEnv *env, jobject thiz, jo ...@@ -41,6 +42,17 @@ jint Java_com_github_shadowsocks_jnihelper_sigterm(JNIEnv *env, jobject thiz, jo
return kill(pid, SIGTERM) == -1 && errno != ESRCH ? errno : 0; return kill(pid, SIGTERM) == -1 && errno != ESRCH ? errno : 0;
} }
jint Java_com_github_shadowsocks_jnihelper_waitpid(JNIEnv *env, jobject thiz, jobject process) {
if (!env->IsInstanceOf(process, ProcessImpl)) {
THROW(env, "java/lang/ClassCastException",
"Unsupported process object. Only java.lang.ProcessManager$ProcessImpl is accepted.");
return -1;
}
jint pid = env->GetIntField(process, ProcessImpl_pid);
int status;
return waitpid(pid, &status, WNOHANG);
}
void Java_com_github_shadowsocks_jnihelper_close(JNIEnv *env, jobject thiz, jint fd) { void Java_com_github_shadowsocks_jnihelper_close(JNIEnv *env, jobject thiz, jint fd) {
close(fd); close(fd);
} }
...@@ -84,11 +96,11 @@ static JNINativeMethod method_table[] = { ...@@ -84,11 +96,11 @@ static JNINativeMethod method_table[] = {
{ "sendFd", "(ILjava/lang/String;)I", { "sendFd", "(ILjava/lang/String;)I",
(void*) Java_com_github_shadowsocks_jnihelper_sendfd }, (void*) Java_com_github_shadowsocks_jnihelper_sendfd },
{ "sigterm", "(Ljava/lang/Process;)I", { "sigterm", "(Ljava/lang/Process;)I",
(void*) Java_com_github_shadowsocks_jnihelper_sigterm } (void*) Java_com_github_shadowsocks_jnihelper_sigterm },
{ "waitpid", "(Ljava/lang/Process;)I",
(void*) Java_com_github_shadowsocks_jnihelper_waitpid }
}; };
/* /*
* Register several native methods for one class. * Register several native methods for one class.
*/ */
......
Subproject commit f6b0a56c74ff33e3df4c00859bc7ccefa1354fa4
...@@ -123,6 +123,23 @@ trait BaseService extends Service { ...@@ -123,6 +123,23 @@ trait BaseService extends Service {
false false
} else true } else true
def getExternalIp(): String = {
val url = "http://icanhazip.com"
val client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
val request = new Request.Builder()
.url(url)
.build()
val response = client.newCall(request).execute()
if (response.isSuccessful)
response.body.string.trim
else
""
}
def connect() { def connect() {
if (profile.host == "198.199.101.152") { if (profile.host == "198.199.101.152") {
val holder = app.containerHolder val holder = app.containerHolder
......
...@@ -115,7 +115,12 @@ class GuardedProcess(cmd: String*) { ...@@ -115,7 +115,12 @@ class GuardedProcess(cmd: String*) {
private def destroyProcess() { private def destroyProcess() {
if (Build.VERSION.SDK_INT < 24) { if (Build.VERSION.SDK_INT < 24) {
JniHelper.sigtermCompat(process) JniHelper.sigtermCompat(process)
process.waitFor() var tries = 0
while (JniHelper.waitpidCompat(process) == 0 && tries < 3) {
Log.w(TAG, "still waiting for process " + Commandline.toString(cmd))
Thread.sleep(200)
tries += 1
}
} }
process.destroy() process.destroy()
} }
......
...@@ -197,15 +197,17 @@ class ShadowsocksApplication extends Application { ...@@ -197,15 +197,17 @@ class ShadowsocksApplication extends Application {
def copyAssets() { def copyAssets() {
val assetManager = getAssets val assetManager = getAssets
for (f <- List("acl", "overture")) {
var files: Array[String] = null var files: Array[String] = null
try files = assetManager.list("acl") catch { try files = assetManager.list(f) catch {
case e: IOException => case e: IOException =>
Log.e(TAG, e.getMessage) Log.e(TAG, e.getMessage)
app.track(e) app.track(e)
} }
if (files != null) for (file <- files) autoClose(assetManager.open("acl/" + file))(in => if (files != null) for (file <- files) autoClose(assetManager.open(f + "/" + file))(in =>
autoClose(new FileOutputStream(new File(getFilesDir, file)))(out => autoClose(new FileOutputStream(new File(getFilesDir, file)))(out =>
IOUtils.copy(in, out))) IOUtils.copy(in, out)))
}
editor.putInt(Key.currentVersionCode, BuildConfig.VERSION_CODE).apply() editor.putInt(Key.currentVersionCode, BuildConfig.VERSION_CODE).apply()
} }
......
...@@ -49,7 +49,7 @@ class ShadowsocksNatService extends BaseService { ...@@ -49,7 +49,7 @@ class ShadowsocksNatService extends BaseService {
var sslocalProcess: GuardedProcess = _ var sslocalProcess: GuardedProcess = _
var sstunnelProcess: GuardedProcess = _ var sstunnelProcess: GuardedProcess = _
var redsocksProcess: GuardedProcess = _ var redsocksProcess: GuardedProcess = _
var pdnsdProcess: GuardedProcess = _ var overtureProcess: GuardedProcess = _
var su: Shell.Interactive = _ var su: Shell.Interactive = _
def startShadowsocksDaemon() { def startShadowsocksDaemon() {
...@@ -83,21 +83,38 @@ class ShadowsocksNatService extends BaseService { ...@@ -83,21 +83,38 @@ class ShadowsocksNatService extends BaseService {
} }
def startDnsDaemon() { def startDnsDaemon() {
val reject = if (profile.ipv6) "224.0.0.0/3" else "224.0.0.0/3, ::/0" val externalIp = getExternalIp()
IOUtils.writeString(new File(getFilesDir, "pdnsd-nat.conf"), profile.route match { IOUtils.writeString(new File(getFilesDir, "overture-nat.conf"), profile.route match {
case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES => case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getCacheDir.getAbsolutePath, ConfigUtils.OVERTURE_DIRECT.formatLocal(Locale.ENGLISH,
"127.0.0.1", profile.localPort + 53, "114.114.114.114, 223.5.5.5, 1.2.4.8", profile.localPort + 53, // Local Port
getBlackList, reject, profile.localPort + 63, reject) "119.29.29.29", // Primary DNS 1
"udp", // DNS type of Primary DNS 1
"114.114.114.114", // Primary DNS 2
"udp", // DNS type of Primary DNS 2
profile.remoteDns, // Alternative DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp) // External IP
case Acl.CHINALIST => case Acl.CHINALIST =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getCacheDir.getAbsolutePath, ConfigUtils.OVERTURE_LOCAL.formatLocal(Locale.ENGLISH,
"127.0.0.1", profile.localPort + 53, "8.8.8.8, 8.8.4.4, 208.67.222.222", profile.localPort + 53, // Local Port
"", reject, profile.localPort + 63, reject) "119.29.29.29", // Primary DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp, // External IP
"114.114.114.114", // Alternative DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp) // External IP
case _ => case _ =>
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "", getCacheDir.getAbsolutePath, ConfigUtils.OVERTURE_LOCAL.formatLocal(Locale.ENGLISH,
"127.0.0.1", profile.localPort + 53, profile.localPort + 63, reject) profile.localPort + 53, // Local Port
profile.remoteDns, // Primary DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp, // External IP
"208.67.222.222", // Alternative DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp) // External IP
}) })
pdnsdProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", "pdnsd-nat.conf") overtureProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/liboverture.so", "-c", "overture-nat.conf")
.start() .start()
} }
...@@ -111,11 +128,13 @@ class ShadowsocksNatService extends BaseService { ...@@ -111,11 +128,13 @@ class ShadowsocksNatService extends BaseService {
/** Called when the activity is first created. */ /** Called when the activity is first created. */
def handleConnection() { def handleConnection() {
startDNSTunnel()
startRedsocksDaemon() startRedsocksDaemon()
startShadowsocksDaemon() startShadowsocksDaemon()
if (!profile.udpdns) startDnsDaemon() if (!profile.udpdns)
startDnsDaemon()
else
startDNSTunnel()
setupIptables() setupIptables()
...@@ -143,9 +162,9 @@ class ShadowsocksNatService extends BaseService { ...@@ -143,9 +162,9 @@ class ShadowsocksNatService extends BaseService {
redsocksProcess.destroy() redsocksProcess.destroy()
redsocksProcess = null redsocksProcess = null
} }
if (pdnsdProcess != null) { if (overtureProcess != null) {
pdnsdProcess.destroy() overtureProcess.destroy()
pdnsdProcess = null overtureProcess = null
} }
su.addCommand("iptables -t nat -F OUTPUT") su.addCommand("iptables -t nat -F OUTPUT")
......
...@@ -45,8 +45,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -45,8 +45,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
private var notification: ShadowsocksNotification = _ private var notification: ShadowsocksNotification = _
var sslocalProcess: GuardedProcess = _ var sslocalProcess: GuardedProcess = _
var sstunnelProcess: GuardedProcess = _ var overtureProcess: GuardedProcess = _
var pdnsdProcess: GuardedProcess = _
var tun2socksProcess: GuardedProcess = _ var tun2socksProcess: GuardedProcess = _
override def onBind(intent: Intent): IBinder = { override def onBind(intent: Intent): IBinder = {
...@@ -94,17 +93,13 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -94,17 +93,13 @@ class ShadowsocksVpnService extends VpnService with BaseService {
sslocalProcess.destroy() sslocalProcess.destroy()
sslocalProcess = null sslocalProcess = null
} }
if (sstunnelProcess != null) {
sstunnelProcess.destroy()
sstunnelProcess = null
}
if (tun2socksProcess != null) { if (tun2socksProcess != null) {
tun2socksProcess.destroy() tun2socksProcess.destroy()
tun2socksProcess = null tun2socksProcess = null
} }
if (pdnsdProcess != null) { if (overtureProcess != null) {
pdnsdProcess.destroy() overtureProcess.destroy()
pdnsdProcess = null overtureProcess = null
} }
} }
...@@ -149,15 +144,14 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -149,15 +144,14 @@ class ShadowsocksVpnService extends VpnService with BaseService {
/** Called when the activity is first created. */ /** Called when the activity is first created. */
def handleConnection() { def handleConnection() {
val fd = startVpn()
if (!sendFd(fd)) throw new Exception("sendFd failed")
startShadowsocksDaemon() startShadowsocksDaemon()
if (!profile.udpdns) { if (!profile.udpdns) {
startDnsDaemon() startDnsDaemon()
startDnsTunnel()
} }
val fd = startVpn()
if (!sendFd(fd)) throw new Exception("sendFd failed")
} }
override protected def buildPluginCommandLine(): ArrayBuffer[String] = super.buildPluginCommandLine() += "-V" override protected def buildPluginCommandLine(): ArrayBuffer[String] = super.buildPluginCommandLine() += "-V"
...@@ -182,33 +176,41 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -182,33 +176,41 @@ class ShadowsocksVpnService extends VpnService with BaseService {
sslocalProcess = new GuardedProcess(cmd: _*).start() sslocalProcess = new GuardedProcess(cmd: _*).start()
} }
def startDnsTunnel(): Unit =
sstunnelProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/libss-tunnel.so",
"-V",
"-t", "10",
"-b", "127.0.0.1",
"-l", (profile.localPort + 63).toString,
"-L" , profile.remoteDns.trim + ":53",
"-c", buildShadowsocksConfig("ss-tunnel-vpn.conf")).start()
def startDnsDaemon() { def startDnsDaemon() {
val reject = if (profile.ipv6) "224.0.0.0/3" else "224.0.0.0/3, ::/0" val externalIp = getExternalIp()
IOUtils.writeString(new File(getFilesDir, "pdnsd-vpn.conf"), profile.route match { IOUtils.writeString(new File(getFilesDir, "overture-vpn.conf"), profile.route match {
case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES => case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "protect = \"protect_path\";", getCacheDir.getAbsolutePath, ConfigUtils.OVERTURE_DIRECT.formatLocal(Locale.ENGLISH,
"0.0.0.0", profile.localPort + 53, "114.114.114.114, 223.5.5.5, 1.2.4.8", profile.localPort + 53, // Local Port
getBlackList, reject, profile.localPort + 63, reject) "119.29.29.29", // Primary DNS 1
"udp", // DNS type of Primary DNS 1
"114.114.114.114", // Primary DNS 2
"udp", // DNS type of Primary DNS 2
"208.67.222.222", // Alternative DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp) // External IP
case Acl.CHINALIST => case Acl.CHINALIST =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "protect = \"protect_path\";", getCacheDir.getAbsolutePath, ConfigUtils.OVERTURE_LOCAL.formatLocal(Locale.ENGLISH,
"0.0.0.0", profile.localPort + 53, "8.8.8.8, 8.8.4.4, 208.67.222.222", profile.localPort + 53, // Local Port
"", reject, profile.localPort + 63, reject) "119.29.29.29", // Primary DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp, // External IP
"114.114.114.114", // Alternative DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp) // External IP
case _ => case _ =>
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "protect = \"protect_path\";", getCacheDir.getAbsolutePath, ConfigUtils.OVERTURE_LOCAL.formatLocal(Locale.ENGLISH,
"0.0.0.0", profile.localPort + 53, profile.localPort + 63, reject) profile.localPort + 53, // Local Port
profile.remoteDns, // Primary DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp, // External IP
"208.67.222.222", // Alternative DNS
"127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy
externalIp) // External IP
}) })
val cmd = Array(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", "pdnsd-vpn.conf") val cmd = Array(getApplicationInfo.nativeLibraryDir + "/liboverture.so", "-c", "overture-vpn.conf", "-V")
pdnsdProcess = new GuardedProcess(cmd: _*).start() overtureProcess = new GuardedProcess(cmd: _*).start()
} }
def startVpn(): Int = { def startVpn(): Int = {
......
...@@ -46,83 +46,94 @@ object ConfigUtils { ...@@ -46,83 +46,94 @@ object ConfigUtils {
" type = socks5;\n" + " type = socks5;\n" +
"}\n" "}\n"
val PDNSD_LOCAL = val OVERTURE_DIRECT =
""" """
|global { |{
| perm_cache = 2048; | "BindAddress": ":%d",
| %s | "PrimaryDNS": [
| cache_dir = "%s"; | {
| server_ip = %s; | "Name": "Primary-1",
| server_port = %d; | "Address": "%s:53",
| query_method = tcp_only; | "Protocol": "%s",
| min_ttl = 15m; | "Socks5Address": "",
| max_ttl = 1w; | "Timeout": 6,
| timeout = 10; | "EDNSClientSubnet": {
| daemon = off; | "Policy": "disable",
|} | "ExternalIP": ""
| | }
|server { | },
| label = "local"; | {
| ip = 127.0.0.1; | "Name": "Primary-2",
| port = %d; | "Address": "%s:53",
| reject = %s; | "Protocol": "%s",
| reject_policy = negate; | "Socks5Address": "",
| reject_recursively = on; | "Timeout": 6,
|} | "EDNSClientSubnet": {
| | "Policy": "disable",
|rr { | "ExternalIP": ""
| name=localhost; | }
| reverse=on; | }
| a=127.0.0.1; | ],
| owner=localhost; | "AlternativeDNS":[
| soa=localhost,root.localhost,42,86400,900,86400,86400; | {
| "Name": "Alternative",
| "Address": "%s:53",
| "Protocol": "tcp",
| "Socks5Address": "%s",
| "Timeout": 6,
| "EDNSClientSubnet":{
| "Policy": "auto",
| "ExternalIP": "%s"
| }
| }
| ],
| "RedirectIPv6Record": true,
| "IPNetworkFile": "china_ip_list.txt",
| "DomainFile": "gfwlist.txt",
| "DomainBase64Decode": true,
| "HostsFile": "hosts",
| "MinimumTTL": 3600,
| "CacheSize" : 4096
|} |}
""".stripMargin """.stripMargin
val PDNSD_DIRECT = val OVERTURE_LOCAL =
""" """
|global { |{
| perm_cache = 2048; | "BindAddress": ":%d",
| %s | "PrimaryDNS": [
| cache_dir = "%s"; | {
| server_ip = %s; | "Name": "Primary",
| server_port = %d; | "Address": "%s:53",
| query_method = udp_only; | "Protocol": "tcp",
| min_ttl = 15m; | "Socks5Address": "%s",
| max_ttl = 1w; | "Timeout": 6,
| timeout = 10; | "EDNSClientSubnet": {
| daemon = off; | "Policy": "auto",
| par_queries = 4; | "ExternalIP": "%s"
|} | }
| | }
|server { | ],
| label = "remote-servers"; | "AlternativeDNS":[
| ip = %s; | {
| timeout = 3; | "Name": "Alternative",
| query_method = udp_only; | "Address": "%s:53",
| %s | "Protocol": "tcp",
| policy = included; | "Socks5Address": "%s",
| reject = %s; | "Timeout": 6,
| reject_policy = fail; | "EDNSClientSubnet":{
| reject_recursively = on; | "Policy": "auto",
|} | "ExternalIP": "%s"
| | }
|server { | }
| label = "local-server"; | ],
| ip = 127.0.0.1; | "RedirectIPv6Record": true,
| query_method = tcp_only; | "IPNetworkFile": "",
| port = %d; | "DomainFile": "",
| reject = %s; | "DomainBase64Decode": true,
| reject_policy = negate; | "HostsFile": "hosts",
| reject_recursively = on; | "MinimumTTL": 3600,
|} | "CacheSize" : 4096
|
|rr {
| name=localhost;
| reverse=on;
| a=127.0.0.1;
| owner=localhost;
| soa=localhost,root.localhost,42,86400,900,86400,86400;
|} |}
""".stripMargin """.stripMargin
} }
......
* 0.0.3:
* Update support library version to 25.2.0.
* 0.0.2: * 0.0.2:
* Add `getOrDefault` to `PluginOptions`; * Add `getOrDefault` to `PluginOptions`;
* Update support library version to 25.1.1. * Update support library version to 25.1.1.
......
...@@ -2,7 +2,7 @@ enablePlugins(AndroidLib) ...@@ -2,7 +2,7 @@ enablePlugins(AndroidLib)
android.useSupportVectors android.useSupportVectors
name := "plugin" name := "plugin"
version := "0.0.2" version := "0.0.3-SNAPSHOT"
pomExtra in Global := { pomExtra in Global := {
<url>https://github.com/shadowsocks/shadowsocks-android</url> <url>https://github.com/shadowsocks/shadowsocks-android</url>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment