feat: config screen peer action to exclude private ips

closes #402
This commit is contained in:
Zane Schepke 2024-12-31 22:31:31 -05:00
parent 4196a543b2
commit ab858ab59e
11 changed files with 277 additions and 155 deletions

View File

@ -115,7 +115,9 @@ fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel(), appViewModel:
val onAutoTunnelClick = {
if (!uiState.generalState.isLocationDisclosureShown) {
navController.navigate(Route.LocationDisclosure)
} else navController.navigate(Route.AutoTunnel)
} else {
navController.navigate(Route.AutoTunnel)
}
}
SurfaceSelectionGroupButton(
listOf(

View File

@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
@ -21,7 +22,6 @@ import androidx.compose.material.icons.outlined.Security
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material.icons.outlined.SettingsEthernet
import androidx.compose.material.icons.outlined.SignalCellular4Bar
import androidx.compose.material.icons.outlined.VpnKeyOff
import androidx.compose.material.icons.outlined.Wifi
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
@ -135,6 +135,7 @@ fun AutoTunnelScreen(uiState: AppUiState, viewModel: AutoTunnelViewModel = hiltV
.fillMaxSize()
.padding(padding)
.verticalScroll(rememberScrollState())
.imePadding()
.padding(top = 24.dp.scaledHeight())
.padding(horizontal = 24.dp.scaledWidth()),
) {
@ -376,7 +377,7 @@ fun AutoTunnelScreen(uiState: AppUiState, viewModel: AutoTunnelViewModel = hiltV
ForwardButton { navController.navigate(Route.AutoTunnelAdvanced) }
},
),
)
),
)
}
}

View File

@ -39,7 +39,6 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
@Composable
fun AdvancedScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
var isDropDownExpanded by remember {
mutableStateOf(false)
}
@ -47,9 +46,9 @@ fun AdvancedScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
var selected by remember { mutableIntStateOf(appUiState.settings.debounceDelaySeconds) }
LaunchedEffect(selected) {
if(selected == appUiState.settings.debounceDelaySeconds) return@LaunchedEffect
if (selected == appUiState.settings.debounceDelaySeconds) return@LaunchedEffect
appViewModel.saveSettings(appUiState.settings.copy(debounceDelaySeconds = selected))
if(appUiState.settings.isAutoTunnelEnabled) {
if (appUiState.settings.isAutoTunnelEnabled) {
appViewModel.bounceAutoTunnel()
}
}
@ -86,32 +85,36 @@ fun AdvancedScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
trailing = {
Row(
horizontalArrangement = Arrangement.spacedBy(5.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically) {
verticalAlignment = Alignment.CenterVertically,
) {
Text(text = selected.toString(), style = MaterialTheme.typography.bodyMedium)
val icon = Icons.Default.ArrowDropDown
Icon(icon, icon.name)
}
DropdownMenu(
modifier = Modifier.height(140.dp.scaledHeight()),
modifier = Modifier.height(250.dp.scaledHeight()),
scrollState = rememberScrollState(),
containerColor = MaterialTheme.colorScheme.surface,
expanded = isDropDownExpanded,
onDismissRequest = {
isDropDownExpanded = false
}) {
},
) {
(0..10).forEachIndexed { index, num ->
DropdownMenuItem(text = {
Text(text = num.toString())
},
DropdownMenuItem(
text = {
Text(text = num.toString())
},
onClick = {
isDropDownExpanded = false
selected = num
})
},
)
}
}
},
)
)
),
),
)
}
}

View File

@ -0,0 +1,7 @@
package com.zaneschepke.wireguardautotunnel.ui.screens.settings.autotunnel.advanced
enum class InterfaceActions {
TOGGLE_AMNEZIA_VALUES,
SET_AMNEZIA_COMPATIBILITY,
TOGGLE_SHOW_SCRIPTS,
}

View File

@ -0,0 +1,5 @@
package com.zaneschepke.wireguardautotunnel.ui.screens.settings.autotunnel.advanced
enum class PeerActions {
EXCLUDE_LAN,
}

