From 9b4cc201e77c43b6d4d6812c407c9fb584676dbd Mon Sep 17 00:00:00 2001 From: Tamim Hossain <132823494+CodeWithTamim@users.noreply.github.com> Date: Wed, 20 Nov 2024 07:15:11 +0600 Subject: [PATCH] Add preSharedKey support and fix parsing function #3512 (#3989) Add support for preSharedKey in WireGuard configurations and fix the parsing function to correctly handle all necessary fields. Previously, the application did not support the optional preSharedKey parameter in WireGuard config files, forcing users to rely on JSON custom configurations. This update introduces a dedicated field for preSharedKey in the UI, aligning with Xray Core's support and simplifying the setup process for users. Changes include: - Added `preSharedKey` field in the WireGuard UI configuration. - Updated `parseWireguardConfFile` function to correctly parse `PrivateKey`, `PublicKey`, and `preSharedKey`. - Ensured `preSharedKey` is optional and handled gracefully when absent. - Updated `toOutbound` method to include `preSharedKey` in the outbound configuration. - Set `remarks` to the current Unix time during parsing. Tested with the following configuration: ```[Interface] Address = 192.168.6.66/32 DNS = 1.1.1.1,8.8.8.8 PrivateKey = eD/6cpJQaEeDH05AMeFyN3KSLLX+7YFR+MYRdgPDQ3Y= [Peer] publickey=/HS7r3waPuU7tTBLd2FlBhC+VROpJ5bwh5XXxuOoKFs= AllowedIPs = 0.0.0.0/0, ::/0 Endpoint = sg3.vpnjantit.com:1024 ``` Resolves #3512 --- .../java/com/v2ray/ang/dto/ProfileItem.kt | 1 + .../java/com/v2ray/ang/dto/V2rayConfig.kt | 1 + .../java/com/v2ray/ang/fmt/WireguardFmt.kt | 87 ++++++++++++------- .../java/com/v2ray/ang/ui/ServerActivity.kt | 40 ++++----- .../res/layout/activity_server_wireguard.xml | 19 ++++ V2rayNG/app/src/main/res/values/strings.xml | 1 + 6 files changed, 97 insertions(+), 52 deletions(-) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ProfileItem.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ProfileItem.kt index 2112d306a..883a3788e 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ProfileItem.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/ProfileItem.kt @@ -44,6 +44,7 @@ data class ProfileItem( var spiderX: String? = null, var secretKey: String? = null, + var preSharedKey: String? = null, var localAddress: String? = null, var reserved: String? = null, var mtu: Int? = null, diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/dto/V2rayConfig.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/V2rayConfig.kt index 2c3b95c6c..03987679c 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/dto/V2rayConfig.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/dto/V2rayConfig.kt @@ -195,6 +195,7 @@ data class V2rayConfig( data class WireGuardBean( var publicKey: String = "", + var preSharedKey: String = "", var endpoint: String = "" ) } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/WireguardFmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/WireguardFmt.kt index 57f97a90b..112318874 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/WireguardFmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/WireguardFmt.kt @@ -22,9 +22,10 @@ object WireguardFmt : FmtBase() { config.server = uri.idnHost config.serverPort = uri.port.toString() - config.secretKey = uri.userInfo + config.secretKey = uri.userInfo.orEmpty() config.localAddress = (queryParam["address"] ?: WIREGUARD_LOCAL_ADDRESS_V4) config.publicKey = queryParam["publickey"].orEmpty() + config.preSharedKey = queryParam["presharedkey"].orEmpty() config.mtu = Utils.parseInt(queryParam["mtu"] ?: AppConfig.WIREGUARD_LOCAL_MTU) config.reserved = (queryParam["reserved"] ?: "0,0,0") @@ -33,33 +34,75 @@ object WireguardFmt : FmtBase() { fun parseWireguardConfFile(str: String): ProfileItem? { val config = ProfileItem.create(EConfigType.WIREGUARD) - val queryParam: MutableMap = mutableMapOf() + + val interfaceParams: MutableMap = mutableMapOf() + val peerParams: MutableMap = mutableMapOf() var currentSection: String? = null str.lines().forEach { line -> val trimmedLine = line.trim() + if (trimmedLine.isEmpty() || trimmedLine.startsWith("#")) { + return@forEach + } + when { trimmedLine.startsWith("[Interface]", ignoreCase = true) -> currentSection = "Interface" trimmedLine.startsWith("[Peer]", ignoreCase = true) -> currentSection = "Peer" - trimmedLine.isBlank() || trimmedLine.startsWith("#") -> Unit // Skip blank lines or comments - currentSection != null -> { - val (key, value) = trimmedLine.split("=").map { it.trim() } - queryParam[key.lowercase()] = value // Store the key in lowercase for case-insensitivity + else -> { + if (currentSection != null) { + val parts = trimmedLine.split("=", limit = 2).map { it.trim() } + if (parts.size == 2) { + val key = parts[0].lowercase() + val value = parts[1] + when (currentSection) { + "Interface" -> interfaceParams[key] = value + "Peer" -> peerParams[key] = value + } + } + } } } } - config.secretKey = queryParam["privatekey"].orEmpty() - config.localAddress = (queryParam["address"] ?: WIREGUARD_LOCAL_ADDRESS_V4) - config.publicKey = queryParam["publickey"].orEmpty() - config.mtu = Utils.parseInt(queryParam["mtu"] ?: AppConfig.WIREGUARD_LOCAL_MTU) - config.reserved = (queryParam["reserved"] ?: "0,0,0") + config.secretKey = interfaceParams["privatekey"].orEmpty() + config.remarks = System.currentTimeMillis().toString() + config.localAddress = interfaceParams["address"] ?: WIREGUARD_LOCAL_ADDRESS_V4 + config.mtu = Utils.parseInt(interfaceParams["mtu"] ?: AppConfig.WIREGUARD_LOCAL_MTU) + config.publicKey = peerParams["publickey"].orEmpty() + config.preSharedKey = peerParams["presharedkey"].orEmpty() + val endpoint = peerParams["endpoint"].orEmpty() + val endpointParts = endpoint.split(":", limit = 2) + if (endpointParts.size == 2) { + config.server = endpointParts[0] + config.serverPort = endpointParts[1] + } else { + config.server = endpoint + config.serverPort = "" + } + config.reserved = peerParams["reserved"] ?: "0,0,0" return config } + fun toOutbound(profileItem: ProfileItem): OutboundBean? { + val outboundBean = OutboundBean.create(EConfigType.WIREGUARD) + + outboundBean?.settings?.let { wireguard -> + wireguard.secretKey = profileItem.secretKey + wireguard.address = (profileItem.localAddress ?: WIREGUARD_LOCAL_ADDRESS_V4).split(",") + wireguard.peers?.firstOrNull()?.let { peer -> + peer.publicKey = profileItem.publicKey.orEmpty() + peer.preSharedKey = profileItem.preSharedKey.orEmpty() + peer.endpoint = Utils.getIpv6Address(profileItem.server) + ":${profileItem.serverPort}" + } + wireguard.mtu = profileItem.mtu + wireguard.reserved = profileItem.reserved?.split(",")?.map { it.toInt() } + } + + return outboundBean + } fun toUri(config: ProfileItem): String { val dicQuery = HashMap() @@ -72,24 +115,10 @@ object WireguardFmt : FmtBase() { if (config.mtu != null) { dicQuery["mtu"] = config.mtu.toString() } - - return toUri(config, config.secretKey, dicQuery) - } - - fun toOutbound(profileItem: ProfileItem): OutboundBean? { - val outboundBean = OutboundBean.create(EConfigType.WIREGUARD) - - outboundBean?.settings?.let { wireguard -> - wireguard.secretKey = profileItem.secretKey - wireguard.address = (profileItem.localAddress ?: WIREGUARD_LOCAL_ADDRESS_V4).split(",") - wireguard.peers?.first()?.publicKey = profileItem.publicKey.orEmpty() - wireguard.peers?.first()?.endpoint = Utils.getIpv6Address(profileItem.server) + ":${profileItem.serverPort}" - wireguard.mtu = profileItem.mtu?.toInt() - wireguard.reserved = profileItem.reserved?.split(",")?.map { it.toInt() } + if (config.preSharedKey != null) { + dicQuery["presharedkey"] = Utils.removeWhiteSpace(config.preSharedKey).orEmpty() } - return outboundBean + return toUri(config, config.secretKey, dicQuery) } - - -} \ No newline at end of file +} diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt index f609a49ba..9beb39bf8 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt @@ -113,6 +113,7 @@ class ServerActivity : BaseActivity() { private val sp_stream_alpn: Spinner? by lazy { findViewById(R.id.sp_stream_alpn) } //uTLS private val container_alpn: LinearLayout? by lazy { findViewById(R.id.lay_stream_alpn) } private val et_public_key: EditText? by lazy { findViewById(R.id.et_public_key) } + private val et_preshared_key: EditText? by lazy { findViewById(R.id.et_preshared_key) } private val container_public_key: LinearLayout? by lazy { findViewById(R.id.lay_public_key) } private val et_short_id: EditText? by lazy { findViewById(R.id.et_short_id) } private val container_short_id: LinearLayout? by lazy { findViewById(R.id.lay_short_id) } @@ -150,7 +151,7 @@ class ServerActivity : BaseActivity() { parent: AdapterView<*>?, view: View?, position: Int, - id: Long + id: Long, ) { val types = transportTypes(networks[position]) sp_header_type?.isEnabled = types.size > 1 @@ -243,7 +244,7 @@ class ServerActivity : BaseActivity() { parent: AdapterView<*>?, view: View?, position: Int, - id: Long + id: Long, ) { val isBlank = streamSecuritys[position].isBlank() val isTLS = streamSecuritys[position] == TLS @@ -321,29 +322,21 @@ class ServerActivity : BaseActivity() { } else if (config.configType == EConfigType.WIREGUARD) { et_id.text = Utils.getEditable(config.secretKey.orEmpty()) et_public_key?.text = Utils.getEditable(config.publicKey.orEmpty()) - if (config.reserved == null) { - et_reserved1?.text = Utils.getEditable("0,0,0") - } else { - et_reserved1?.text = Utils.getEditable(config.reserved?.toString()) - } - if (config.localAddress == null) { - et_local_address?.text = Utils.getEditable("${WIREGUARD_LOCAL_ADDRESS_V4},${WIREGUARD_LOCAL_ADDRESS_V6}") - } else { - et_local_address?.text = Utils.getEditable(config.localAddress) - } - if (config.mtu == null) { - et_local_mtu?.text = Utils.getEditable(WIREGUARD_LOCAL_MTU) - } else { - et_local_mtu?.text = Utils.getEditable(config.mtu.toString()) - } + et_preshared_key?.visibility = View.VISIBLE + et_preshared_key?.text = Utils.getEditable(config.preSharedKey.orEmpty()) + et_reserved1?.text = Utils.getEditable(config.reserved ?: "0,0,0") + et_local_address?.text = Utils.getEditable( + config.localAddress ?: "$WIREGUARD_LOCAL_ADDRESS_V4,$WIREGUARD_LOCAL_ADDRESS_V6" + ) + et_local_mtu?.text = Utils.getEditable(config.mtu?.toString() ?: WIREGUARD_LOCAL_MTU) } else if (config.configType == EConfigType.HYSTERIA2) { et_obfs_password?.text = Utils.getEditable(config.obfsPassword) et_port_hop?.text = Utils.getEditable(config.portHopping) et_port_hop_interval?.text = Utils.getEditable(config.portHoppingInterval) et_pinsha256?.text = Utils.getEditable(config.pinSHA256) } - - val securityEncryptions = if (config.configType == EConfigType.SHADOWSOCKS) shadowsocksSecuritys else securitys + val securityEncryptions = + if (config.configType == EConfigType.SHADOWSOCKS) shadowsocksSecuritys else securitys val security = Utils.arrayFind(securityEncryptions, config.method.orEmpty()) if (security >= 0) { sp_security?.setSelection(security) @@ -374,7 +367,7 @@ class ServerActivity : BaseActivity() { container_public_key?.visibility = View.GONE container_short_id?.visibility = View.GONE container_spider_x?.visibility = View.GONE - } else if (config.security == REALITY) { // reality settings + } else if (config.security == REALITY) { container_public_key?.visibility = View.VISIBLE et_public_key?.text = Utils.getEditable(config.publicKey.orEmpty()) container_short_id?.visibility = View.VISIBLE @@ -394,7 +387,6 @@ class ServerActivity : BaseActivity() { container_short_id?.visibility = View.GONE container_spider_x?.visibility = View.GONE } - val network = Utils.arrayFind(networks, config.network.orEmpty()) if (network >= 0) { sp_network?.setSelection(network) @@ -448,7 +440,8 @@ class ServerActivity : BaseActivity() { return false } } - val config = MmkvManager.decodeServerConfig(editGuid) ?: ProfileItem.create(createConfigType) + val config = + MmkvManager.decodeServerConfig(editGuid) ?: ProfileItem.create(createConfigType) if (config.configType != EConfigType.SOCKS && config.configType != EConfigType.HTTP && TextUtils.isEmpty(et_id.text.toString()) @@ -511,6 +504,7 @@ class ServerActivity : BaseActivity() { } else if (config.configType == EConfigType.WIREGUARD) { config.secretKey = et_id.text.toString().trim() config.publicKey = et_public_key?.text.toString().trim() + config.preSharedKey = et_preshared_key?.text.toString().trim() config.reserved = et_reserved1?.text.toString().trim() config.localAddress = et_local_address?.text.toString().trim() config.mtu = Utils.parseInt(et_local_mtu?.text.toString()) @@ -555,7 +549,7 @@ class ServerActivity : BaseActivity() { val allowInsecure = if (allowInsecureField == null || allowinsecures[allowInsecureField].isBlank()) { - MmkvManager.decodeSettingsBool(PREF_ALLOW_INSECURE) == true + MmkvManager.decodeSettingsBool(PREF_ALLOW_INSECURE) } else { allowinsecures[allowInsecureField].toBoolean() } diff --git a/V2rayNG/app/src/main/res/layout/activity_server_wireguard.xml b/V2rayNG/app/src/main/res/layout/activity_server_wireguard.xml index 7901ceea8..93bc43f75 100644 --- a/V2rayNG/app/src/main/res/layout/activity_server_wireguard.xml +++ b/V2rayNG/app/src/main/res/layout/activity_server_wireguard.xml @@ -51,6 +51,25 @@ android:layout_height="@dimen/edit_height" android:inputType="text" /> + + + + + + + + encryption flow PublicKey + PreSharedKey(optional) ShortId SpiderX SecretKey