Compare commits

...

2 Commits

Author SHA1 Message Date
zaneschepke 9124fcc133 fix: dns bracketing for raw ipv6 dns upstream
#1203
2026-06-01 17:53:41 -04:00
zaneschepke fed9537f5c fix: parser key rotation, name comment, export name clarity
closes #1243
closes #1217
2026-06-01 15:37:17 -04:00
5 changed files with 55 additions and 7 deletions
@@ -85,7 +85,10 @@ data class TunnelConfig(
fun tunnelConfFromQuick(amQuick: String, name: String? = null): TunnelConfig {
val config = Config.parseQuickString(amQuick)
return TunnelConfig(name = name ?: config.defaultName(), quickConfig = amQuick)
return TunnelConfig(
name = config.name ?: name ?: config.defaultName(),
quickConfig = amQuick,
)
}
fun generateDefaultGlobalConfig(): TunnelConfig {
@@ -34,7 +34,6 @@ import io.ktor.client.request.prepareGet
import io.ktor.client.statement.bodyAsText
import java.io.File
import java.io.IOException
import java.time.Instant
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@@ -335,7 +334,9 @@ class SharedAppViewModel(
fun exportSelectedTunnels(uri: Uri?) = intent {
val selectedTunnels = tunnelsUiState.value.selectedTunnels
val files = createConfFiles(selectedTunnels)
val shareFileName = "wgtunnel-export_${Instant.now().epochSecond}.zip"
val shareFileName = createExportFileName(selectedTunnels.size)
val onFailure = { action: Throwable ->
intent {
postSideEffect(
@@ -349,6 +350,7 @@ class SharedAppViewModel(
}
Unit
}
fileUtils
.createNewShareFile(shareFileName)
.onSuccess {
@@ -366,6 +368,17 @@ class SharedAppViewModel(
.onFailure(onFailure)
}
private fun createExportFileName(tunnelCount: Int): String {
val timestamp =
java.time.LocalDateTime.now()
.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm"))
return when (tunnelCount) {
1 -> "WGTunnel_Export_$timestamp.zip"
else -> "WGTunnel_Export_${timestamp}_${tunnelCount}_Tunnels.zip"
}
}
fun setScreenRecordingSecurity(to: Boolean) = intent {
settingsRepository.updateScreenRecordingSecurity(to)
}
+1
View File
@@ -26,6 +26,7 @@ fun allowedLicenseUrls(): List<String> {
"https://github.com/RikkaApps/Shizuku-API/blob/master/LICENSE",
"https://github.com/rafi0101/Android-Room-Database-Backup/blob/master/LICENSE",
"https://opensource.org/license/mit",
"https://www.bouncycastle.org/licence.html",
)
}
+1 -3
View File
@@ -1,5 +1,4 @@
[versions]
app="5.0.0"
accompanist = "0.37.3"
activityCompose = "1.13.0"
androidx-junit = "1.3.0"
@@ -44,7 +43,7 @@ storage = "1.6.0"
ktfmt = "0.26.0"
licensee = "1.14.1"
lifecycleViewmodelNavigation3 = "2.10.0"
parser = "1.0.7"
parser = "1.1.0"
relinker = "1.4.5"
libsu = "6.0.0"
jetbrainsKotlinJvm = "2.3.21"
@@ -200,7 +199,6 @@ libsu = { module = "com.github.topjohnwu.libsu:core", version.ref = "libsu" }
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
androidLibrary = { id = "com.android.library", version.ref = "androidGradlePlugin" }
+34 -1
View File
@@ -153,6 +153,7 @@ func parseUpstream(upstreamURL string) (network, address string, err error) {
shared.LogDebug("DNS", "Parsing upstream URL: %s", upstreamURL)
u := upstreamURL
if !strings.Contains(u, "://") {
u = normalizeHostPort(u)
u = "udp://" + u
}
parsed, err := url.Parse(u)
@@ -229,6 +230,8 @@ func resolveServerAddrs(
defaultPort string,
underlying string,
) ([]string, string, error) {
address = normalizeHostPort(address)
host, port, err := net.SplitHostPort(address)
if err != nil {
host = address
@@ -379,7 +382,8 @@ func buildTransport(
return nil, fmt.Errorf("no addresses resolved for DoH server")
}
// Custom dialer that tries servers in order (IPv4 → IPv6)
// Custom dialer that tries servers in order
// tries ipv4 first and then ipv6
dialer := GetDialer(bypass)
transport := &http.Transport{
DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {
@@ -447,6 +451,35 @@ func buildTransport(
}
}
// normalizeHostPort makes sure raw IPv6 is correctly bracketed.
func normalizeHostPort(s string) string {
s = strings.TrimSpace(s)
if s == "" || strings.Contains(s, "://") || strings.Contains(s, "]") {
return s
}
if strings.Count(s, ":") < 2 {
return s // definitely not IPv6
}
lastColon := strings.LastIndexByte(s, ':')
potentialHost := s[:lastColon]
potentialPort := s[lastColon+1:]
if ip := net.ParseIP(potentialHost); ip != nil && ip.To4() == nil {
if potentialPort != "" {
return "[" + potentialHost + "]:" + potentialPort
}
return "[" + potentialHost + "]"
}
// fallback with no port
if ip := net.ParseIP(s); ip != nil && ip.To4() == nil {
return "[" + s + "]"
}
return s
}
func GetDialer(bypass bool) *net.Dialer {
if !bypass {
return &net.Dialer{LocalAddr: nil}