This commit is contained in:
Max Lv
2014-11-16 21:35:54 +08:00
parent b15a4604f2
commit 9a724cd063
14 changed files with 206 additions and 117 deletions
@@ -120,15 +120,15 @@ object Shadowsocks {
val PREFS_NAME = "Shadowsocks"
val PROXY_PREFS = Array(Key.profileName, Key.proxy, Key.remotePort, Key.localPort, Key.sitekey,
Key.encMethod)
val FEATRUE_PREFS = Array(Key.isGFWList, Key.isGlobalProxy, Key.proxyedApps,
val FEATRUE_PREFS = Array(Key.route, Key.isGlobalProxy, Key.proxyedApps,
Key.isUdpDns, Key.isAutoConnect)
val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.IPTABLES)
// Helper functions
def updateListPreference(pref: Preference, value: String) {
pref.setSummary(value)
pref.asInstanceOf[ListPreference].setValue(value)
pref.setSummary(pref.asInstanceOf[ListPreference].getEntry)
}
def updatePasswordEditTextPreference(pref: Preference, value: String) {
@@ -158,7 +158,7 @@ object Shadowsocks {
case Key.localPort => updateSummaryEditTextPreference(pref, profile.localPort.toString)
case Key.sitekey => updatePasswordEditTextPreference(pref, profile.password)
case Key.encMethod => updateListPreference(pref, profile.method)
case Key.isGFWList => updateCheckBoxPreference(pref, profile.chnroute)
case Key.route => updateListPreference(pref, profile.route)
case Key.isGlobalProxy => updateCheckBoxPreference(pref, profile.global)
case Key.isUdpDns => updateCheckBoxPreference(pref, profile.udpdns)
case _ =>
@@ -93,19 +93,14 @@ class ShadowsocksNatService extends Service with BaseService {
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
def isACLEnabled: Boolean = {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
true
} else {
false
}
}
def startShadowsocksDaemon() {
if (isACLEnabled && config.isGFWList) {
val chn_list: Array[String] = getResources.getStringArray(R.array.chn_list_full)
ConfigUtils.printToFile(new File(Path.BASE + "chn.acl"))(p => {
chn_list.foreach(item => p.println(item))
if (config.route != Route.ALL) {
val acl: Array[String] = config.route match {
case Route.BYPASS_LAN => getResources.getStringArray(R.array.private_route)
case Route.BYPASS_CHN => getResources.getStringArray(R.array.chn_route_full)
}
ConfigUtils.printToFile(new File(Path.BASE + "acl.list"))(p => {
acl.foreach(item => p.println(item))
})
}
@@ -117,11 +112,11 @@ class ShadowsocksNatService extends Service with BaseService {
, "-l" , config.localPort.toString
, "-k" , config.sitekey
, "-m" , config.encMethod
, "-f" , (Path.BASE + "ss-local.pid"))
, "-f" , Path.BASE + "ss-local.pid")
if (config.isGFWList && isACLEnabled) {
if (config.route != Route.ALL) {
cmd += "--acl"
cmd += (Path.BASE + "chn.acl")
cmd += (Path.BASE + "acl.list")
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
@@ -140,7 +135,7 @@ class ShadowsocksNatService extends Service with BaseService {
, "-p" , config.remotePort.toString
, "-k" , config.sitekey
, "-m" , config.encMethod
, "-f" , (Path.BASE + "ss-tunnel.pid"))
, "-f" , Path.BASE + "ss-tunnel.pid")
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Core.sstunnel(cmd.toArray)
} else {
@@ -298,15 +293,6 @@ 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))
if (config.isGFWList) {
if (!isACLEnabled)
{
val chn_list: Array[String] = getResources.getStringArray(R.array.chn_list)
for (item <- chn_list) {
init_sb.append(cmd_bypass.replace("0.0.0.0", item))
}
}
}
if (hasRedirectSupport) {
init_sb
.append(Utils.getIptables + " -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to "
@@ -64,7 +64,6 @@ class ShadowsocksVpnService extends VpnService with BaseService {
val TAG = "ShadowsocksVpnService"
val VPN_MTU = 1500
val PRIVATE_VLAN = "26.26.26.%s"
var conn: ParcelFileDescriptor = null
@@ -88,28 +87,47 @@ class ShadowsocksVpnService extends VpnService with BaseService {
info.isInRange(config.proxy)
}
def isPrivateA(a: Int): Boolean = {
if (a == 10 || a == 192 || a == 172) {
true
} else {
false
}
}
def isPrivateB(a: Int, b: Int): Boolean = {
if (a == 10 || (a == 192 && b == 168) || (a == 172 && b >= 16 && b < 32)) {
true
} else {
false
}
}
def startShadowsocksDaemon() {
if (isLollipopOrAbove && config.isGFWList) {
val chn_list: Array[String] = getResources.getStringArray(R.array.chn_list_full)
ConfigUtils.printToFile(new File(Path.BASE + "chn.acl"))(p => {
chn_list.foreach(item => p.println(item))
if (isLollipopOrAbove && config.route != Route.ALL) {
val acl: Array[String] = config.route match {
case Route.BYPASS_LAN => getResources.getStringArray(R.array.private_route)
case Route.BYPASS_CHN => getResources.getStringArray(R.array.chn_route_full)
}
ConfigUtils.printToFile(new File(Path.BASE + "acl.list"))(p => {
acl.foreach(item => p.println(item))
})
}
val cmd = new ArrayBuffer[String]
cmd += ("ss-local" , "-u"
, "-b" , "127.0.0.1"
, "-s" , config.proxy
, "-p" , config.remotePort.toString
, "-l" , config.localPort.toString
, "-k" , config.sitekey
, "-m" , config.encMethod
, "-f" , Path.BASE + "ss-local.pid")
cmd +=("ss-local", "-u"
, "-b", "127.0.0.1"
, "-s", config.proxy
, "-p", config.remotePort.toString
, "-l", config.localPort.toString
, "-k", config.sitekey
, "-m", config.encMethod
, "-f", Path.BASE + "ss-local.pid")
if (config.isGFWList && isLollipopOrAbove) {
if (isLollipopOrAbove && config.route != Route.ALL) {
cmd += "--acl"
cmd += (Path.BASE + "chn.acl")
cmd += (Path.BASE + "acl.list")
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
@@ -118,15 +136,15 @@ class ShadowsocksVpnService extends VpnService with BaseService {
def startDnsTunnel() = {
val cmd = new ArrayBuffer[String]
cmd += ("ss-tunnel"
, "-b" , "127.0.0.1"
, "-l" , "8163"
, "-L" , "8.8.8.8:53"
, "-s" , config.proxy
, "-p" , config.remotePort.toString
, "-k" , config.sitekey
, "-m" , config.encMethod
, "-f" , Path.BASE + "ss-tunnel.pid")
cmd +=("ss-tunnel"
, "-b", "127.0.0.1"
, "-l", "8163"
, "-L", "8.8.8.8:53"
, "-s", config.proxy
, "-p", config.remotePort.toString
, "-k", config.sitekey
, "-m", config.encMethod
, "-f", Path.BASE + "ss-tunnel.pid")
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Core.sstunnel(cmd.toArray)
}
@@ -195,52 +213,76 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (InetAddressUtils.isIPv6Address(config.proxy)) {
builder.addRoute("0.0.0.0", 0)
} else if (!isLollipopOrAbove && config.isGFWList) {
val gfwList = {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
getResources.getStringArray(R.array.simple_list)
} else {
getResources.getStringArray(R.array.gfw_list)
}
}
gfwList.foreach(cidr => {
val net = new SubnetUtils(cidr)
if (!isByass(net)) {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
}
})
} else {
if (isLollipopOrAbove) {
val privateList = getResources.getStringArray(R.array.private_list)
privateList.foreach(cidr => {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
})
} else {
for (i <- 1 to 223) {
if (i != 26 && i != 127) {
val addr = i.toString + ".0.0.0"
val cidr = addr + "/8"
val net = new SubnetUtils(cidr)
if (!isLollipopOrAbove) {
config.route match {
case Route.ALL =>
for (i <- 1 to 223) {
if (i != 26 && i != 127) {
val addr = i.toString + ".0.0.0"
val cidr = addr + "/8"
val net = new SubnetUtils(cidr)
if (!isByass(net)) {
if (!InetAddress.getByName(addr).isSiteLocalAddress) {
builder.addRoute(addr, 8)
}
} else {
for (j <- 0 to 255) {
val subAddr = i.toString + "." + j.toString + ".0.0"
val subCidr = subAddr + "/16"
val subNet = new SubnetUtils(subCidr)
if (!isByass(subNet)) {
if (!InetAddress.getByName(subAddr).isSiteLocalAddress) {
builder.addRoute(subAddr, 16)
if (!isByass(net)) {
builder.addRoute(addr, 8)
} else {
for (j <- 0 to 255) {
val subAddr = i.toString + "." + j.toString + ".0.0"
val subCidr = subAddr + "/16"
val subNet = new SubnetUtils(subCidr)
if (!isByass(subNet)) {
builder.addRoute(subAddr, 16)
}
}
}
}
}
}
case Route.BYPASS_LAN =>
for (i <- 1 to 223) {
if (i != 26 && i != 127) {
val addr = i.toString + ".0.0.0"
val cidr = addr + "/8"
val net = new SubnetUtils(cidr)
if (!isByass(net) && !isPrivateA(i)) {
builder.addRoute(addr, 8)
} else {
for (j <- 0 to 255) {
val subAddr = i.toString + "." + j.toString + ".0.0"
val subCidr = subAddr + "/16"
val subNet = new SubnetUtils(subCidr)
if (!isByass(subNet) && !isPrivateB(i, j)) {
builder.addRoute(subAddr, 16)
}
}
}
}
}
case Route.BYPASS_CHN =>
val list = {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
getResources.getStringArray(R.array.simple_route)
} else {
getResources.getStringArray(R.array.gfw_route)
}
}
list.foreach(cidr => {
val net = new SubnetUtils(cidr)
if (!isByass(net)) {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
}
})
}
} else {
if (config.route == Route.ALL) {
builder.addRoute("0.0.0.0", 0)
} else {
val privateList = getResources.getStringArray(R.array.bypass_private_route)
privateList.foreach(cidr => {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
})
}
}
}
@@ -440,6 +482,8 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
override def getTag = TAG
override def getServiceMode = Mode.VPN
override def getContext = getBaseContext
}
@@ -51,7 +51,7 @@ object DBHelper {
}
class DBHelper(val context: Context)
extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 8) {
extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 9) {
lazy val profileDao: Dao[Profile, Int] = getDao(classOf[Profile])
@@ -64,6 +64,9 @@ class DBHelper(val context: Context)
if (oldVersion != newVersion) {
if (oldVersion < 8) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN udpdns SMALLINT;")
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
} else if (oldVersion < 9) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
} else {
profileDao.executeRaw("DROP TABLE IF EXISTS 'profile';")
onCreate(database, connectionSource)
@@ -66,6 +66,9 @@ class Profile {
@DatabaseField
var date: String = ""
@DatabaseField
var route: String = ""
@DatabaseField
var upload: Int = 0
@@ -77,7 +77,7 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
} catch {
case ex: Exception =>
Log.e(Shadowsocks.TAG, "getProfile", ex)
return None
None
}
}
@@ -130,6 +130,7 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
edit.putString(Key.localPort, profile.localPort.toString)
edit.putString(Key.proxied, profile.individual)
edit.putInt(Key.profileId, profile.id)
edit.putString(Key.route, profile.route)
edit.commit()
profile
@@ -149,19 +150,18 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
profile.host = settings.getString(Key.proxy, "127.0.0.1")
profile.password = settings.getString(Key.sitekey, "default")
profile.method = settings.getString(Key.encMethod, "table")
profile.route = settings.getString(Key.route, "all")
profile.remotePort = try {
Integer.valueOf(settings.getString(Key.remotePort, "1984"))
} catch {
case ex: NumberFormatException => {
case ex: NumberFormatException =>
1984
}
}
profile.localPort = try {
Integer.valueOf(settings.getString(Key.localPort, "1984"))
} catch {
case ex: NumberFormatException => {
case ex: NumberFormatException =>
1984
}
}
profile.individual = settings.getString(Key.proxied, "")
@@ -48,7 +48,7 @@ class SummaryListPreference(context: Context, attrs: AttributeSet)
override def setValue(text: String) {
super.setValue(text)
setSummary(text.toUpperCase)
setSummary(getEntry)
}
override def setSummary(summary: CharSequence) {
@@ -198,7 +198,7 @@ object ConfigUtils {
val method = proxy(3).trim
new Config(config.isGlobalProxy, config.isGFWList, config.isBypassApps, config.isTrafficStat,
config.isUdpDns, config.profileName, host, password, method, config.proxiedAppString, port,
config.isUdpDns, config.profileName, host, password, method, config.proxiedAppString, config.route, port,
config.localPort)
}
@@ -213,6 +213,8 @@ object ConfigUtils {
val proxy = settings.getString(Key.proxy, "127.0.0.1")
val sitekey = settings.getString(Key.sitekey, "default")
val encMethod = settings.getString(Key.encMethod, "table")
val route = settings.getString(Key.route, "all")
val remotePort: Int = try {
settings.getString(Key.remotePort, "1984").toInt
} catch {
@@ -228,6 +230,6 @@ object ConfigUtils {
val proxiedAppString = settings.getString(Key.proxied, "")
new Config(isGlobalProxy, isGFWList, isBypassApps, isTrafficStat, isUdpDns, profileName, proxy,
sitekey, encMethod, proxiedAppString, remotePort, localPort)
sitekey, encMethod, proxiedAppString, route, remotePort, localPort)
}
}
@@ -68,6 +68,7 @@ object Key {
val isRoot = "isRoot"
val status = "status"
val proxyedApps = "proxyedApps"
val route = "route"
val isRunning = "isRunning"
val isAutoConnect = "isAutoConnect"
@@ -110,3 +111,9 @@ object Action {
val UPDATE_FRAGMENT = "com.github.shadowsocks.ACTION_UPDATE_FRAGMENT"
val UPDATE_PREFS = "com.github.shadowsocks.ACTION_UPDATE_PREFS"
}
object Route {
val ALL = "all"
val BYPASS_LAN = "bypass-lan"
val BYPASS_CHN = "bypass-china"
}