diff --git a/src/main/java/com/github/shadowsocks/System.java b/src/main/java/com/github/shadowsocks/System.java index 47b10ed6..cc89e624 100755 --- a/src/main/java/com/github/shadowsocks/System.java +++ b/src/main/java/com/github/shadowsocks/System.java @@ -43,7 +43,7 @@ public class System { java.lang.System.loadLibrary("system"); } - public static native void exec(String cmd); + public static native int exec(String cmd); public static native String getABI(); public static native int sendfd(int fd); public static native void jniclose(int fd); diff --git a/src/main/jni/Android.mk b/src/main/jni/Android.mk index 43614f65..a4034411 100755 --- a/src/main/jni/Android.mk +++ b/src/main/jni/Android.mk @@ -214,7 +214,7 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) -REDSOCKS_SOURCES := base.c dnstc.c http-connect.c \ +REDSOCKS_SOURCES := base.c http-connect.c \ log.c md5.c socks5.c \ base64.c http-auth.c http-relay.c main.c \ parser.c redsocks.c socks4.c utils.c @@ -223,7 +223,8 @@ LOCAL_STATIC_LIBRARIES := libevent LOCAL_MODULE := redsocks LOCAL_SRC_FILES := $(addprefix redsocks/, $(REDSOCKS_SOURCES)) -LOCAL_CFLAGS := -O2 -std=gnu99 -I$(LOCAL_PATH)/redsocks \ +LOCAL_CFLAGS := -O2 -std=gnu99 -DUSE_IPTABLES \ + -I$(LOCAL_PATH)/redsocks \ -I$(LOCAL_PATH)/libevent/include \ -I$(LOCAL_PATH)/libevent diff --git a/src/main/jni/redsocks b/src/main/jni/redsocks index 65d039c7..76348e93 160000 --- a/src/main/jni/redsocks +++ b/src/main/jni/redsocks @@ -1 +1 @@ -Subproject commit 65d039c7b302510188dc7b3d765a206c3980db51 +Subproject commit 76348e933a3a15176fdb54616d04bc6fdd3c8e0b diff --git a/src/main/jni/system.cpp b/src/main/jni/system.cpp index 39cfc1e4..1252fb0a 100644 --- a/src/main/jni/system.cpp +++ b/src/main/jni/system.cpp @@ -37,10 +37,27 @@ jstring Java_com_github_shadowsocks_system_getabi(JNIEnv *env, jobject thiz) { return env->NewStringUTF(abi); } -void Java_com_github_shadowsocks_system_exec(JNIEnv *env, jobject thiz, jstring cmd) { - const char *str = env->GetStringUTFChars(cmd, 0); - system(str); - env->ReleaseStringUTFChars(cmd, str); +jint Java_com_github_shadowsocks_system_exec(JNIEnv *env, jobject thiz, jstring cmd) { + const char *cmd_str = env->GetStringUTFChars(cmd, 0); + + pid_t pid; + + /* Fork off the parent process */ + pid = fork(); + if (pid < 0) { + env->ReleaseStringUTFChars(cmd, cmd_str); + return -1; + } + + if (pid > 0) { + env->ReleaseStringUTFChars(cmd, cmd_str); + return pid; + } + + execl("/system/bin/sh", "sh", "-c", cmd_str, NULL); + env->ReleaseStringUTFChars(cmd, cmd_str); + + return 1; } void Java_com_github_shadowsocks_system_jniclose(JNIEnv *env, jobject thiz, jint fd) { @@ -83,7 +100,7 @@ static JNINativeMethod method_table[] = { (void*) Java_com_github_shadowsocks_system_jniclose }, { "sendfd", "(I)I", (void*) Java_com_github_shadowsocks_system_sendfd }, - { "exec", "(Ljava/lang/String;)V", + { "exec", "(Ljava/lang/String;)I", (void*) Java_com_github_shadowsocks_system_exec }, { "getABI", "()Ljava/lang/String;", (void*) Java_com_github_shadowsocks_system_getabi } diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala index 54fdfa3d..52e11c9d 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala @@ -75,6 +75,11 @@ class ShadowsocksNatService extends Service with BaseService { var apps: Array[ProxiedApp] = null val myUid = Process.myUid() + var sslocalPid: Int = 0; + var sstunnelPid: Int = 0; + var redsocksPid: Int = 0; + var pdnsdPid: Int = 0; + private val dnsAddressCache = new SparseArray[String] def getNetId(network: Network): Int = { @@ -184,8 +189,7 @@ class ShadowsocksNatService extends Service with BaseService { cmd += (Path.BASE + "ss-local" , "-b" , "127.0.0.1" , "-t" , "600" - , "-c" , Path.BASE + "ss-local-nat.conf" - , "-f" , Path.BASE + "ss-local-nat.pid") + , "-c" , Path.BASE + "ss-local-nat.conf") if (config.isAuth) cmd += "-A" @@ -195,7 +199,7 @@ class ShadowsocksNatService extends Service with BaseService { } if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) - Console.runCommand(cmd.mkString(" ")) + sslocalPid = System.exec(cmd.mkString(" ")) } def startTunnel() { @@ -212,8 +216,7 @@ class ShadowsocksNatService extends Service with BaseService { , "-t" , "10" , "-b" , "127.0.0.1" , "-L" , "8.8.8.8:53" - , "-c" , Path.BASE + "ss-tunnel-nat.conf" - , "-f" , Path.BASE + "ss-tunnel-nat.pid") + , "-c" , Path.BASE + "ss-tunnel-nat.conf") cmd += ("-l" , "8153") @@ -221,7 +224,7 @@ class ShadowsocksNatService extends Service with BaseService { if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) - Console.runCommand(cmd.mkString(" ")) + sstunnelPid = System.exec(cmd.mkString(" ")) } else { val conf = ConfigUtils @@ -237,13 +240,13 @@ class ShadowsocksNatService extends Service with BaseService { , "-b" , "127.0.0.1" , "-l" , "8163" , "-L" , "8.8.8.8:53" - , "-c" , Path.BASE + "ss-tunnel-nat.conf" - , "-f" , Path.BASE + "ss-tunnel-nat.pid") + , "-c" , Path.BASE + "ss-tunnel-nat.conf") if (config.isAuth) cmdBuf += "-A" if (BuildConfig.DEBUG) Log.d(TAG, cmdBuf.mkString(" ")) - Console.runCommand(cmdBuf.mkString(" ")) + + sstunnelPid = System.exec(cmdBuf.mkString(" ")) } } @@ -253,10 +256,10 @@ class ShadowsocksNatService extends Service with BaseService { val reject = ConfigUtils.getRejectList(getContext) val blackList = ConfigUtils.getBlackList(getContext) ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "127.0.0.1", 8153, - Path.BASE + "pdnsd-nat.pid", reject, blackList, 8163, "") + reject, blackList, 8163, "") } else { ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "127.0.0.1", 8153, - Path.BASE + "pdnsd-nat.pid", 8163, "") + 8163, "") } ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-nat.conf"))(p => { @@ -266,7 +269,7 @@ class ShadowsocksNatService extends Service with BaseService { if (BuildConfig.DEBUG) Log.d(TAG, cmd) - Console.runCommand(cmd) + pdnsdPid = System.exec(cmd) } @@ -284,14 +287,14 @@ class ShadowsocksNatService extends Service with BaseService { def startRedsocksDaemon() { val conf = ConfigUtils.REDSOCKS.formatLocal(Locale.ENGLISH, config.localPort) - val cmd = Path.BASE + "redsocks -p %sredsocks-nat.pid -c %sredsocks-nat.conf" + val cmd = Path.BASE + "redsocks -c %sredsocks-nat.conf" .formatLocal(Locale.ENGLISH, Path.BASE, Path.BASE) ConfigUtils.printToFile(new File(Path.BASE + "redsocks-nat.conf"))(p => { p.println(conf) }) if (BuildConfig.DEBUG) Log.d(TAG, cmd) - Console.runCommand(cmd) + redsocksPid = System.exec(cmd) } /** Called when the activity is first created. */ @@ -348,27 +351,27 @@ class ShadowsocksNatService extends Service with BaseService { } def killProcesses() { - val cmd = new ArrayBuffer[String]() - - for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks")) { - cmd.append("chmod 666 %s%s-nat.pid".formatLocal(Locale.ENGLISH, Path.BASE, task)) + try { + Process.killProcess(sslocalPid) + } catch { + case e: Throwable => Log.e(TAG, "unable to kill ss-local") } - Console.runRootCommand(cmd.toArray) - cmd.clear() - - for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks")) { - try { - val pid = scala.io.Source.fromFile(Path.BASE + task + "-nat.pid").mkString.trim.toInt - cmd.append("kill -9 %d".formatLocal(Locale.ENGLISH, pid)) - Process.killProcess(pid) - } catch { - case e: Throwable => Log.e(TAG, "unable to kill " + task) - } - cmd.append("rm -f %s%s-nat.pid".formatLocal(Locale.ENGLISH, Path.BASE, task)) - cmd.append("rm -f %s%s-nat.conf".formatLocal(Locale.ENGLISH, Path.BASE, task)) + try { + Process.killProcess(sstunnelPid) + } catch { + case e: Throwable => Log.e(TAG, "unable to kill ss-tunnel") + } + try { + Process.killProcess(redsocksPid) + } catch { + case e: Throwable => Log.e(TAG, "unable to kill redsocks") + } + try { + Process.killProcess(pdnsdPid) + } catch { + case e: Throwable => Log.e(TAG, "unable to kill pdnsd") } - Console.runRootCommand(cmd.toArray) Console.runRootCommand(Utils.getIptables + " -t nat -F OUTPUT") } diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala index 0b454a62..8b78ba7c 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala @@ -71,6 +71,11 @@ class ShadowsocksVpnService extends VpnService with BaseService { var vpnThread: ShadowsocksVpnThread = null var closeReceiver: BroadcastReceiver = null + var sslocalPid: Int = 0; + var sstunnelPid: Int = 0; + var tun2socksPid: Int = 0; + var pdnsdPid: Int = 0; + def isByass(net: SubnetUtils): Boolean = { val info = net.getInfo info.isInRange(config.proxy) @@ -188,13 +193,25 @@ class ShadowsocksVpnService extends VpnService with BaseService { } def killProcesses() { - for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "tun2socks")) { - try { - val pid = scala.io.Source.fromFile(Path.BASE + task + "-vpn.pid").mkString.trim.toInt - Process.killProcess(pid) - } catch { - case e: Throwable => Log.e(TAG, "unable to kill " + task) - } + try { + Process.killProcess(sslocalPid) + } catch { + case e: Throwable => Log.e(TAG, "unable to kill ss-local") + } + try { + Process.killProcess(sstunnelPid) + } catch { + case e: Throwable => Log.e(TAG, "unable to kill ss-tunnel") + } + try { + Process.killProcess(tun2socksPid) + } catch { + case e: Throwable => Log.e(TAG, "unable to kill tun2socks") + } + try { + Process.killProcess(pdnsdPid) + } catch { + case e: Throwable => Log.e(TAG, "unable to kill pdnsd") } } @@ -316,8 +333,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { cmd += (Path.BASE + "ss-local", "-V", "-u" , "-b", "127.0.0.1" , "-t", "600" - , "-c", Path.BASE + "ss-local-vpn.conf" - , "-f", Path.BASE + "ss-local-vpn.pid") + , "-c", Path.BASE + "ss-local-vpn.conf") if (config.isAuth) cmd += "-A" @@ -327,7 +343,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { } if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) - Console.runCommand(cmd.mkString(" ")) + sslocalPid = System.exec(cmd.mkString(" ")) } def startDnsTunnel() = { @@ -345,13 +361,12 @@ class ShadowsocksVpnService extends VpnService with BaseService { , "-b", "127.0.0.1" , "-l", "8163" , "-L", "8.8.8.8:53" - , "-c", Path.BASE + "ss-tunnel-vpn.conf" - , "-f", Path.BASE + "ss-tunnel-vpn.pid") + , "-c", Path.BASE + "ss-tunnel-vpn.conf") if (config.isAuth) cmd += "-A" if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) - Console.runCommand(cmd.mkString(" ")) + sstunnelPid = System.exec(cmd.mkString(" ")) } def startDnsDaemon() { @@ -361,10 +376,10 @@ class ShadowsocksVpnService extends VpnService with BaseService { val reject = ConfigUtils.getRejectList(getContext) val blackList = ConfigUtils.getBlackList(getContext) ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "0.0.0.0", 8153, - Path.BASE + "pdnsd-vpn.pid", reject, blackList, 8163, ipv6) + reject, blackList, 8163, ipv6) } else { ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "0.0.0.0", 8153, - Path.BASE + "pdnsd-vpn.pid", 8163, ipv6) + 8163, ipv6) } } ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-vpn.conf"))(p => { @@ -373,7 +388,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd-vpn.conf" if (BuildConfig.DEBUG) Log.d(TAG, cmd) - Console.runCommand(cmd) + pdnsdPid = System.exec(cmd) } override def getContext = getBaseContext @@ -446,8 +461,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { + "--socks-server-addr 127.0.0.1:%d " + "--tunfd %d " + "--tunmtu %d " - + "--loglevel 3 " - + "--pid %stun2socks-vpn.pid") + + "--loglevel 3 ") .formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "2"), config.localPort, fd, VPN_MTU, Path.BASE) @@ -462,7 +476,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { if (BuildConfig.DEBUG) Log.d(TAG, cmd) - Console.runCommand(cmd) + tun2socksPid = System.exec(cmd) fd } diff --git a/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala b/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala index 73dc5db0..046eabba 100644 --- a/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala +++ b/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala @@ -51,16 +51,16 @@ object ConfigUtils { " log_debug = off;" + " log_info = off;" + " log = stderr;" + - " daemon = on;" + + " daemon = off;" + " redirector = iptables;" + - "}" + + " }\n" + "redsocks {" + " local_ip = 127.0.0.1;" + " local_port = 8123;" + " ip = 127.0.0.1;" + " port = %d;" + " type = socks5;" + - "}" + " }" val PDNSD_LOCAL = """ @@ -74,8 +74,7 @@ object ConfigUtils { | min_ttl = 15m; | max_ttl = 1w; | timeout = 10; - | daemon = on; - | pid_file = %s; + | daemon = off; |} | |server { @@ -109,8 +108,7 @@ object ConfigUtils { | min_ttl = 15m; | max_ttl = 1w; | timeout = 10; - | daemon = on; - | pid_file = "%s"; + | daemon = off; |} | |server { @@ -153,8 +151,7 @@ object ConfigUtils { | min_ttl = 15m; | max_ttl = 1w; | timeout = 10; - | daemon = on; - | pid_file = "%s"; + | daemon = off; |} | |server {