Compare commits

..
18 Commits
Author SHA1 Message Date
Max Lv 4b37d88f74 refine VPN mode on L 2014-11-29 10:26:58 +08:00
Max Lv 8ee5d77c6f decrease timeout 2014-11-29 10:09:27 +08:00
Max Lv 8cbfad80f4 refine NAT mode on Lollipop 2014-11-29 10:03:28 +08:00
Max Lv 9857e42776 enable NAT mode on 5.0 again 2014-11-28 22:12:02 +08:00
Max Lv 2f84c74d06 bump version 2014-11-27 09:03:41 +08:00
Max Lv bf207eb9b8 fix an issue on 64bit 2014-11-26 13:13:11 +08:00
Max Lv 7e8dad5c76 Revert "fake proc name failed on LRX21R"
This reverts commit 185e7608ae.
2014-11-26 09:12:01 +08:00
Max Lv 185e7608ae fake proc name failed on LRX21R 2014-11-25 21:43:12 +08:00
Max Lv d844fc2457 refine fake proc name 2014-11-25 19:11:18 +08:00
Max Lv a1bdfa5bd9 fix #161 2014-11-25 16:52:04 +08:00
Max Lv 6c7f62c237 pass the tun fd directly to tun2socks 2014-11-25 08:59:30 +08:00
Max Lv 383e9404ec Run tun2socks in seprate process for now 2014-11-24 21:22:42 +08:00
Max Lv 16d2cd9a29 Merge branch 'master' of github.com:shadowsocks/shadowsocks-android 2014-11-24 18:08:31 +08:00
Max Lv 9ee2345fd6 add unix socket 2014-11-24 18:08:15 +08:00
Max Lv 567543d00e Call tun2socks in main process 2014-11-24 10:39:45 +08:00
Max Lv 7c2b717141 update gitignore 2014-11-21 21:08:06 +08:00
Max Lv 08d5d56e46 fix #158 and #155 2014-11-21 16:20:15 +08:00
Max Lv e22b145023 fix #158 2014-11-21 14:51:16 +08:00
22 changed files with 676 additions and 647 deletions
+1 -3
View File
@@ -1,7 +1,6 @@
classes
bin
gen
obj
target
local.properties
.classpath
@@ -24,11 +23,10 @@ local.sbt
out/
#NDK
src/main/obj
src/main/libs
src/main/assets/armeabi
src/main/assets/armeabi-v7a
src/main/assets/x86
src/main/assets/api-16/
jni/Application.mk
obj
libs
+1
View File
@@ -18,5 +18,6 @@ install:
- echo "y" | android update sdk --filter extra-android-m2repository --no-ui --no-https -a
script:
- cp local.properties.travis local.properties
- ./build.sh
- sbt android:package-release
- exit 0
+6
View File
@@ -28,6 +28,9 @@ Help to translate shadowsocks: http://crowdin.net/project/shadowsocks/invite
```bash
git submodule update --init
# Build native binaries
./build.sh
# Build the App
sbt clean android:package-release
@@ -47,6 +50,9 @@ Help to translate shadowsocks: http://crowdin.net/project/shadowsocks/invite
```bash
git submodule update --init
# Build native binaries
./build.sh
# Build the apk
sbt clean android:package-release
```
+2
View File
@@ -12,6 +12,8 @@ compileOrder in Compile := CompileOrder.JavaThenScala
ndkJavah in Android := List()
ndkBuild in Android := List()
resolvers += "JRAF" at "http://JRAF.org/static/maven/2"
resolvers += "madeye private releases" at "http://madeye-maven-repository.googlecode.com/git/"
Executable
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
function try () {
"$@" || exit -1
}
try pushd src/main
# Build
try $ANDROID_NDK_HOME/ndk-build clean
try $ANDROID_NDK_HOME/ndk-build
# 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
do
try mv libs/armeabi-v7a/$app assets/armeabi-v7a/
try mv libs/x86/$app assets/x86/
done
try popd
+3 -1
View File
@@ -2,4 +2,6 @@ resolvers += Resolver.url("scalasbt releases", new URL("http://scalasbt.artifact
addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.3.10")
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
resolvers += Resolver.sbtPluginRepo("snapshots")
addSbtPlugin("com.hanhuy.sbt" % "sbt-idea" % "1.7.0-SNAPSHOT")
+4 -2
View File
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.shadowsocks"
android:versionCode="83"
android:versionName="2.4.3">
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">
@@ -1,55 +0,0 @@
/* Shadowsocks - A shadowsocks client for Android
* Copyright (C) 2012 <max.c.lv@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
* ___====-_ _-====___
* _--^^^#####// \\#####^^^--_
* _-^##########// ( ) \\##########^-_
* -############// |\^^/| \\############-
* _/############// (@::@) \\############\_
* /#############(( \\// ))#############\
* -###############\\ (oo) //###############-
* -#################\\ / VV \ //#################-
* -###################\\/ \//###################-
* _#/|##########/\######( /\ )######/\##########|\#_
* |/ |#/\#/\#/\/ \#/\##\ | | /##/\#/ \/\#/\#/\#| \|
* ` |/ V V ` V \#\| | | |/#/ V ' V V \| '
* ` ` ` ` / | | | | \ ' ' ' '
* ( | | | | )
* __\ | | | | /__
* (vvv(VVV)(VVV)vvv)
*
* HERE BE DRAGONS
*
*/
package com.github.shadowsocks;
public class Core {
static {
java.lang.System.loadLibrary("ss-local-jni");
java.lang.System.loadLibrary("ss-tunnel-jni");
java.lang.System.loadLibrary("tun2socks-jni");
java.lang.System.loadLibrary("pdnsd-jni");
java.lang.System.loadLibrary("redsocks-jni");
}
public static native void sslocal(String[] cmd);
public static native void sstunnel(String[] cmd);
public static native void tun2socks(String[] cmd);
public static native void pdnsd(String[] cmd);
public static native void redsocks(String[] cmd);
}
+20 -24
View File
@@ -120,13 +120,13 @@ REDSOCKS_SOURCES := base.c dnstc.c http-connect.c \
LOCAL_STATIC_LIBRARIES := libevent
LOCAL_MODULE := redsocks-jni
LOCAL_SRC_FILES := $(addprefix redsocks/, $(REDSOCKS_SOURCES)) main-jni.cpp
LOCAL_CFLAGS := -O2 -std=gnu99 -DREDSOCKS_JNI -I$(LOCAL_PATH)/redsocks \
LOCAL_MODULE := redsocks
LOCAL_SRC_FILES := $(addprefix redsocks/, $(REDSOCKS_SOURCES))
LOCAL_CFLAGS := -O2 -std=gnu99 -I$(LOCAL_PATH)/redsocks \
-I$(LOCAL_PATH)/libevent/include \
-I$(LOCAL_PATH)/libevent
include $(BUILD_SHARED_LIBRARY)
include $(BUILD_EXECUTABLE)
########################################################
## pdnsd library
@@ -134,13 +134,13 @@ include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
PDNSD_SOURCES := $(wildcard $(LOCAL_PATH)/pdnsd/src/*.c) main-jni.cpp
PDNSD_SOURCES := $(wildcard $(LOCAL_PATH)/pdnsd/src/*.c)
LOCAL_MODULE := pdnsd-jni
LOCAL_MODULE := pdnsd
LOCAL_SRC_FILES := $(PDNSD_SOURCES:$(LOCAL_PATH)/%=%)
LOCAL_CFLAGS := -Wall -O2 -DPDNSD_JNI -I$(LOCAL_PATH)/pdnsd
LOCAL_CFLAGS := -Wall -O2 -I$(LOCAL_PATH)/pdnsd
include $(BUILD_SHARED_LIBRARY)
include $(BUILD_EXECUTABLE)
########################################################
## shadowsocks local library
@@ -150,9 +150,9 @@ include $(CLEAR_VARS)
SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c utils.c json.c jconf.c acl.c
LOCAL_MODULE := ss-local-jni
LOCAL_SRC_FILES := $(addprefix shadowsocks/src/, $(SHADOWSOCKS_SOURCES)) main-jni.cpp
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DUDPRELAY_LOCAL -DSSLOCAL_JNI \
LOCAL_MODULE := ss-local
LOCAL_SRC_FILES := $(addprefix shadowsocks/src/, $(SHADOWSOCKS_SOURCES))
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DUDPRELAY_LOCAL \
-DUSE_CRYPTO_OPENSSL -DANDROID -DHAVE_CONFIG_H \
-I$(LOCAL_PATH)/libev/ \
-I$(LOCAL_PATH)/openssl/include \
@@ -163,22 +163,18 @@ LOCAL_STATIC_LIBRARIES := libev libcrypto libipset libcork
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
include $(BUILD_EXECUTABLE)
########################################################
## shadowsocks tunnel
########################################################
########################################################
## shadowsocks tunnel library
########################################################
include $(CLEAR_VARS)
SHADOWSOCKS_SOURCES := tunnel.c cache.c udprelay.c encrypt.c utils.c json.c jconf.c
LOCAL_MODULE := ss-tunnel-jni
LOCAL_SRC_FILES := $(addprefix shadowsocks/src/, $(SHADOWSOCKS_SOURCES)) main-jni.cpp
LOCAL_MODULE := ss-tunnel
LOCAL_SRC_FILES := $(addprefix shadowsocks/src/, $(SHADOWSOCKS_SOURCES))
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL \
-DUSE_CRYPTO_OPENSSL -DANDROID -DHAVE_CONFIG_H -DSSTUNNEL_JNI \
-I$(LOCAL_PATH)/libev/ \
@@ -188,7 +184,7 @@ LOCAL_STATIC_LIBRARIES := libev libcrypto
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
include $(BUILD_EXECUTABLE)
########################################################
## system
@@ -208,7 +204,7 @@ LOCAL_STATIC_LIBRARIES := cpufeatures
include $(BUILD_SHARED_LIBRARY)
########################################################
## tun2socks-library
## tun2socks
########################################################
include $(CLEAR_VARS)
@@ -218,7 +214,7 @@ LOCAL_CFLAGS += -DBADVPN_THREADWORK_USE_PTHREAD -DBADVPN_LINUX -DBADVPN_BREACTOR
LOCAL_CFLAGS += -DBADVPN_USE_SELFPIPE -DBADVPN_USE_EPOLL
LOCAL_CFLAGS += -DBADVPN_LITTLE_ENDIAN -DBADVPN_THREAD_SAFE
LOCAL_CFLAGS += -DNDEBUG -DANDROID
LOCAL_CFLAGS += -DTUN2SOCKS_JNI
# LOCAL_CFLAGS += -DTUN2SOCKS_JNI
LOCAL_C_INCLUDES:= \
$(LOCAL_PATH)/badvpn/lwip/src/include/ipv4 \
@@ -288,13 +284,13 @@ TUN2SOCKS_SOURCES := \
tun2socks/SocksUdpGwClient.c \
udpgw_client/UdpGwClient.c
LOCAL_MODULE := tun2socks-jni
LOCAL_MODULE := tun2socks
LOCAL_LDLIBS := -ldl -llog
LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES)) main-jni.cpp
LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES))
include $(BUILD_SHARED_LIBRARY)
include $(BUILD_EXECUTABLE)
# OpenSSL
openssl_subdirs := $(addprefix $(LOCAL_PATH)/openssl/,$(addsuffix /Android.mk, \
+1 -1
View File
@@ -1,4 +1,4 @@
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_ABI := armeabi-v7a x86
APP_PLATFORM := android-16
APP_STL := stlport_static
NDK_TOOLCHAIN_VERSION := 4.9
File diff suppressed because it is too large Load Diff
-86
View File
@@ -1,86 +0,0 @@
#include <jni.h>
#include <string.h>
#include <unistd.h>
typedef unsigned short char16_t;
class String8 {
public:
String8() {
mString = 0;
}
~String8() {
if (mString) {
free(mString);
}
}
void set(const char16_t* o, size_t numChars) {
if (mString) {
free(mString);
}
mString = (char*) malloc(numChars + 1);
if (!mString) {
return;
}
for (size_t i = 0; i < numChars; i++) {
mString[i] = (char) o[i];
}
mString[numChars] = '\0';
}
const char* string() {
return mString;
}
private:
char* mString;
};
extern "C" {
int main(int argc, char* args[]);
#if defined(PDNSD_JNI)
jint Java_com_github_shadowsocks_Core_pdnsd(JNIEnv *env, jobject thiz, jobjectArray argv) {
#elif defined(SSLOCAL_JNI)
jint Java_com_github_shadowsocks_Core_sslocal(JNIEnv *env, jobject thiz, jobjectArray argv) {
#elif defined(SSTUNNEL_JNI)
jint Java_com_github_shadowsocks_Core_sstunnel(JNIEnv *env, jobject thiz, jobjectArray argv) {
#elif defined(REDSOCKS_JNI)
jint Java_com_github_shadowsocks_Core_redsocks(JNIEnv *env, jobject thiz, jobjectArray argv) {
#elif defined(TUN2SOCKS_JNI)
jint Java_com_github_shadowsocks_Core_tun2socks(JNIEnv *env, jobject thiz, jobjectArray argv) {
#else
#error "invalid header"
#endif
int argc = argv ? env->GetArrayLength(argv) : 0;
char **args = NULL;
String8 tmp_8;
if (argc > 0) {
args = (char **)malloc((argc+1)*sizeof(char *));
for (int i = 0; i < argc; ++i) {
jstring arg = reinterpret_cast<jstring>(env->GetObjectArrayElement(argv, i));
const jchar *str = env->GetStringCritical(arg, 0);
tmp_8.set(str, env->GetStringLength(arg));
env->ReleaseStringCritical(arg, str);
args[i] = strdup(tmp_8.string());
}
args[argc] = NULL;
pid_t pid;
pid = fork();
if (pid == 0) {
int ret = main(argc, args);
return ret;
}
if (args != NULL) free(args);
}
return 0;
}
}
+1 -1
View File
@@ -15,7 +15,7 @@ LOCAL_CFLAGS += -DOPENSSL_NO_EC_NISTP_64_GCC_128 -DOPENSSL_NO_SCTP \
# LOCAL_CFLAGS += -DOPENSSL_NO_DEPRECATED
# Extra
LOCAL_CFLAGS += -DOPENSSL_NO_HW -DOPENSSL_NO_ASM -DOPENSSL_NO_ENGINE -DZLIB
LOCAL_CFLAGS += -DOPENSSL_NO_HW -DOPENSSL_NO_ENGINE -DZLIB
# Debug
# LOCAL_CFLAGS += -DCIPHER_DEBUG
@@ -100,8 +100,8 @@ static int rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx,
return 1;
}
// Disable asm for Android x86_64
#if !defined(OPENSSL_NO_ASM) && ( \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) || \
defined(__INTEL__) ) && \
!(defined(__APPLE__) && defined(__MACH__))
+2 -3
View File
@@ -32,9 +32,6 @@ jstring Java_com_github_shadowsocks_system_getabi(JNIEnv *env, jobject thiz) {
void Java_com_github_shadowsocks_system_exec(JNIEnv *env, jobject thiz, jstring cmd) {
const char *str = env->GetStringUTFChars(cmd, 0);
setenv("LD_LIBRARY_PATH", "/vendor/lib:/system/lib", 1);
setegid(getgid());
seteuid(getuid());
system(str);
env->ReleaseStringUTFChars(cmd, str);
}
@@ -48,6 +45,8 @@ static JNINativeMethod method_table[] = {
(void*) Java_com_github_shadowsocks_system_getabi }
};
/*
* Register several native methods for one class.
*/
@@ -123,7 +123,7 @@ object Shadowsocks {
val FEATRUE_PREFS = Array(Key.route, Key.isGlobalProxy, Key.proxyedApps,
Key.isUdpDns, Key.isAutoConnect)
val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.IPTABLES)
val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL, Executable.TUN2SOCKS)
// Helper functions
def updateListPreference(pref: Preference, value: String) {
@@ -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()
@@ -834,6 +833,14 @@ class Shadowsocks
crash_recovery()
copyAssets(System.getABI)
val ab = new ArrayBuffer[String]
for (executable <- Shadowsocks.EXECUTABLES) {
ab.append("chmod 755 " + Path.BASE + executable)
}
Console.runCommand(ab.toArray)
}
private def recovery() {
@@ -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 {
@@ -102,15 +139,18 @@ 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-nat.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd += ("ss-local"
cmd += (Path.BASE + "ss-local"
, "-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")
, "-c" , Path.BASE + "ss-local-nat.conf"
, "-f" , Path.BASE + "ss-local-nat.pid")
if (config.route != Route.ALL) {
cmd += "--acl"
@@ -118,47 +158,79 @@ class ShadowsocksNatService extends Service with BaseService {
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Console.runCommand(cmd.mkString(" "))
}
Core.sslocal(cmd.toArray)
def startTunnel() {
if (config.isUdpDns) {
val conf = ConfigUtils
.SHADOWSOCKS.format(config.proxy, config.remotePort, 8153,
config.sitekey, config.encMethod, 10)
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" , "8.8.8.8:53"
, "-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(" "))
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-nat.conf"))(p => {
p.println(conf)
})
val cmdBuf = new ArrayBuffer[String]
cmdBuf += (Path.BASE + "ss-tunnel"
, "-b" , "127.0.0.1"
, "-l" , "8163"
, "-L" , "8.8.8.8:53"
, "-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(" "))
}
}
def startDnsDaemon() {
if (config.isUdpDns) {
val cmd = new ArrayBuffer[String]
cmd += ("ss-tunnel" , "-u"
, "-b" , "127.0.0.1"
, "-l" , "8153"
, "-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)
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 {
val cmdBuf = new ArrayBuffer[String]
cmdBuf += ("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, cmdBuf.mkString(" "))
Core.sstunnel(cmdBuf.toArray)
val conf = ConfigUtils
.PDNSD_BYPASS.format("127.0.0.1", getString(R.string.exclude), 8163)
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd.conf"))(p => {
p.println(conf)
})
val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd.conf"
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
Core.pdnsd(cmd.split(" "))
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-nat.conf"
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
if (Utils.isLollipopOrAbove) {
Console.runRootCommand(cmd)
} else {
Console.runCommand(cmd)
}
}
def getVersionName: String = {
@@ -175,20 +247,21 @@ class ShadowsocksNatService extends Service with BaseService {
def startRedsocksDaemon() {
val conf = ConfigUtils.REDSOCKS.format(config.localPort)
val cmd = "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)
Core.redsocks(cmd.split(" "))
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
Console.runCommand(cmd)
}
/** Called when the activity is first created. */
def handleConnection: Boolean = {
startDnsDaemon()
startTunnel()
if (!config.isUdpDns) startDnsDaemon()
startRedsocksDaemon()
startShadowsocksDaemon()
setupIptables()
@@ -266,22 +339,28 @@ 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 + "-nat.pid").mkString.trim.toInt
cmd.append("kill -9 %d".format(pid))
Process.killProcess(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")
val ab = new ArrayBuffer[String]
ab.append("kill -9 `cat " + Path.BASE + "ss-tunnel.pid`")
ab.append("kill -9 `cat " + Path.BASE +"redsocks.pid`")
ab.append("killall -9 redsocks")
ab.append("kill -15 `cat " + Path.BASE + "pdnsd.pid`")
ab.append("killall -15 pdnsd")
Console.runRootCommand(ab.toArray)
ab.clear()
ab.append("kill -9 `cat " + Path.BASE + "ss-local.pid`")
Console.runCommand(ab.toArray)
}
def flushDNS() {
@@ -300,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)
}
@@ -374,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()
@@ -436,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()
@@ -446,12 +537,6 @@ class ShadowsocksNatService extends Service with BaseService {
.setLabel(getVersionName)
.build())
// reset timer
if (timer != null) {
timer.cancel()
timer = null
}
// reset NAT
killProcesses()
@@ -460,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.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._
@@ -107,15 +105,18 @@ 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-vpn.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd +=("ss-local", "-u"
cmd +=(Path.BASE + "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")
, "-c", Path.BASE + "ss-local-vpn.conf"
, "-f", Path.BASE + "ss-local-vpn.pid")
if (Utils.isLollipopOrAbove && config.route != Route.ALL) {
cmd += "--acl"
@@ -123,38 +124,43 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Core.sslocal(cmd.toArray)
Console.runCommand(cmd.mkString(" "))
}
def startDnsTunnel() = {
val conf = ConfigUtils
.SHADOWSOCKS.format(config.proxy, config.remotePort, 8163,
config.sitekey, config.encMethod, 10)
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-vpn.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd +=("ss-tunnel"
cmd +=(Path.BASE + "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")
, "-c", Path.BASE + "ss-tunnel-vpn.conf"
, "-f", Path.BASE + "ss-tunnel-vpn.pid")
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Core.sstunnel(cmd.toArray)
Console.runCommand(cmd.mkString(" "))
}
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)
Core.pdnsd(cmd.split(" "))
Console.runCommand(cmd)
}
def getVersionName: String = {
@@ -208,27 +214,6 @@ class ShadowsocksVpnService extends VpnService with BaseService {
} else {
if (!Utils.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)) {
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) {
@@ -265,6 +250,27 @@ class ShadowsocksVpnService extends VpnService with BaseService {
builder.addRoute(addr(0), addr(1).toInt)
}
})
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)) {
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)
}
}
}
}
}
}
} else {
if (config.route == Route.ALL) {
@@ -304,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)
@@ -312,19 +318,23 @@ class ShadowsocksVpnService extends VpnService with BaseService {
else
cmd += " --dnsgw %s:8153".format(PRIVATE_VLAN.format("1"))
if (Utils.isLollipopOrAbove) {
cmd += " --fake-proc"
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
Core.tun2socks(cmd.split(" "))
System.exec(cmd)
}
/** Called when the activity is first created. */
def handleConnection: Boolean = {
startVpn()
startShadowsocksDaemon()
if (!config.isUdpDns) {
startDnsDaemon()
startDnsTunnel()
}
startVpn()
true
}
@@ -352,11 +362,10 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
def killProcesses() {
for (task <- Array("ss-local", "ss-tunnel", "tun2socks", "pdnsd")) {
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)
}
@@ -470,7 +479,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
override def stopBackgroundService() {
stopRunner()
stopSelf()
}
override def getTag = TAG
@@ -46,7 +46,7 @@ import scalaj.http.{HttpOptions, Http}
import com.github.shadowsocks.aidl.Config
object ConfigUtils {
val SHADOWSOCKS = "{\"server\": [%s], \"server_port\": %d, \"local_port\": %d, \"password\": %s, \"timeout\": %d}"
val SHADOWSOCKS = "{\"server\": \"%s\", \"server_port\": %d, \"local_port\": %d, \"password\": \"%s\", \"method\":\"%s\", \"timeout\": %d}"
val REDSOCKS = "base {" +
" log_debug = off;" +
" log_info = off;" +
@@ -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()