Compare commits

..

6 Commits

Author SHA1 Message Date
2dust 0542d913f2 Merge pull request #131 from galvasis193/feature-customediting
Give user the ability to edit/copy/paste custom config for convenience. Fix Import
2019-10-14 08:22:39 +08:00
Annoymous contributor 746254bb7e Give user the ability to edit/copy/paste custom config for convenience.
Fix import for go.Seq
2019-10-13 04:55:00 +00:00
2dust 2227ea3ed6 Merge pull request #129 from galvasis193/feature-ProxySharing
Add proxy sharing function. Fix potential security vulnerbility.
2019-10-12 09:40:19 +08:00
Annoymous contributor 4d0e9e2b44 Bugfix: When a setting is changed proxy will now auto restart to apply the change. Fix proxy service cannot be stopped bug. 2019-10-11 10:28:45 +00:00
Annoymous contributor 5cba8a228c Add proxy sharing. Fix potential unahthorized access from LAN/Internet. 2019-10-11 10:26:46 +00:00
2dust 2d8ed22dba mge 2019-10-11 14:17:10 +08:00
13 changed files with 174 additions and 43 deletions
@@ -11,6 +11,7 @@ class AngApplication : Application() {
const val PREF_LAST_VERSION = "pref_last_version" const val PREF_LAST_VERSION = "pref_last_version"
} }
var curIndex = -1 //Current proxy that is opened. (Used to implement restart feature)
var firstRun = false var firstRun = false
private set private set
@@ -37,6 +37,7 @@ import java.lang.ref.SoftReference
import android.os.Build import android.os.Build
import android.annotation.TargetApi import android.annotation.TargetApi
import android.util.Log import android.util.Log
import go.Seq
import org.jetbrains.anko.doAsync import org.jetbrains.anko.doAsync
class V2RayVpnService : VpnService() { class V2RayVpnService : VpnService() {
@@ -64,7 +65,6 @@ class V2RayVpnService : VpnService() {
private var mNotificationManager: NotificationManager? = null private var mNotificationManager: NotificationManager? = null
/** /**
* Unfortunately registerDefaultNetworkCallback is going to return our VPN interface: https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e * Unfortunately registerDefaultNetworkCallback is going to return our VPN interface: https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e
* *
@@ -282,12 +282,19 @@ class V2RayVpnService : VpnService() {
unregisterReceiver(mMsgReceive) unregisterReceiver(mMsgReceive)
} catch (e: Exception) { } catch (e: Exception) {
} }
//stopSelf has to be called ahead of mInterface.close(). otherwise v2ray core cannot be stooped
//It's strage but true.
//This can be verified by putting stopself() behind and call stopLoop and startLoop
//in a row for several times. You will find that later created v2ray core report port in use
//which means the first v2ray core somehow failed to stop and release the port.
stopSelf()
try { try {
mInterface.close() mInterface.close()
} catch (ignored: Exception) { } catch (ignored: Exception) {
} }
stopSelf()
} }
} }
@@ -232,7 +232,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
R.id.export_all -> { R.id.export_all -> {
if (AngConfigManager.shareAll2Clipboard() == 0) { if (AngConfigManager.shareAll2Clipboard() == 0) {
toast(R.string.toast_success) //remove toast, otherwise it will block previous warning message
} else { } else {
toast(R.string.toast_failure) toast(R.string.toast_failure)
} }
@@ -1,9 +1,11 @@
package com.v2ray.ang.ui package com.v2ray.ang.ui
import android.os.Bundle import android.os.Bundle
import android.text.Editable
import android.text.TextUtils import android.text.TextUtils
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import com.google.gson.Gson
import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig
import com.v2ray.ang.R import com.v2ray.ang.R
import com.v2ray.ang.extension.defaultDPreference import com.v2ray.ang.extension.defaultDPreference
@@ -12,6 +14,7 @@ import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.Utils import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_server2.* import kotlinx.android.synthetic.main.activity_server2.*
import org.jetbrains.anko.* import org.jetbrains.anko.*
import java.lang.Exception
class Server2Activity : BaseActivity() { class Server2Activity : BaseActivity() {
@@ -50,7 +53,7 @@ class Server2Activity : BaseActivity() {
*/ */
fun bindingServer(vmess: AngConfig.VmessBean): Boolean { fun bindingServer(vmess: AngConfig.VmessBean): Boolean {
et_remarks.text = Utils.getEditable(vmess.remarks) et_remarks.text = Utils.getEditable(vmess.remarks)
tv_content.text = defaultDPreference.getPrefString(AppConfig.ANG_CONFIG + edit_guid, "") tv_content.text = Editable.Factory.getInstance().newEditable(defaultDPreference.getPrefString(AppConfig.ANG_CONFIG + edit_guid, ""))
return true return true
} }
@@ -66,21 +69,40 @@ class Server2Activity : BaseActivity() {
* save server config * save server config
*/ */
fun saveServer(): Boolean { fun saveServer(): Boolean {
var saveSuccess: Boolean
val vmess = configs.vmess[edit_index] val vmess = configs.vmess[edit_index]
vmess.remarks = et_remarks.text.toString() vmess.remarks = et_remarks.text.toString()
if (TextUtils.isEmpty(vmess.remarks)) { if (TextUtils.isEmpty(vmess.remarks)) {
toast(R.string.server_lab_remarks) toast(R.string.server_lab_remarks)
return false saveSuccess = false
} }
if (AngConfigManager.addCustomServer(vmess, edit_index) == 0) { if (AngConfigManager.addCustomServer(vmess, edit_index) == 0) {
toast(R.string.toast_success) toast(R.string.toast_success)
saveSuccess = true
} else {
toast(R.string.toast_failure)
saveSuccess = false
}
try {
Gson().fromJson<Object>(tv_content.text.toString(), Object::class.java)
} catch (e: Exception) {
e.printStackTrace()
toast(R.string.toast_malformed_josn)
saveSuccess = false
}
if (saveSuccess) {
//update config
defaultDPreference.setPrefString(AppConfig.ANG_CONFIG + edit_guid, tv_content.text.toString())
finish() finish()
return true return true
} else { } else {
toast(R.string.toast_failure)
return false return false
} }
} }
@@ -4,10 +4,8 @@ import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.preference.CheckBoxPreference import android.preference.*
import android.preference.EditTextPreference import com.v2ray.ang.AngApplication
import android.preference.Preference
import android.preference.PreferenceFragment
import com.v2ray.ang.BuildConfig import com.v2ray.ang.BuildConfig
//import com.v2ray.ang.InappBuyActivity //import com.v2ray.ang.InappBuyActivity
import com.v2ray.ang.R import com.v2ray.ang.R
@@ -29,6 +27,7 @@ class SettingsActivity : BaseActivity() {
// const val PREF_MUX_ENAimport libv2ray.Libv2rayBLED = "pref_mux_enabled" // const val PREF_MUX_ENAimport libv2ray.Libv2rayBLED = "pref_mux_enabled"
const val PREF_SPEED_ENABLED = "pref_speed_enabled" const val PREF_SPEED_ENABLED = "pref_speed_enabled"
const val PREF_SNIFFING_ENABLED = "pref_sniffing_enabled" const val PREF_SNIFFING_ENABLED = "pref_sniffing_enabled"
const val PREF_PROXY_SHARING = "pref_proxy_sharing_enabled"
const val PREF_LOCAL_DNS_ENABLED = "pref_local_dns_enabled" const val PREF_LOCAL_DNS_ENABLED = "pref_local_dns_enabled"
const val PREF_REMOTE_DNS = "pref_remote_dns" const val PREF_REMOTE_DNS = "pref_remote_dns"
const val PREF_DOMESTIC_DNS = "pref_domestic_dns" const val PREF_DOMESTIC_DNS = "pref_domestic_dns"
@@ -59,12 +58,19 @@ class SettingsActivity : BaseActivity() {
class SettingsFragment : PreferenceFragment(), SharedPreferences.OnSharedPreferenceChangeListener { class SettingsFragment : PreferenceFragment(), SharedPreferences.OnSharedPreferenceChangeListener {
val perAppProxy by lazy { findPreference(PREF_PER_APP_PROXY) as CheckBoxPreference } val perAppProxy by lazy { findPreference(PREF_PER_APP_PROXY) as CheckBoxPreference }
// val autoRestart by lazy { findPreference(PREF_AUTO_RESTART) as CheckBoxPreference } val sppedEnabled by lazy { findPreference(PREF_SPEED_ENABLED) as CheckBoxPreference }
val remoteDns by lazy { findPreference(PREF_REMOTE_DNS) as EditTextPreference } val sniffingEnabled by lazy { findPreference(PREF_SNIFFING_ENABLED) as CheckBoxPreference }
val domesticDns by lazy { findPreference(PREF_DOMESTIC_DNS) as EditTextPreference } val proxySharing by lazy { findPreference(PREF_PROXY_SHARING) as CheckBoxPreference }
val domainStrategy by lazy { findPreference(PREF_ROUTING_DOMAIN_STRATEGY) as ListPreference }
val routingMode by lazy { findPreference(PREF_ROUTING_MODE) as ListPreference }
val enableLocalDns by lazy { findPreference(PREF_LOCAL_DNS_ENABLED) as CheckBoxPreference }
val forwardIpv6 by lazy { findPreference(PREF_FORWARD_IPV6) as CheckBoxPreference } val forwardIpv6 by lazy { findPreference(PREF_FORWARD_IPV6) as CheckBoxPreference }
val enableLocalDns by lazy { findPreference(PREF_LOCAL_DNS_ENABLED) as CheckBoxPreference }
val domesticDns by lazy { findPreference(PREF_DOMESTIC_DNS) as EditTextPreference }
val remoteDns by lazy { findPreference(PREF_REMOTE_DNS) as EditTextPreference }
// val autoRestart by lazy { findPreference(PREF_AUTO_RESTART) as CheckBoxPreference }
// val socksPort by lazy { findPreference(PREF_SOCKS_PORT) as EditTextPreference } // val socksPort by lazy { findPreference(PREF_SOCKS_PORT) as EditTextPreference }
// val httpPort by lazy { findPreference(PREF_HTTP_PORT) as EditTextPreference } // val httpPort by lazy { findPreference(PREF_HTTP_PORT) as EditTextPreference }
@@ -76,14 +82,95 @@ class SettingsActivity : BaseActivity() {
// val tgGroup: Preference by lazy { findPreference(PREF_TG_GROUP) } // val tgGroup: Preference by lazy { findPreference(PREF_TG_GROUP) }
val version: Preference by lazy { findPreference(PREF_VERSION) } val version: Preference by lazy { findPreference(PREF_VERSION) }
private fun restartProxy() {
Utils.stopVService(activity)
Utils.startVService(activity)
}
private fun isRunning(): Boolean {
return Utils.isServiceRun(activity, "com.v2ray.ang.service.V2RayVpnService")
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
addPreferencesFromResource(R.xml.pref_settings) addPreferencesFromResource(R.xml.pref_settings)
var app = activity.application as AngApplication
perAppProxy.setOnPreferenceClickListener {
if (isRunning()) {
Utils.stopVService(activity)
}
startActivity<PerAppProxyActivity>()
perAppProxy.isChecked = true
true
}
sppedEnabled.setOnPreferenceClickListener {
if (isRunning())
restartProxy()
true
}
sniffingEnabled.setOnPreferenceClickListener {
if (isRunning())
restartProxy()
true
}
proxySharing.setOnPreferenceClickListener {
if (proxySharing.isChecked)
toast(R.string.toast_warning_pref_proxysharing)
if (isRunning())
restartProxy()
true
}
domainStrategy.setOnPreferenceChangeListener { _, _ ->
if (isRunning())
restartProxy()
true
}
routingMode.setOnPreferenceChangeListener { _, _ ->
if (isRunning())
restartProxy()
true
}
routingCustom.onClick { routingCustom.onClick {
if (isRunning())
Utils.stopVService(activity)
startActivity<RoutingSettingsActivity>() startActivity<RoutingSettingsActivity>()
} }
forwardIpv6.setOnPreferenceClickListener {
if (isRunning())
restartProxy()
true
}
enableLocalDns.setOnPreferenceClickListener {
if (isRunning())
restartProxy()
true
}
domesticDns.setOnPreferenceChangeListener { preference, any ->
// domesticDns.summary = any as String
val nval = any as String
domesticDns.summary = if (nval == "") AppConfig.DNS_DIRECT else nval
if (isRunning())
restartProxy()
true
}
remoteDns.setOnPreferenceChangeListener { preference, any ->
// remoteDns.summary = any as String
val nval = any as String
remoteDns.summary = if (nval == "") AppConfig.DNS_AGENT else nval
if (isRunning())
restartProxy()
true
}
// donate.onClick { // donate.onClick {
// startActivity<InappBuyActivity>() // startActivity<InappBuyActivity>()
// } // }
@@ -110,24 +197,7 @@ class SettingsActivity : BaseActivity() {
// } // }
// } // }
perAppProxy.setOnPreferenceClickListener {
startActivity<PerAppProxyActivity>()
perAppProxy.isChecked = true
false
}
remoteDns.setOnPreferenceChangeListener { preference, any ->
// remoteDns.summary = any as String
val nval = any as String
remoteDns.summary = if (nval == "") AppConfig.DNS_AGENT else nval
true
}
domesticDns.setOnPreferenceChangeListener { preference, any ->
// domesticDns.summary = any as String
val nval = any as String
domesticDns.summary = if (nval == "") AppConfig.DNS_DIRECT else nval
true
}
// socksPort.setOnPreferenceChangeListener { preference, any -> // socksPort.setOnPreferenceChangeListener { preference, any ->
// socksPort.summary = any as String // socksPort.summary = any as String
// true // true
@@ -147,13 +147,15 @@ object AngConfigManager {
fun setActiveServer(index: Int): Int { fun setActiveServer(index: Int): Int {
try { try {
if (index < 0 || index > angConfig.vmess.count() - 1) { if (index < 0 || index > angConfig.vmess.count() - 1) {
app.curIndex = -1
return -1 return -1
} }
angConfig.index = index angConfig.index = index
app.curIndex = index
storeConfigFile() storeConfigFile()
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
app.curIndex = -1
return -1 return -1
} }
return 0 return 0
@@ -27,6 +27,7 @@ import com.v2ray.ang.AngApplication
import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig
import com.v2ray.ang.R import com.v2ray.ang.R
import com.v2ray.ang.extension.responseLength import com.v2ray.ang.extension.responseLength
import com.v2ray.ang.extension.v2RayApplication
import com.v2ray.ang.service.V2RayVpnService import com.v2ray.ang.service.V2RayVpnService
import com.v2ray.ang.ui.SettingsActivity import com.v2ray.ang.ui.SettingsActivity
import kotlinx.android.synthetic.main.activity_logcat.* import kotlinx.android.synthetic.main.activity_logcat.*
@@ -311,7 +312,11 @@ object Utils {
* startVService * startVService
*/ */
fun startVService(context: Context): Boolean { fun startVService(context: Context): Boolean {
context.toast(R.string.toast_services_start) if (context.v2RayApplication.defaultDPreference.getPrefBoolean(SettingsActivity.PREF_PROXY_SHARING, false)) {
context.toast(R.string.toast_warning_pref_proxysharing_short)
}else{
context.toast(R.string.toast_services_start)
}
if (AngConfigManager.genStoreV2rayConfig(-1)) { if (AngConfigManager.genStoreV2rayConfig(-1)) {
val configContent = AngConfigManager.currGeneratedV2rayConfig() val configContent = AngConfigManager.currGeneratedV2rayConfig()
val configType = AngConfigManager.currConfigType() val configType = AngConfigManager.currConfigType()
@@ -335,6 +340,7 @@ object Utils {
*/ */
fun startVService(context: Context, guid: String): Boolean { fun startVService(context: Context, guid: String): Boolean {
val index = AngConfigManager.getIndexViaGuid(guid) val index = AngConfigManager.getIndexViaGuid(guid)
context.v2RayApplication.curIndex=index
return startVService(context, index) return startVService(context, index)
} }
@@ -129,6 +129,12 @@ object V2rayConfigUtil {
*/ */
private fun inbounds(vmess: VmessBean, v2rayConfig: V2rayConfig, app: AngApplication): Boolean { private fun inbounds(vmess: VmessBean, v2rayConfig: V2rayConfig, app: AngApplication): Boolean {
try { try {
v2rayConfig.inbounds.forEach { curInbound ->
if (!app.defaultDPreference.getPrefBoolean(SettingsActivity.PREF_PROXY_SHARING, false)) {
//bind all inbounds to localhost if the user requests
curInbound.listen = "127.0.0.1"
}
}
v2rayConfig.inbounds[0].port = 10808 v2rayConfig.inbounds[0].port = 10808
// val socksPort = Utils.parseInt(app.defaultDPreference.getPrefString(SettingsActivity.PREF_SOCKS_PORT, "10808")) // val socksPort = Utils.parseInt(app.defaultDPreference.getPrefString(SettingsActivity.PREF_SOCKS_PORT, "10808"))
// val lanconnPort = Utils.parseInt(app.defaultDPreference.getPrefString(SettingsActivity.PREF_HTTP_PORT, "")) // val lanconnPort = Utils.parseInt(app.defaultDPreference.getPrefString(SettingsActivity.PREF_HTTP_PORT, ""))
@@ -547,7 +553,7 @@ object V2rayConfigUtil {
mux = null)) mux = null))
} }
// DNS routing // DNS routing
v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean( v2rayConfig.routing.rules.add(0, V2rayConfig.RoutingBean.RulesBean(
type = "field", type = "field",
outboundTag = AppConfig.TAG_DIRECT, outboundTag = AppConfig.TAG_DIRECT,
@@ -68,20 +68,15 @@
android:text="@string/server_lab_content" android:text="@string/server_lab_content"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" /> android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
<TextView <EditText
android:id="@+id/tv_content" android:id="@+id/tv_content"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_marginTop="@dimen/layout_margin_top_height" android:layout_marginTop="@dimen/layout_margin_top_height"
android:text="" /> android:text="" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:layout_marginBottom="@dimen/layout_margin_top_height"
android:orientation="vertical" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
@@ -180,5 +180,10 @@
<item>绕过大陆地址</item> <item>绕过大陆地址</item>
<item>绕过局域网及大陆地址</item> <item>绕过局域网及大陆地址</item>
</string-array> </string-array>
<string name="title_pref_proxy_sharing_enabled">代理共享</string>
<string name="summary_pref_proxy_sharing_enabled">绑定代理入口ip到0.0.0.0</string>
<string name="toast_warning_pref_proxysharing">其他设备可以使用socks/http协议通过您的IP地址连接到代理\nHttp 代理: http://您的ip:10809\nSocks 代理: socks(4/5)://您的ip:10808\n仅在受信任的网络中启用以避免未经授权的连接</string>
<string name="toast_warning_pref_proxysharing_short">代理共享已启用,请确保处于受信网络</string>
<string name="toast_malformed_josn">配置格式错误</string>
</resources> </resources>
@@ -182,4 +182,9 @@
<item>略過中國大陸</item> <item>略過中國大陸</item>
<item>略過局域網及中國大陸</item> <item>略過局域網及中國大陸</item>
</string-array> </string-array>
<string name="title_pref_proxy_sharing_enabled">代理共享</string>
<string name="summary_pref_proxy_sharing_enabled">綁定代理入口ip到0.0.0.0</string>
<string name="toast_warning_pref_proxysharing">其他設備可以使用socks/http協議通過您的IP地址連接到代理\nHttp 代理: http://您的ip:10809\nSocks 代理: socks(4/5)://您的ip:10808\n僅在受信任的網絡中啟用以避免未經授權的連接</string>
<string name="toast_warning_pref_proxysharing_short">代理共享已啟用,請確保處於受信網絡</string>
<string name="toast_malformed_josn">配置格式錯誤</string>
</resources> </resources>
@@ -181,5 +181,10 @@
<item>Bypass mainland address</item> <item>Bypass mainland address</item>
<item>Bypassing LAN and mainland address</item> <item>Bypassing LAN and mainland address</item>
</string-array> </string-array>
<string name="title_pref_proxy_sharing_enabled">Proxy sharing</string>
<string name="summary_pref_proxy_sharing_enabled">Bind inbound to 0.0.0.0</string>
<string name="toast_warning_pref_proxysharing">Other devices can connect to proxy by your ip address through socks/http protocol\nHttp Proxy: http://yourIP:10809\nSocks Proxy: socks(4/5)://yourIP:10808\nOnly enable in trusted network to avoid unauthorized connection</string>
<string name="toast_warning_pref_proxysharing_short">Proxy sharing enabled\nMake sure you are in a trusted network</string>
<string name="toast_malformed_josn">Config malformed</string>
</resources> </resources>
@@ -22,6 +22,13 @@
android:summary="@string/summary_pref_sniffing_enabled" android:summary="@string/summary_pref_sniffing_enabled"
android:title="@string/title_pref_sniffing_enabled" /> android:title="@string/title_pref_sniffing_enabled" />
<CheckBoxPreference
android:defaultValue="false"
android:key="pref_proxy_sharing_enabled"
android:onClick="proxySharingOnClick"
android:summary="@string/summary_pref_proxy_sharing_enabled"
android:title="@string/title_pref_proxy_sharing_enabled" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/title_pref_routing"> <PreferenceCategory android:title="@string/title_pref_routing">