Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/java/io/nekohasekai/sagernet/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ object Key {
const val CONCURRENT_DIAL = "concurrentDial"

const val MIXED_PORT = "mixedPort"
const val MIXED_SECRET = "mixedSecret" // storage key for the generated inbound secret
const val MIXED_USERNAME = "neko" // username presented to the authed mixed inbound
const val ALLOW_ACCESS = "allowAccess"
const val SPEED_INTERVAL = "speedInterval"
const val SHOW_DIRECT_SPEED = "showDirectSpeed"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ class BaseService {
fun stopRunner(restart: Boolean = false, msg: String? = null) {
DataStore.baseService = null
DataStore.vpnService = null
DataStore.mixedInboundAuthed = false

if (data.state == State.Stopping) return
data.notification?.destroy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ abstract class BoxInstance(

protected open fun buildConfig() {
config = buildConfig(profile)
DataStore.mixedInboundAuthed = DataStore.mixedInboundNeedsAuth
}

protected open suspend fun loadConfig() {
Expand Down Expand Up @@ -219,4 +220,4 @@ abstract class BoxInstance(
}
}

}
}
21 changes: 21 additions & 0 deletions app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.nekohasekai.sagernet.database

import android.os.Binder
import android.os.Build
import androidx.preference.PreferenceDataStore
import io.nekohasekai.sagernet.CONNECTION_TEST_URL
import io.nekohasekai.sagernet.GroupType
Expand All @@ -27,6 +28,9 @@ object DataStore : OnPreferenceDataStoreChangeListener {
@Volatile
var serviceState = BaseService.State.Idle

@Volatile
var mixedInboundAuthed: Boolean = false

val configurationStore = RoomPreferenceDataStore(PublicDatabase.kvPairDao)
val profileCacheStore = RoomPreferenceDataStore(TempDatabase.profileCacheDao)

Expand Down Expand Up @@ -134,10 +138,27 @@ object DataStore : OnPreferenceDataStoreChangeListener {

// hopefully hashCode = mHandle doesn't change, currently this is true from KitKat to Nougat
private val userIndex by lazy { Binder.getCallingUserHandle().hashCode() }
val mixedSecret: String
@Synchronized get() {
var s = configurationStore.getString(Key.MIXED_SECRET)
if (s.isNullOrEmpty()) {
s = java.util.UUID.randomUUID().toString().replace("-", "")
configurationStore.putString(Key.MIXED_SECRET, s)
}
return s
}

var mixedPort: Int
get() = getLocalPort(Key.MIXED_PORT, 2080)
set(value) = saveLocalPort(Key.MIXED_PORT, value)

val mixedInboundNeedsAuth: Boolean
get() = serviceMode == Key.MODE_VPN &&
!(appendHttpProxy && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)

val mixedInboundUser: String get() = if (mixedInboundAuthed) Key.MIXED_USERNAME else ""
val mixedInboundPass: String get() = if (mixedInboundAuthed) mixedSecret else ""

fun initGlobal() {
if (configurationStore.getString(Key.MIXED_PORT) == null) {
mixedPort = mixedPort
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ fun buildConfig(
domain_strategy = genDomainStrategy(DataStore.resolveDestination)
sniff = needSniff
sniff_override_destination = needSniffOverride
if (DataStore.mixedInboundNeedsAuth) {
users = listOf(User().also { u ->
u.username = Key.MIXED_USERNAME
u.password = DataStore.mixedSecret
})
}
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ object RawUpdater : GroupUpdater() {
} else {

val response = Libcore.newHttpClient().apply {
trySocks5(DataStore.mixedPort)
trySocks5(
DataStore.mixedPort,
DataStore.mixedInboundUser,
DataStore.mixedInboundPass
)
tryH3Direct()
when (DataStore.appTLSVersion) {
"1.3" -> restrictedTLS()
Expand Down
8 changes: 6 additions & 2 deletions app/src/main/java/io/nekohasekai/sagernet/ui/AboutFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,11 @@ class AboutFragment : ToolbarFragment(R.layout.layout_about) {
try {
val client = Libcore.newHttpClient().apply {
modernTLS()
trySocks5(DataStore.mixedPort)
trySocks5(
DataStore.mixedPort,
DataStore.mixedInboundUser,
DataStore.mixedInboundPass
)
}
val response = client.newRequest().apply {
if (checkPreview) {
Expand Down Expand Up @@ -276,4 +280,4 @@ class AboutFragment : ToolbarFragment(R.layout.layout_about) {

}

}
}
12 changes: 10 additions & 2 deletions app/src/main/java/io/nekohasekai/sagernet/ui/AssetsActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,11 @@ class AssetsActivity : ThemedActivity() {
val client = Libcore.newHttpClient().apply {
modernTLS()
keepAlive()
trySocks5(DataStore.mixedPort)
trySocks5(
DataStore.mixedPort,
DataStore.mixedInboundUser,
DataStore.mixedInboundPass
)
}

try {
Expand Down Expand Up @@ -345,7 +349,11 @@ class AssetsActivity : ThemedActivity() {
val client = Libcore.newHttpClient().apply {
modernTLS()
keepAlive()
trySocks5(DataStore.mixedPort)
trySocks5(
DataStore.mixedPort,
DataStore.mixedInboundUser,
DataStore.mixedInboundPass
)
}
try {
val response = client.newRequest().apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,23 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
}

mixedPort.onPreferenceChangeListener = reloadListener
appendHttpProxy.onPreferenceChangeListener = reloadListener
appendHttpProxy.setOnPreferenceChangeListener { _, newValue ->
if (newValue as Boolean) {
MaterialAlertDialogBuilder(requireContext()).apply {
setTitle(R.string.append_http_proxy_security_title)
setMessage(R.string.append_http_proxy_security_message)
setNegativeButton(android.R.string.cancel, null)
setPositiveButton(R.string.enable_anyway) { _, _ ->
appendHttpProxy.isChecked = true
needReload()
}
}.show()
false
} else {
needReload()
true
}
}
strictRoute.onPreferenceChangeListener = reloadListener
showDirectSpeed.onPreferenceChangeListener = reloadListener
trafficSniffing.onPreferenceChangeListener = reloadListener
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values-fa/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@
<string name="connection_test_timeout_error">بدون پاسخ</string>
<string name="append_http_proxy">پراکسی HTTP را به VPN اضافه کنید</string>
<string name="append_http_proxy_sum">پروکسی HTTP مستقیماً از (مرورگر/برخی برنامه‌های پشتیبانی‌شده) بدون استفاده از دستگاه NIC مجازی (نسخه اندروید بالاتر از 10) استفاده می‌شود.</string>
<string name="append_http_proxy_security_title">اطلاعیه امنیتی</string>
<string name="append_http_proxy_security_message">پس از فعال‌سازی، برنامه‌های دیگر در این دستگاه می‌توانند مستقیماً از پورت پروکسی محلی استفاده کنند.\n\nتوصیه: تنها در صورتی که به تمام برنامه‌های نصب‌شده اعتماد دارید، این گزینه را فعال کنید.</string>
<string name="enable_anyway">همچنان فعال کن</string>
<string name="protocol_settings">تنظیمات پروتکل‌ها</string>
<string name="trojan_provider">تأمین‌کننده Trojan</string>
<string name="group_basic">ابتدایی</string>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values-ja/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@
<string name="connection_test_timeout_error">タイムアウト</string>
<string name="append_http_proxy">VPN に HTTP プロキシを追加</string>
<string name="append_http_proxy_sum">HTTP プロキシは仮想 NIC デバイスを経由せず、(ブラウザ/一部の対応アプリ) から直接使用されます (Android 10+)</string>
<string name="append_http_proxy_security_title">セキュリティに関する通知</string>
<string name="append_http_proxy_security_message">有効にすると、このデバイス上の他のアプリがローカルプロキシポートを直接使用できるようになります。\n\n推奨:インストールされているすべてのアプリを信頼している場合にのみ有効にしてください。</string>
<string name="enable_anyway">それでも有効にする</string>
<string name="strict_route">厳格なルーティング</string>
<string name="protocol_settings">プロトコル設定</string>
<string name="trojan_provider">Trojan プロバイダー</string>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values-ko/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@
<string name="connection_test_timeout_error">시간 초과</string>
<string name="append_http_proxy">VPN에 HTTP 프록시 추가</string>
<string name="append_http_proxy_sum">HTTP 프록시는 가상 NIC 장치를 거치지 않고 (브라우저/일부 지원 앱)에서 직접 사용됩니다 (Android 10+)</string>
<string name="append_http_proxy_security_title">보안 알림</string>
<string name="append_http_proxy_security_message">활성화하면 이 기기의 다른 앱이 로컬 프록시 포트를 직접 사용할 수 있습니다.\n\n권장 사항: 설치된 모든 앱을 신뢰하는 경우에만 활성화하세요.</string>
<string name="enable_anyway">그래도 활성화</string>
<string name="strict_route">엄격한 라우팅</string>
<string name="protocol_settings">프로토콜 설정</string>
<string name="trojan_provider">Trojan 공급자</string>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<string name="app_version">Версия</string>
<string name="append_http_proxy">Добавить HTTP-прокси к VPN</string>
<string name="append_http_proxy_sum">HTTP-прокси будет использоваться напрямую из (браузера / некоторых поддерживаемых приложений), без использования виртуального сетевого интерфейса (Android 10+)</string>
<string name="append_http_proxy_security_title">Уведомление о безопасности</string>
<string name="append_http_proxy_security_message">При включении другие приложения на этом устройстве смогут напрямую использовать локальный прокси-порт.\n\nРекомендация: Включайте эту функцию только если доверяете всем установленным приложениям.</string>
<string name="enable_anyway">Всё равно включить</string>
<string name="apply">Применить</string>
<string name="apps">Приложения</string>
<string name="apps_message">%d приложений</string>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@
<string name="tile_title">开关</string>
<string name="append_http_proxy">追加 HTTP 代理至 VPN</string>
<string name="append_http_proxy_sum">浏览器 / 一些支持的应用 将直接使用 HTTP 代理, 而不经过虚拟网卡设备 (Android 10+)</string>
<string name="append_http_proxy_security_title">安全提示</string>
<string name="append_http_proxy_security_message">开启后,本机其他应用可以直接使用本地代理端口。\n\n建议:仅在你信任所有已安装应用时开启。</string>
<string name="enable_anyway">仍然开启</string>
<string name="strict_route">严格路由</string>
<string name="connection_test_icmp_ping_unavailable">ICMPing 不可用</string>
<string name="protocol_settings">协议设置</string>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@
<string name="connection_test_timeout_error">逾時</string>
<string name="append_http_proxy">為 VPN 附加 HTTP 代理</string>
<string name="append_http_proxy_sum">HTTP 代理將直接被支援的瀏覽器/應用程式使用,而無需經過虛擬網路卡(Android 10+)</string>
<string name="append_http_proxy_security_title">安全提示</string>
<string name="append_http_proxy_security_message">開啟後,本機其他應用程式可以直接使用本機代理連接埠。\n\n建議:僅在你信任所有已安裝應用程式時開啟。</string>
<string name="enable_anyway">仍然開啟</string>
<string name="trojan_provider">Trojan 提供程式</string>
<string name="protocol_settings">協議設定</string>
<string name="group_basic">基本</string>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,9 @@
<string name="append_http_proxy">Append HTTP Proxy to VPN</string>
<string name="append_http_proxy_sum">HTTP proxy will be used directly from (browser/ some
supported apps), without going through the virtual NIC device (Android 10+)</string>
<string name="append_http_proxy_security_title">Security Notice</string>
<string name="append_http_proxy_security_message">When enabled, other apps on this device can directly use the local proxy port.\n\nRecommendation: Only enable this if you trust all installed apps.</string>
<string name="enable_anyway">Enable Anyway</string>
<string name="strict_route">Strict Route</string>
<string name="protocol_settings">Protocol Settings</string>
<string name="trojan_provider">Trojan Provider</string>
Expand Down
6 changes: 3 additions & 3 deletions libcore/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type HTTPClient interface {
ModernTLS()
PinnedTLS12()
PinnedSHA256(sumHex string)
TrySocks5(port int32)
TrySocks5(port int32, username string, password string)
TryH3Direct()
KeepAlive()
NewRequest() HTTPRequest
Expand Down Expand Up @@ -114,7 +114,7 @@ func (c *httpClient) PinnedSHA256(sumHex string) {
}
}

func (c *httpClient) TrySocks5(port int32) {
func (c *httpClient) TrySocks5(port int32, username string, password string) {
dialer := new(net.Dialer)
c.h1h2Transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
for {
Expand All @@ -125,7 +125,7 @@ func (c *httpClient) TrySocks5(port int32) {
}
break
}
_, err = socks.ClientHandshake5(socksConn, socks5.CommandConnect, metadata.ParseSocksaddr(addr), "", "")
_, err = socks.ClientHandshake5(socksConn, socks5.CommandConnect, metadata.ParseSocksaddr(addr), username, password)
if err != nil {
if c.tryH3Direct {
return nil, errFailConnectSocks5
Expand Down
Loading