diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt index 3047874e..a5d6dbdc 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt @@ -26,6 +26,7 @@ object AppConfig { const val PREF_LOCAL_DNS_PORT = "pref_local_dns_port" const val PREF_VPN_DNS = "pref_vpn_dns" const val PREF_VPN_BYPASS_LAN = "pref_vpn_bypass_lan" + const val PREF_VPN_INTERFACE_ADDRESS_CONFIG_INDEX = "pref_vpn_interface_address_config_index" const val PREF_ROUTING_DOMAIN_STRATEGY = "pref_routing_domain_strategy" const val PREF_ROUTING_RULESET = "pref_routing_ruleset" const val PREF_MUX_ENABLED = "pref_mux_enabled" diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/dto/VpnInterfaceAddressConfig.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/VpnInterfaceAddressConfig.kt new file mode 100644 index 00000000..6b7bc379 --- /dev/null +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/VpnInterfaceAddressConfig.kt @@ -0,0 +1,39 @@ +package com.v2ray.ang.dto + +/** + * VPN interface address configuration enum class + * Defines predefined IPv4 and IPv6 address pairs for VPN TUN interface configuration. + * Each option provides client and router addresses to establish point-to-point VPN tunnels. + */ +enum class VpnInterfaceAddressConfig( + val displayName: String, + val ipv4Client: String, + val ipv4Router: String, + val ipv6Client: String, + val ipv6Router: String +) { + OPTION_1("10.10.14.x", "10.10.14.1", "10.10.14.2", "fc00::10:10:14:1", "fc00::10:10:14:2"), + OPTION_2("10.1.0.x", "10.1.0.1", "10.1.0.2", "fc00::10:1:0:1", "fc00::10:1:0:2"), + OPTION_3("10.0.0.x", "10.0.0.1", "10.0.0.2", "fc00::10:0:0:1", "fc00::10:0:0:2"), + OPTION_4("172.31.0.x", "172.31.0.1", "172.31.0.2", "fc00::172:31:0:1", "fc00::172:31:0:2"), + OPTION_5("172.20.0.x", "172.20.0.1", "172.20.0.2", "fc00::172:20:0:1", "fc00::172:20:0:2"), + OPTION_6("172.16.0.x", "172.16.0.1", "172.16.0.2", "fc00::172:16:0:1", "fc00::172:16:0:2"), + OPTION_7("192.168.100.x", "192.168.100.1", "192.168.100.2", "fc00::192:168:100:1", "fc00::192:168:100:2"); + + companion object { + /** + * Retrieves the VPN interface address configuration based on the specified index. + * + * @param index The configuration index (0-based) corresponding to user selection + * @return The VpnInterfaceAddressConfig instance at the specified index, + * or OPTION_1 (default) if the index is out of bounds + */ + fun getConfigByIndex(index: Int): VpnInterfaceAddressConfig { + return if (index in values().indices) { + values()[index] + } else { + OPTION_1 // Default to the first configuration + } + } + } +} diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt index a488e593..b2e23f7f 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/handler/SettingsManager.kt @@ -16,6 +16,7 @@ import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.dto.RoutingType import com.v2ray.ang.dto.RulesetItem import com.v2ray.ang.dto.V2rayConfig +import com.v2ray.ang.dto.VpnInterfaceAddressConfig import com.v2ray.ang.handler.MmkvManager.decodeServerConfig import com.v2ray.ang.handler.MmkvManager.decodeServerList import com.v2ray.ang.util.JsonUtil @@ -356,4 +357,17 @@ object SettingsManager { "2" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) } } + + /** + * Retrieves the currently selected VPN interface address configuration. + * This method reads the user's preference for VPN interface addressing and returns + * the corresponding configuration containing IPv4 and IPv6 addresses. + * + * @return The selected VpnInterfaceAddressConfig instance, or the default configuration + * if no valid selection is found or if the stored index is invalid. + */ + fun getCurrentVpnInterfaceAddressConfig(): VpnInterfaceAddressConfig { + val selectedIndex = MmkvManager.decodeSettingsString(AppConfig.PREF_VPN_INTERFACE_ADDRESS_CONFIG_INDEX, "0")?.toInt() + return VpnInterfaceAddressConfig.getConfigByIndex(selectedIndex ?: 0) + } } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayVpnService.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayVpnService.kt index 6d30843c..d734c299 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayVpnService.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/service/V2RayVpnService.kt @@ -33,12 +33,7 @@ import java.lang.ref.SoftReference class V2RayVpnService : VpnService(), ServiceControl { companion object { private const val VPN_MTU = 1500 - private const val PRIVATE_VLAN4_CLIENT = "10.10.14.1" - private const val PRIVATE_VLAN4_ROUTER = "10.10.14.2" - private const val PRIVATE_VLAN6_CLIENT = "fc00::10:10:14:1" - private const val PRIVATE_VLAN6_ROUTER = "fc00::10:10:14:2" private const val TUN2SOCKS = "libtun2socks.so" - } private lateinit var mInterface: ParcelFileDescriptor @@ -160,10 +155,11 @@ class V2RayVpnService : VpnService(), ServiceControl { // If the old interface has exactly the same parameters, use it! // Configure a builder while parsing the parameters. val builder = Builder() + val vpnConfig = SettingsManager.getCurrentVpnInterfaceAddressConfig() //val enableLocalDns = defaultDPreference.getPrefBoolean(AppConfig.PREF_LOCAL_DNS_ENABLED, false) builder.setMtu(VPN_MTU) - builder.addAddress(PRIVATE_VLAN4_CLIENT, 30) + builder.addAddress(vpnConfig.ipv4Client, 30) //builder.addDnsServer(PRIVATE_VLAN4_ROUTER) val bypassLan = SettingsManager.routingRulesetsBypassLan() if (bypassLan) { @@ -176,7 +172,7 @@ class V2RayVpnService : VpnService(), ServiceControl { } if (MmkvManager.decodeSettingsBool(AppConfig.PREF_PREFER_IPV6) == true) { - builder.addAddress(PRIVATE_VLAN6_CLIENT, 126) + builder.addAddress(vpnConfig.ipv6Client, 126) if (bypassLan) { builder.addRoute("2000::", 3) //currently only 1/8 of total ipV6 is in use builder.addRoute("fc00::", 18) //Xray-core default FakeIPv6 Pool @@ -260,9 +256,10 @@ class V2RayVpnService : VpnService(), ServiceControl { private fun runTun2socks() { Log.i(AppConfig.TAG, "Start run $TUN2SOCKS") val socksPort = SettingsManager.getSocksPort() + val vpnConfig = SettingsManager.getCurrentVpnInterfaceAddressConfig() val cmd = arrayListOf( File(applicationContext.applicationInfo.nativeLibraryDir, TUN2SOCKS).absolutePath, - "--netif-ipaddr", PRIVATE_VLAN4_ROUTER, + "--netif-ipaddr", vpnConfig.ipv4Router, "--netif-netmask", "255.255.255.252", "--socks-server-addr", "$LOOPBACK:${socksPort}", "--tunmtu", VPN_MTU.toString(), @@ -273,7 +270,7 @@ class V2RayVpnService : VpnService(), ServiceControl { if (MmkvManager.decodeSettingsBool(AppConfig.PREF_PREFER_IPV6)) { cmd.add("--netif-ip6addr") - cmd.add(PRIVATE_VLAN6_ROUTER) + cmd.add(vpnConfig.ipv6Router) } if (MmkvManager.decodeSettingsBool(AppConfig.PREF_LOCAL_DNS_ENABLED)) { val localDnsPort = Utils.parseInt(MmkvManager.decodeSettingsString(AppConfig.PREF_LOCAL_DNS_PORT), AppConfig.PORT_LOCAL_DNS.toInt()) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SettingsActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SettingsActivity.kt index 4ec2294a..515bc65f 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SettingsActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/SettingsActivity.kt @@ -44,6 +44,7 @@ class SettingsActivity : BaseActivity() { private val localDnsPort by lazy { findPreference(AppConfig.PREF_LOCAL_DNS_PORT) } private val vpnDns by lazy { findPreference(AppConfig.PREF_VPN_DNS) } private val vpnBypassLan by lazy { findPreference(AppConfig.PREF_VPN_BYPASS_LAN) } + private val vpnInterfaceAddress by lazy { findPreference(AppConfig.PREF_VPN_INTERFACE_ADDRESS_CONFIG_INDEX) } private val mux by lazy { findPreference(AppConfig.PREF_MUX_ENABLED) } private val muxConcurrency by lazy { findPreference(AppConfig.PREF_MUX_CONCURRENCY) } @@ -249,6 +250,7 @@ class SettingsActivity : BaseActivity() { listOf( AppConfig.PREF_VPN_BYPASS_LAN, + AppConfig.PREF_VPN_INTERFACE_ADDRESS_CONFIG_INDEX, AppConfig.PREF_ROUTING_DOMAIN_STRATEGY, AppConfig.PREF_MUX_XUDP_QUIC, AppConfig.PREF_FRAGMENT_PACKETS, @@ -273,7 +275,7 @@ class SettingsActivity : BaseActivity() { localDnsPort?.isEnabled = vpn vpnDns?.isEnabled = vpn vpnBypassLan?.isEnabled = vpn - vpn + vpnInterfaceAddress?.isEnabled = vpn if (vpn) { updateLocalDns( MmkvManager.decodeSettingsBool( diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt index d78b1307..e12a56e5 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/viewmodel/SettingsViewModel.kt @@ -41,6 +41,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application AppConfig.PREF_MODE, AppConfig.PREF_VPN_DNS, AppConfig.PREF_VPN_BYPASS_LAN, + AppConfig.PREF_VPN_INTERFACE_ADDRESS_CONFIG_INDEX, AppConfig.PREF_REMOTE_DNS, AppConfig.PREF_DOMESTIC_DNS, AppConfig.PREF_DNS_HOSTS, diff --git a/V2rayNG/app/src/main/res/values-ar/strings.xml b/V2rayNG/app/src/main/res/values-ar/strings.xml index 49b724b1..b7843b69 100644 --- a/V2rayNG/app/src/main/res/values-ar/strings.xml +++ b/V2rayNG/app/src/main/res/values-ar/strings.xml @@ -181,6 +181,8 @@ VPN DNS (IPv4/v6 فقط) Does VPN bypass LAN + VPN Interface Address + DNS المحلي (اختياري) DNS diff --git a/V2rayNG/app/src/main/res/values-bn/strings.xml b/V2rayNG/app/src/main/res/values-bn/strings.xml index bd7c492f..888081e5 100644 --- a/V2rayNG/app/src/main/res/values-bn/strings.xml +++ b/V2rayNG/app/src/main/res/values-bn/strings.xml @@ -181,6 +181,8 @@ VPN DNS (শুধুমাত্র IPv4/v6) Does VPN bypass LAN + VPN Interface Address + ঘরোয়া DNS (ঐচ্ছিক) DNS diff --git a/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml b/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml index 41e81fbb..fe0738f1 100644 --- a/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml +++ b/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml @@ -181,6 +181,8 @@ VPN DNS (تینا IPv4/v6) VPN ز شبکه مهلی اگوڌرته؟ + VPN Interface Address + DNS منی (اختیاری) DNS diff --git a/V2rayNG/app/src/main/res/values-fa/strings.xml b/V2rayNG/app/src/main/res/values-fa/strings.xml index 16bbd4ff..d4e1ff35 100644 --- a/V2rayNG/app/src/main/res/values-fa/strings.xml +++ b/V2rayNG/app/src/main/res/values-fa/strings.xml @@ -179,6 +179,8 @@ VPN DNS (فقط IPv4/v6) آیا VPN از شبکه محلی عبور می کند؟ + VPN Interface Address + DNS داخلی (اختیاری) DNS diff --git a/V2rayNG/app/src/main/res/values-ru/strings.xml b/V2rayNG/app/src/main/res/values-ru/strings.xml index 9b5e39f6..3caf1bd9 100644 --- a/V2rayNG/app/src/main/res/values-ru/strings.xml +++ b/V2rayNG/app/src/main/res/values-ru/strings.xml @@ -180,6 +180,8 @@ VPN DNS (только IPv4/v6) VPN пропускает LAN + VPN частный IP + Внутренняя DNS (необязательно) DNS diff --git a/V2rayNG/app/src/main/res/values-vi/strings.xml b/V2rayNG/app/src/main/res/values-vi/strings.xml index 72cdee64..fbbc17da 100644 --- a/V2rayNG/app/src/main/res/values-vi/strings.xml +++ b/V2rayNG/app/src/main/res/values-vi/strings.xml @@ -181,6 +181,8 @@ VPN DNS (Chỉ IPv4 / IPv6) Does VPN bypass LAN + VPN Interface Address + DNS nội địa (Không bắt buộc) DNS diff --git a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml index a0aa7a5a..246d11c4 100644 --- a/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml +++ b/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml @@ -178,6 +178,8 @@ VPN DNS (仅支持 IPv4/v6) VPN 是否绕过局域网 + VPN 接口地址 + 境内 DNS (可选) DNS diff --git a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml index e655e18f..135992f4 100644 --- a/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml +++ b/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml @@ -180,6 +180,8 @@ VPN DNS (僅支援 IPv4/v6) VPN 是否繞過區域網 + VPN 介面位址 + DNS 境内 DNS (可选) DNS hosts (格式: 網域:位址,…) @@ -360,4 +362,5 @@ 不繞過 + diff --git a/V2rayNG/app/src/main/res/values/arrays.xml b/V2rayNG/app/src/main/res/values/arrays.xml index 1863ccdd..2f03ac86 100644 --- a/V2rayNG/app/src/main/res/values/arrays.xml +++ b/V2rayNG/app/src/main/res/values/arrays.xml @@ -182,4 +182,24 @@ 2 + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + + + + 10.10.14.x + 10.1.0.x + 10.0.0.x + 172.31.0.x + 172.20.0.x + 172.16.0.x + 192.168.100.x + + \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/values/strings.xml b/V2rayNG/app/src/main/res/values/strings.xml index 39defc59..90534f20 100644 --- a/V2rayNG/app/src/main/res/values/strings.xml +++ b/V2rayNG/app/src/main/res/values/strings.xml @@ -182,6 +182,8 @@ VPN DNS (only IPv4/v6) Does VPN bypass LAN + VPN Interface Address + Domestic DNS (Optional) DNS diff --git a/V2rayNG/app/src/main/res/xml/pref_settings.xml b/V2rayNG/app/src/main/res/xml/pref_settings.xml index cbfbb932..b9ed38f2 100644 --- a/V2rayNG/app/src/main/res/xml/pref_settings.xml +++ b/V2rayNG/app/src/main/res/xml/pref_settings.xml @@ -20,9 +20,9 @@ + android:key="pref_prefer_ipv6" + android:summary="@string/summary_pref_prefer_ipv6" + android:title="@string/title_pref_prefer_ipv6" /> + +