diff --git a/mobile/src/main/scala/com/github/shadowsocks/BaseService.scala b/mobile/src/main/scala/com/github/shadowsocks/BaseService.scala index 53246ac1..e8c41d0b 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/BaseService.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/BaseService.scala @@ -39,11 +39,11 @@ import com.github.shadowsocks.database.Profile import com.github.shadowsocks.plugin.{PluginConfiguration, PluginManager, PluginOptions} import com.github.shadowsocks.utils._ import okhttp3.{Dns, FormBody, OkHttpClient, Request} -import org.json.JSONObject +import org.json.{JSONArray, JSONObject} +import scala.collection.JavaConversions._ import scala.collection.mutable import scala.collection.mutable.ArrayBuffer -import scala.collection.JavaConversions._ import scala.util.Random trait BaseService extends Service { @@ -123,23 +123,6 @@ trait BaseService extends Service { false } else true - def getExternalIp(): String = { - val url = "http://icanhazip.com" - val client = new OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .readTimeout(30, TimeUnit.SECONDS) - .build() - val request = new Request.Builder() - .url(url) - .build() - val response = client.newCall(request).execute() - if (response.isSuccessful) - response.body.string.trim - else - "" - } - def connect() { if (profile.host == "198.199.101.152") { val holder = app.containerHolder @@ -345,4 +328,60 @@ trait BaseService extends Service { IOUtils.writeString(new File(getFilesDir, file), config.toString) file } + + protected final def buildOvertureConfig(file: String): String = { + val url = "http://icanhazip.com" + val client = new OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .build() + val request = new Request.Builder() + .url(url) + .build() + val response = client.newCall(request).execute() + val externalIp = if (response.isSuccessful) response.body.string.trim else "" + + val config = new JSONObject() + .put("BindAddress", ":" + (profile.localPort + 53)) + .put("RedirectIPv6Record", true) + .put("DomainBase64Decode", true) + .put("HostsFile", "hosts") + .put("MinimumTTL", 3600) + .put("CacheSize", 4096) + def makeDns(name: String, address: String, edns: Boolean = true) = { + val dns = new JSONObject() + .put("Name", name) + .put("Address", address + ":53") + .put("Timeout", 6) + if (edns) dns + .put("Protocol", "tcp") + .put("Socks5Address", "127.0.0.1:" + profile.localPort) + .put("EDNSClientSubnet", new JSONObject() + .put("Policy", "auto") + .put("ExternalIP", externalIp)) + else dns + .put("Protocol", "udp") + .put("EDNSClientSubnet", new JSONObject().put("Policy", "disable")) + dns + } + profile.route match { + case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES => config + .put("PrimaryDNS", new JSONArray(Array( + makeDns("Primary-1", "119.29.29.29", edns = false), + makeDns("Primary-2", "114.114.114.114", edns = false) + ))) + .put("AlternativeDNS", new JSONArray().put(makeDns("Alternative", profile.remoteDns))) + .put("IPNetworkFile", "china_ip_list.txt") + .put("DomainFile", "gfwlist.txt") + case Acl.CHINALIST => config + .put("PrimaryDNS", new JSONArray().put(makeDns("Primary", "119.29.29.29"))) + .put("AlternativeDNS", new JSONArray().put(makeDns("Alternative", profile.remoteDns))) + case _ => config + .put("PrimaryDNS", new JSONArray().put(makeDns("Primary", profile.remoteDns))) + .put("AlternativeDNS", new JSONArray().put(makeDns("Alternative", "208.67.222.222"))) + } + IOUtils.writeString(new File(getFilesDir, file), config.toString) + file + } } diff --git a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala index e4b73f63..3ba848a5 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala @@ -83,38 +83,8 @@ class ShadowsocksNatService extends BaseService { } def startDnsDaemon() { - val externalIp = getExternalIp() - IOUtils.writeString(new File(getFilesDir, "overture-nat.conf"), profile.route match { - case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES => - ConfigUtils.OVERTURE_DIRECT.formatLocal(Locale.ENGLISH, - profile.localPort + 53, // Local Port - "119.29.29.29", // Primary DNS 1 - "udp", // DNS type of Primary DNS 1 - "114.114.114.114", // Primary DNS 2 - "udp", // DNS type of Primary DNS 2 - profile.remoteDns, // Alternative DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp) // External IP - case Acl.CHINALIST => - ConfigUtils.OVERTURE_LOCAL.formatLocal(Locale.ENGLISH, - profile.localPort + 53, // Local Port - "119.29.29.29", // Primary DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp, // External IP - "114.114.114.114", // Alternative DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp) // External IP - case _ => - ConfigUtils.OVERTURE_LOCAL.formatLocal(Locale.ENGLISH, - profile.localPort + 53, // Local Port - profile.remoteDns, // Primary DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp, // External IP - "208.67.222.222", // Alternative DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp) // External IP - }) - overtureProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/liboverture.so", "-c", "overture-nat.conf") + overtureProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/liboverture.so", + "-c", buildOvertureConfig("overture-nat.conf")) .start() } diff --git a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala index 5120d189..f94484f3 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala @@ -177,40 +177,9 @@ class ShadowsocksVpnService extends VpnService with BaseService { } def startDnsDaemon() { - val externalIp = getExternalIp() - IOUtils.writeString(new File(getFilesDir, "overture-vpn.conf"), profile.route match { - case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES => - ConfigUtils.OVERTURE_DIRECT.formatLocal(Locale.ENGLISH, - profile.localPort + 53, // Local Port - "119.29.29.29", // Primary DNS 1 - "udp", // DNS type of Primary DNS 1 - "114.114.114.114", // Primary DNS 2 - "udp", // DNS type of Primary DNS 2 - "208.67.222.222", // Alternative DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp) // External IP - case Acl.CHINALIST => - ConfigUtils.OVERTURE_LOCAL.formatLocal(Locale.ENGLISH, - profile.localPort + 53, // Local Port - "119.29.29.29", // Primary DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp, // External IP - "114.114.114.114", // Alternative DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp) // External IP - case _ => - ConfigUtils.OVERTURE_LOCAL.formatLocal(Locale.ENGLISH, - profile.localPort + 53, // Local Port - profile.remoteDns, // Primary DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp, // External IP - "208.67.222.222", // Alternative DNS - "127.0.0.1:" + profile.localPort, // Local SOCKS5 Proxy - externalIp) // External IP - }) - val cmd = Array(getApplicationInfo.nativeLibraryDir + "/liboverture.so", "-c", "overture-vpn.conf", "-V") - - overtureProcess = new GuardedProcess(cmd: _*).start() + overtureProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/liboverture.so", + "-c", buildOvertureConfig("overture-vpn.conf")) + .start() } def startVpn(): Int = { diff --git a/mobile/src/main/scala/com/github/shadowsocks/utils/Constants.scala b/mobile/src/main/scala/com/github/shadowsocks/utils/Constants.scala index bdafa8c9..80bd0f4a 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/utils/Constants.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/utils/Constants.scala @@ -45,97 +45,6 @@ object ConfigUtils { " port = %d;\n" + " type = socks5;\n" + "}\n" - - val OVERTURE_DIRECT = - """ - |{ - | "BindAddress": ":%d", - | "PrimaryDNS": [ - | { - | "Name": "Primary-1", - | "Address": "%s:53", - | "Protocol": "%s", - | "Socks5Address": "", - | "Timeout": 6, - | "EDNSClientSubnet": { - | "Policy": "disable", - | "ExternalIP": "" - | } - | }, - | { - | "Name": "Primary-2", - | "Address": "%s:53", - | "Protocol": "%s", - | "Socks5Address": "", - | "Timeout": 6, - | "EDNSClientSubnet": { - | "Policy": "disable", - | "ExternalIP": "" - | } - | } - | ], - | "AlternativeDNS":[ - | { - | "Name": "Alternative", - | "Address": "%s:53", - | "Protocol": "tcp", - | "Socks5Address": "%s", - | "Timeout": 6, - | "EDNSClientSubnet":{ - | "Policy": "auto", - | "ExternalIP": "%s" - | } - | } - | ], - | "RedirectIPv6Record": true, - | "IPNetworkFile": "china_ip_list.txt", - | "DomainFile": "gfwlist.txt", - | "DomainBase64Decode": true, - | "HostsFile": "hosts", - | "MinimumTTL": 3600, - | "CacheSize" : 4096 - |} - """.stripMargin - - val OVERTURE_LOCAL = - """ - |{ - | "BindAddress": ":%d", - | "PrimaryDNS": [ - | { - | "Name": "Primary", - | "Address": "%s:53", - | "Protocol": "tcp", - | "Socks5Address": "%s", - | "Timeout": 6, - | "EDNSClientSubnet": { - | "Policy": "auto", - | "ExternalIP": "%s" - | } - | } - | ], - | "AlternativeDNS":[ - | { - | "Name": "Alternative", - | "Address": "%s:53", - | "Protocol": "tcp", - | "Socks5Address": "%s", - | "Timeout": 6, - | "EDNSClientSubnet":{ - | "Policy": "auto", - | "ExternalIP": "%s" - | } - | } - | ], - | "RedirectIPv6Record": true, - | "IPNetworkFile": "", - | "DomainFile": "", - | "DomainBase64Decode": true, - | "HostsFile": "hosts", - | "MinimumTTL": 3600, - | "CacheSize" : 4096 - |} - """.stripMargin } object Key {