diff --git a/src/main/aidl/com/github/shadowsocks/aidl/Config.java b/src/main/aidl/com/github/shadowsocks/aidl/Config.java
index f0afc982..96060b1b 100644
--- a/src/main/aidl/com/github/shadowsocks/aidl/Config.java
+++ b/src/main/aidl/com/github/shadowsocks/aidl/Config.java
@@ -14,6 +14,7 @@ public class Config implements Parcelable {
public String profileName = "Untitled";
public String proxy = "127.0.0.1";
public String sitekey = "null";
+ public String route = "all";
public String encMethod = "rc4";
public String proxiedAppString = "";
@@ -33,7 +34,7 @@ public class Config implements Parcelable {
public Config(boolean isGlobalProxy, boolean isGFWList, boolean isBypassApps,
boolean isTrafficStat, boolean isUdpDns, String profileName, String proxy, String sitekey,
- String encMethod, String proxiedAppString, int remotePort, int localPort) {
+ String encMethod, String proxiedAppString, String route, int remotePort, int localPort) {
this.isGlobalProxy = isGlobalProxy;
this.isGFWList = isGFWList;
this.isBypassApps = isBypassApps;
@@ -44,6 +45,7 @@ public class Config implements Parcelable {
this.sitekey = sitekey;
this.encMethod = encMethod;
this.proxiedAppString = proxiedAppString;
+ this.route = route;
this.remotePort = remotePort;
this.localPort = localPort;
}
@@ -63,6 +65,7 @@ public class Config implements Parcelable {
sitekey = in.readString();
encMethod = in.readString();
proxiedAppString = in.readString();
+ route = in.readString();
remotePort = in.readInt();
localPort = in.readInt();
}
@@ -82,6 +85,7 @@ public class Config implements Parcelable {
out.writeString(sitekey);
out.writeString(encMethod);
out.writeString(proxiedAppString);
+ out.writeString(route);
out.writeInt(remotePort);
out.writeInt(localPort);
}
diff --git a/src/main/res/values-zh/strings.xml b/src/main/res/values-zh/strings.xml
index a32266fe..2d4b5e81 100755
--- a/src/main/res/values-zh/strings.xml
+++ b/src/main/res/values-zh/strings.xml
@@ -25,6 +25,8 @@
重定向 DNS 查询到远程服务器
国内路由
绕过所有位于中国的网站
+ 路由
+ 绕过指定路由列表中的地址
全局代理
设置系统代理
局部代理
@@ -76,4 +78,10 @@
- 手动设置
+
+ - 全局
+ - 绕过局域网地址
+ - 绕过局域网及中国大陆地址
+
+
diff --git a/src/main/res/values/arrays.xml b/src/main/res/values/arrays.xml
index b2c4579c..0d9b3011 100644
--- a/src/main/res/values/arrays.xml
+++ b/src/main/res/values/arrays.xml
@@ -38,7 +38,36 @@
- seed-cfb
-
+
+ - All
+ - Bypass LAN
+ - Bypass LAN & China
+
+
+
+ - all
+ - bypass-lan
+ - bypass-china
+
+
+
+ - 0.0.0.0/8
+ - 10.0.0.0/8
+ - 100.64.0.0/10
+ - 127.0.0.0/8
+ - 169.254.0.0/16
+ - 172.16.0.0/12
+ - 192.0.0.0/29
+ - 192.0.2.0/24
+ - 192.88.99.0/24
+ - 192.168.0.0/16
+ - 198.18.0.0/15
+ - 198.51.100.0/24
+ - 203.0.113.0/24
+ - 224.0.0.0/3
+
+
+
- 1.0.0.0/8
- 2.0.0.0/7
- 4.0.0.0/6
@@ -162,7 +191,10 @@
- 208.0.0.0/4
-
+
+ - 10.0.0.0/8
+ - 172.16.0.0/12
+ - 192.168.0.0/16
- 1.0.1.0/24
- 1.0.2.0/23
- 1.0.8.0/21
@@ -222,7 +254,6 @@
- 1.192.0.0/13
- 1.202.0.0/15
- 1.204.0.0/14
- - 10.0.0.0/8
- 14.0.0.0/21
- 14.0.12.0/22
- 14.1.0.0/22
@@ -1924,7 +1955,6 @@
- 171.116.0.0/14
- 171.120.0.0/13
- 171.208.0.0/12
- - 172.16.0.0/12
- 175.0.0.0/12
- 175.16.0.0/13
- 175.24.0.0/14
@@ -2028,7 +2058,6 @@
- 183.184.0.0/13
- 183.192.0.0/10
- 192.124.154.0/24
- - 192.168.0.0/16
- 192.188.170.0/24
- 202.0.100.0/23
- 202.0.122.0/23
@@ -3970,9 +3999,8 @@
- 223.255.252.0/23
-
+
- 0.0.0.0/7
- - 10.0.0.0/8
- 14.0.0.0/8
- 27.0.0.0/8
- 36.0.0.0/8
@@ -4017,7 +4045,7 @@
- 220.0.0.0/6
-
+
- 1.0.0.0/23
- 1.0.4.0/22
- 1.0.16.0/20
@@ -8507,7 +8535,7 @@
- 223.255.254.0/23
-
+
- 1.0.0.0/15
- 1.2.0.0/16
- 1.4.0.0/14
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index f9ee2beb..b18e2897 100755
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -32,6 +32,8 @@
CHN Route
Bypass all sites located in China
+ Route
+ Bypass IP addresses in the route list
Global Proxy
Set up system-wide proxy
diff --git a/src/main/res/xml/pref_all.xml b/src/main/res/xml/pref_all.xml
index c59f3054..4b3bbe8b 100644
--- a/src/main/res/xml/pref_all.xml
+++ b/src/main/res/xml/pref_all.xml
@@ -48,12 +48,14 @@
-
-
+
+
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 _ =>
diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
index f76cfb45..bfbf4f1b 100644
--- a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
+++ b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
@@ -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 "
diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
index a7821f8f..e9d6d0cb 100644
--- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
+++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
@@ -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
}
diff --git a/src/main/scala/com/github/shadowsocks/database/DBHelper.scala b/src/main/scala/com/github/shadowsocks/database/DBHelper.scala
index 736dfb62..946bcb51 100644
--- a/src/main/scala/com/github/shadowsocks/database/DBHelper.scala
+++ b/src/main/scala/com/github/shadowsocks/database/DBHelper.scala
@@ -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)
diff --git a/src/main/scala/com/github/shadowsocks/database/Profile.scala b/src/main/scala/com/github/shadowsocks/database/Profile.scala
index 14d3b8ee..b2f0e9b1 100644
--- a/src/main/scala/com/github/shadowsocks/database/Profile.scala
+++ b/src/main/scala/com/github/shadowsocks/database/Profile.scala
@@ -66,6 +66,9 @@ class Profile {
@DatabaseField
var date: String = ""
+ @DatabaseField
+ var route: String = ""
+
@DatabaseField
var upload: Int = 0
diff --git a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala
index 602a04af..34e2d3fd 100644
--- a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala
+++ b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala
@@ -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, "")
diff --git a/src/main/scala/com/github/shadowsocks/preferences/SummaryListPreference.scala b/src/main/scala/com/github/shadowsocks/preferences/SummaryListPreference.scala
index d4759d2d..f1007766 100644
--- a/src/main/scala/com/github/shadowsocks/preferences/SummaryListPreference.scala
+++ b/src/main/scala/com/github/shadowsocks/preferences/SummaryListPreference.scala
@@ -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) {
diff --git a/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala b/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala
index 9dc9f706..0ee5d488 100644
--- a/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala
+++ b/src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala
@@ -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)
}
}
diff --git a/src/main/scala/com/github/shadowsocks/utils/Constants.scala b/src/main/scala/com/github/shadowsocks/utils/Constants.scala
index d42b51a7..679cec50 100644
--- a/src/main/scala/com/github/shadowsocks/utils/Constants.scala
+++ b/src/main/scala/com/github/shadowsocks/utils/Constants.scala
@@ -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"
+}