Drop domain fronting and other network hacks since #1147

This commit is contained in:
tarsin committed 2023-06-17 16:37:51 +08:00
1 parent cf95e7b034
commit 2d20da70b8
8 files changed
+6 -248

No files matched your search

-1
View File
@@ -226,7 +226,6 @@ dependencies {
implementation(platform("com.squareup.okhttp3:okhttp-bom:5.0.0-alpha.11"))
implementation("com.squareup.okhttp3:okhttp-android")
implementation("com.squareup.okhttp3:okhttp-coroutines")
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps")
implementation("com.squareup.okio:okio-jvm:3.3.0")
@@ -18,6 +18,7 @@ package com.hippo.ehviewer
import android.app.Application
import android.content.ComponentCallbacks2
import android.os.Build
import androidx.appcompat.app.AppCompatDelegate
import androidx.collection.LruCache
import androidx.lifecycle.ProcessLifecycleOwner
@@ -26,11 +27,8 @@ import coil.decode.ImageDecoderDecoder
import coil.util.DebugLogger
import com.chuckerteam.chucker.api.ChuckerInterceptor
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhDns
import com.hippo.ehviewer.client.EhSSLSocketFactory
import com.hippo.ehviewer.client.EhTagDatabase
import com.hippo.ehviewer.client.data.GalleryDetail
import com.hippo.ehviewer.client.install
import com.hippo.ehviewer.coil.MergeInterceptor
import com.hippo.ehviewer.coil.diskCache
import com.hippo.ehviewer.coil.imageLoader
@@ -48,6 +46,9 @@ import com.hippo.ehviewer.yorozuya.FileUtils
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlinx.coroutines.DelicateCoroutinesApi
import okhttp3.AsyncDns
import okhttp3.Dns
import okhttp3.android.AndroidAsyncDns
import okio.Path.Companion.toOkioPath
import splitties.arch.room.roomDb
import splitties.init.appCtx
@@ -146,15 +147,15 @@ class EhApplication : Application(), ImageLoaderFactory {
companion object {
val nonCacheOkHttpClient by lazy {
val systemDns = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) AsyncDns.toDns(AndroidAsyncDns.IPv4, AndroidAsyncDns.IPv6) else Dns.SYSTEM
httpClient {
cookieJar(EhCookieStore)
dns(EhDns)
dns(systemDns)
addInterceptor(
ChuckerInterceptor.Builder(appCtx).apply {
alwaysReadResponseBody(false)
}.build(),
)
if (Settings.dF) install(EhSSLSocketFactory)
}
}
@@ -1,52 +0,0 @@
package com.hippo.ehviewer
import com.hippo.ehviewer.client.hosts
import com.hippo.ehviewer.client.hostsDsl
val builtInHosts = hostsDsl {
hosts("ehgt.org", "gt0.ehgt.org", "gt1.ehgt.org", "gt2.ehgt.org", "gt3.ehgt.org") {
"37.48.89.44" blockedInCN false
"81.171.10.48" blockedInCN false
"178.162.139.24" blockedInCN false
"178.162.140.212" blockedInCN false
"2001:1af8:4700:a062:8::47de" blockedInCN false
"2001:1af8:4700:a062:9::47de" blockedInCN true
"2001:1af8:4700:a0c9:4::47de" blockedInCN false
"2001:1af8:4700:a0c9:3::47de" blockedInCN true
}
hosts("e-hentai.org") {
"104.20.134.21" blockedInCN false
"104.20.135.21" blockedInCN false
"172.67.0.127" blockedInCN false
}
hosts("exhentai.org") {
"178.175.128.252" blockedInCN false
"178.175.129.252" blockedInCN false
"178.175.129.254" blockedInCN false
"178.175.128.254" blockedInCN false
"178.175.132.20" blockedInCN false
"178.175.132.22" blockedInCN false
}
hosts("s.exhentai.org") {
"178.175.129.254" blockedInCN false
"178.175.128.254" blockedInCN false
"178.175.132.22" blockedInCN false
}
hosts("repo.e-hentai.org") {
"94.100.28.57" blockedInCN true
"94.100.29.73" blockedInCN true
}
hosts("forums.e-hentai.org") {
"94.100.18.243" blockedInCN false
}
hosts("ul.ehgt.org") {
"94.100.24.82" blockedInCN true
"94.100.24.72" blockedInCN true
}
hosts("raw.githubusercontent.com") {
"151.101.0.133" blockedInCN true
"151.101.64.133" blockedInCN false
"151.101.128.133" blockedInCN false
"151.101.192.133" blockedInCN false
}
}
@@ -12,8 +12,6 @@ import kotlin.reflect.KProperty
object Settings : DataStorePreferences(null) {
private const val KEY_SHOW_TAG_TRANSLATIONS = "show_tag_translations"
private const val KEY_BUILT_IN_HOSTS = "built_in_hosts_2"
private const val KEY_DOMAIN_FRONTING = "domain_fronting"
var downloadScheme by stringOrNullPref("image_scheme", null)
var downloadAuthority by stringOrNullPref("image_authority", null)
@@ -48,14 +46,11 @@ object Settings : DataStorePreferences(null) {
var saveParseErrorBody by boolPref("save_parse_error_body", true)
var saveCrashLog by boolPref("save_crash_log", true)
var security by boolPref("require_unlock", false)
var builtInHosts by boolPref(KEY_BUILT_IN_HOSTS, false)
var removeImageFiles by boolPref("include_pic", true)
var needSignIn by boolPref("need_sign_in", true)
var blackDarkTheme by boolPref("black_dark_theme", false).observed { updateWhenAmoledModeChanges() }
var preloadThumbAggressively by boolPref("preload_thumb_aggressively", false)
var dF by boolPref(KEY_DOMAIN_FRONTING, false)
var downloadOriginImage by boolPref("download_origin_image", false)
var bypassVpn by boolPref("bypass_vpn", true)
var thumbSizeDp by intPref("thumb_size_", 120)
var favLocalCount by intPref("fav_local", 0)
var favCloudCount by intPref("fav_cloud", 0)
@@ -78,8 +73,6 @@ object Settings : DataStorePreferences(null) {
init {
if ("CN" == Locale.getDefault().country) {
edit {
if (KEY_BUILT_IN_HOSTS !in prefs) builtInHosts = true
if (KEY_DOMAIN_FRONTING !in prefs) dF = true
if (KEY_SHOW_TAG_TRANSLATIONS !in prefs) showTagTranslations = true
}
}
@@ -1,34 +0,0 @@
package com.hippo.ehviewer.client
import android.os.Build
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.builtInHosts
import com.hippo.ehviewer.ui.settings.EhDoH
import okhttp3.AsyncDns
import okhttp3.Dns
import okhttp3.android.AndroidAsyncDns
import java.net.InetAddress
private typealias HostsMap = MutableMap<String, List<InetAddress>>
fun hostsDsl(builder: HostsMap.() -> Unit): HostsMap = mutableMapOf<String, List<InetAddress>>().apply(builder)
fun interface HostMapBuilder {
infix fun String.blockedInCN(boolean: Boolean)
}
fun HostsMap.hosts(vararg hosts: String, builder: HostMapBuilder.() -> Unit) = apply {
hosts.forEach { host ->
fun String.toInetAddress() = InetAddress.getByName(this).let { InetAddress.getByAddress(host, it.address) }
mutableListOf<InetAddress>().apply {
HostMapBuilder { if (!(Settings.dF && it)) add(toInetAddress()) }.apply(builder)
put(host, this)
}
}
}
val systemDns = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) AsyncDns.toDns(AndroidAsyncDns.IPv4, AndroidAsyncDns.IPv6) else Dns.SYSTEM
object EhDns : Dns {
override fun lookup(hostname: String): List<InetAddress> = builtInHosts[hostname].takeIf { Settings.builtInHosts } ?: EhDoH.lookup(hostname) ?: systemDns.lookup(hostname)
}
@@ -1,55 +0,0 @@
/*
* Copyright 2022 Tarsin Norbin
*
* This file is part of EhViewer
*
* EhViewer 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.
*
* EhViewer 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 EhViewer.
* If not, see <https://www.gnu.org/licenses/>.
*/
package com.hippo.ehviewer.client
import android.util.Log
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.builtInHosts
import okhttp3.OkHttpClient
import java.net.InetAddress
import java.net.Socket
import java.security.KeyStore
import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
private const val EXCEPTIONAL_DOMAIN = "hath.network"
private val sslSocketFactory = SSLSocketFactory.getDefault() as SSLSocketFactory
object EhSSLSocketFactory : SSLSocketFactory() {
override fun getDefaultCipherSuites(): Array<String> = sslSocketFactory.defaultCipherSuites
override fun getSupportedCipherSuites(): Array<String> = sslSocketFactory.supportedCipherSuites
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket {
val address = s.inetAddress.hostAddress.takeIf { host in builtInHosts || EXCEPTIONAL_DOMAIN in host || host in Settings.dohUrl }
Log.d("EhSSLSocketFactory", "Host: $host Address: $address")
return sslSocketFactory.createSocket(s, address ?: host, port, autoClose) as SSLSocket
}
override fun createSocket(host: String, port: Int): Socket = sslSocketFactory.createSocket(host, port)
override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket = sslSocketFactory.createSocket(host, port, localHost, localPort)
override fun createSocket(host: InetAddress, port: Int): Socket = sslSocketFactory.createSocket(host, port)
override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket = sslSocketFactory.createSocket(address, port, localAddress, localPort)
}
fun OkHttpClient.Builder.install(sslSocketFactory: SSLSocketFactory) = apply {
val factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())!!
factory.init(null as KeyStore?)
val manager = factory.trustManagers!!
val trustManager = manager.filterIsInstance<X509TrustManager>().first()
sslSocketFactory(sslSocketFactory, trustManager)
}
@@ -24,14 +24,10 @@ import android.content.pm.verify.domain.DomainVerificationManager
import android.content.pm.verify.domain.DomainVerificationUserState
import android.graphics.Bitmap
import android.graphics.ImageDecoder
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
@@ -201,9 +197,6 @@ class MainActivity : EhActivity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
if (Settings.dF && Settings.bypassVpn) {
bypassVpn()
}
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
@@ -251,19 +244,6 @@ class MainActivity : EhActivity() {
}
}
private fun bypassVpn() {
val network = connectivityManager.activeNetwork
val capabilities = connectivityManager.getNetworkCapabilities(network)
capabilities?.let {
if (it.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
val builder = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_FOREGROUND)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
connectivityManager.registerNetworkCallback(builder.build(), mNetworkCallback)
}
}
}
@RequiresApi(Build.VERSION_CODES.S)
@Throws(PackageManager.NameNotFoundException::class)
private fun checkAppLinkVerify() {
@@ -484,25 +464,4 @@ class MainActivity : EhActivity() {
super.onProvideAssistContent(outContent)
mShareUrl?.let { outContent?.webUri = Uri.parse(mShareUrl) }
}
private val mNetworkCallback = object : ConnectivityManager.NetworkCallback() {
private val TAG = "mNetworkCallback"
override fun onAvailable(network: Network) {
Log.d(TAG, "onAvailable: $network")
connectivityManager.bindProcessToNetwork(network)
availableNetworks.add(network)
}
override fun onLost(network: Network) {
Log.d(TAG, "onLost: $network")
val activeNetwork = availableNetworks.last()
availableNetworks.remove(network)
if (network == activeNetwork) {
connectivityManager.bindProcessToNetwork(
availableNetworks.takeIf { it.isNotEmpty() }?.last(),
)
}
}
}
}
@@ -1,7 +1,6 @@
package com.hippo.ehviewer.ui.settings
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
@@ -32,15 +31,12 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.hippo.ehviewer.AppConfig
import com.hippo.ehviewer.BuildConfig
import com.hippo.ehviewer.EhApplication
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhEngine
import com.hippo.ehviewer.client.data.FavListUrlBuilder
import com.hippo.ehviewer.client.systemDns
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.legacy.EditTextDialogBuilder
import com.hippo.ehviewer.ui.tools.observed
import com.hippo.ehviewer.util.LogCat
import com.hippo.ehviewer.util.ReadableTime
@@ -48,10 +44,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import moe.tarsin.coroutines.runSuspendCatching
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.dnsoverhttps.DnsOverHttps
import java.io.File
import java.net.InetAddress
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
@@ -133,37 +126,6 @@ fun AdvancedScreen() {
entryValueRes = R.array.app_language_entry_values,
value = Settings::language,
)
SwitchPreference(
title = stringResource(id = R.string.settings_advanced_built_in_hosts_title),
value = Settings::builtInHosts,
)
Preference(title = stringResource(id = R.string.settings_advanced_dns_over_http_title)) {
val builder = EditTextDialogBuilder(context, Settings.dohUrl, context.getString(R.string.settings_advanced_dns_over_http_hint))
builder.setTitle(R.string.settings_advanced_dns_over_http_title)
builder.setPositiveButton(android.R.string.ok, null)
val dialog = builder.create().apply { show() }
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
val text = builder.text.trim()
runCatching {
doh = if (text.isNotBlank()) buildDoHDNS(text) else null
}.onFailure {
builder.setError("Invalid URL!")
}.onSuccess {
Settings.dohUrl = text
dialog.dismiss()
}
}
}
SwitchPreference(
title = stringResource(id = R.string.settings_advanced_domain_fronting_title),
summary = stringResource(id = R.string.settings_advanced_domain_fronting_summary),
value = Settings::dF,
)
SwitchPreference(
title = stringResource(id = R.string.settings_advanced_bypass_vpn_title),
summary = stringResource(id = R.string.settings_advanced_bypass_vpn_summary),
value = Settings::bypassVpn,
)
SwitchPreference(
title = stringResource(id = R.string.preload_thumb_aggressively),
value = Settings::preloadThumbAggressively,
@@ -265,18 +227,3 @@ fun AdvancedScreen() {
}
}
}
private fun buildDoHDNS(url: String): DnsOverHttps {
return DnsOverHttps.Builder().apply {
client(EhApplication.okHttpClient)
url(url.toHttpUrl())
post(true)
systemDns(systemDns)
}.build()
}
private var doh: DnsOverHttps? = Settings.dohUrl.runCatching { buildDoHDNS(this) }.getOrNull()
object EhDoH {
fun lookup(hostname: String): List<InetAddress>? = doh?.runCatching { lookup(hostname).takeIf { it.isNotEmpty() } }?.onFailure { it.printStackTrace() }?.getOrNull()
}