Commit b9a33cf1 authored by Max Lv's avatar Max Lv Committed by GitHub

Add KCP support (#788)

Add KCP support for shadowsocks.

KCPTUN should be setup on a different port to avoid conflicts with Shadowsocks' UDP support.
parent bae5e9d0
...@@ -26,8 +26,8 @@ out/ ...@@ -26,8 +26,8 @@ out/
#NDK #NDK
src/main/obj src/main/obj
src/main/libs src/main/libs
src/main/assets/armeabi src/main/assets/armeabi-v7a/*
src/main/assets/armeabi-v7a !src/main/assets/armeabi-v7a/kcptun
src/main/assets/x86 src/main/assets/x86/*
src/main/assets/api-16/ !src/main/assets/x86/kcptun
jni/Application.mk jni/Application.mk
...@@ -55,6 +55,8 @@ proguardCache in Android := Seq() ...@@ -55,6 +55,8 @@ proguardCache in Android := Seq()
proguardOptions in Android ++= Seq( proguardOptions in Android ++= Seq(
"-keep class com.github.shadowsocks.System { *; }", "-keep class com.github.shadowsocks.System { *; }",
"-dontwarn com.google.android.gms.**",
"-keep class com.google.android.gms.**",
"-dontnote com.google.android.gms.internal.**", "-dontnote com.google.android.gms.internal.**",
"-dontnote com.j256.ormlite.**", "-dontnote com.j256.ormlite.**",
"-dontnote me.dm7.barcodescannerview.**", "-dontnote me.dm7.barcodescannerview.**",
......
...@@ -11,12 +11,10 @@ try pushd src/main ...@@ -11,12 +11,10 @@ try pushd src/main
try $ANDROID_NDK_HOME/ndk-build -j8 try $ANDROID_NDK_HOME/ndk-build -j8
# copy executables # copy executables
rm -rf assets/armeabi-v7a
rm -rf assets/x86
mkdir -p assets/armeabi-v7a
mkdir -p assets/x86
for app in pdnsd redsocks ss-local ss-tunnel tun2socks for app in pdnsd redsocks ss-local ss-tunnel tun2socks
do do
rm -f assets/armeabi-v7a/$app
rm -f assets/x86/$app
try mv libs/armeabi-v7a/$app assets/armeabi-v7a/ try mv libs/armeabi-v7a/$app assets/armeabi-v7a/
try mv libs/x86/$app assets/x86/ try mv libs/x86/$app assets/x86/
done done
......
addSbtPlugin("org.scala-android" % "sbt-android" % "1.6.8") addSbtPlugin("org.scala-android" % "sbt-android" % "1.6.10")
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.10") addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.10")
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" package="com.github.shadowsocks" xmlns:tools="http://schemas.android.com/tools" package="com.github.shadowsocks"
android:versionCode="141" android:versionCode="142"
android:versionName="2.10.8"> android:versionName="3.0.0">
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
......
Subproject commit d4aabcb40b4bcbca352269a1474a19de691950d0 Subproject commit 84cc109743e656b549dc4e8a9572b6063563852c
...@@ -134,4 +134,11 @@ ...@@ -134,4 +134,11 @@
<!-- status --> <!-- status -->
<string name="sent">Отправлено:</string> <string name="sent">Отправлено:</string>
<string name="received">Получено:</string> <string name="received">Получено:</string>
<!-- kcp -->
<string name="kcp_summary">Включить Shadowsocks над KCPTUN</string>
<string name="kcp_port">KCP порт</string>
<string name="kcp_port_summary">%d (KCPTUN омер порта удалённого сервера)</string>
<string name="kcpcli">KCP параметры</string>
<string name="kcpcli_summary">Командная строка KCPTUN</string>
</resources> </resources>
...@@ -134,4 +134,11 @@ ...@@ -134,4 +134,11 @@
<string name="sent">发送:</string> <string name="sent">发送:</string>
<string name="received">接收:</string> <string name="received">接收:</string>
<!-- kcp -->
<string name="kcp_summary">启用 KCP 协议</string>
<string name="kcp_port">KCP 端口</string>
<string name="kcp_port_summary">%d(远端 KCPTUN 服务器的端口号)</string>
<string name="kcpcli">KCP 参数</string>
<string name="kcpcli_summary">KCPTUN 的命令行参数</string>
</resources> </resources>
...@@ -136,4 +136,11 @@ ...@@ -136,4 +136,11 @@
<string name="sent">傳送:</string> <string name="sent">傳送:</string>
<string name="received">接收:</string> <string name="received">接收:</string>
<!-- kcp -->
<string name="kcp_summary">啟用 KCP 協定</string>
<string name="kcp_port">KCP 連接埠</string>
<string name="kcp_port_summary">%d(遠端 KCPTUN 伺服器的連接埠號碼)</string>
<string name="kcpcli">KCP 參數</string>
<string name="kcpcli_summary">KCPTUN 的命令行參數</string>
</resources> </resources>
...@@ -139,4 +139,12 @@ ...@@ -139,4 +139,12 @@
<!-- status --> <!-- status -->
<string name="sent">Sent:</string> <string name="sent">Sent:</string>
<string name="received">Received:</string> <string name="received">Received:</string>
<!-- kcp -->
<string name="kcp" translatable="false">KCP</string>
<string name="kcp_summary">Enable Shadowsocks over KCP</string>
<string name="kcp_port">KCP Port</string>
<string name="kcp_port_summary">%d (port number of the remote KCPTUN server)</string>
<string name="kcpcli">KCP Parameters (CLI)</string>
<string name="kcpcli_summary">The command line of KCPTUN</string>
</resources> </resources>
...@@ -77,6 +77,31 @@ ...@@ -77,6 +77,31 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory
android:title="@string/kcp">
<SwitchPreference
android:key="kcp"
android:persistent="false"
android:summary="@string/kcp_summary"
android:title="@string/kcp"/>
<com.github.shadowsocks.preferences.NumberPickerPreference
app:min="1"
app:max="65535"
android:key="kcpPort"
android:persistent="false"
android:summary="@string/kcp_port_summary"
android:title="@string/kcp_port"/>
<com.github.shadowsocks.preferences.SummaryEditTextPreference
android:key="kcpcli"
android:persistent="false"
android:summary="@string/kcpcli_summary"
android:title="@string/kcpcli"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/misc_cat"> <PreferenceCategory android:title="@string/misc_cat">
<SwitchPreference <SwitchPreference
......
...@@ -94,7 +94,7 @@ object Shadowsocks { ...@@ -94,7 +94,7 @@ object Shadowsocks {
private final val TAG = "Shadowsocks" private final val TAG = "Shadowsocks"
private final val REQUEST_CONNECT = 1 private final val REQUEST_CONNECT = 1
private val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL, private val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL,
Executable.TUN2SOCKS) Executable.TUN2SOCKS, Executable.KCPTUN)
} }
class Shadowsocks extends AppCompatActivity with ServiceBoundContext { class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
...@@ -286,7 +286,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext { ...@@ -286,7 +286,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
def crashRecovery() { def crashRecovery() {
val cmd = new ArrayBuffer[String]() val cmd = new ArrayBuffer[String]()
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks")) { for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks", "kcptun")) {
cmd.append("killall %s".formatLocal(Locale.ENGLISH, task)) cmd.append("killall %s".formatLocal(Locale.ENGLISH, task))
cmd.append("rm -f %1$s/%2$s-nat.conf %1$s/%2$s-vpn.conf" cmd.append("rm -f %1$s/%2$s-nat.conf %1$s/%2$s-vpn.conf"
.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, task)) .formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, task))
......
...@@ -65,6 +65,7 @@ class ShadowsocksNatService extends BaseService { ...@@ -65,6 +65,7 @@ class ShadowsocksNatService extends BaseService {
private var notification: ShadowsocksNotification = _ private var notification: ShadowsocksNotification = _
val myUid = android.os.Process.myUid() val myUid = android.os.Process.myUid()
var kcptunProcess: Process = _
var sslocalProcess: Process = _ var sslocalProcess: Process = _
var sstunnelProcess: Process = _ var sstunnelProcess: Process = _
var redsocksProcess: Process = _ var redsocksProcess: Process = _
...@@ -84,9 +85,15 @@ class ShadowsocksNatService extends BaseService { ...@@ -84,9 +85,15 @@ class ShadowsocksNatService extends BaseService {
}) })
} }
val conf = ConfigUtils val conf = if (profile.kcp) {
ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, "127.0.0.1", profile.localPort + 90, profile.localPort,
profile.password, profile.method, 600)
} else {
ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, profile.localPort, .SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, profile.localPort,
profile.password, profile.method, 600) profile.password, profile.method, 600)
}
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-local-nat.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-local-nat.conf"))(p => {
p.println(conf) p.println(conf)
}) })
...@@ -109,10 +116,23 @@ class ShadowsocksNatService extends BaseService { ...@@ -109,10 +116,23 @@ class ShadowsocksNatService extends BaseService {
sslocalProcess = new GuardedProcess(cmd).start() sslocalProcess = new GuardedProcess(cmd).start()
} }
def startTunnel() { def startKcptunDaemon() {
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/kcptun"
, "-r", profile.host + ":" + profile.kcpPort
, "-l", "127.0.0.1:" + (profile.localPort + 90)
, profile.kcpcli)
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
kcptunProcess = new GuardedProcess(cmd.mkString(" ").split(" ").toSeq).start()
}
def startDNSTunnel() {
if (profile.udpdns) { if (profile.udpdns) {
val conf = ConfigUtils val conf = ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, 8153, .SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, profile.localPort + 53,
profile.password, profile.method, 10) profile.password, profile.method, 10)
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => {
p.println(conf) p.println(conf)
...@@ -123,11 +143,10 @@ class ShadowsocksNatService extends BaseService { ...@@ -123,11 +143,10 @@ class ShadowsocksNatService extends BaseService {
, "-t" , "10" , "-t" , "10"
, "-b" , "127.0.0.1" , "-b" , "127.0.0.1"
, "-L" , "8.8.8.8:53" , "-L" , "8.8.8.8:53"
, "-l" , (profile.localPort + 53).toString
, "-P" , getApplicationInfo.dataDir , "-P" , getApplicationInfo.dataDir
, "-c" , getApplicationInfo.dataDir + "/ss-tunnel-nat.conf") , "-c" , getApplicationInfo.dataDir + "/ss-tunnel-nat.conf")
cmd += ("-l" , "8153")
if (profile.auth) cmd += "-A" if (profile.auth) cmd += "-A"
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
...@@ -135,18 +154,23 @@ class ShadowsocksNatService extends BaseService { ...@@ -135,18 +154,23 @@ class ShadowsocksNatService extends BaseService {
sstunnelProcess = new GuardedProcess(cmd).start() sstunnelProcess = new GuardedProcess(cmd).start()
} else { } else {
val conf = ConfigUtils val conf = if (profile.kcp) {
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, 8163, ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, "127.0.0.1", profile.localPort + 90,
profile.localPort + 63, profile.password, profile.method, 10)
} else {
ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, profile.localPort + 63,
profile.password, profile.method, 10) profile.password, profile.method, 10)
}
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => {
p.println(conf) p.println(conf)
}) })
val cmdBuf = new ArrayBuffer[String] val cmdBuf = new ArrayBuffer[String]
cmdBuf += (getApplicationInfo.dataDir + "/ss-tunnel" cmdBuf += (getApplicationInfo.dataDir + "/ss-tunnel"
, "-u"
, "-t" , "10" , "-t" , "10"
, "-b" , "127.0.0.1" , "-b" , "127.0.0.1"
, "-l" , "8163" , "-l" , (profile.localPort + 63).toString
, "-L" , "8.8.8.8:53" , "-L" , "8.8.8.8:53"
, "-P", getApplicationInfo.dataDir , "-P", getApplicationInfo.dataDir
, "-c" , getApplicationInfo.dataDir + "/ss-tunnel-nat.conf") , "-c" , getApplicationInfo.dataDir + "/ss-tunnel-nat.conf")
...@@ -163,10 +187,10 @@ class ShadowsocksNatService extends BaseService { ...@@ -163,10 +187,10 @@ class ShadowsocksNatService extends BaseService {
val conf = if (profile.route == Route.BYPASS_CHN || profile.route == Route.BYPASS_LAN_CHN) { val conf = if (profile.route == Route.BYPASS_CHN || profile.route == Route.BYPASS_LAN_CHN) {
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"127.0.0.1", 8153, getBlackList, 8163, "") "127.0.0.1", profile.localPort + 53, getBlackList, profile.localPort + 63, "")
} else { } else {
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"127.0.0.1", 8153, 8163, "") "127.0.0.1", profile.localPort + 53, profile.localPort + 63, "")
} }
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-nat.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-nat.conf"))(p => {
...@@ -194,10 +218,13 @@ class ShadowsocksNatService extends BaseService { ...@@ -194,10 +218,13 @@ class ShadowsocksNatService extends BaseService {
/** Called when the activity is first created. */ /** Called when the activity is first created. */
def handleConnection { def handleConnection {
startTunnel() startDNSTunnel()
if (!profile.udpdns) startDnsDaemon()
startRedsocksDaemon() startRedsocksDaemon()
startShadowsocksDaemon() startShadowsocksDaemon()
if (!profile.udpdns) startDnsDaemon()
if (profile.kcp) startKcptunDaemon()
setupIptables() setupIptables()
} }
...@@ -212,6 +239,10 @@ class ShadowsocksNatService extends BaseService { ...@@ -212,6 +239,10 @@ class ShadowsocksNatService extends BaseService {
} }
def killProcesses() { def killProcesses() {
if (kcptunProcess != null) {
kcptunProcess.destroy()
kcptunProcess = null
}
if (sslocalProcess != null) { if (sslocalProcess != null) {
sslocalProcess.destroy() sslocalProcess.destroy()
sslocalProcess = null sslocalProcess = null
...@@ -247,7 +278,8 @@ class ShadowsocksNatService extends BaseService { ...@@ -247,7 +278,8 @@ class ShadowsocksNatService extends BaseService {
init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-m owner --uid-owner " + myUid)) init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-m owner --uid-owner " + myUid))
init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "--dport 53")) init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "--dport 53"))
init_sb.append("iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:8153") init_sb.append("iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:"
+ (profile.localPort + 53))
if (!profile.proxyApps || profile.bypass) { if (!profile.proxyApps || profile.bypass) {
http_sb.append(CMD_IPTABLES_DNAT_ADD_SOCKS) http_sb.append(CMD_IPTABLES_DNAT_ADD_SOCKS)
......
...@@ -18,7 +18,7 @@ object ShadowsocksSettings { ...@@ -18,7 +18,7 @@ object ShadowsocksSettings {
// Constants // Constants
private final val TAG = "ShadowsocksSettings" private final val TAG = "ShadowsocksSettings"
private val PROXY_PREFS = Array(Key.name, Key.host, Key.remotePort, Key.localPort, Key.password, Key.method, private val PROXY_PREFS = Array(Key.name, Key.host, Key.remotePort, Key.localPort, Key.password, Key.method,
Key.auth) Key.auth, Key.kcp, Key.kcpPort, Key.kcpcli)
private val FEATURE_PREFS = Array(Key.route, Key.proxyApps, Key.udpdns, Key.ipv6) private val FEATURE_PREFS = Array(Key.route, Key.proxyApps, Key.udpdns, Key.ipv6)
// Helper functions // Helper functions
...@@ -36,9 +36,11 @@ object ShadowsocksSettings { ...@@ -36,9 +36,11 @@ object ShadowsocksSettings {
} }
def updateSummaryEditTextPreference(pref: Preference, value: String) { def updateSummaryEditTextPreference(pref: Preference, value: String) {
if (value != null) {
pref.setSummary(value) pref.setSummary(value)
pref.asInstanceOf[SummaryEditTextPreference].setText(value) pref.asInstanceOf[SummaryEditTextPreference].setText(value)
} }
}
def updateSwitchPreference(pref: Preference, value: Boolean) { def updateSwitchPreference(pref: Preference, value: Boolean) {
pref.asInstanceOf[SwitchPreference].setChecked(value) pref.asInstanceOf[SwitchPreference].setChecked(value)
...@@ -57,6 +59,9 @@ object ShadowsocksSettings { ...@@ -57,6 +59,9 @@ object ShadowsocksSettings {
case Key.udpdns => updateSwitchPreference(pref, profile.udpdns) case Key.udpdns => updateSwitchPreference(pref, profile.udpdns)
case Key.auth => updateSwitchPreference(pref, profile.auth) case Key.auth => updateSwitchPreference(pref, profile.auth)
case Key.ipv6 => updateSwitchPreference(pref, profile.ipv6) case Key.ipv6 => updateSwitchPreference(pref, profile.ipv6)
case Key.kcp => updateSwitchPreference(pref, profile.kcp)
case Key.kcpPort => updateNumberPickerPreference(pref, profile.kcpPort)
case Key.kcpcli => updateSummaryEditTextPreference(pref, profile.kcpcli)
} }
} }
} }
...@@ -103,6 +108,19 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan ...@@ -103,6 +108,19 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
app.profileManager.updateProfile(profile) app.profileManager.updateProfile(profile)
}) })
findPreference(Key.kcp).setOnPreferenceChangeListener((_, value) => {
profile.kcp = value.asInstanceOf[Boolean]
app.profileManager.updateProfile(profile)
})
findPreference(Key.kcpPort).setOnPreferenceChangeListener((_, value) => {
profile.kcpPort = value.asInstanceOf[Int]
app.profileManager.updateProfile(profile)
})
findPreference(Key.kcpcli).setOnPreferenceChangeListener((_, value) => {
profile.kcpcli = value.asInstanceOf[String]
app.profileManager.updateProfile(profile)
})
isProxyApps = findPreference(Key.proxyApps).asInstanceOf[SwitchPreference] isProxyApps = findPreference(Key.proxyApps).asInstanceOf[SwitchPreference]
isProxyApps.setOnPreferenceClickListener(_ => { isProxyApps.setOnPreferenceClickListener(_ => {
startActivity(new Intent(activity, classOf[AppManager])) startActivity(new Intent(activity, classOf[AppManager]))
......
...@@ -63,6 +63,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -63,6 +63,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
var vpnThread: ShadowsocksVpnThread = _ var vpnThread: ShadowsocksVpnThread = _
private var notification: ShadowsocksNotification = _ private var notification: ShadowsocksNotification = _
var kcptunProcess: Process = _
var sslocalProcess: Process = _ var sslocalProcess: Process = _
var sstunnelProcess: Process = _ var sstunnelProcess: Process = _
var pdnsdProcess: Process = _ var pdnsdProcess: Process = _
...@@ -109,6 +110,10 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -109,6 +110,10 @@ class ShadowsocksVpnService extends VpnService with BaseService {
} }
def killProcesses() { def killProcesses() {
if (kcptunProcess != null) {
kcptunProcess.destroy()
kcptunProcess = null
}
if (sslocalProcess != null) { if (sslocalProcess != null) {
sslocalProcess.destroy() sslocalProcess.destroy()
sslocalProcess = null sslocalProcess = null
...@@ -177,18 +182,65 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -177,18 +182,65 @@ class ShadowsocksVpnService extends VpnService with BaseService {
/** Called when the activity is first created. */ /** Called when the activity is first created. */
def handleConnection: Boolean = { def handleConnection: Boolean = {
startShadowsocksDaemon()
if (!profile.udpdns) { if (!profile.udpdns) {
startDnsDaemon() startDnsDaemon()
startDnsTunnel() startDnsTunnel()
} }
startShadowsocksDaemon()
if (profile.udpdns) {
startShadowsocksUDPDaemon()
}
val fd = startVpn() val fd = startVpn()
sendFd(fd) val ret = sendFd(fd)
if (ret && profile.kcp) {
startKcptunDaemon()
} }
def startShadowsocksDaemon() { ret
}
def startKcptunDaemon() {
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/kcptun"
, "-r", profile.host + ":" + profile.kcpPort
, "-l", "127.0.0.1:" + (profile.localPort + 90)
, "--path", getApplicationInfo.dataDir + "/protect_path"
, profile.kcpcli)
if (BuildConfig.DEBUG)
Log.d(TAG, cmd.mkString(" "))
kcptunProcess = new GuardedProcess(cmd.mkString(" ").split(" ").toSeq).start()
}
def startShadowsocksUDPDaemon() {
val conf = ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, profile.localPort,
profile.password, profile.method, 600)
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-local-udp-vpn.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/ss-local", "-V", "-U"
, "-b", "127.0.0.1"
, "-t", "600"
, "-P", getApplicationInfo.dataDir
, "-c", getApplicationInfo.dataDir + "/ss-local-udp-vpn.conf")
if (profile.auth) cmd += "-A"
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
sstunnelProcess = new GuardedProcess(cmd).start()
}
def startShadowsocksDaemon() {
if (profile.route != Route.ALL) { if (profile.route != Route.ALL) {
val acl: Array[Array[String]] = profile.route match { val acl: Array[Array[String]] = profile.route match {
case Route.BYPASS_LAN => Array(getResources.getStringArray(R.array.private_route)) case Route.BYPASS_LAN => Array(getResources.getStringArray(R.array.private_route))
...@@ -201,15 +253,21 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -201,15 +253,21 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}) })
} }
val conf = ConfigUtils val conf = if (profile.kcp) {
ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, "127.0.0.1", profile.localPort + 90, profile.localPort,
profile.password, profile.method, 600)
} else {
ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, profile.localPort, .SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, profile.localPort,
profile.password, profile.method, 600) profile.password, profile.method, 600)
}
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-local-vpn.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-local-vpn.conf"))(p => {
p.println(conf) p.println(conf)
}) })
val cmd = new ArrayBuffer[String] val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/ss-local", "-V", "-u" cmd += (getApplicationInfo.dataDir + "/ss-local", "-V"
, "-b", "127.0.0.1" , "-b", "127.0.0.1"
, "-t", "600" , "-t", "600"
, "-P", getApplicationInfo.dataDir , "-P", getApplicationInfo.dataDir
...@@ -228,19 +286,23 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -228,19 +286,23 @@ class ShadowsocksVpnService extends VpnService with BaseService {
} }
def startDnsTunnel() = { def startDnsTunnel() = {
val conf = ConfigUtils val conf = if (profile.kcp) {
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, 8163, ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, "127.0.0.1", profile.localPort + 90, profile.localPort + 63,
profile.password, profile.method, 10) profile.password, profile.method, 10)
} else {
ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, profile.host, profile.remotePort, profile.localPort + 63,
profile.password, profile.method, 10)
}
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf"))(p => {
p.println(conf) p.println(conf)
}) })
val cmd = new ArrayBuffer[String] val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/ss-tunnel" cmd += (getApplicationInfo.dataDir + "/ss-tunnel"
, "-V" , "-V"
, "-u"
, "-t", "10" , "-t", "10"
, "-b", "127.0.0.1" , "-b", "127.0.0.1"
, "-l", "8163"
, "-L", "8.8.8.8:53" , "-L", "8.8.8.8:53"
, "-P", getApplicationInfo.dataDir , "-P", getApplicationInfo.dataDir
, "-c", getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf") , "-c", getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf")
...@@ -257,10 +319,10 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -257,10 +319,10 @@ class ShadowsocksVpnService extends VpnService with BaseService {
val conf = { val conf = {
if (profile.route == Route.BYPASS_CHN || profile.route == Route.BYPASS_LAN_CHN) { if (profile.route == Route.BYPASS_CHN || profile.route == Route.BYPASS_LAN_CHN) {
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"0.0.0.0", 8153, getBlackList, 8163, ipv6) "0.0.0.0", profile.localPort + 53, getBlackList, profile.localPort + 63, ipv6)
} else { } else {
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"0.0.0.0", 8153, 8163, ipv6) "0.0.0.0", profile.localPort + 53, profile.localPort + 63, ipv6)
} }
} }
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-vpn.conf"))(p => { Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-vpn.conf"))(p => {
...@@ -354,7 +416,8 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -354,7 +416,8 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (profile.udpdns) if (profile.udpdns)
cmd += " --enable-udprelay" cmd += " --enable-udprelay"
else else
cmd += " --dnsgw %s:8153".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1")) cmd += " --dnsgw %s:%d".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"),
profile.localPort + 53)
if (BuildConfig.DEBUG) Log.d(TAG, cmd) if (BuildConfig.DEBUG) Log.d(TAG, cmd)
......
...@@ -64,7 +64,7 @@ object DBHelper { ...@@ -64,7 +64,7 @@ object DBHelper {
} }
class DBHelper(val context: Context) class DBHelper(val context: Context)
extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 16) { extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 18) {
import DBHelper._ import DBHelper._
lazy val profileDao: Dao[Profile, Int] = getDao(classOf[Profile]) lazy val profileDao: Dao[Profile, Int] = getDao(classOf[Profile])
...@@ -125,6 +125,15 @@ class DBHelper(val context: Context) ...@@ -125,6 +125,15 @@ class DBHelper(val context: Context)
if (oldVersion < 16) { if (oldVersion < 16) {
profileDao.executeRawNoArgs("UPDATE `profile` SET route = 'bypass-lan-china' WHERE route = 'bypass-china'") profileDao.executeRawNoArgs("UPDATE `profile` SET route = 'bypass-lan-china' WHERE route = 'bypass-china'")
} }
if (oldVersion < 17) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN kcp SMALLINT;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN kcpcli VARCHAR;")
}
if (oldVersion < 18) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN kcpPort INTEGER;")
}
} }
} }
} }
...@@ -99,6 +99,15 @@ class Profile { ...@@ -99,6 +99,15 @@ class Profile {
@DatabaseField @DatabaseField
var userOrder: Long = _ var userOrder: Long = _
@DatabaseField
var kcp: Boolean = false
@DatabaseField
var kcpPort: Int = 8399
@DatabaseField
var kcpcli: String = ""
override def toString = "ss://" + Base64.encodeToString("%s%s:%s@%s:%d".formatLocal(Locale.ENGLISH, override def toString = "ss://" + Base64.encodeToString("%s%s:%s@%s:%d".formatLocal(Locale.ENGLISH,
method, if (auth) "-auth" else "", password, host, remotePort).getBytes, Base64.NO_PADDING | Base64.NO_WRAP) method, if (auth) "-auth" else "", password, host, remotePort).getBytes, Base64.NO_PADDING | Base64.NO_WRAP)
......
...@@ -45,6 +45,7 @@ object Executable { ...@@ -45,6 +45,7 @@ object Executable {
val SS_LOCAL = "ss-local" val SS_LOCAL = "ss-local"
val SS_TUNNEL = "ss-tunnel" val SS_TUNNEL = "ss-tunnel"
val TUN2SOCKS = "tun2socks" val TUN2SOCKS = "tun2socks"
val KCPTUN = "kcptun"
} }
object ConfigUtils { object ConfigUtils {
...@@ -166,6 +167,10 @@ object Key { ...@@ -166,6 +167,10 @@ object Key {
val localPort = "localPortNum" val localPort = "localPortNum"
val profileTip = "profileTip" val profileTip = "profileTip"
val kcp = "kcp"
val kcpPort = "kcpPort"
val kcpcli = "kcpcli"
} }
object State { object State {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment