Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b37d88f74 | ||
|
|
8ee5d77c6f | ||
|
|
8cbfad80f4 | ||
|
|
9857e42776 | ||
|
|
2f84c74d06 |
@@ -1,7 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.shadowsocks"
|
||||
android:versionCode="86"
|
||||
android:versionName="2.4.6">
|
||||
android:versionCode="88"
|
||||
android:versionName="2.5.0">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
@@ -74,11 +74,13 @@
|
||||
|
||||
<service
|
||||
android:name=".ShadowsocksNatService"
|
||||
android:process=":nat"
|
||||
android:exported="false">
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".ShadowsocksVpnService"
|
||||
android:process=":vpn"
|
||||
android:label="@string/app_name"
|
||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||
android:exported="false">
|
||||
|
||||
@@ -322,35 +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)
|
||||
|
||||
if (!Utils.isLollipopOrAbove) {
|
||||
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/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")
|
||||
|
||||
ab.append(Utils.getIptables + " -t nat -F OUTPUT")
|
||||
|
||||
Console.runRootCommand(ab.toArray)
|
||||
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 = {
|
||||
@@ -506,7 +505,7 @@ class Shadowsocks
|
||||
|
||||
// Bind to the service
|
||||
spawn {
|
||||
val isRoot = !Utils.isLollipopOrAbove && Console.isRoot
|
||||
val isRoot = Console.isRoot
|
||||
handler.post(new Runnable {
|
||||
override def run() {
|
||||
status.edit.putBoolean(Key.isRoot, isRoot).commit()
|
||||
|
||||
@@ -41,11 +41,11 @@ package com.github.shadowsocks
|
||||
|
||||
import java.io.File
|
||||
import java.lang.reflect.{InvocationTargetException, Method}
|
||||
import java.util.{Timer, TimerTask}
|
||||
|
||||
import android.app.{Notification, NotificationManager, PendingIntent, Service}
|
||||
import android.content._
|
||||
import android.content.pm.{PackageInfo, PackageManager}
|
||||
import android.net.{Network, ConnectivityManager}
|
||||
import android.os._
|
||||
import android.support.v4.app.NotificationCompat
|
||||
import android.util.Log
|
||||
@@ -71,7 +71,8 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
private val mStopForegroundSignature = Array[Class[_]](classOf[Boolean])
|
||||
private val mSetForegroundSignature = Array[Class[_]](classOf[Boolean])
|
||||
|
||||
var receiver: BroadcastReceiver = null
|
||||
var closeReceiver: BroadcastReceiver = null
|
||||
var conReceiver: BroadcastReceiver = null
|
||||
var notificationManager: NotificationManager = null
|
||||
var config: Config = null
|
||||
var apps: Array[ProxiedApp] = null
|
||||
@@ -84,13 +85,49 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
private var mStartForegroundArgs = new Array[AnyRef](2)
|
||||
private var mStopForegroundArgs = new Array[AnyRef](1)
|
||||
|
||||
private var lastTxRate = 0
|
||||
private var lastRxRate = 0
|
||||
private var timer: Timer = null
|
||||
private val TIMER_INTERVAL = 2
|
||||
|
||||
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
|
||||
|
||||
def setDnsForAllNetwork(dns: String) {
|
||||
val manager = getSystemService(Context.CONNECTIVITY_SERVICE).asInstanceOf[ConnectivityManager]
|
||||
val networks = manager.getAllNetworks
|
||||
val cmdBuf = new ArrayBuffer[String]()
|
||||
networks.foreach(network => {
|
||||
val networkInfo = manager.getNetworkInfo(network)
|
||||
if (networkInfo.isAvailable) {
|
||||
val netId = network.getClass.getDeclaredField("netId").get(network).asInstanceOf[Int]
|
||||
cmdBuf.append("ndc resolver setnetdns %d \"\" %s".format(netId, dns))
|
||||
}
|
||||
})
|
||||
Console.runRootCommand(cmdBuf.toArray)
|
||||
}
|
||||
|
||||
def setupDns() = {
|
||||
setDnsForAllNetwork("127.0.0.1")
|
||||
}
|
||||
|
||||
def resetDns() = {
|
||||
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() {
|
||||
if (config.route != Route.ALL) {
|
||||
val acl: Array[String] = config.route match {
|
||||
@@ -105,15 +142,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"
|
||||
@@ -129,24 +166,35 @@ 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" , "8153"
|
||||
, "-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")
|
||||
} else {
|
||||
cmd += ("-l" , "8153")
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
|
||||
Console.runCommand(cmd.mkString(" "))
|
||||
|
||||
if (Utils.isLollipopOrAbove) {
|
||||
Console.runRootCommand(cmd.mkString(" "))
|
||||
} else {
|
||||
Console.runCommand(cmd.mkString(" "))
|
||||
}
|
||||
|
||||
} else {
|
||||
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]
|
||||
@@ -154,8 +202,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(" "))
|
||||
@@ -163,15 +211,26 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
}
|
||||
|
||||
def startDnsDaemon() {
|
||||
val conf = ConfigUtils
|
||||
.PDNSD_BYPASS.format("127.0.0.1", getString(R.string.exclude), 8163)
|
||||
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd.conf"))(p => {
|
||||
val conf = if (Utils.isLollipopOrAbove) {
|
||||
ConfigUtils
|
||||
.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, Path.BASE + "pdnsd-nat.pid", getString(R.string.exclude), 8163)
|
||||
}
|
||||
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)
|
||||
Console.runCommand(cmd)
|
||||
|
||||
if (Utils.isLollipopOrAbove) {
|
||||
Console.runRootCommand(cmd)
|
||||
} else {
|
||||
Console.runCommand(cmd)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def getVersionName: String = {
|
||||
@@ -188,14 +247,14 @@ 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)
|
||||
})
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
|
||||
Console.runCommand(cmd);
|
||||
Console.runCommand(cmd)
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@@ -280,15 +339,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".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
|
||||
val pid = scala.io.Source.fromFile(Path.BASE + task + "-nat.pid").mkString.trim.toInt
|
||||
cmd.append("kill -9 %d".format(pid))
|
||||
Process.killProcess(pid)
|
||||
Log.d(TAG, "kill pid: " + 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")
|
||||
}
|
||||
|
||||
@@ -308,9 +379,13 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
}
|
||||
init_sb.append(cmd_bypass.replace("0.0.0.0", "127.0.0.1"))
|
||||
init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "-m owner --uid-owner " + myUid))
|
||||
init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "--dport 53"))
|
||||
|
||||
if (!Utils.isLollipopOrAbove) {
|
||||
init_sb.append(Utils.getIptables
|
||||
+ " -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:" + DNS_PORT)
|
||||
}
|
||||
|
||||
init_sb.append(Utils.getIptables
|
||||
+ " -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:" + DNS_PORT)
|
||||
if (config.isGlobalProxy || config.isBypassApps) {
|
||||
http_sb.append(Utils.getIptables + CMD_IPTABLES_DNAT_ADD_SOCKS)
|
||||
}
|
||||
@@ -382,13 +457,15 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
val filter = new IntentFilter()
|
||||
filter.addAction(Intent.ACTION_SHUTDOWN)
|
||||
filter.addAction(Action.CLOSE)
|
||||
receiver = new BroadcastReceiver() {
|
||||
closeReceiver = new BroadcastReceiver() {
|
||||
def onReceive(p1: Context, p2: Intent) {
|
||||
stopRunner()
|
||||
}
|
||||
}
|
||||
registerReceiver(receiver, filter)
|
||||
registerReceiver(closeReceiver, filter)
|
||||
|
||||
// register connection receiver
|
||||
if (Utils.isLollipopOrAbove) initConnectionReceiver()
|
||||
|
||||
// send event
|
||||
application.tracker.send(new HitBuilders.EventBuilder()
|
||||
@@ -444,8 +521,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()
|
||||
@@ -454,12 +537,6 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
.setLabel(getVersionName)
|
||||
.build())
|
||||
|
||||
// reset timer
|
||||
if (timer != null) {
|
||||
timer.cancel()
|
||||
timer = null
|
||||
}
|
||||
|
||||
// reset NAT
|
||||
killProcesses()
|
||||
|
||||
@@ -468,17 +545,14 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
// clean up context
|
||||
if (receiver != null) {
|
||||
unregisterReceiver(receiver)
|
||||
receiver = null
|
||||
}
|
||||
|
||||
stopForegroundCompat(1)
|
||||
|
||||
// change the state
|
||||
changeState(State.STOPPED)
|
||||
}
|
||||
|
||||
override def stopBackgroundService() {
|
||||
stopRunner()
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
override def getTag = TAG
|
||||
|
||||
@@ -72,7 +72,7 @@ class ShadowsocksRunnerActivity extends Activity {
|
||||
|
||||
def isVpnEnabled: Boolean = {
|
||||
if (vpnEnabled < 0) {
|
||||
vpnEnabled = if (Utils.isLollipopOrAbove || !Console.isRoot) {
|
||||
vpnEnabled = if (!Console.isRoot) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
|
||||
@@ -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", 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)
|
||||
@@ -252,7 +250,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
builder.addRoute(addr(0), addr(1).toInt)
|
||||
}
|
||||
})
|
||||
case _ =>
|
||||
case Route.ALL =>
|
||||
for (i <- 1 to 223) {
|
||||
if (i != 26 && i != 127) {
|
||||
val addr = i.toString + ".0.0.0"
|
||||
@@ -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)
|
||||
}
|
||||
@@ -482,7 +479,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
}
|
||||
|
||||
override def stopBackgroundService() {
|
||||
stopRunner()
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
override def getTag = TAG
|
||||
|
||||
@@ -130,14 +130,14 @@ object ConfigUtils {
|
||||
| perm_cache = 2048;
|
||||
| cache_dir = "/data/data/com.github.shadowsocks";
|
||||
| server_ip = %s;
|
||||
| server_port = 8153;
|
||||
| server_port = %d;
|
||||
| query_method = tcp_only;
|
||||
| run_ipv4 = on;
|
||||
| min_ttl = 15m;
|
||||
| max_ttl = 1w;
|
||||
| timeout = 10;
|
||||
| daemon = on;
|
||||
| pid_file = "/data/data/com.github.shadowsocks/pdnsd.pid";
|
||||
| pid_file = "%s";
|
||||
|}
|
||||
|
|
||||
|server {
|
||||
|
||||
@@ -45,36 +45,21 @@ import java.util
|
||||
|
||||
object Console {
|
||||
|
||||
private var shell: Shell.Interactive = null
|
||||
private var rootShell: Shell.Interactive = null
|
||||
|
||||
private def openShell() {
|
||||
if (shell == null) {
|
||||
val builder = new Builder()
|
||||
shell = builder
|
||||
.useSH()
|
||||
.setWatchdogTimeout(10)
|
||||
.open(new OnCommandResultListener {
|
||||
override def onCommandResult(commandCode: Int, exitCode: Int,
|
||||
output: util.List[String]) {
|
||||
if (exitCode < 0) {
|
||||
shell.close()
|
||||
shell = null
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
private def openShell(): Shell.Interactive = {
|
||||
val builder = new Builder()
|
||||
builder
|
||||
.useSH()
|
||||
.setWatchdogTimeout(10)
|
||||
.open()
|
||||
}
|
||||
|
||||
private def openRootShell() {
|
||||
if (rootShell == null) {
|
||||
val builder = new Builder()
|
||||
rootShell = builder
|
||||
.setShell(SU.shell(0, "u:r:untrusted_app:s0"))
|
||||
.setWantSTDERR(true)
|
||||
.setWatchdogTimeout(10)
|
||||
.open()
|
||||
}
|
||||
private def openRootShell(context: String): Shell.Interactive = {
|
||||
val builder = new Builder()
|
||||
builder
|
||||
.setShell(SU.shell(0, context))
|
||||
.setWantSTDERR(true)
|
||||
.setWatchdogTimeout(10)
|
||||
.open()
|
||||
}
|
||||
|
||||
def runCommand(command: String) {
|
||||
@@ -82,39 +67,48 @@ object Console {
|
||||
}
|
||||
|
||||
def runCommand(commands: Array[String]) {
|
||||
if (shell == null) {
|
||||
openShell()
|
||||
}
|
||||
val ts = shell
|
||||
ts.addCommand(commands)
|
||||
ts.waitForIdle()
|
||||
val shell = openShell()
|
||||
shell.addCommand(commands, 0, new OnCommandResultListener {
|
||||
override def onCommandResult(commandCode: Int, exitCode: Int,
|
||||
output: util.List[String]) {
|
||||
if (exitCode < 0) {
|
||||
shell.close()
|
||||
}
|
||||
}
|
||||
})
|
||||
shell.waitForIdle()
|
||||
shell.close()
|
||||
}
|
||||
|
||||
def runRootCommand(command: String): String = runRootCommand(Array(command))
|
||||
def runRootCommand(command: String, context: String): String = runRootCommand(Array(command), context)
|
||||
def runRootCommand(commands: Array[String]): String = runRootCommand(commands, "u:r:init_shell:s0")
|
||||
|
||||
def runRootCommand(commands: Array[String]): String = {
|
||||
def runRootCommand(commands: Array[String], context: String): String = {
|
||||
if (!isRoot) {
|
||||
return null
|
||||
}
|
||||
if (rootShell == null) {
|
||||
openRootShell()
|
||||
}
|
||||
val ts = rootShell
|
||||
val shell = openRootShell(context)
|
||||
val sb = new StringBuilder
|
||||
ts.addCommand(commands, 0, new OnCommandResultListener {
|
||||
shell.addCommand(commands, 0, new OnCommandResultListener {
|
||||
override def onCommandResult(commandCode: Int, exitCode: Int,
|
||||
output: util.List[String]) {
|
||||
if (exitCode < 0) {
|
||||
rootShell.close()
|
||||
rootShell = null
|
||||
shell.close()
|
||||
} else {
|
||||
import scala.collection.JavaConversions._
|
||||
output.foreach(line => sb.append(line).append('\n'))
|
||||
}
|
||||
}
|
||||
})
|
||||
if (ts.waitForIdle()) sb.toString()
|
||||
else null
|
||||
if (shell.waitForIdle()) {
|
||||
shell.close()
|
||||
sb.toString()
|
||||
}
|
||||
else {
|
||||
shell.close()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
def isRoot: Boolean = SU.available()
|
||||
|
||||
Reference in New Issue
Block a user