View File

@ -3,12 +3,12 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.CallSplit
import androidx.compose.material.icons.outlined.Adjust
import androidx.compose.material.icons.outlined.Bolt
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Star
@ -32,28 +32,17 @@ import com.zaneschepke.wireguardautotunnel.ui.Route
import com.zaneschepke.wireguardautotunnel.ui.common.button.ScaledSwitch
import com.zaneschepke.wireguardautotunnel.ui.common.button.surface.SelectionItem
import com.zaneschepke.wireguardautotunnel.ui.common.button.surface.SurfaceSelectionGroupButton
import com.zaneschepke.wireguardautotunnel.ui.common.label.GroupLabel
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.TopNavBar
import com.zaneschepke.wireguardautotunnel.ui.screens.settings.components.ForwardButton
import com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.model.InterfaceProxy
import com.zaneschepke.wireguardautotunnel.util.extensions.isWgCompatibilityMode
import com.zaneschepke.wireguardautotunnel.util.extensions.resetAmneziaProperties
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
import com.zaneschepke.wireguardautotunnel.util.extensions.toAmneziaCompatibilityConfig
@Composable
fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId: Int) {
val navController = LocalNavController.current
val config = appUiState.tunnels.first { it.id == tunnelId }
// TODO optimize
val amConfig = config.toAmConfig()
val isAmneziaCompatibilityEnabled = amConfig.`interface`.isWgCompatibilityMode()
var currentText by remember { mutableStateOf("") }
LaunchedEffect(config.tunnelNetworks) {
@ -71,6 +60,7 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId:
Modifier
.fillMaxSize()
.padding(it)
.imePadding()
.verticalScroll(rememberScrollState())
.padding(top = 24.dp.scaledHeight())
.padding(horizontal = 24.dp.scaledWidth()),
@ -152,38 +142,6 @@ fun OptionsScreen(appViewModel: AppViewModel, appUiState: AppUiState, tunnelId:
),
),
)
val amneziaClick = {
val proxy = InterfaceProxy.from(amConfig.`interface`)
val `interface` = if (!isAmneziaCompatibilityEnabled) proxy.toAmneziaCompatibilityConfig() else proxy.resetAmneziaProperties()
appViewModel.updateExistingTunnelConfig(config, `interface` = `interface`)
}
GroupLabel(stringResource(R.string.quick_actions))
SurfaceSelectionGroupButton(
listOf(
SelectionItem(
Icons.Outlined.Adjust,
title = {
Text(
stringResource(R.string.enable_amnezia),
style = MaterialTheme.typography.bodyMedium.copy(MaterialTheme.colorScheme.onSurface),
)
},
description = {
Text(
stringResource(R.string.wg_compat_mode),
style = MaterialTheme.typography.bodySmall.copy(MaterialTheme.colorScheme.outline),
)
},
trailing = {
ScaledSwitch(
isAmneziaCompatibilityEnabled,
onClick = { amneziaClick() },
)
},
onClick = { amneziaClick() },
),
),
)
}
}
}

View File

