diff --git a/.gitmodules b/.gitmodules index 612dbe2551..c52676b133 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,3 +28,7 @@ [submodule "src/main/jni/pcre"] path = src/main/jni/pcre url = https://android.googlesource.com/platform/external/pcre +[submodule "src/main/jni/proxychains"] + path = src/main/jni/proxychains + url = https://github.com/esdeathlove/proxychains-ng.git + branch = master diff --git a/build.sbt b/build.sbt index 3dea35ac0a..fdbb768dd2 100644 --- a/build.sbt +++ b/build.sbt @@ -51,9 +51,8 @@ libraryDependencies ++= "com.squareup.okhttp3" % "okhttp" % "3.5.0" :: "com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2" :: "dnsjava" % "dnsjava" % "2.1.7" :: - "eu.chainfire" % "libsuperuser" % "1.0.0.201608240809" :: + "eu.chainfire" % "libsuperuser" % "1.0.0.+" :: "net.glxn.qrgen" % "android" % "2.0" :: - "com.arasthel" % "asyncjob-library" % "1.0.3" :: Nil lazy val nativeBuild = TaskKey[Unit]("native-build", "Build native executables") diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 7931ff104a..e6ba638eae 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + android:versionCode="293" + android:versionName="3.3.9"> @@ -31,7 +31,8 @@ android:backupAgent=".ShadowsocksBackupAgent" android:label="@string/app_name" android:theme="@style/Theme.Material" - android:banner="@drawable/ic_start_connected"> + android:banner="@drawable/ic_start_connected" + android:debuggable="true"> @@ -62,7 +63,7 @@ android:name=".ShadowsocksRunnerActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:excludeFromRecents="true" - android:taskAffinity="" + android:taskAffinity="" android:launchMode="singleTask"> diff --git a/src/main/jni/Android.mk b/src/main/jni/Android.mk index 7d07b510d7..d44bbe34fc 100755 --- a/src/main/jni/Android.mk +++ b/src/main/jni/Android.mk @@ -389,7 +389,7 @@ SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c \ LOCAL_MODULE := ss-local LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES)) -LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DMODULE_LOCAL \ +LOCAL_CFLAGS := -Wall -O0 -g -fno-strict-aliasing -DMODULE_LOCAL \ -DUSE_CRYPTO_MBEDTLS -DANDROID -DHAVE_CONFIG_H \ -DCONNECT_IN_PROGRESS=EINPROGRESS \ -I$(LOCAL_PATH)/include/shadowsocks-libev \ @@ -518,7 +518,7 @@ TUN2SOCKS_SOURCES := \ base/DebugObject.c \ base/BLog.c \ base/BPending.c \ - system/BDatagram_unix.c \ + system/BDatagram_unix.c \ flowextra/PacketPassInactivityMonitor.c \ tun2socks/SocksUdpGwClient.c \ udpgw_client/UdpGwClient.c @@ -586,5 +586,35 @@ LOCAL_SRC_FILES := $(addprefix pcre/, $(libpcre_src_files)) include $(BUILD_STATIC_LIBRARY) +######################################################## +## libproxychains4 +######################################################## + +include $(CLEAR_VARS) + +LOCAL_MODULE:= libproxychains4 + +LOCAL_C_INCLUDES:= $(LOCAL_PATH)/proxychains/src + +PROXYCHAINS_SOURCES := version.c core.c common.c libproxychains.c \ + allocator_thread.c ip_type.c hostsreader.c \ + hash.c debug.c + +LOCAL_SRC_FILES := $(addprefix proxychains/src/, $(PROXYCHAINS_SOURCES)) + +LOCAL_CFLAGS := -fPIC -pthread -ldl -Wl,--no-as-needed -Wl,-soname=libproxychains4.so \ + -DANDROID -O0 -g\ + -I$(LOCAL_PATH)/include/proxychains \ + -I$(LOCAL_PATH)/proxychains/src \ + -I$(LOCAL_PATH)/libancillary \ + -DLIB_DIR=\"/data/user/0/in.zhaoj.shadowsocksr/lib\" -DINSTALL_PREFIX=\"/data/user/0/in.zhaoj.shadowsocksr/\" \ + -DDLL_NAME=\"libproxychains4.so\" -DSYSCONFDIR=\"/data/user/0/in.zhaoj.shadowsocksr/\" + +LOCAL_STATIC_LIBRARIES := libancillary + +LOCAL_LDLIBS := -ldl -llog + +include $(BUILD_SHARED_LIBRARY) + # Import cpufeatures $(call import-module,android/cpufeatures) diff --git a/src/main/jni/include/proxychains/config.h b/src/main/jni/include/proxychains/config.h new file mode 100644 index 0000000000..77322303c6 --- /dev/null +++ b/src/main/jni/include/proxychains/config.h @@ -0,0 +1,8 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#define DLL_NAME "libproxychains4.so" + +typedef in_port_t uint16_t diff --git a/src/main/jni/proxychains b/src/main/jni/proxychains new file mode 160000 index 0000000000..3d74aaec3c --- /dev/null +++ b/src/main/jni/proxychains @@ -0,0 +1 @@ +Subproject commit 3d74aaec3cb83125861113819aca4477694655ff diff --git a/src/main/jni/system.cpp b/src/main/jni/system.cpp index dcad8aa36a..2015be99c5 100644 --- a/src/main/jni/system.cpp +++ b/src/main/jni/system.cpp @@ -25,6 +25,8 @@ jstring Java_com_github_shadowsocks_system_getabi(JNIEnv *env, jobject thiz) { if (family == ANDROID_CPU_FAMILY_X86) { abi = "x86"; + } else if (family == ANDROID_CPU_FAMILY_ARM64) { + abi = "arm64-v8a"; } else if (family == ANDROID_CPU_FAMILY_MIPS) { abi = "mips"; } else if (family == ANDROID_CPU_FAMILY_ARM) { diff --git a/src/main/res/layout/layout_front_proxy.xml b/src/main/res/layout/layout_front_proxy.xml new file mode 100644 index 0000000000..769f9c264a --- /dev/null +++ b/src/main/res/layout/layout_front_proxy.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/res/values-ja/strings.xml b/src/main/res/values-ja/strings.xml index 4a60dc0d0a..e2333b808f 100644 --- a/src/main/res/values-ja/strings.xml +++ b/src/main/res/values-ja/strings.xml @@ -168,6 +168,14 @@ レイテンシによる自動ソート Ping + 有効にする + サーバーアドレス + リモートポート + ユーザー名 + パスワード + タイプ + フロントエージェント + 送信済み: 受信済み: diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml index 33734d267d..12830c45f0 100644 --- a/src/main/res/values-ru/strings.xml +++ b/src/main/res/values-ru/strings.xml @@ -159,6 +159,14 @@ Автоматическая сортировка по времени ожидания пинг + включить + Адрес + порт + имя пользователя + пароль + Тип + фронт полномочие + Сканирование подсказки кода Кажется, вы не установили сканер в соответствии с ZXing стандартами, нажмите кнопку «ОК» приведет вас в магазин приложений, где вы установили загрузку, или вы можете нажать кнопку «Загрузить», чтобы загрузить APK установлен непосредственно. diff --git a/src/main/res/values-zh-rCN/strings.xml b/src/main/res/values-zh-rCN/strings.xml index a85e788e7a..cf88cb3b10 100644 --- a/src/main/res/values-zh-rCN/strings.xml +++ b/src/main/res/values-zh-rCN/strings.xml @@ -171,6 +171,14 @@ 基于延时自动排序 测试延时 + 启用 + 地址 + 端口 + 用户名 + 密码 + 类型 + 前置代理 + 发送: 接收: diff --git a/src/main/res/values-zh-rTW/strings.xml b/src/main/res/values-zh-rTW/strings.xml index e92d69a341..2df229145a 100644 --- a/src/main/res/values-zh-rTW/strings.xml +++ b/src/main/res/values-zh-rTW/strings.xml @@ -173,6 +173,14 @@ 基於延時自動排序 測試延時 + 啟用 + 地址 + 連接埠 + 用戶名 + 密碼 + 類型 + 前置代理 + 傳送: 接收: diff --git a/src/main/res/values/arrays.xml b/src/main/res/values/arrays.xml index a78a7fa574..2ac7b24b9c 100644 --- a/src/main/res/values/arrays.xml +++ b/src/main/res/values/arrays.xml @@ -1,5 +1,11 @@ + + http + socks4 + socks5 + + none table diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index fd4e221ac2..6c5cf24876 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -167,6 +167,14 @@ Auto sort by latency Ping + Enable + Address + Port + Username + Password + Type + FrontProxy + Scan tips diff --git a/src/main/res/xml/pref_all.xml b/src/main/res/xml/pref_all.xml index ce29e62f8c..3a3f4e9211 100644 --- a/src/main/res/xml/pref_all.xml +++ b/src/main/res/xml/pref_all.xml @@ -125,6 +125,7 @@ android:summary="@string/recovery_summary"/> + diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala index 2189dc2327..6c02debb4a 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala @@ -214,7 +214,7 @@ class ShadowsocksApplication extends Application { def crashRecovery() { val cmd = new ArrayBuffer[String]() - for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks", "kcptun")) { + for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks", "proxychains")) { cmd.append("killall %s".formatLocal(Locale.ENGLISH, task)) cmd.append("rm -f %1$s/%2$s-nat.conf %1$s/%2$s-vpn.conf" .formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, task)) diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala index fb1aa66333..3d15017586 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala @@ -46,12 +46,15 @@ import scala.io.Source import android.content._ import android.os._ +import android.system.Os import android.util.Log import com.github.shadowsocks.ShadowsocksApplication.app import com.github.shadowsocks.database.Profile import com.github.shadowsocks.job.AclSyncJob import com.github.shadowsocks.utils._ import eu.chainfire.libsuperuser.Shell +import android.preference.PreferenceManager +import java.io.RandomAccessFile import scala.collection.JavaConversions._ import scala.collection.mutable.ArrayBuffer @@ -71,6 +74,7 @@ class ShadowsocksNatService extends BaseService { var redsocksProcess: GuardedProcess = _ var pdnsdProcess: GuardedProcess = _ var su: Shell.Interactive = _ + var proxychains_enable: Boolean = false def startShadowsocksDaemon() { @@ -94,6 +98,11 @@ class ShadowsocksNatService extends BaseService { cmd += getApplicationInfo.dataDir + '/' + profile.route + ".acl" } + if (proxychains_enable) { + cmd prepend "LD_PRELOAD=" + getApplicationInfo.dataDir + "/lib/libproxychains4.so" + cmd prepend "env" + } + if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) sslocalProcess = new GuardedProcess(cmd).start() } @@ -120,6 +129,11 @@ class ShadowsocksNatService extends BaseService { else cmd += profile.dns.split(",")(0) + if (proxychains_enable) { + cmd prepend "LD_PRELOAD=" + getApplicationInfo.dataDir + "/lib/libproxychains4.so" + cmd prepend "env" + } + if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) sstunnelProcess = new GuardedProcess(cmd).start() @@ -145,6 +159,11 @@ class ShadowsocksNatService extends BaseService { else cmdBuf += profile.dns.split(",")(0) + if (proxychains_enable) { + cmdBuf prepend "LD_PRELOAD=" + getApplicationInfo.dataDir + "/lib/libproxychains4.so" + cmdBuf prepend "env" + } + if (BuildConfig.DEBUG) Log.d(TAG, cmdBuf.mkString(" ")) sstunnelProcess = new GuardedProcess(cmdBuf).start() @@ -237,13 +256,11 @@ class ShadowsocksNatService extends BaseService { /** Called when the activity is first created. */ def handleConnection() { - startTunnel() if (!profile.udpdns) startDnsDaemon() startRedsocksDaemon() startShadowsocksDaemon() setupIptables() - } def onBind(intent: Intent): IBinder = { @@ -285,7 +302,34 @@ class ShadowsocksNatService extends BaseService { val cmd_bypass = "iptables -t nat -A OUTPUT -p tcp -d 0.0.0.0 -j RETURN" if (!InetAddress.getByName(profile.host.toUpperCase).isInstanceOf[Inet6Address]) { - init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-d " + profile.host)) + if (proxychains_enable) { + val raf = new RandomAccessFile(getApplicationInfo.dataDir + "/proxychains.conf", "r"); + val len = raf.length(); + var lastLine = ""; + if (len != 0L) { + var pos = len - 1; + while (pos > 0) { + pos -= 1; + raf.seek(pos); + if (raf.readByte() == '\n' && lastLine.equals("")) { + lastLine = raf.readLine(); + } + } + } + raf.close(); + + val str_array = lastLine.split(' ') + var host = str_array(1) + + if (!Utils.isNumeric(host)) Utils.resolve(host, enableIPv6 = true) match { + case Some(a) => host = a + case None => throw NameNotResolvedException() + } + + init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-d " + host)) + } else { + init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-d " + profile.host)) + } } init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-d 127.0.0.1")) init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-m owner --uid-owner " + myUid)) @@ -329,6 +373,14 @@ class ShadowsocksNatService extends BaseService { // Clean up killProcesses() + if (new File(getApplicationInfo.dataDir + "/proxychains.conf").exists) { + proxychains_enable = true + Os.setenv("PROXYCHAINS_CONF_FILE", getApplicationInfo.dataDir + "/proxychains.conf", true) + Os.setenv("PROXYCHAINS_PROTECT_FD_PREFIX", getApplicationInfo.dataDir, true) + } else { + proxychains_enable = false + } + if (!Utils.isNumeric(profile.host)) Utils.resolve(profile.host, enableIPv6 = true) match { case Some(a) => profile.host = a case None => throw NameNotResolvedException() diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala index 4b55a25f11..44f53bf198 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala @@ -13,9 +13,9 @@ import android.support.design.widget.Snackbar import android.support.v7.app.AlertDialog import android.app.ProgressDialog import android.content._ +import android.view.View import android.webkit.{WebView, WebViewClient} -import android.widget.EditText -import android.widget.TextView +import android.widget._ import android.os.Looper import com.github.shadowsocks.ShadowsocksApplication.app import com.github.shadowsocks.database.Profile @@ -23,9 +23,12 @@ import com.github.shadowsocks.preferences._ import com.github.shadowsocks.utils.{Key, TcpFastOpen, Utils} import com.github.shadowsocks.utils.CloseUtils._ import com.github.shadowsocks.utils.IOUtils +import android.content.Context +import com.github.shadowsocks.utils._ import java.io.InputStreamReader import java.io.BufferedReader +import android.util.Log object ShadowsocksSettings { // Constants @@ -300,6 +303,85 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan .show() true }) + + findPreference(Key.frontproxy).setOnPreferenceClickListener((preference: Preference) => { + getPreferenceManager.setSharedPreferencesMode(Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS) + val prefs = getPreferenceManager.getSharedPreferences() + + val view = View.inflate(activity, R.layout.layout_front_proxy, null); + val sw_frontproxy_enable = view.findViewById(R.id.sw_frontproxy_enable).asInstanceOf[Switch] + val sp_frontproxy_type = view.findViewById(R.id.sp_frontproxy_type).asInstanceOf[Spinner] + val et_frontproxy_addr = view.findViewById(R.id.et_frontproxy_addr).asInstanceOf[EditText] + val et_frontproxy_port = view.findViewById(R.id.et_frontproxy_port).asInstanceOf[EditText] + val et_frontproxy_username = view.findViewById(R.id.et_frontproxy_username).asInstanceOf[EditText] + val et_frontproxy_password = view.findViewById(R.id.et_frontproxy_password).asInstanceOf[EditText] + + sp_frontproxy_type.setSelection(getResources().getStringArray(R.array.frontproxy_type_entry).indexOf(prefs.getString("frontproxy_type", "socks5"))) + + if (prefs.getInt("frontproxy_enable", 0) == 1) { + sw_frontproxy_enable.setChecked(true) + } + + et_frontproxy_addr.setText(prefs.getString("frontproxy_addr", "")) + et_frontproxy_port.setText(prefs.getString("frontproxy_port", "")) + et_frontproxy_username.setText(prefs.getString("frontproxy_username", "")) + et_frontproxy_password.setText(prefs.getString("frontproxy_password", "")) + + sw_frontproxy_enable.setOnCheckedChangeListener(((_, isChecked: Boolean) => { + val prefs_edit = prefs.edit() + if (isChecked) { + prefs_edit.putInt("frontproxy_enable", 1) + if (!new File(app.getApplicationInfo.dataDir + "/proxychains.conf").exists) { + val proxychains_conf = ConfigUtils + .PROXYCHAINS.formatLocal(Locale.ENGLISH, prefs.getString("frontproxy_type", "socks5") + , prefs.getString("frontproxy_addr", "") + , prefs.getString("frontproxy_port", "") + , prefs.getString("frontproxy_username", "") + , prefs.getString("frontproxy_password", "")) + Utils.printToFile(new File(app.getApplicationInfo.dataDir + "/proxychains.conf"))(p => { + p.println(proxychains_conf) + }) + } + } else { + prefs_edit.putInt("frontproxy_enable", 0) + if (new File(app.getApplicationInfo.dataDir + "/proxychains.conf").exists) { + new File(app.getApplicationInfo.dataDir + "/proxychains.conf").delete + } + } + prefs_edit.apply() + }): CompoundButton.OnCheckedChangeListener) + + new AlertDialog.Builder(activity) + .setTitle(getString(R.string.frontproxy_set)) + .setPositiveButton(android.R.string.ok, ((_, _) => { + val prefs_edit = prefs.edit() + prefs_edit.putString("frontproxy_type", sp_frontproxy_type.getSelectedItem().toString()) + + prefs_edit.putString("frontproxy_addr", et_frontproxy_addr.getText().toString()) + prefs_edit.putString("frontproxy_port", et_frontproxy_port.getText().toString()) + prefs_edit.putString("frontproxy_username", et_frontproxy_username.getText().toString()) + prefs_edit.putString("frontproxy_password", et_frontproxy_password.getText().toString()) + + prefs_edit.apply() + + if (new File(app.getApplicationInfo.dataDir + "/proxychains.conf").exists) { + val proxychains_conf = ConfigUtils + .PROXYCHAINS.formatLocal(Locale.ENGLISH, prefs.getString("frontproxy_type", "socks5") + , prefs.getString("frontproxy_addr", "") + , prefs.getString("frontproxy_port", "") + , prefs.getString("frontproxy_username", "") + , prefs.getString("frontproxy_password", "")) + Utils.printToFile(new File(app.getApplicationInfo.dataDir + "/proxychains.conf"))(p => { + p.println(proxychains_conf) + }) + } + }): DialogInterface.OnClickListener) + .setNegativeButton(android.R.string.no, null) + .setView(view) + .create() + .show() + true + }) } def downloadAcl(url: String) { diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala index a22f28eac9..893cd033b7 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala @@ -49,6 +49,7 @@ import android.content._ import android.content.pm.PackageManager.NameNotFoundException import android.net.VpnService import android.os._ +import android.system.Os import android.util.Log import com.github.shadowsocks.ShadowsocksApplication.app import com.github.shadowsocks.database.Profile @@ -70,6 +71,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { var sstunnelProcess: GuardedProcess = _ var pdnsdProcess: GuardedProcess = _ var tun2socksProcess: GuardedProcess = _ + var proxychains_enable: Boolean = false override def onBind(intent: Intent): IBinder = { val action = intent.getAction @@ -147,6 +149,14 @@ class ShadowsocksVpnService extends VpnService with BaseService { override def connect() = { super.connect() + if (new File(getApplicationInfo.dataDir + "/proxychains.conf").exists) { + proxychains_enable = true + Os.setenv("PROXYCHAINS_CONF_FILE", getApplicationInfo.dataDir + "/proxychains.conf", true) + Os.setenv("PROXYCHAINS_PROTECT_FD_PREFIX", getApplicationInfo.dataDir, true) + } else { + proxychains_enable = false + } + vpnThread = new ShadowsocksVpnThread(this) vpnThread.start() @@ -195,15 +205,27 @@ class ShadowsocksVpnService extends VpnService with BaseService { p.println(conf) }) - val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local", "-V", "-U", "-x" + //val old_ld = Os.getenv("LD_PRELOAD") + + //Os.setenv("LD_PRELOAD", getApplicationInfo.dataDir + "/lib/libproxychains4.so", true) + //Os.setenv("PROXYCHAINS_CONF_FILE", getApplicationInfo.dataDir + "/proxychains.conf", true) + + var cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local", "-V", "-U", "-x" , "-b", "127.0.0.1" , "-t", "600" , "-P", getApplicationInfo.dataDir , "-c", getApplicationInfo.dataDir + "/ss-local-udp-vpn.conf") + if (proxychains_enable) { + cmd prepend "LD_PRELOAD=" + getApplicationInfo.dataDir + "/lib/libproxychains4.so" + cmd prepend "env" + } + if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) sstunnelProcess = new GuardedProcess(cmd).start() + + //Os.setenv("LD_PRELOAD", old_ld, true) } def startShadowsocksDaemon() { @@ -215,6 +237,11 @@ class ShadowsocksVpnService extends VpnService with BaseService { p.println(conf) }) + //val old_ld = Os.getenv("LD_PRELOAD") + + //Os.setenv("LD_PRELOAD", getApplicationInfo.dataDir + "/lib/libproxychains4.so", true) + //Os.setenv("PROXYCHAINS_CONF_FILE", getApplicationInfo.dataDir + "/proxychains.conf", true) + val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local", "-V", "-x" , "-b", "127.0.0.1" , "-t", "600" @@ -230,9 +257,16 @@ class ShadowsocksVpnService extends VpnService with BaseService { if (TcpFastOpen.sendEnabled) cmd += "--fast-open" + if (proxychains_enable) { + cmd prepend "LD_PRELOAD=" + getApplicationInfo.dataDir + "/lib/libproxychains4.so" + cmd prepend "env" + } + if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) sslocalProcess = new GuardedProcess(cmd).start() + + //Os.setenv("LD_PRELOAD", old_ld, true) } def startDnsTunnel() = { @@ -243,6 +277,11 @@ class ShadowsocksVpnService extends VpnService with BaseService { p.println(conf) }) + //val old_ld = Os.getenv("LD_PRELOAD") + + //Os.setenv("LD_PRELOAD", getApplicationInfo.dataDir + "/lib/libproxychains4.so", true) + //Os.setenv("PROXYCHAINS_CONF_FILE", getApplicationInfo.dataDir + "/proxychains.conf", true) + val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local" , "-V" , "-u" @@ -257,9 +296,16 @@ class ShadowsocksVpnService extends VpnService with BaseService { else cmd += profile.dns.split(",")(0) + if (proxychains_enable) { + cmd prepend "LD_PRELOAD=" + getApplicationInfo.dataDir + "/lib/libproxychains4.so" + cmd prepend "env" + } + if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) sstunnelProcess = new GuardedProcess(cmd).start() + + //Os.setenv("LD_PRELOAD", old_ld, true) } def startDnsDaemon() { diff --git a/src/main/scala/com/github/shadowsocks/utils/Constants.scala b/src/main/scala/com/github/shadowsocks/utils/Constants.scala index 5511042909..a6eb3a24ee 100644 --- a/src/main/scala/com/github/shadowsocks/utils/Constants.scala +++ b/src/main/scala/com/github/shadowsocks/utils/Constants.scala @@ -72,6 +72,11 @@ object ConfigUtils { " type = socks5;\n" + "}\n" + val PROXYCHAINS = "strict_chain\n" + + "localnet 127.0.0.0/255.0.0.0\n" + + "[ProxyList]\n" + + "%s %s %s %s %s" + val PDNSD_LOCAL = """ |global { @@ -195,6 +200,7 @@ object Key { val tfo = "tcp_fastopen" val currentVersionCode = "currentVersionCode" val logcat = "logcat" + val frontproxy = "frontproxy" } object State {