diff --git a/build.sh b/build.sh index c53756bb..14cfaff6 100755 --- a/build.sh +++ b/build.sh @@ -15,7 +15,7 @@ rm -rf assets/armeabi-v7a rm -rf assets/x86 mkdir -p assets/armeabi-v7a mkdir -p assets/x86 -for app in iptables pdnsd redsocks ss-local ss-tunnel tun2socks +for app in pdnsd redsocks ss-local ss-tunnel tun2socks do try mv libs/armeabi-v7a/$app assets/armeabi-v7a/ try mv libs/x86/$app assets/x86/ diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index a251f753..759095db 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + android:versionCode="88" + android:versionName="2.5.0"> @@ -74,6 +74,7 @@ diff --git a/src/main/jni/Android.mk b/src/main/jni/Android.mk index fe5a8d10..a8093491 100755 --- a/src/main/jni/Android.mk +++ b/src/main/jni/Android.mk @@ -300,13 +300,13 @@ openssl_subdirs := $(addprefix $(LOCAL_PATH)/openssl/,$(addsuffix /Android.mk, \ include $(openssl_subdirs) # Iptables -LOCAL_PATH := $(ROOT_PATH) -iptables_subdirs := $(addprefix $(LOCAL_PATH)/iptables/,$(addsuffix /Android.mk, \ - iptables \ - extensions \ - libiptc \ - )) -include $(iptables_subdirs) +# LOCAL_PATH := $(ROOT_PATH) +# iptables_subdirs := $(addprefix $(LOCAL_PATH)/iptables/,$(addsuffix /Android.mk, \ +# iptables \ +# extensions \ +# libiptc \ +# )) +# include $(iptables_subdirs) # Import cpufeatures $(call import-module,android/cpufeatures) diff --git a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala index 5a3a48da..ed295f3c 100644 --- a/src/main/scala/com/github/shadowsocks/Shadowsocks.scala +++ b/src/main/scala/com/github/shadowsocks/Shadowsocks.scala @@ -123,7 +123,7 @@ object Shadowsocks { val FEATRUE_PREFS = Array(Key.route, Key.isGlobalProxy, Key.proxyedApps, Key.isUdpDns, Key.isAutoConnect) - val EXECUTABLES = Array(Executable.IPTABLES, Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL, Executable.TUN2SOCKS) + val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL, Executable.TUN2SOCKS) // Helper functions def updateListPreference(pref: Preference, value: String) { @@ -261,7 +261,7 @@ class Shadowsocks override def run() { switchButton.setEnabled(true) } - }, 1000) + }, 2000) } switchButton.setOnCheckedChangeListener(this) } @@ -322,38 +322,34 @@ class Shadowsocks } private def crash_recovery() { - val ab = new ArrayBuffer[String] + val cmd = new ArrayBuffer[String]() - ab.append("kill -9 `cat /data/data/com.github.shadowsocks/ss-local.pid`") - ab.append("kill -9 `cat /data/data/com.github.shadowsocks/ss-tunnel.pid`") - ab.append("kill -9 `cat /data/data/com.github.shadowsocks/tun2socks.pid`") - - ab.append("kill -9 `cat /data/data/com.github.shadowsocks/pdnsd.pid`") - ab.append("rm /data/data/com.github.shadowsocks/pdnsd.pid") - ab.append("rm /data/data/com.github.shadowsocks/pdnsd.conf") - ab.append("rm /data/data/com.github.shadowsocks/pdnsd.cache") - - Console.runCommand(ab.toArray) - - { - ab.clear() - - ab.append("kill -9 `cat /data/data/com.github.shadowsocks/redsocks.pid`") - ab.append("rm /data/data/com.github.shadowsocks/redsocks.conf") - ab.append("rm /data/data/com.github.shadowsocks/redsocks.pid") - - ab.append("kill -9 `cat /data/data/com.github.shadowsocks/ss-tunnel.pid`") - ab.append("rm /data/data/com.github.shadowsocks/ss-tunnel.conf") - ab.append("rm /data/data/com.github.shadowsocks/ss-tunnel.pid") - - ab.append("kill -9 `cat /data/data/com.github.shadowsocks/pdnsd.pid`") - ab.append("rm /data/data/com.github.shadowsocks/pdnsd.pid") - ab.append("rm /data/data/com.github.shadowsocks/pdnsd.conf") - ab.append("rm /data/data/com.github.shadowsocks/pdnsd.cache") - - Console.runRootCommand(ab.toArray) - Console.runRootCommand(Utils.getIptables + " -t nat -F OUTPUT") + for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks")) { + cmd.append("chmod 666 %s%s-nat.pid".format(Path.BASE, task)) + cmd.append("chmod 666 %s%s-vpn.pid".format(Path.BASE, task)) } + Console.runRootCommand(cmd.toArray) + cmd.clear() + + for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks")) { + try { + val pid_nat = scala.io.Source.fromFile(Path.BASE + task + "-nat.pid").mkString.trim.toInt + val pid_vpn = scala.io.Source.fromFile(Path.BASE + task + "-vpn.pid").mkString.trim.toInt + cmd.append("kill -9 %d".format(pid_nat)) + cmd.append("kill -9 %d".format(pid_vpn)) + Process.killProcess(pid_nat) + Process.killProcess(pid_vpn) + } catch { + case e: Throwable => Log.e(Shadowsocks.TAG, "unable to kill " + task, e) + } + cmd.append("rm -f %s%s-nat.pid".format(Path.BASE, task)) + cmd.append("rm -f %s%s-nat.conf".format(Path.BASE, task)) + cmd.append("rm -f %s%s-vpn.pid".format(Path.BASE, task)) + cmd.append("rm -f %s%s-vpn.conf".format(Path.BASE, task)) + } + Console.runCommand(cmd.toArray) + Console.runRootCommand(cmd.toArray) + Console.runRootCommand(Utils.getIptables + " -t nat -F OUTPUT") } private def getVersionName: String = { diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala index 1eb73c62..6d162c21 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala @@ -41,15 +41,14 @@ package com.github.shadowsocks import java.io.File import java.lang.reflect.{InvocationTargetException, Method} -import java.util.{Timer, TimerTask} +import java.util.Timer import android.app.{Notification, NotificationManager, PendingIntent, Service} import android.content._ import android.content.pm.{PackageInfo, PackageManager} -import android.net.ConnectivityManager +import android.net.{Network, ConnectivityManager} import android.os._ import android.support.v4.app.NotificationCompat -import android.support.v4.net.ConnectivityManagerCompat import android.util.Log import com.github.shadowsocks.aidl.Config import com.github.shadowsocks.utils._ @@ -94,7 +93,7 @@ class ShadowsocksNatService extends Service with BaseService { private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication] - def setDns(dns: String) { + def setDnsForAllNetwork(dns: String) { val manager = getSystemService(Context.CONNECTIVITY_SERVICE).asInstanceOf[ConnectivityManager] val networks = manager.getAllNetworks val cmdBuf = new ArrayBuffer[String]() @@ -108,18 +107,31 @@ class ShadowsocksNatService extends Service with BaseService { Console.runRootCommand(cmdBuf.toArray) } - def initConnectionReceiver() { - val filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION) - conReceiver = new BroadcastReceiver { - override def onReceive(context: Context, intent: Intent): Unit = { - setDns("127.0.0.1") - } - } - registerReceiver(conReceiver, filter) + def setupDns() = { + setDnsForAllNetwork("127.0.0.1") } def resetDns() = { - setDns("8.8.8.8 208.67.222.222 114.114.114.114") + setDnsForAllNetwork("8.8.8.8 208.67.222.222 114.114.114.114") + } + + def destroyConnectionReceiver() { + if (conReceiver != null) { + unregisterReceiver(conReceiver) + conReceiver = null + } + resetDns() + } + + def initConnectionReceiver() { + setupDns() + val filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION) + conReceiver = new BroadcastReceiver { + override def onReceive(context: Context, intent: Intent) = { + setupDns() + } + } + registerReceiver(conReceiver, filter) } def startShadowsocksDaemon() { @@ -136,15 +148,15 @@ class ShadowsocksNatService extends Service with BaseService { val conf = ConfigUtils .SHADOWSOCKS.format(config.proxy, config.remotePort, config.localPort, config.sitekey, config.encMethod, 10) - ConfigUtils.printToFile(new File(Path.BASE + "ss-local.json"))(p => { + ConfigUtils.printToFile(new File(Path.BASE + "ss-local-nat.conf"))(p => { p.println(conf) }) val cmd = new ArrayBuffer[String] cmd += (Path.BASE + "ss-local" , "-b" , "127.0.0.1" - , "-c" , Path.BASE + "ss-local.json" - , "-f" , Path.BASE + "ss-local.pid") + , "-c" , Path.BASE + "ss-local-nat.conf" + , "-f" , Path.BASE + "ss-local-nat.pid") if (config.route != Route.ALL) { cmd += "--acl" @@ -160,15 +172,15 @@ class ShadowsocksNatService extends Service with BaseService { val conf = ConfigUtils .SHADOWSOCKS.format(config.proxy, config.remotePort, 8153, config.sitekey, config.encMethod, 10) - ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel.json"))(p => { + ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-nat.conf"))(p => { p.println(conf) }) val cmd = new ArrayBuffer[String] cmd += (Path.BASE + "ss-tunnel" , "-u" , "-b" , "127.0.0.1" , "-L" , "8.8.8.8:53" - , "-c" , Path.BASE + "ss-tunnel.json" - , "-f" , Path.BASE + "ss-tunnel.pid") + , "-c" , Path.BASE + "ss-tunnel-nat.conf" + , "-f" , Path.BASE + "ss-tunnel-nat.pid") if (Utils.isLollipopOrAbove) { cmd += ("-l" , "53") @@ -188,7 +200,7 @@ class ShadowsocksNatService extends Service with BaseService { val conf = ConfigUtils .SHADOWSOCKS.format(config.proxy, config.remotePort, 8163, config.sitekey, config.encMethod, 10) - ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel.json"))(p => { + ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-nat.conf"))(p => { p.println(conf) }) val cmdBuf = new ArrayBuffer[String] @@ -196,8 +208,8 @@ class ShadowsocksNatService extends Service with BaseService { , "-b" , "127.0.0.1" , "-l" , "8163" , "-L" , "8.8.8.8:53" - , "-c" , Path.BASE + "ss-tunnel.json" - , "-f" , Path.BASE + "ss-tunnel.pid") + , "-c" , Path.BASE + "ss-tunnel-nat.conf" + , "-f" , Path.BASE + "ss-tunnel-nat.pid") if (BuildConfig.DEBUG) Log.d(TAG, cmdBuf.mkString(" ")) Console.runCommand(cmdBuf.mkString(" ")) @@ -207,15 +219,15 @@ class ShadowsocksNatService extends Service with BaseService { def startDnsDaemon() { val conf = if (Utils.isLollipopOrAbove) { ConfigUtils - .PDNSD_BYPASS.format("127.0.0.1", 53, getString(R.string.exclude), 8163) + .PDNSD_BYPASS.format("127.0.0.1", 53, Path.BASE + "pdnsd-nat.pid", getString(R.string.exclude), 8163) } else { ConfigUtils - .PDNSD_BYPASS.format("127.0.0.1", 8153, getString(R.string.exclude), 8163) + .PDNSD_BYPASS.format("127.0.0.1", 8153, Path.BASE + "pdnsd-nat.pid", getString(R.string.exclude), 8163) } - ConfigUtils.printToFile(new File(Path.BASE + "pdnsd.conf"))(p => { + ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-nat.conf"))(p => { p.println(conf) }) - val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd.conf" + val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd-nat.conf" if (BuildConfig.DEBUG) Log.d(TAG, cmd) @@ -241,9 +253,9 @@ class ShadowsocksNatService extends Service with BaseService { def startRedsocksDaemon() { val conf = ConfigUtils.REDSOCKS.format(config.localPort) - val cmd = Path.BASE + "redsocks -p %sredsocks.pid -c %sredsocks.conf" + val cmd = Path.BASE + "redsocks -p %sredsocks-nat.pid -c %sredsocks-nat.conf" .format(Path.BASE, Path.BASE) - ConfigUtils.printToFile(new File(Path.BASE + "redsocks.conf"))(p => { + ConfigUtils.printToFile(new File(Path.BASE + "redsocks-nat.conf"))(p => { p.println(conf) }) @@ -334,17 +346,25 @@ 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".format(Path.BASE, task)) + } + 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 + ".pid").mkString.trim.toInt - Process.killProcess(pid) + val pid = scala.io.Source.fromFile(Path.BASE + task + "-nat.pid").mkString.trim.toInt cmd.append("kill -9 %d".format(pid)) - cmd.append("rm -rf %s%s.pid", Path.BASE, task) - Log.d(TAG, "kill pid: " + pid) + Process.killProcess(pid) } catch { case e: Throwable => Log.e(TAG, "unable to kill " + task, e) } + cmd.append("rm -f %s%s-nat.pid".format(Path.BASE, task)) + cmd.append("rm -f %s%s-nat.conf".format(Path.BASE, task)) } + Console.runRootCommand(cmd.toArray) Console.runRootCommand(Utils.getIptables + " -t nat -F OUTPUT") } @@ -507,8 +527,14 @@ class ShadowsocksNatService extends Service with BaseService { override def stopRunner() { - // change the state - changeState(State.STOPPED) + // clean up recevier + if (closeReceiver != null) { + unregisterReceiver(closeReceiver) + closeReceiver = null + } + if (Utils.isLollipopOrAbove) { + destroyConnectionReceiver() + } // send event application.tracker.send(new HitBuilders.EventBuilder() @@ -531,20 +557,10 @@ class ShadowsocksNatService extends Service with BaseService { stopSelf() } - // clean up recevier - if (closeReceiver != null) { - unregisterReceiver(closeReceiver) - closeReceiver = null - } - if (Utils.isLollipopOrAbove) { - if (conReceiver != null) { - unregisterReceiver(conReceiver) - conReceiver = null - } - resetDns() - } - stopForegroundCompat(1) + + // change the state + changeState(State.STOPPED) } override def stopBackgroundService() { diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala index 385b458d..b2ac3597 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala @@ -40,14 +40,12 @@ package com.github.shadowsocks import java.io.File -import java.net.InetAddress import android.app._ import android.content._ import android.content.pm.{PackageInfo, PackageManager} -import android.net.{LocalServerSocket, VpnService, LocalSocket, LocalSocketAddress} +import android.net.VpnService import android.os._ -import android.support.v4.app.NotificationCompat import android.util.Log import com.github.shadowsocks.aidl.Config import com.github.shadowsocks.utils._ @@ -110,15 +108,15 @@ class ShadowsocksVpnService extends VpnService with BaseService { val conf = ConfigUtils .SHADOWSOCKS.format(config.proxy, config.remotePort, config.localPort, config.sitekey, config.encMethod, 10) - ConfigUtils.printToFile(new File(Path.BASE + "ss-local.json"))(p => { + ConfigUtils.printToFile(new File(Path.BASE + "ss-local-vpn.conf"))(p => { p.println(conf) }) val cmd = new ArrayBuffer[String] cmd +=(Path.BASE + "ss-local", "-u" , "-b", "127.0.0.1" - , "-c", Path.BASE + "ss-local.json" - , "-f", Path.BASE + "ss-local.pid") + , "-c", Path.BASE + "ss-local-vpn.conf" + , "-f", Path.BASE + "ss-local-vpn.pid") if (Utils.isLollipopOrAbove && config.route != Route.ALL) { cmd += "--acl" @@ -133,7 +131,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { val conf = ConfigUtils .SHADOWSOCKS.format(config.proxy, config.remotePort, 8163, config.sitekey, config.encMethod, 10) - ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel.json"))(p => { + ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-vpn.conf"))(p => { p.println(conf) }) val cmd = new ArrayBuffer[String] @@ -141,8 +139,8 @@ class ShadowsocksVpnService extends VpnService with BaseService { , "-b", "127.0.0.1" , "-l", "8163" , "-L", "8.8.8.8:53" - , "-c", Path.BASE + "ss-tunnel.json" - , "-f", Path.BASE + "ss-tunnel.pid") + , "-c", Path.BASE + "ss-tunnel-vpn.conf" + , "-f", Path.BASE + "ss-tunnel-vpn.pid") if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) Console.runCommand(cmd.mkString(" ")) @@ -151,15 +149,15 @@ class ShadowsocksVpnService extends VpnService with BaseService { def startDnsDaemon() { val conf = { if (Utils.isLollipopOrAbove) { - ConfigUtils.PDNSD_BYPASS.format("0.0.0.0", 8153, getString(R.string.exclude), 8163) + ConfigUtils.PDNSD_BYPASS.format("0.0.0.0", 8153, Path.BASE + "pdnsd-vpn.pid", getString(R.string.exclude), 8163) } else { ConfigUtils.PDNSD_LOCAL.format("0.0.0.0", 8163) } } - ConfigUtils.printToFile(new File(Path.BASE + "pdnsd.conf"))(p => { + ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-vpn.conf"))(p => { p.println(conf) }) - val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd.conf" + val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd-vpn.conf" if (BuildConfig.DEBUG) Log.d(TAG, cmd) Console.runCommand(cmd) @@ -312,7 +310,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { + "--tunfd %d " + "--tunmtu %d " + "--loglevel 3 " - + "--pid %stun2socks.pid") + + "--pid %stun2socks-vpn.pid") .format(PRIVATE_VLAN.format("2"), config.localPort, fd, VPN_MTU, Path.BASE) if (config.isUdpDns) @@ -321,12 +319,12 @@ class ShadowsocksVpnService extends VpnService with BaseService { cmd += " --dnsgw %s:8153".format(PRIVATE_VLAN.format("1")) if (Utils.isLollipopOrAbove) { - cmd += " --fake-proc"; + cmd += " --fake-proc" } if (BuildConfig.DEBUG) Log.d(TAG, cmd) - System.exec(cmd); + System.exec(cmd) } /** Called when the activity is first created. */ @@ -366,9 +364,8 @@ 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 + ".pid").mkString.trim.toInt + val pid = scala.io.Source.fromFile(Path.BASE + task + "-vpn.pid").mkString.trim.toInt Process.killProcess(pid) - Log.d(TAG, "kill pid: " + pid) } catch { case e: Throwable => Log.e(TAG, "unable to kill " + task, e) } diff --git a/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala b/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala index 329a8705..430d983b 100644 --- a/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala +++ b/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala @@ -137,7 +137,7 @@ object ConfigUtils { | max_ttl = 1w; | timeout = 10; | daemon = on; - | pid_file = "/data/data/com.github.shadowsocks/pdnsd.pid"; + | pid_file = "%s"; |} | |server { diff --git a/src/main/scala/com/github/shadowsocks/utils/Utils.scala b/src/main/scala/com/github/shadowsocks/utils/Utils.scala index 7c2b3474..fd62d047 100644 --- a/src/main/scala/com/github/shadowsocks/utils/Utils.scala +++ b/src/main/scala/com/github/shadowsocks/utils/Utils.scala @@ -68,8 +68,8 @@ object Utils { val DEFAULT_SHELL: String = "/system/bin/sh" val DEFAULT_ROOT: String = "/system/bin/su" val ALTERNATIVE_ROOT: String = "/system/xbin/su" - val DEFAULT_IPTABLES: String = "/data/data/com.github.shadowsocks/iptables" - val ALTERNATIVE_IPTABLES: String = "/system/bin/iptables" + val DEFAULT_IPTABLES: String = "/system/bin/iptables" + val ALTERNATIVE_IPTABLES: String = "/data/data/com.github.shadowsocks/iptables" val TIME_OUT: Int = -99 var initialized: Boolean = false var hasRedirectSupport: Int = -1