@ -1,5 +1,6 @@
package com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.layout.Arrangement
@ -8,7 +9,9 @@ import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
@ -19,7 +22,10 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Save
import androidx.compose.material.icons.rounded.ContentCopy
import androidx.compose.material.icons.rounded.Delete
import androidx.compose.material.icons.rounded.MoreVert
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@ -30,15 +36,14 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.runtime.toMutableStateList
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.platform.ClipboardManager
@ -56,18 +61,19 @@ import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.ui.AppUiState
import com.zaneschepke.wireguardautotunnel.ui.AppViewModel
import com.zaneschepke.wireguardautotunnel.ui.common.config.ConfigurationTextBox
import com.zaneschepke.wireguardautotunnel.ui.common.config.ConfigurationToggle
import com.zaneschepke.wireguardautotunnel.ui.common.label.GroupLabel
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.TopNavBar
import com.zaneschepke.wireguardautotunnel.ui.common.prompt.AuthorizationPrompt
import com.zaneschepke.wireguardautotunnel.ui.common.snackbar.SnackbarController
import com.zaneschepke.wireguardautotunnel.ui.screens.settings.autotunnel.advanced.InterfaceActions
import com.zaneschepke.wireguardautotunnel.ui.screens.settings.autotunnel.advanced.PeerActions
import com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.model.InterfaceProxy
import com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.model.PeerProxy
import com.zaneschepke.wireguardautotunnel.ui.theme.iconSize
import com.zaneschepke.wireguardautotunnel.util.Constants
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
import kotlinx.coroutines.launch
import org.amnezia.awg.crypto.KeyPair
@Composable
@ -77,21 +83,16 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
val clipboardManager: ClipboardManager = LocalClipboardManager.current
val keyboardController = LocalSoftwareKeyboardController.current
val navController = LocalNavController.current
val scope = rememberCoroutineScope()
var isInterfaceDropDownExpanded by remember {
mutableStateOf(false)
}
val popBackStack by appViewModel.popBackStack.collectAsStateWithLifecycle(false)
val tunnelConfig by remember {
derivedStateOf {
appUiState.tunnels.firstOrNull { it.id == tunnelId }
}
}
val tunnelConfig = appUiState.tunnels.firstOrNull { it.id == tunnelId }
val configPair by remember {
derivedStateOf {
Pair(tunnelConfig?.name ?: "", tunnelConfig?.toAmConfig())
}
}
val configPair = Pair(tunnelConfig?.name ?: "", tunnelConfig?.toAmConfig())
var tunnelName by remember {
mutableStateOf(configPair.first)
@ -173,6 +174,7 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
Modifier
.fillMaxSize()
.padding(padding)
.imePadding()
.verticalScroll(rememberScrollState())
.padding(top = 24.dp.scaledHeight())
.padding(horizontal = 24.dp.scaledWidth()),
@ -188,35 +190,103 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
.padding(16.dp.scaledWidth())
.focusGroup(),
) {
GroupLabel(
stringResource(R.string.interface_),
)
ConfigurationToggle(
stringResource(id = R.string.show_amnezia_properties),
checked = showAmneziaValues,
onCheckChanged = {
if (appUiState.settings.isKernelEnabled) {
snackbar.showMessage(context.getString(R.string.amnezia_kernel_message))
} else {
showAmneziaValues = it
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier =
Modifier.fillMaxWidth(),
) {
GroupLabel(
stringResource(R.string.interface_),
)
Column {
IconButton(
modifier = Modifier.size(iconSize),
onClick = {
isInterfaceDropDownExpanded = true
},
) {
val icon = Icons.Rounded.MoreVert
Icon(icon, icon.name)
}
},
)
ConfigurationToggle(
stringResource(id = R.string.show_scripts),
checked = showScripts,
onCheckChanged = { checked ->
if (appUiState.settings.isKernelEnabled) {
showScripts = checked
} else {
scope.launch {
appViewModel.requestRoot().onSuccess {
showScripts = checked
}
DropdownMenu(
containerColor = MaterialTheme.colorScheme.surface,
expanded = isInterfaceDropDownExpanded,
modifier = Modifier.shadow(12.dp).background(MaterialTheme.colorScheme.surface),
onDismissRequest = {
isInterfaceDropDownExpanded = false
},
) {
val isAmneziaCompatibilitySet = interfaceState.isAmneziaCompatibilityModeSet()
InterfaceActions.entries.forEach { action ->
DropdownMenuItem(
text = {
Text(
text = when (action) {
InterfaceActions.TOGGLE_SHOW_SCRIPTS -> if (showScripts) {
stringResource(R.string.hide_scripts)
} else {
stringResource(R.string.show_scripts)
}
InterfaceActions.TOGGLE_AMNEZIA_VALUES -> if (showAmneziaValues) {
stringResource(R.string.hide_amnezia_properties)
} else {
stringResource(R.string.show_amnezia_properties)
}
InterfaceActions.SET_AMNEZIA_COMPATIBILITY -> if (isAmneziaCompatibilitySet) {
stringResource(R.string.remove_amnezia_compatibility)
} else {
stringResource(R.string.enable_amnezia_compatibility)
}
},
)
},
onClick = {
isInterfaceDropDownExpanded = false
when (action) {
InterfaceActions.TOGGLE_AMNEZIA_VALUES -> showAmneziaValues = !showAmneziaValues
InterfaceActions.TOGGLE_SHOW_SCRIPTS -> showScripts = !showScripts
InterfaceActions.SET_AMNEZIA_COMPATIBILITY -> if (isAmneziaCompatibilitySet) {
showAmneziaValues = false
interfaceState = interfaceState.resetAmneziaProperties()
} else {
showAmneziaValues = true
interfaceState = interfaceState.toAmneziaCompatibilityConfig()
}
}
},
)
}
}
},
)
}
}
// ConfigurationToggle(
// stringResource(id = R.string.show_amnezia_properties),
// checked = showAmneziaValues,
// onCheckChanged = {
// if (appUiState.settings.isKernelEnabled) {
// snackbar.showMessage(context.getString(R.string.amnezia_kernel_message))
// } else {
// showAmneziaValues = it
// }
// },
// )
// ConfigurationToggle(
// stringResource(id = R.string.show_scripts),
// checked = showScripts,
// onCheckChanged = { checked ->
// if (appUiState.settings.isKernelEnabled) {
// showScripts = checked
// } else {
// scope.launch {
// appViewModel.requestRoot().onSuccess {
// showScripts = checked
// }
// }
// }
// },
// )
ConfigurationTextBox(
value = tunnelName,
onValueChange = { tunnelName = it },
@ -246,7 +316,7 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
trailingIcon = {
IconButton(
enabled = privateKeyEnabled,
modifier = Modifier.focusRequester(FocusRequester.Default),
modifier = Modifier.focusRequester(FocusRequester.Default).size(iconSize),
onClick = {
val keypair = KeyPair()
interfaceState = interfaceState.copy(
@ -287,7 +357,7 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
},
trailingIcon = {
IconButton(
modifier = Modifier.focusRequester(FocusRequester.Default),
modifier = Modifier.focusRequester(FocusRequester.Default).size(iconSize),
onClick = {
clipboardManager.setText(
AnnotatedString(interfaceState.publicKey),
@ -540,13 +610,17 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
}
}
peersState.forEachIndexed { index, peer ->
var isPeerDropDownExpanded by remember {
mutableStateOf(false)
}
val isLanExcluded = peer.isLanExcluded()
Surface(
shape = RoundedCornerShape(12.dp),
color = MaterialTheme.colorScheme.surface,
) {
Column(
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.Top),
verticalArrangement = Arrangement.spacedBy(10.dp, Alignment.Top),
modifier = Modifier
.padding(16.dp.scaledWidth())
.focusGroup(),
@ -560,11 +634,65 @@ fun ConfigScreen(appUiState: AppUiState, appViewModel: AppViewModel, tunnelId: I
GroupLabel(
stringResource(R.string.peer),
)
IconButton(onClick = {
peersState.removeAt(index)
}) {
val icon = Icons.Rounded.Delete
Icon(icon, icon.name)
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.End),
verticalAlignment = Alignment.CenterVertically,
) {
IconButton(
modifier = Modifier.size(iconSize),
onClick = {
// TODO make a dialog to confirm this
peersState.removeAt(index)
},
) {
val icon = Icons.Rounded.Delete
Icon(icon, icon.name)
}
Column {
IconButton(
modifier = Modifier.size(iconSize),
onClick = {
isPeerDropDownExpanded = true
},
) {
val icon = Icons.Rounded.MoreVert
Icon(icon, icon.name)
}
DropdownMenu(
containerColor = MaterialTheme.colorScheme.surface,
expanded = isPeerDropDownExpanded,
modifier = Modifier.shadow(12.dp).background(MaterialTheme.colorScheme.surface),
onDismissRequest = {
isPeerDropDownExpanded = false
},
) {
PeerActions.entries.forEach { action ->
DropdownMenuItem(
text = {
Text(
text = when (action) {
PeerActions.EXCLUDE_LAN -> if (isLanExcluded) {
stringResource(R.string.include_lan)
} else {
stringResource(R.string.exclude_lan)
}
},
)
},
onClick = {
isPeerDropDownExpanded = false
when (action) {
PeerActions.EXCLUDE_LAN -> if (isLanExcluded) {
peersState[index] = peer.includeLan()
} else {
peersState[index] = peer.excludeLan()
}
}
},
)
}
}
}
}
}

View File

@ -3,6 +3,7 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.mode
import com.wireguard.config.Interface
import com.zaneschepke.wireguardautotunnel.util.extensions.joinAndTrim
import com.zaneschepke.wireguardautotunnel.util.extensions.toTrimmedList
import kotlin.ranges.contains
data class InterfaceProxy(
val privateKey: String = "",
@ -44,6 +45,46 @@ data class InterfaceProxy(
}.build()
}
fun toAmneziaCompatibilityConfig(): InterfaceProxy {
return copy(
junkPacketCount = "4",
junkPacketMinSize = "40",
junkPacketMaxSize = "70",
initPacketJunkSize = "0",
responsePacketJunkSize = "0",
initPacketMagicHeader = "1",
responsePacketMagicHeader = "2",
underloadPacketMagicHeader = "3",
transportPacketMagicHeader = "4",
)
}
fun resetAmneziaProperties(): InterfaceProxy {
return copy(
junkPacketCount = "",
junkPacketMinSize = "",
junkPacketMaxSize = "",
initPacketJunkSize = "",
responsePacketJunkSize = "",
initPacketMagicHeader = "",
responsePacketMagicHeader = "",
underloadPacketMagicHeader = "",
transportPacketMagicHeader = "",
)
}
fun isAmneziaCompatibilityModeSet(): Boolean {
return junkPacketCount.toIntOrNull() in 3..<5 &&
junkPacketMinSize.toIntOrNull() == 40 &&
junkPacketMaxSize.toIntOrNull() == 70 &&
with(initPacketJunkSize.toIntOrNull()) { this == 0 || this == null } &&
with(responsePacketJunkSize.toIntOrNull()) { this == 0 || this == null } &&
initPacketMagicHeader.toLongOrNull() == 1L &&
responsePacketMagicHeader.toLongOrNull() == 2L &&
underloadPacketMagicHeader.toLongOrNull() == 3L &&
transportPacketMagicHeader.toLongOrNull() == 4L
}
fun toAmInterface(): org.amnezia.awg.config.Interface {
return org.amnezia.awg.config.Interface.Builder().apply {
parseAddresses(addresses)

View File

@ -8,7 +8,7 @@ data class PeerProxy(
val preSharedKey: String = "",
val persistentKeepalive: String = "",
val endpoint: String = "",
val allowedIps: String = IPV4_WILDCARD.joinAndTrim(),
val allowedIps: String = ALL_IPS.joinAndTrim(),
) {
fun toWgPeer(): Peer {
return Peer.Builder().apply {
@ -29,6 +29,22 @@ data class PeerProxy(
}.build()
}
fun isLanExcluded(): Boolean {
return this.allowedIps.contains(IPV4_PUBLIC_NETWORKS.joinAndTrim())
}
fun includeLan(): PeerProxy {
return this.copy(
allowedIps = ALL_IPS.joinAndTrim(),
)
}
fun excludeLan(): PeerProxy {
return this.copy(
allowedIps = IPV4_PUBLIC_NETWORKS.joinAndTrim(),
)
}
companion object {
fun from(peer: Peer): PeerProxy {
return PeerProxy(
@ -113,6 +129,6 @@ data class PeerProxy(
"200.0.0.0/5",
"208.0.0.0/4",
)
val IPV4_WILDCARD = setOf("0.0.0.0/0")
val ALL_IPS = setOf("0.0.0.0/0", "::/0")
}
}

View File

@ -6,17 +6,14 @@ import com.wireguard.config.Peer
import com.zaneschepke.wireguardautotunnel.service.tunnel.BackendState
import com.zaneschepke.wireguardautotunnel.service.tunnel.HandshakeStatus
import com.zaneschepke.wireguardautotunnel.service.tunnel.statistics.TunnelStatistics
import com.zaneschepke.wireguardautotunnel.ui.screens.tunneloptions.config.model.InterfaceProxy
import com.zaneschepke.wireguardautotunnel.ui.theme.SilverTree
import com.zaneschepke.wireguardautotunnel.ui.theme.Straw
import com.zaneschepke.wireguardautotunnel.util.Constants
import com.zaneschepke.wireguardautotunnel.util.NumberUtils
import org.amnezia.awg.backend.Backend
import org.amnezia.awg.config.Config
import org.amnezia.awg.config.Interface
import timber.log.Timber
import java.net.InetAddress
import kotlin.jvm.optionals.getOrNull
fun TunnelStatistics.mapPeerStats(): Map<org.amnezia.awg.crypto.Key, TunnelStatistics.PeerStats?> {
return this.getPeers().associateWith { key -> (this.peerStats(key)) }
@ -98,45 +95,3 @@ fun Backend.BackendState.asBackendState(): BackendState {
fun BackendState.asAmBackendState(): Backend.BackendState {
return Backend.BackendState.valueOf(this.name)
}
fun Interface.isWgCompatibilityMode(): Boolean {
return (
junkPacketCount.getOrNull() in 3..<5 &&
junkPacketMinSize.getOrNull() == 40 &&
junkPacketMaxSize.getOrNull() == 70 &&
with(initPacketJunkSize.getOrNull()) { this == 0 || this == null } &&
with(responsePacketJunkSize.getOrNull()) { this == 0 || this == null } &&
initPacketMagicHeader.getOrNull() == 1L &&
responsePacketMagicHeader.getOrNull() == 2L &&
underloadPacketMagicHeader.getOrNull() == 3L &&
transportPacketMagicHeader.getOrNull() == 4L
)
}
fun InterfaceProxy.toAmneziaCompatibilityConfig(): InterfaceProxy {
return copy(
junkPacketCount = "4",
junkPacketMinSize = "40",
junkPacketMaxSize = "70",
initPacketJunkSize = "0",
responsePacketJunkSize = "0",
initPacketMagicHeader = "1",
responsePacketMagicHeader = "2",
underloadPacketMagicHeader = "3",
transportPacketMagicHeader = "4",
)
}
fun InterfaceProxy.resetAmneziaProperties(): InterfaceProxy {
return copy(
junkPacketCount = "",
junkPacketMinSize = "",
junkPacketMaxSize = "",
initPacketJunkSize = "",
responsePacketJunkSize = "",
initPacketMagicHeader = "",
responsePacketMagicHeader = "",
underloadPacketMagicHeader = "",
transportPacketMagicHeader = "",
)
}

View File

@ -196,4 +196,10 @@
<string name="quick_actions">Quick actions</string>
<string name="advanced_settings">Advanced settings</string>
<string name="debounce_delay">Debounce delay</string>
<string name="hide_amnezia_properties">Hide Amnezia properties</string>
<string name="hide_scripts">Hide scripts</string>
<string name="enable_amnezia_compatibility">Enable Amnezia compatibility</string>
<string name="remove_amnezia_compatibility">Remove Amnezia compatibility</string>
<string name="exclude_lan">Exclude LAN</string>
<string name="include_lan">Include LAN</string>
</resources>