Compare commits

..

37 Commits

Author SHA1 Message Date
Zane Schepke 6f48147b3e feat: add amneziawg support 2024-04-27 21:44:41 -04:00
Zane Schepke 16979dbb2b Update ic_channel.xml 2024-04-26 01:50:08 -04:00
Hosted Weblate 5d8190628d Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: WG Tunnel/strings
Translate-URL: https://hosted.weblate.org/projects/wg-tunnel/strings/
2024-04-26 01:50:08 -04:00
Anonymous 6d597a235d Translated using Weblate (Spanish)
Currently translated at 100.0% (159 of 159 strings)

Translation: WG Tunnel/strings
Translate-URL: https://hosted.weblate.org/projects/wg-tunnel/strings/es/
2024-04-26 01:49:49 -04:00
Anonymous 61fd2f01b9 Translated using Weblate (German)
Currently translated at 49.0% (78 of 159 strings)

Translation: WG Tunnel/strings
Translate-URL: https://hosted.weblate.org/projects/wg-tunnel/strings/de/
2024-04-26 01:49:08 -04:00
Anonymous 914a641977 Translated using Weblate (Russian)
Currently translated at 3.1% (5 of 159 strings)

Translation: WG Tunnel/strings
Translate-URL: https://hosted.weblate.org/projects/wg-tunnel/strings/ru/
2024-04-26 01:49:08 -04:00
Anonymous c97a3afbc4 Translated using Weblate (Turkish)
Currently translated at 100.0% (159 of 159 strings)

Translation: WG Tunnel/strings
Translate-URL: https://hosted.weblate.org/projects/wg-tunnel/strings/tr/
2024-04-26 01:49:08 -04:00
gallegonovato fadc2d1562 Translated using Weblate (Spanish)
Currently translated at 100.0% (159 of 159 strings)

Translation: WG Tunnel/strings
Translate-URL: https://hosted.weblate.org/projects/wg-tunnel/strings/es/
2024-04-26 01:49:08 -04:00
Languages add-on 106ab76b82 Added translation using Weblate (Spanish) 2024-04-26 01:48:39 -04:00
Weblate (bot) 48b3f60b37 Translations update from Hosted Weblate (#177)
Co-authored-by: Languages add-on <noreply-addon-languages@weblate.org>
Co-authored-by: Gabriel Franz <gabrielfranz31@gmail.com>
Co-authored-by: Saratoga79 <ordizi79@gmail.com>
2024-04-24 03:49:57 -04:00
WINZORT e7f5cee6dd Add fastlane tr (#173) 2024-04-22 23:21:19 -04:00
Zane Schepke 5e01fd6c85 Merge pull request #175 from zaneschepke/i18n
Translations update from Hosted Weblate
2024-04-22 23:18:46 -04:00
Dominik Thalhammer dcbd72c6f6 Translated using Weblate (German)
Currently translated at 40.9% (9 of 22 strings)

Translation: WG Tunnel/fastlane
Translate-URL: https://hosted.weblate.org/projects/wg-tunnel/fastlane/de/
2024-04-22 13:18:21 +02:00
Languages add-on f27aa1452a Added translation using Weblate (German) 2024-04-22 07:52:45 +02:00
Languages add-on 82c3521c58 Added translation using Weblate (Russian) 2024-04-21 06:19:53 +02:00
Zane Schepke c6535ffe7e chore: update chats 2024-04-20 18:36:40 -04:00
Zane Schepke be5fe94ce6 chore: cleanup unused strings 2024-04-20 17:42:14 -04:00
Zane Schepke 1e905c1cfb chore: update README.md 2024-04-20 17:09:36 -04:00
Zane Schepke a549c111aa Merge pull request #170 from yurtpage/i18n
i18n
2024-04-20 16:28:15 -04:00
Zane Schepke 5ab344044e chore: add Weblate details to README 2024-04-20 14:30:21 -04:00
Zane Schepke 7030f68548 chore: update README 2024-04-20 13:57:33 -04:00
Zane Schepke ecd51b6fe5 chore: add code of conduct 2024-04-20 13:52:28 -04:00
Yurt Page 3e4f8e0791 fastlane i18n ru
Signed-off-by: Yurt Page <yurtpage@gmail.com>
2024-04-19 18:28:58 +03:00
Zane Schepke e940a0dbc5 Merge pull request #167 from mikropsoft/main
Improve tr locales
2024-04-18 22:12:21 -04:00
WINZORT 8e233475df Update strings.xml 2024-04-17 17:41:49 +03:00
WINZORT 24789826ad Update strings.xml 2024-04-17 17:38:00 +03:00
WINZORT 787e0d1a71 Update strings.xml 2024-04-17 17:37:22 +03:00
WINZORT 914ef53ef0 Improve tr locales 2024-04-17 17:23:27 +03:00
Zane Schepke a569974beb add Turkish localization 2024-04-16 16:13:41 -04:00
Zane Schepke 87bc89b6f1 Merge branch 'main' of https://github.com/zaneschepke/wgtunnel 2024-04-16 00:50:43 -04:00
Zane Schepke c343220e96 Merge pull request #156 from mikropsoft/main
Add tr locales
2024-04-16 00:41:14 -04:00
Zane Schepke 5447ec73f7 fix: stop tunnel regression
Fixes regression where tunnel is stuck in on state after x amount of toggles. Closes #163

Adds obfuscation of potentially sensitive data from logs.
Closes #160

Adds hiding of FAB on scroll to allow users to toggle tunnels when they have many tunnel configs.
Closes #161
2024-04-16 00:14:06 -04:00
Zane Schepke a2b8eb5b0b ci: update release wording 2024-04-06 11:06:19 -04:00
Zane Schepke e37777e662 fix: improve auto-tunnel reliability
Improved service manager stop service command to improve reliability
Closes #148

Added assets required by Google Play for AndroidTV to fix Google Play release

Added apk fingerprint hash to release to allow verification of apk signature via apksigner

Improve tile sync when tiles are first added

Bump versions
2024-04-06 10:43:00 -04:00
WINZORT ee3fcabcf1 Add tr locales 2024-04-06 15:39:46 +03:00
Zane Schepke 2a8895ffbc docs: update readme, add security 2024-03-30 23:16:19 -04:00
Zane Schepke b1fdb5b9b2 feat: auto-tunneling flexibility
Added tunnel settings feature where users can configure a tunnel to be used on certain SSID or with mobile data.
Closes #50

Added feature where if a tunnel was active when phone restarted, the app will start that tunnel on boot.

Removed automatic auto-tunnel toggling/override from the tunnel tile and app shortcuts as it can cause undesirable behavior.

Added second tile to control auto-tunneling pause/resume state from a tile.

Added two additional static shortcuts to be able to control auto-tunneling pause/resume state from shortcuts.

Fixed bug where crashes can happen from serializing and deserializing tunnel configs by removing the need for serialization of tunnel configs.

Refactored logic of watcher and tunnel service to make state more predictable.
#127

Fixed bug where rapidly toggling tunnels can cause crashes.
Closes #145

Improved how tunnels are manually toggled from one to another.

Improved logic/storage around primary tunnel behavior.

Fixes issue where info level logs were not populating on release builds.

Increase allowed name length displayed in UI.
Closes #143

Fixes bug where androidTV could crash in certain situations.

Bump versions.

Updated screenshots.
2024-03-30 00:00:35 -04:00
77 changed files with 852 additions and 180 deletions
+22
View File
@@ -0,0 +1,22 @@
# Contributor Code of Conduct
## Pledge
We as individuals involved in this project, pledge to participate in this
community in a respectful, constructive, and civil manner as we work towards a common goal
of delivering free, open source, and value adding software for all.
## Standard
The standard for this community is the Golden Rule.
> “Do unto others as you would have them do unto you.”
## Scope
This Code of Conduct applies to all spaces related to WG Tunnel.
## Incidents or Concerns
For any incidents or concerns, reach out to Zane at
<support@zaneschepke.com>.
+26
View File
@@ -89,6 +89,32 @@ jobs:
draft: false
prerelease: true
files: ${{ github.workspace }}/${{ steps.apk-path.outputs.path }}
- name: Install apksigner
run: |
sudo apt-get update
sudo apt-get install -y apksigner
- name: Get checksum
id: checksum
run: echo "checksum=$(apksigner verify -print-certs ${{ steps.apk-path.outputs.path }} | grep -Po "(?<=SHA-256 digest:) .*" | tr -d "[:blank:]")" >> $GITHUB_OUTPUT
- name: Append checksum
id: append_checksum
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
body: |
SHA256 fingerprint:
```${{ steps.checksum.outputs.checksum }}```
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }}
draft: false
prerelease: true
append_body: true
- name: Deploy with fastlane
uses: ruby/setup-ruby@v1
with:
+26
View File
@@ -95,6 +95,32 @@ jobs:
draft: false
prerelease: false
files: ${{ github.workspace }}/${{ steps.apk-path.outputs.path }}
- name: Install apksigner
run: |
sudo apt-get update
sudo apt-get install -y apksigner
- name: Get checksum
id: checksum
run: echo "checksum=$(apksigner verify -print-certs ${{ steps.apk-path.outputs.path }} | grep -Po "(?<=SHA-256 digest:) .*" | tr -d "[:blank:]")" >> $GITHUB_OUTPUT
- name: Append checksum
id: append_checksum
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
body: |
SHA256 fingerprint:
```${{ steps.checksum.outputs.checksum }}```
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }}
draft: false
prerelease: false
append_body: true
- name: Deploy with fastlane
uses: ruby/setup-ruby@v1
with:
+24 -7
View File
@@ -4,8 +4,9 @@ WG Tunnel
<div align="center">
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Discord Chat](https://img.shields.io/discord/1108285024631001111.svg)](https://discord.gg/rbRRNh6H7V)
[![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/rbRRNh6H7V)
[![X Community](https://img.shields.io/badge/X-000000?style=for-the-badge&logo=x&logoColor=white)](https://twitter.com/i/communities/1780655267685736818)
[![Telegram](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](https://t.me/wgtunnel)
</div>
@@ -49,24 +50,40 @@ and on while on different networks. This app was created to offer a free solutio
## Features
* Add tunnels via .conf file, zip, manual entry, or QR code
* Auto connect to VPN based on Wi-Fi SSID, ethernet, or mobile data
* Auto connect to tunnels based on Wi-Fi SSID, ethernet, or mobile data
* Split tunneling by application with search
* WireGuard support for kernel and userspace modes
* Always-On VPN support
* Export tunnels to zip
* Quick tile support for VPN toggling
* Static shortcuts support for primary tunnel for automation integration
* Quick tile support for tunnel toggling, auto-tunneling
* Static shortcuts support for tunnel toggling, auto-tunneling
* Intent automation support for all tunnels
* Automatic service restart after reboot
* Automatic auto-tunneling service restart after reboot
* Automatic tunnel restart after reboot
* Battery preservation measures
* Restart tunnel on ping failure (beta)
## Docs (WIP)
## Docs
Basic documentation of the feature and behaviors of this app can be
found [here](https://zaneschepke.com/wgtunnel-docs/overview.html).
The repository for these docs can be found [here](https://github.com/zaneschepke/wgtunnel-docs).
## Contributing
Any contributions in the form of feedback, issues, code, or translations are welcome and much appreciated!
Please read the [code of conduct](https://github.com/zaneschepke/wgtunnel?tab=coc-ov-file#contributor-code-of-conduct) before contributing.
## Translation
This app is using [Weblate](https://weblate.org) to assist with translations.
Help translate WG Tunnel into your language at [Hosted Weblate](https://hosted.weblate.org/engage/wg-tunnel/).\
[![Translation status](https://hosted.weblate.org/widgets/wg-tunnel/-/multi-auto.svg)](https://hosted.weblate.org/engage/wg-tunnel/)
## Building
```
+5
View File
@@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Please report security issues to `support@zaneschepke.com`
+6 -4
View File
@@ -12,6 +12,10 @@ android {
namespace = Constants.APP_ID
compileSdk = Constants.TARGET_SDK
androidResources {
generateLocaleConfig = true
}
defaultConfig {
applicationId = Constants.APP_ID
minSdk = Constants.MIN_SDK
@@ -25,8 +29,6 @@ android {
getByName("debug").assets.srcDirs(files("$projectDir/schemas")) // Room
}
resourceConfigurations.addAll(listOf("en"))
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { useSupportLibrary = true }
}
@@ -158,8 +160,8 @@ dependencies {
debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.androidx.compose.manifest)
// get tunnel lib from github packages or mavenLocal
implementation(libs.tunnel)
// tunnel
implementation(libs.amneziawg.android)
coreLibraryDesugaring(libs.desugar.jdk.libs)
// logging
+1 -1
View File
@@ -52,7 +52,7 @@
<application
android:name=".WireGuardAutoTunnel"
android:allowBackup="true"
android:banner="@mipmap/ic_banner"
android:banner="@drawable/ic_banner"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
@@ -4,7 +4,7 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import com.wireguard.config.Config
import org.amnezia.awg.config.Config
import java.io.InputStream
@Entity(indices = [Index(value = ["name"], unique = true)])
@@ -1,11 +1,6 @@
package com.zaneschepke.wireguardautotunnel.module
import android.content.Context
import com.wireguard.android.backend.Backend
import com.wireguard.android.backend.GoBackend
import com.wireguard.android.backend.WgQuickBackend
import com.wireguard.android.util.RootShell
import com.wireguard.android.util.ToolsInstaller
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
@@ -15,6 +10,11 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import org.amnezia.awg.backend.AwgQuickBackend
import org.amnezia.awg.backend.Backend
import org.amnezia.awg.backend.GoBackend
import org.amnezia.awg.util.RootShell
import org.amnezia.awg.util.ToolsInstaller
import javax.inject.Singleton
@Module
@@ -37,7 +37,7 @@ class TunnelModule {
@Singleton
@Kernel
fun provideKernelBackend(@ApplicationContext context: Context, rootShell: RootShell): Backend {
return WgQuickBackend(context, rootShell, ToolsInstaller(context, rootShell))
return AwgQuickBackend(context, rootShell, ToolsInstaller(context, rootShell))
}
@Provides
@@ -24,7 +24,7 @@ class NotificationActionReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) = goAsync {
try {
//TODO fix for manual start changes when enabled
serviceManager.stopVpnService(context)
serviceManager.stopVpnServiceForeground(context)
delay(Constants.TOGGLE_TUNNEL_DELAY)
serviceManager.startVpnServiceForeground(context)
} catch (e: Exception) {
@@ -3,5 +3,6 @@ package com.zaneschepke.wireguardautotunnel.service.foreground
enum class Action {
START,
START_FOREGROUND,
STOP
STOP,
STOP_FOREGROUND
}
@@ -24,8 +24,7 @@ open class ForegroundService : LifecycleService() {
when (action) {
Action.START.name,
Action.START_FOREGROUND.name -> startService(intent.extras)
Action.STOP.name -> stopService(intent.extras)
Action.STOP.name, Action.STOP_FOREGROUND.name -> stopService()
Constants.ALWAYS_ON_VPN_ACTION -> {
Timber.i("Always-on VPN starting service")
startService(intent.extras)
@@ -38,29 +37,19 @@ open class ForegroundService : LifecycleService() {
"with a null intent. It has been probably restarted by the system.",
)
}
// by returning this we make sure the service is restarted if the system kills the service
return START_STICKY
}
override fun onDestroy() {
super.onDestroy()
Timber.d("The service has been destroyed")
}
protected open fun startService(extras: Bundle?) {
if (isServiceStarted) return
Timber.d("Starting ${this.javaClass.simpleName}")
isServiceStarted = true
}
protected open fun stopService(extras: Bundle?) {
protected open fun stopService() {
Timber.d("Stopping ${this.javaClass.simpleName}")
try {
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
} catch (e: Exception) {
Timber.e(e)
}
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
isServiceStarted = false
}
}
@@ -23,15 +23,8 @@ class ServiceManager(private val appDataRepository: AppDataRepository) {
intent.component?.javaClass
try {
when (action) {
Action.START_FOREGROUND -> {
context.startForegroundService(intent)
}
Action.START -> {
context.startService(intent)
}
Action.STOP -> context.startService(intent)
Action.START_FOREGROUND, Action.STOP_FOREGROUND -> context.startForegroundService(intent)
Action.START, Action.STOP -> context.startService(intent)
}
} catch (e: Exception) {
Timber.e(e.message)
@@ -52,9 +45,19 @@ class ServiceManager(private val appDataRepository: AppDataRepository) {
)
}
suspend fun stopVpnServiceForeground(context: Context, isManualStop: Boolean = false) {
if (isManualStop) onManualStop()
Timber.i("Stopping vpn service")
actionOnService(
Action.STOP_FOREGROUND,
context,
WireGuardTunnelService::class.java,
)
}
suspend fun stopVpnService(context: Context, isManualStop: Boolean = false) {
if (isManualStop) onManualStop()
Timber.d("Stopping vpn service action")
Timber.i("Stopping vpn service")
actionOnService(
Action.STOP,
context,
@@ -1,6 +0,0 @@
package com.zaneschepke.wireguardautotunnel.service.foreground
enum class ServiceState {
STARTED,
STOPPED,
}
@@ -1,8 +1,8 @@
package com.zaneschepke.wireguardautotunnel.service.foreground
import com.wireguard.android.backend.Tunnel
import com.zaneschepke.wireguardautotunnel.data.model.Settings
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
import org.amnezia.awg.backend.Tunnel
data class WatcherState(
val isWifiConnected: Boolean = false,
@@ -5,7 +5,6 @@ import android.os.Bundle
import android.os.PowerManager
import androidx.core.app.ServiceCompat
import androidx.lifecycle.lifecycleScope
import com.wireguard.android.backend.Tunnel
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
@@ -18,12 +17,14 @@ import com.zaneschepke.wireguardautotunnel.service.notification.NotificationServ
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
import com.zaneschepke.wireguardautotunnel.util.Constants
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.amnezia.awg.backend.Tunnel
import timber.log.Timber
import java.net.InetAddress
import javax.inject.Inject
@@ -56,7 +57,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
private val networkEventsFlow = MutableStateFlow(WatcherState())
private lateinit var watcherJob: Job
private var watcherJob: Job? = null
private var wakeLock: PowerManager.WakeLock? = null
private val tag = this.javaClass.name
@@ -86,8 +87,8 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
}
}
override fun stopService(extras: Bundle?) {
super.stopService(extras)
override fun stopService() {
super.stopService()
wakeLock?.let {
if (it.isHeld) {
it.release()
@@ -134,8 +135,10 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
}
private fun cancelWatcherJob() {
if (this::watcherJob.isInitialized) {
watcherJob.cancel()
try {
watcherJob?.cancel()
} catch (e : CancellationException) {
Timber.i("Watcher job cancelled")
}
}
@@ -231,7 +234,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
}
if (results.contains(false)) {
Timber.i("Restarting VPN for ping failure")
serviceManager.stopVpnService(this)
serviceManager.stopVpnServiceForeground(this)
delay(Constants.VPN_RESTART_DELAY)
serviceManager.startVpnServiceForeground(this)
delay(Constants.PING_COOLDOWN)
@@ -319,7 +322,9 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
)
val ssid = wifiService.getNetworkName(it.networkCapabilities)
ssid?.let {
Timber.i("Detected SSID: $ssid")
if(it.contains(Constants.UNREADABLE_SSID)) {
Timber.w("SSID unreadable: missing permissions")
} else Timber.i("Detected valid SSID")
appDataRepository.appState.setCurrentSsid(ssid)
networkEventsFlow.value =
networkEventsFlow.value.copy(
@@ -376,7 +381,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
watcherState.isTunnelOffOnMobileDataConditionMet() -> {
Timber.i("$autoTunnel - tunnel off on mobile data met, turning vpn off")
serviceManager.stopVpnService(this)
serviceManager.stopVpnServiceForeground(this)
}
watcherState.isTunnelNotWifiNamePreferredMet(watcherState.currentNetworkSSID) -> {
@@ -402,17 +407,17 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
watcherState.isTrustedWifiConditionMet() -> {
Timber.i("$autoTunnel - tunnel off on trusted wifi condition met, turning vpn off")
serviceManager.stopVpnService(this)
serviceManager.stopVpnServiceForeground(this)
}
watcherState.isTunnelOffOnWifiConditionMet() -> {
Timber.i("$autoTunnel - tunnel off on wifi condition met, turning vpn off")
serviceManager.stopVpnService(this)
serviceManager.stopVpnServiceForeground(this)
}
watcherState.isTunnelOffOnNoConnectivityMet() -> {
Timber.i("$autoTunnel - tunnel off on no connectivity met, turning vpn off")
serviceManager.stopVpnService(this)
serviceManager.stopVpnServiceForeground(this)
}
else -> {
@@ -5,7 +5,6 @@ import android.content.Intent
import android.os.Bundle
import androidx.core.app.ServiceCompat
import androidx.lifecycle.lifecycleScope
import com.wireguard.android.backend.Tunnel
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
import com.zaneschepke.wireguardautotunnel.receiver.NotificationActionReceiver
@@ -16,10 +15,13 @@ import com.zaneschepke.wireguardautotunnel.util.Constants
import com.zaneschepke.wireguardautotunnel.util.handshakeStatus
import com.zaneschepke.wireguardautotunnel.util.mapPeerStats
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.amnezia.awg.backend.Tunnel
import timber.log.Timber
import javax.inject.Inject
@AndroidEntryPoint
@@ -35,7 +37,7 @@ class WireGuardTunnelService : ForegroundService() {
@Inject
lateinit var notificationService: NotificationService
private lateinit var job: Job
private var job: Job? = null
private var didShowConnected = false
@@ -117,8 +119,8 @@ class WireGuardTunnelService : ForegroundService() {
)
}
override fun stopService(extras: Bundle?) {
super.stopService(extras)
override fun stopService() {
super.stopService()
lifecycleScope.launch(Dispatchers.IO) {
vpnService.stopTunnel()
didShowConnected = false
@@ -177,8 +179,10 @@ class WireGuardTunnelService : ForegroundService() {
}
private fun cancelJob() {
if (this::job.isInitialized) {
job.cancel()
try {
job?.cancel()
} catch (e : CancellationException) {
Timber.i("Tunnel job cancelled")
}
}
}
@@ -40,7 +40,7 @@ class ShortcutsActivity : ComponentActivity() {
this@ShortcutsActivity, tunnelConfig?.id, isManualStart = true,
)
Action.STOP.name -> serviceManager.stopVpnService(
Action.STOP.name -> serviceManager.stopVpnServiceForeground(
this@ShortcutsActivity,
isManualStop = true,
)
@@ -53,6 +53,11 @@ class AutoTunnelControlTile : TileService() {
}
}
override fun onTileAdded() {
super.onTileAdded()
onStartListening()
}
override fun onDestroy() {
super.onDestroy()
scope.cancel()
@@ -3,7 +3,6 @@ package com.zaneschepke.wireguardautotunnel.service.tile
import android.os.Build
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import com.wireguard.android.backend.Tunnel
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
@@ -13,6 +12,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import org.amnezia.awg.backend.Tunnel
import timber.log.Timber
import javax.inject.Inject
@@ -69,13 +69,21 @@ class TunnelControlTile : TileService() {
scope.cancel()
}
override fun onTileAdded() {
super.onTileAdded()
onStartListening()
}
override fun onClick() {
super.onClick()
unlockAndRun {
scope.launch {
try {
if (vpnService.getState() == Tunnel.State.UP) {
serviceManager.stopVpnService(this@TunnelControlTile, isManualStop = true)
serviceManager.stopVpnServiceForeground(
this@TunnelControlTile,
isManualStop = true,
)
} else {
serviceManager.startVpnServiceForeground(
this@TunnelControlTile, manualStartConfig?.id, isManualStart = true,
@@ -1,8 +1,8 @@
package com.zaneschepke.wireguardautotunnel.service.tunnel
import com.wireguard.android.backend.Tunnel
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
import kotlinx.coroutines.flow.StateFlow
import org.amnezia.awg.backend.Tunnel
interface VpnService : Tunnel {
suspend fun startTunnel(tunnelConfig: TunnelConfig? = null): Tunnel.State
@@ -1,8 +1,8 @@
package com.zaneschepke.wireguardautotunnel.service.tunnel
import com.wireguard.android.backend.Statistics
import com.wireguard.android.backend.Tunnel
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
import org.amnezia.awg.backend.Statistics
import org.amnezia.awg.backend.Tunnel
data class VpnState(
val status: Tunnel.State = Tunnel.State.DOWN,
@@ -1,15 +1,12 @@
package com.zaneschepke.wireguardautotunnel.service.tunnel
import com.wireguard.android.backend.Backend
import com.wireguard.android.backend.BackendException
import com.wireguard.android.backend.Statistics
import com.wireguard.android.backend.Tunnel.State
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
import com.zaneschepke.wireguardautotunnel.module.Kernel
import com.zaneschepke.wireguardautotunnel.module.Userspace
import com.zaneschepke.wireguardautotunnel.util.Constants
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -18,6 +15,10 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.amnezia.awg.backend.Backend
import org.amnezia.awg.backend.BackendException
import org.amnezia.awg.backend.Statistics
import org.amnezia.awg.backend.Tunnel
import timber.log.Timber
import javax.inject.Inject
@@ -33,7 +34,7 @@ constructor(
private val scope = CoroutineScope(Dispatchers.IO)
private lateinit var statsJob: Job
private var statsJob: Job? = null
private var backend: Backend = userspaceBackend
@@ -55,7 +56,7 @@ constructor(
}
}
override suspend fun startTunnel(tunnelConfig: TunnelConfig?): State {
override suspend fun startTunnel(tunnelConfig: TunnelConfig?): Tunnel.State {
return try {
//TODO we need better error handling here
val config = tunnelConfig ?: appDataRepository.getPrimaryOrFirstTunnel()
@@ -65,18 +66,18 @@ constructor(
val state =
backend.setState(
this,
State.UP,
Tunnel.State.UP,
wgConfig,
)
state
} else throw Exception("No tunnels")
} catch (e: BackendException) {
Timber.e("Failed to start tunnel with error: ${e.message}")
State.DOWN
Tunnel.State.DOWN
}
}
private fun emitTunnelState(state: State) {
private fun emitTunnelState(state: Tunnel.State) {
_vpnState.tryEmit(
_vpnState.value.copy(
status = state,
@@ -102,8 +103,8 @@ constructor(
override suspend fun stopTunnel() {
try {
if (getState() == State.UP) {
val state = backend.setState(this, State.DOWN, null)
if (getState() == Tunnel.State.UP) {
val state = backend.setState(this, Tunnel.State.DOWN, null)
emitTunnelState(state)
}
} catch (e: BackendException) {
@@ -111,7 +112,7 @@ constructor(
}
}
override fun getState(): State {
override fun getState(): Tunnel.State {
return backend.getState(this)
}
@@ -119,11 +120,11 @@ constructor(
return _vpnState.value.tunnelConfig?.name ?: ""
}
override fun onStateChange(state: State) {
override fun onStateChange(state: Tunnel.State) {
val tunnel = this
emitTunnelState(state)
WireGuardAutoTunnel.requestTunnelTileServiceStateUpdate(WireGuardAutoTunnel.instance)
if (state == State.UP) {
if (state == Tunnel.State.UP) {
statsJob =
scope.launch {
while (true) {
@@ -133,9 +134,11 @@ constructor(
}
}
}
if (state == State.DOWN) {
if (this::statsJob.isInitialized) {
statsJob.cancel()
if (state == Tunnel.State.DOWN) {
try {
statsJob?.cancel()
} catch (e : CancellationException) {
Timber.i("Stats job cancelled")
}
}
}
@@ -8,7 +8,6 @@ import android.widget.Toast
import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wireguard.android.backend.GoBackend
import com.zaneschepke.logcatter.Logcatter
import com.zaneschepke.logcatter.model.LogMessage
import com.zaneschepke.wireguardautotunnel.R
@@ -20,6 +19,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.amnezia.awg.backend.GoBackend
import timber.log.Timber
import java.time.Instant
import javax.inject.Inject
@@ -118,12 +118,12 @@ constructor(
fun readLogCatOutput() =
viewModelScope.launch(viewModelScope.coroutineContext + Dispatchers.IO) {
launch {
Logcatter.logs {
Logcatter.logs(callback = {
logs.add(it)
if (logs.size > Constants.LOG_BUFFER_SIZE) {
logs.removeRange(0, (logs.size - Constants.LOG_BUFFER_SIZE).toInt())
}
}
})
}
}
@@ -4,13 +4,17 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Home
import androidx.compose.material.icons.rounded.QuestionMark
import androidx.compose.material.icons.rounded.Settings
import androidx.compose.ui.res.stringResource
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.BottomNavItem
import com.zaneschepke.wireguardautotunnel.util.StringValue
sealed class Screen(val route: String) {
data object Main : Screen("main") {
val navItem =
BottomNavItem(
name = "Tunnels",
name = WireGuardAutoTunnel.instance.getString(R.string.tunnels),
route = route,
icon = Icons.Rounded.Home,
)
@@ -19,7 +23,7 @@ sealed class Screen(val route: String) {
data object Settings : Screen("settings") {
val navItem =
BottomNavItem(
name = "Settings",
name = WireGuardAutoTunnel.instance.getString(R.string.settings),
route = route,
icon = Icons.Rounded.Settings,
)
@@ -28,7 +32,7 @@ sealed class Screen(val route: String) {
data object Support : Screen("support") {
val navItem =
BottomNavItem(
name = "Support",
name = WireGuardAutoTunnel.instance.getString(R.string.support),
route = route,
icon = Icons.Rounded.QuestionMark,
)
@@ -17,9 +17,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.wireguard.android.backend.Statistics
import com.zaneschepke.wireguardautotunnel.util.NumberUtils
import com.zaneschepke.wireguardautotunnel.util.toThreeDecimalPlaceString
import org.amnezia.awg.backend.Statistics
@OptIn(ExperimentalFoundationApi::class)
@Composable
@@ -28,7 +28,12 @@ fun ConfigurationToggle(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(label, textAlign = TextAlign.Start)
Text(label, textAlign = TextAlign.Start, modifier = Modifier
.weight(
weight = 1.0f,
fill = false,
),
softWrap = true)
Switch(
modifier = modifier,
enabled = enabled,
@@ -1,6 +1,6 @@
package com.zaneschepke.wireguardautotunnel.ui.models
import com.wireguard.config.Interface
import org.amnezia.awg.config.Interface
data class InterfaceProxy(
var privateKey: String = "",
@@ -1,6 +1,6 @@
package com.zaneschepke.wireguardautotunnel.ui.models
import com.wireguard.config.Peer
import org.amnezia.awg.config.Peer
data class PeerProxy(
var publicKey: String = "",
@@ -7,11 +7,6 @@ import android.content.pm.PackageManager
import android.os.Build
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wireguard.config.Config
import com.wireguard.config.Interface
import com.wireguard.config.Peer
import com.wireguard.crypto.Key
import com.wireguard.crypto.KeyPair
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
@@ -28,6 +23,11 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.amnezia.awg.config.Config
import org.amnezia.awg.config.Interface
import org.amnezia.awg.config.Peer
import org.amnezia.awg.crypto.Key
import org.amnezia.awg.crypto.KeyPair
import timber.log.Timber
import javax.inject.Inject
@@ -198,12 +198,12 @@ constructor(
val tunnelConfig = when (uiState.value.tunnel) {
null -> TunnelConfig(
name = _uiState.value.tunnelName,
wgQuick = config.toWgQuickString(),
wgQuick = config.toAwgQuickString(),
)
else -> uiState.value.tunnel!!.copy(
name = _uiState.value.tunnelName,
wgQuick = config.toWgQuickString(),
wgQuick = config.toAwgQuickString(),
)
}
updateTunnelConfig(tunnelConfig)
@@ -71,8 +71,12 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback
@@ -85,7 +89,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanOptions
import com.wireguard.android.backend.Tunnel
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
@@ -106,6 +109,7 @@ import com.zaneschepke.wireguardautotunnel.util.truncateWithEllipsis
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.amnezia.awg.backend.Tunnel
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@@ -124,6 +128,25 @@ fun MainScreen(
val sheetState = rememberModalBottomSheetState()
var showBottomSheet by remember { mutableStateOf(false) }
// Nested scroll for control FAB
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
// Hide FAB
if (available.y < -1) {
isVisible.value = false
}
// Show FAB
if (available.y > 1) {
isVisible.value = true
}
return Offset.Zero
}
}
}
var showDeleteTunnelAlertDialog by remember { mutableStateOf(false) }
var selectedTunnel by remember { mutableStateOf<TunnelConfig?>(null) }
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
@@ -377,8 +400,8 @@ fun MainScreen(
verticalArrangement = Arrangement.Top,
modifier =
Modifier
.fillMaxWidth()
.overscroll(ScrollableDefaults.overscrollEffect()),
.fillMaxSize()
.overscroll(ScrollableDefaults.overscrollEffect()).nestedScroll(nestedScrollConnection),
state = rememberLazyListState(0, uiState.tunnels.count()),
userScrollEnabled = true,
reverseLayout = false,
@@ -7,7 +7,6 @@ import android.net.Uri
import android.provider.OpenableColumns
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wireguard.config.Config
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
import com.zaneschepke.wireguardautotunnel.data.model.Settings
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
@@ -25,6 +24,7 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.amnezia.awg.config.Config
import timber.log.Timber
import java.io.InputStream
import java.util.zip.ZipInputStream
@@ -119,7 +119,7 @@ constructor(
val bufferReader = stream.bufferedReader(charset = Charsets.UTF_8)
val config = Config.parse(bufferReader)
val tunnelName = getNameFromFileName(fileName)
addTunnel(TunnelConfig(name = tunnelName, wgQuick = config.toWgQuickString()))
addTunnel(TunnelConfig(name = tunnelName, wgQuick = config.toAwgQuickString()))
withContext(Dispatchers.IO) { stream.close() }
}
@@ -164,7 +164,7 @@ constructor(
val name = getNameFromFileName(it.name)
val config = Config.parse(zip)
viewModelScope.launch(Dispatchers.IO) {
addTunnel(TunnelConfig(name = name, wgQuick = config.toWgQuickString()))
addTunnel(TunnelConfig(name = name, wgQuick = config.toAwgQuickString()))
}
}
}
@@ -26,6 +26,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
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
import androidx.compose.foundation.text.KeyboardActions
@@ -70,8 +71,6 @@ import androidx.navigation.NavController
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
import com.wireguard.android.backend.Tunnel
import com.wireguard.android.backend.WgQuickBackend
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
import com.zaneschepke.wireguardautotunnel.ui.AppViewModel
@@ -85,6 +84,8 @@ import com.zaneschepke.wireguardautotunnel.util.FileUtils
import com.zaneschepke.wireguardautotunnel.util.Result
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.amnezia.awg.backend.AwgQuickBackend
import org.amnezia.awg.backend.Tunnel
import timber.log.Timber
import xyz.teamgravity.pin_lock_compose.PinManager
import java.io.File
@@ -550,7 +551,7 @@ fun SettingsScreen(
}
}
}
if (WgQuickBackend.hasKernelSupport()) {
if (AwgQuickBackend.hasKernelSupport()) {
Surface(
tonalElevation = 2.dp,
shadowElevation = 2.dp,
@@ -6,7 +6,6 @@ import android.location.LocationManager
import androidx.core.location.LocationManagerCompat
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wireguard.android.util.RootShell
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
import com.zaneschepke.wireguardautotunnel.data.model.Settings
import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository
@@ -20,6 +19,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.amnezia.awg.util.RootShell
import timber.log.Timber
import javax.inject.Inject
@@ -37,6 +37,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
@@ -122,7 +123,13 @@ fun SupportScreen(
Text(
stringResource(id = R.string.docs_description),
textAlign = TextAlign.Justify,
modifier = Modifier.padding(start = 10.dp),
modifier = Modifier
.padding(start = 10.dp)
.weight(
weight = 1.0f,
fill = false,
),
softWrap = true
)
}
Icon(
@@ -270,8 +277,21 @@ fun SupportScreen(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(25.dp),
) {
Text("Version: ${BuildConfig.VERSION_NAME}", modifier = Modifier.focusable())
Text("Mode: ${if (uiState.settings.isKernelEnabled) "Kernel" else "Userspace"}")
val version = buildAnnotatedString {
append(stringResource(id = R.string.version))
append(": ")
append(BuildConfig.VERSION_NAME)
}
val mode = buildAnnotatedString {
append(stringResource(R.string.mode))
append(": ")
when(uiState.settings.isKernelEnabled){
true -> append(stringResource(id = R.string.kernel))
false -> append(stringResource(id = R.string.userspace))
}
}
Text(version.text, modifier = Modifier.focusable())
Text(mode.text)
}
}
}
@@ -35,4 +35,6 @@ object Constants {
const val TUNNEL_EXTRA_KEY = "tunnelId"
const val UNREADABLE_SSID = "<unknown ssid>"
}
@@ -2,15 +2,14 @@ package com.zaneschepke.wireguardautotunnel.util
import android.content.BroadcastReceiver
import android.content.pm.PackageInfo
import com.wireguard.android.backend.Statistics
import com.wireguard.android.backend.Statistics.PeerStats
import com.wireguard.crypto.Key
import com.zaneschepke.wireguardautotunnel.data.model.TunnelConfig
import com.zaneschepke.wireguardautotunnel.service.tunnel.HandshakeStatus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.amnezia.awg.backend.Statistics
import org.amnezia.awg.crypto.Key
import java.math.BigDecimal
import java.text.DecimalFormat
import kotlin.coroutines.CoroutineContext
@@ -50,15 +49,15 @@ typealias TunnelConfigs = List<TunnelConfig>
typealias Packages = List<PackageInfo>
fun Statistics.mapPeerStats(): Map<Key, PeerStats?> {
fun Statistics.mapPeerStats(): Map<Key, Statistics.PeerStats?> {
return this.peers().associateWith { key -> (this.peer(key)) }
}
fun PeerStats.latestHandshakeSeconds(): Long? {
fun Statistics.PeerStats.latestHandshakeSeconds(): Long? {
return NumberUtils.getSecondsBetweenTimestampAndNow(this.latestHandshakeEpochMillis)
}
fun PeerStats.handshakeStatus(): HandshakeStatus {
fun Statistics.PeerStats.handshakeStatus(): HandshakeStatus {
// TODO add never connected status after duration
return this.latestHandshakeSeconds().let {
when {
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_channel_background" />
</adaptive-icon>
+1
View File
@@ -0,0 +1 @@
unqualifiedResLocale=en-US
+76
View File
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WG Tunnel</string>
<string name="error_file_extension">Dies ist keine .conf oder .zip Datei</string>
<string name="no_tunnels">Noch keine Tunnel hinzugefügt!</string>
<string name="watcher_notification_text_active">Überwachung der Netzwerkänderungen: aktiv</string>
<string name="tunnels">Tunnel</string>
<string name="enable_auto_tunnel">Starte automatisches Verbinden</string>
<string name="tunnel_mobile_data">Verbinden im Mobilnetzwerk</string>
<string name="one_tunnel_required">Mindestens eine Verbindung wird für diese Funktion benötigt</string>
<string name="privacy_policy">Siehe Privacy Policy</string>
<string name="disable_auto_tunnel">Stoppe automatisches Verbinden</string>
<string name="okay">Okay</string>
<string name="tunnel_on_ethernet">Verbindung über Ethernet</string>
<string name="search_icon">Suchsymbol</string>
<string name="attempt_connection">Versuche zu verbinden..</string>
<string name="auto_tunneling">Automatisches verbinden</string>
<string name="default_vpn_off">Primärer VPN aus</string>
<string name="turn_on_tunnel">Für diese Altion muss eine Verbindung bestehen</string>
<string name="watcher_notification_text_paused">Überwachung der Netzwerkänderungen: pausiert</string>
<string name="tunnel_start_title">VPN verbunden</string>
<string name="tunnel_start_text">Mit Tunnel verbunden</string>
<string name="notification_permission_required">Berechtigung für die Benachrichtigung benötigt.</string>
<string name="add_trusted_ssid">Vertrauenswürdiger WiFi-Name hinzugügen</string>
<string name="prominent_background_location_message">Diese Funktion benötigt Standortberechtigung im Hintergrund um die WiFi SSIDs auch wenn die Applikation geschlossen ist zu überwachen. Für mehr Infos, siehe Privacy Policy auf der Hilfeseite.</string>
<string name="prominent_background_location_title">Vereinbarung der Standortberechtigung im Hintergrund</string>
<string name="thank_you">Danke fürs benutzen von WG Tunnel!</string>
<string name="trusted_ssid_empty_description">SSID eingeben</string>
<string name="trusted_ssid_value_description">SSID bestätigen</string>
<string name="add_tunnels_text">Von Datei oder ZIP hinzufügen</string>
<string name="open_file">Datei geöffnet</string>
<string name="add_from_qr">Von QR-Code hinzufügen</string>
<string name="qr_scan">Scanne QR</string>
<string name="tunnel_name">Verbindungsname</string>
<string name="add_tunnel">Verbindung hinzufügen</string>
<string name="exclude">Ausgenommen</string>
<string name="include">Eingeschlossen</string>
<string name="tunnel_all">Verbinde alle Apps</string>
<string name="config_changes_saved">Änderungen der Konfiguration gespeichert.</string>
<string name="save_changes">Speichern</string>
<string name="icon">Symbol</string>
<string name="no_thanks">Nein danke</string>
<string name="turn_on">Einschalten</string>
<string name="map">Karte</string>
<string name="public_key">Öffentlicher Schlüssel</string>
<string name="addresses">Adressen</string>
<string name="dns_servers">DNS-Server</string>
<string name="mtu">MTU</string>
<string name="peer">Peer</string>
<string name="allowed_ips">Erlaubte IPs</string>
<string name="endpoint">Endpunkt</string>
<string name="name">Name</string>
<string name="restart">Verbindung neustarten</string>
<string name="vpn_connection_failed">Verbindung fehlgeschlagen</string>
<string name="always_on_vpn_support">Erlaube Always-On VPN</string>
<string name="location_services_not_detected">Standortdienste Nicht Erkannt</string>
<string name="hint_search_packages">Suche packete</string>
<string name="clear_icon">Lösche Symbol</string>
<string name="vpn_starting">VPN startet</string>
<string name="db_name">wg-tunnel-db</string>
<string name="scanning_qr">Scanne nach QR</string>
<string name="none">Keine vertrauenswürdigen WiFi Namen</string>
<string name="other">Andere</string>
<string name="vpn_on">VPN an</string>
<string name="vpn_off">VPN aus</string>
<string name="default_vpn_on">Primärer VPN an</string>
<string name="create_import">Starte von Grund auf neu</string>
<string name="turn_off_auto">Für diese Aktion muss automatisches Verbinden ausgeschaltet oder pausiert sein</string>
<string name="add_peer">Peer hinzufügen</string>
<string name="done">Erledigt</string>
<string name="rotate_keys">Schlüssel ändern</string>
<string name="private_key">Privater Schlüssel</string>
<string name="copy_public_key">Öffentlicher Schlüssel kopieren</string>
<string name="base64_key">base64-Schlüssel</string>
<string name="comma_separated_list">Kommaseparierte Liste</string>
</resources>
+162
View File
@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="map">Mapa</string>
<string name="allowed_ips">Allowed IPs</string>
<string name="email_chooser">Enviar un email…</string>
<string name="go">ir</string>
<string name="discord_description">Únete a la comunidad</string>
<string name="kernel">Kernel</string>
<string name="restart">Reiniciar túnel</string>
<string name="vpn_connection_failed">Error de conexión</string>
<string name="error_none">Sin error</string>
<string name="other">Otros</string>
<string name="add_peer">Añadir peer</string>
<string name="done">Hecho</string>
<string name="copy_public_key">Copiar public key</string>
<string name="base64_key">clave base64</string>
<string name="exported_configs_message">Configuración exportada a Descargas</string>
<string name="tunnel_on_wifi">Túnel en Wi-Fi no de confianza</string>
<string name="location_services_missing_message">La app no detecta activado el servicio de ubicación en tu dispositivo. Dependiendo del dispositivo, esto podría hacer que la característica de Wi-Fi no de confianza falle al leer el nombre Wi-Fi. ¿Quieres continuar de todas formas?</string>
<string name="excluded">excluida(s)</string>
<string name="all">todas</string>
<string name="mobile_data_tunnel">Establecer como túnel en datos móviles</string>
<string name="use_tunnel_on_wifi_name">Usar tunnel en nombre Wi-Fi</string>
<string name="disabled">desactivado</string>
<string name="version">Versión</string>
<string name="userspace">Espacio del usuario</string>
<string name="mode">Modo</string>
<string name="support">Ayuda</string>
<string name="private_key">Clave privada</string>
<string name="trusted_ssid_value_description">Enviar SSID</string>
<string name="trusted_ssid_empty_description">Introducir SSID</string>
<string name="add_tunnels_text">Añadir desde archivo o zip</string>
<string name="open_file">Abrir archivo</string>
<string name="add_from_qr">Añadir mediante código QR</string>
<string name="qr_scan">Escanear QR</string>
<string name="tunnel_name">Nombre de túnel</string>
<string name="add_tunnel">Añadir túnel</string>
<string name="exclude">Excluir</string>
<string name="include">Incluir</string>
<string name="tunnel_all">Todas las apps por el túnel</string>
<string name="config_changes_saved">Cambios de configuración guardados.</string>
<string name="save_changes">Guardar</string>
<string name="icon">Icono</string>
<string name="no_thanks">No gracias</string>
<string name="turn_on">Activar</string>
<string name="mtu">MTU</string>
<string name="dns_servers">DNS servers</string>
<string name="addresses">Addresses</string>
<string name="public_key">Public key</string>
<string name="error_file_extension">No es un archivo .conf o .zip</string>
<string name="turn_off_tunnel">Desactiva antes el túnel</string>
<string name="no_tunnels">¡Ningún túnel añadido aún!</string>
<string name="watcher_notification_text_paused">Monitoreando cambios de red: En pausa</string>
<string name="watcher_notification_text_active">Monitoreando cambios de red: Activado</string>
<string name="tunnel_start_title">VPN conectada</string>
<string name="tunnel_start_text">Conectado al túnel</string>
<string name="notification_permission_required">Necesita permiso de notificaciones.</string>
<string name="add_trusted_ssid">Añadir nombres Wi-Fi de confianza</string>
<string name="tunnels">Túneles</string>
<string name="enable_auto_tunnel">Iniciar túnel-automático</string>
<string name="disable_auto_tunnel">Parar túnel-automático</string>
<string name="tunnel_mobile_data">Activar túnel en datos móviles</string>
<string name="one_tunnel_required">Esta característica necesita ser usada en almenos por un túnel</string>
<string name="privacy_policy">Ver Política de Privacidad</string>
<string name="okay">OK</string>
<string name="tunnel_on_ethernet">Túnel en ethernet</string>
<string name="prominent_background_location_title">Divulgación de la ubicación en segundo plano</string>
<string name="thank_you">¡Gracias por usar WG Tunnel!</string>
<string name="endpoint">Endpoint</string>
<string name="peer">Peer</string>
<string name="name">Nombre</string>
<string name="always_on_vpn_support">Permitir VPN siempre-activada</string>
<string name="location_services_not_detected">Servicios de Ubicación No Detectados</string>
<string name="hint_search_packages">Buscar paquetes</string>
<string name="clear_icon">Icono claro</string>
<string name="attempt_connection">Intentando conexión...</string>
<string name="vpn_starting">Iniciando VPN</string>
<string name="db_name">wg-tunnel-db</string>
<string name="scanning_qr">Escaneando QR</string>
<string name="none">Sin nombres Wi-Fi de confianza</string>
<string name="auto_tunneling">Túnel-automático</string>
<string name="vpn_on">VPN on</string>
<string name="vpn_off">VPN off</string>
<string name="default_vpn_on">VPN Principal on</string>
<string name="default_vpn_off">VPN Principal off</string>
<string name="create_import">Crear desde cero</string>
<string name="turn_off_auto">La acción necesita que túnel-automático esté desactivado o en pausa</string>
<string name="turn_on_tunnel">La acción necesita un túnel activado</string>
<string name="rotate_keys">Rotar claves</string>
<string name="comma_separated_list">lista separada por comas</string>
<string name="random">(aleatorio)</string>
<string name="optional">(opcional)</string>
<string name="optional_no_recommend">(opcional, no recomendado)</string>
<string name="seconds">segundos</string>
<string name="cancel">Cancelar</string>
<string name="error_authentication_failed">Fallo de autenticación</string>
<string name="error_authorization_failed">Fallo de autorización</string>
<string name="enabled_app_shortcuts">Habilitar acesos directos de app</string>
<string name="export_configs">Exportar configuración</string>
<string name="background_location_required">Se necesita ubicación en segundo plano</string>
<string name="location_services_required">Se necesita servicio de ubicación</string>
<string name="precise_location_required">Necesita ubicación precisa</string>
<string name="unknown_error">Error desconocido</string>
<string name="email_subject">Ayuda WG Tunnel</string>
<string name="interface_">Interfaz</string>
<string name="listen_port">Puerto de escucha</string>
<string name="preshared_key">Clave previamente compartida</string>
<string name="persistent_keepalive">Keepalive persistente</string>
<string name="search_icon">Icono de búsqueda</string>
<string name="docs_description">Leer documentación</string>
<string name="email_description">Envíame un email</string>
<string name="support_help_text">Si tienes problemas, ideas para mejoras, o simlemente comprometerte, tienes disponibles los siguientes recursos:</string>
<string name="use_kernel">Usar módulo del Kernel</string>
<string name="error_ssid_exists">SSID existente</string>
<string name="error_root_denied">Shell root denegado</string>
<string name="error_no_file_explorer">Explorador de archivos no instalado</string>
<string name="error_invalid_code">Código QR no valido</string>
<string name="auto_tunnel_title">Servicio túnel-automático</string>
<string name="delete_tunnel">Eliminar túnel</string>
<string name="delete_tunnel_message">¿Estás seguro de que quieres eliminar este túnel?</string>
<string name="yes"></string>
<string name="resume">Reanudar</string>
<string name="pause">Pausar</string>
<string name="active">activado</string>
<string name="paused">en pausa</string>
<string name="tunneling_apps">Apps por el túnel</string>
<string name="included">incluida(s)</string>
<string name="always_on_disabled">VPN siempre-activada ha intentado iniciar un túnel, pero está característica está deshabilitada en los ajustes.</string>
<string name="no_email_detected">Ninguna app de email detectada</string>
<string name="no_browser_detected">Ningún navegador detectado</string>
<string name="logs_saved">Registros guardados en Descargas</string>
<string name="open_issue">Abrir una incidencia</string>
<string name="read_logs">Leer los registros</string>
<string name="auto">(automático)</string>
<string name="config_parse_error">Fallo al analizar la configuración</string>
<string name="incorrect_pin">El pin no es correcto</string>
<string name="pin_created">Pin creado con éxito</string>
<string name="enter_pin">Introduce tu pin</string>
<string name="create_pin">Crear pin</string>
<string name="enable_app_lock">Bloqueo de app activado</string>
<string name="restart_on_ping">Reiniciar al fallar ping (beta)</string>
<string name="set_primary_tunnel">Establecer como túnel Principal</string>
<string name="no_wifi_names_configured">No hay nombres Wi-Fi configurados para este túnel</string>
<string name="general">General</string>
<string name="edit_tunnel">Editar túnel</string>
<string name="auto_on">Reanudar túnel-automático</string>
<string name="auto_off">Pausar túnel-automático</string>
<string name="auto_tun_on">Reanudar el túnel automático</string>
<string name="auto_tun_off">Pausa del túnel automático</string>
<string name="settings">Ajustes</string>
<string name="app_name">WG Tunnel</string>
<string name="vpn_channel_id">Canal VPN</string>
<string name="vpn_channel_name">Canal de notificación VPN</string>
<string name="watcher_channel_id">Canal del obvervador</string>
<string name="watcher_channel_name">Canal de notificación del obvervador</string>
<string name="prominent_background_location_message">La monitorización SSID Wi-Fi necesita de permiso de ubicación en segundo plano incluso si la app está cerrada. Mira el enlace a la Política de Privacidad en la pantalla de ayuda para más detalles.</string>
<string name="privacy_policy_url" translatable="false"></string>
<string name="docs_url" translatable="false"></string>
<string name="github_url" translatable="false"></string>
<string name="discord_url" translatable="false"></string>
<string name="my_email" translatable="false"></string>
</resources>
+3
View File
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>
+162
View File
@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WG Tunnel</string>
<string name="vpn_channel_id">VPN Kanalı</string>
<string name="vpn_channel_name">VPN Bildirim Kanalı</string>
<string name="watcher_channel_id">İzleyici Kanalı</string>
<string name="watcher_channel_name">İzleyici Bildirim Kanalı</string>
<string name="github_url" translatable="false">https://github.com/zaneschepke/wgtunnel/issues</string>
<string name="docs_url" translatable="false">https://zaneschepke.com/wgtunnel-docs/overview.html</string>
<string name="privacy_policy_url" translatable="false">https://zaneschepke.com/wgtunnel-docs/privacypolicy.html</string>
<string name="error_file_extension">Dosya bir .conf veya .zip değil</string>
<string name="turn_off_tunnel">Eylem tünelin kapalı olmasını gerektiriyor</string>
<string name="no_tunnels">Henüz bir tünel ekli değil!</string>
<string name="discord_url" translatable="false">https://discord.gg/rbRRNh6H7V</string>
<string name="watcher_notification_text_active">Ağ durumu değişikliklerini izleme: etkin</string>
<string name="watcher_notification_text_paused">Ağ durumu değişikliklerini izleme: duraklatıldı</string>
<string name="tunnel_start_title">VPN bağlandı</string>
<string name="tunnel_start_text">Tünele bağlı</string>
<string name="notification_permission_required">Bildirim izni gerekli.</string>
<string name="add_trusted_ssid">Güvenilir Wi-Fi adı ekle</string>
<string name="tunnels">Tüneller</string>
<string name="enable_auto_tunnel">Otomatik tünellemeyi başlat</string>
<string name="disable_auto_tunnel">Otomatik tünellemeyi durdur</string>
<string name="tunnel_mobile_data">Mobil veri üzerinde tünel</string>
<string name="one_tunnel_required">Bu özelliği kullanabilmek için en az bir tünel gereklidir.</string>
<string name="privacy_policy">Gizlilik Politikası</string>
<string name="okay">Tamam</string>
<string name="tunnel_on_ethernet">Ethernet üzerinde tünel</string>
<string name="prominent_background_location_message">Bu özellik, uygulama kapalıyken bile Wi-Fi SSID izlemesini etkinleştirmek için arka plan konumu izni gerektirir. Daha fazla bilgi için lütfen Destek ekranında bağlantısı verilen Gizlilik Politikasına bakın.</string>
<string name="prominent_background_location_title">Arka Plan Konum Açıklaması</string>
<string name="thank_you">WG Tunnel\'i kullandığınız için teşekkür ederiz!</string>
<string name="trusted_ssid_empty_description">SSID\'yi gir</string>
<string name="trusted_ssid_value_description">SSID\'yi gönder</string>
<string name="add_tunnels_text">Dosyadan veya ZIP\'ten ekle</string>
<string name="open_file">Dosya Aç</string>
<string name="add_from_qr">QR kodundan ekle</string>
<string name="qr_scan">QR kodu tarat</string>
<string name="tunnel_name">Tünel adı</string>
<string name="add_tunnel">Tünel ekle</string>
<string name="exclude">Hariç tut</string>
<string name="include">Dahil et</string>
<string name="tunnel_all">Tüm uygulamaları dahil et</string>
<string name="config_changes_saved">Yapılandırma değişiklikleri kaydedildi.</string>
<string name="save_changes">Kaydet</string>
<string name="icon">Simge</string>
<string name="no_thanks">Hayır, teşekkürler</string>
<string name="turn_on"></string>
<string name="map">Harita</string>
<string name="public_key">Genel anahtar</string>
<string name="addresses">Adresler</string>
<string name="dns_servers">DNS sunucuları</string>
<string name="mtu">MTU</string>
<string name="peer">Eş (peer)</string>
<string name="allowed_ips">İzin verilen IP\'ler</string>
<string name="endpoint">Uç nokta (endpoint)</string>
<string name="name">Ad</string>
<string name="restart">Tüneli Yeniden Başlat</string>
<string name="vpn_connection_failed">Bağlantı kurulamadı</string>
<string name="always_on_vpn_support">Her Zaman Açık VPN\'e İzin Ver</string>
<string name="location_services_not_detected">Konum Hizmetleri Algılanmadı</string>
<string name="hint_search_packages">Uygulama arayın</string>
<string name="clear_icon">Simgeyi Temizle</string>
<string name="search_icon">Simge Ara</string>
<string name="attempt_connection">Bağlantı kurulmaya çalışılıyor..</string>
<string name="vpn_starting">VPN başlatılıyor</string>
<string name="db_name">wg-tunnel-db</string>
<string name="scanning_qr">QR taranıyor</string>
<string name="none">Güvenilir Wi-Fi adı yok</string>
<string name="other">Diğer</string>
<string name="auto_tunneling">Otomatik tünelleme</string>
<string name="vpn_on">VPN açık</string>
<string name="vpn_off">VPN kapalı</string>
<string name="default_vpn_on">Birincil VPN açık</string>
<string name="default_vpn_off">Birincil VPN kapalı</string>
<string name="create_import">Sıfırdan oluştur</string>
<string name="turn_off_auto">Eylem, otomatik tünelin devre dışı bırakılmasını veya duraklatılmasını gerektirir</string>
<string name="turn_on_tunnel">Eylem aktif tünel gerektirir</string>
<string name="add_peer">Eş (peer) ekle</string>
<string name="done">Tamam</string>
<string name="interface_">Arayüz</string>
<string name="rotate_keys">Tuşları döndür</string>
<string name="private_key">Özel anahtar</string>
<string name="copy_public_key">Genel anahtarı kopyala</string>
<string name="base64_key">Base64 anahtarı</string>
<string name="comma_separated_list">Virgül ile ayrılmış liste ekleyin</string>
<string name="listen_port">Bağlantı noktası</string>
<string name="random">(Rastgele)</string>
<string name="optional">(İsteğe bağlı)</string>
<string name="optional_no_recommend">(İsteğe bağlı, önerilmez)</string>
<string name="preshared_key">Ön paylaşımlı anahtar</string>
<string name="seconds">saniye</string>
<string name="persistent_keepalive">Kalıcı olarak canlı tutma</string>
<string name="cancel">İptal</string>
<string name="error_authentication_failed">Kimlik doğrulama başarısız oldu</string>
<string name="error_authorization_failed">Yetkilendirilemedi</string>
<string name="enabled_app_shortcuts">Uygulama kısayollarını etkinleştir</string>
<string name="export_configs">Yapılandırmaları dışa aktar</string>
<string name="location_services_required">Gerekli konum hizmetleri</string>
<string name="background_location_required">Arka plan konumu gerekli</string>
<string name="precise_location_required">Kesin konum gerekli</string>
<string name="unknown_error">Bilinmeyen bir hata oluştu</string>
<string name="exported_configs_message">Yapılandırmalar indirilenler\'e aktarıldı</string>
<string name="tunnel_on_wifi">Güvenilmeyen kablosuz internet bağlantısında tünel</string>
<string name="my_email" translatable="false">support@zaneschepke.com</string>
<string name="email_subject">WG Tunnel Desteği</string>
<string name="email_chooser">Bir e-posta gönderin…</string>
<string name="go">git</string>
<string name="docs_description">Belgeleri oku</string>
<string name="discord_description">Topluluğa katıl</string>
<string name="email_description">Bana e-posta gönder</string>
<string name="support_help_text">Sorun yaşıyorsanız, iyileştirme fikirleriniz varsa veya sadece etkileşimde bulunmak istiyorsanız, aşağıdaki kaynaklar mevcuttur:</string>
<string name="kernel">Çekirdek</string>
<string name="use_kernel">Çekirdek modülünü kullan</string>
<string name="error_ssid_exists">SSID zaten var</string>
<string name="error_root_denied">Kök kabuğu reddedildi</string>
<string name="error_no_file_explorer">Yüklü dosya gezgini yok</string>
<string name="error_invalid_code">Geçersiz QR kodu</string>
<string name="error_none">Hata yok</string>
<string name="location_services_missing_message">Uygulama, cihazınızda etkinleştirilen herhangi bir konum hizmeti algılamıyor. Cihaza bağlı olarak bu, güvenilmeyen Wi-Fi özelliğinin Wi-Fi adını okuyamamasına neden olabilir. Yine de devam etmek ister misiniz?</string>
<string name="auto_tunnel_title">Otomatik Tünel Hizmeti</string>
<string name="delete_tunnel">Tüneli sil</string>
<string name="delete_tunnel_message">Bu tüneli silmek istediğinizden emin misiniz?</string>
<string name="yes">Evet</string>
<string name="resume">Devam et</string>
<string name="pause">Duraklat</string>
<string name="paused">duraklatıldı</string>
<string name="active">aktif</string>
<string name="tunneling_apps">Tünellenen uygulamalar</string>
<string name="included">dahil edildi</string>
<string name="excluded">hariç tutuldu</string>
<string name="all">tümü</string>
<string name="always_on_disabled">Her zaman açık VPN bir tünel başlatmaya çalıştı, ancak bu özellik ayarlarda devre dışı bırakıldı.</string>
<string name="no_email_detected">E-posta uygulaması algılanmadı</string>
<string name="no_browser_detected">Tarayıcı algılanmadı</string>
<string name="logs_saved">İndirilenlere kaydedilen günlükler</string>
<string name="open_issue">Bir sorun bildir</string>
<string name="read_logs">Günlükleri oku</string>
<string name="auto">(Otomatik)</string>
<string name="config_parse_error">Yapılandırma kaydedilemedi</string>
<string name="incorrect_pin">PIN kodu yanlış</string>
<string name="pin_created">Pin başarıyla oluşturuldu</string>
<string name="enter_pin">PIN kodunuzu girin</string>
<string name="create_pin">PIN kodu oluştur</string>
<string name="enable_app_lock">Uygulama kilidini etkinleştir</string>
<string name="restart_on_ping">Ping başarısız olduğunda yeniden başlat (beta)</string>
<string name="mobile_data_tunnel">Mobil veri tüneli olarak ayarla</string>
<string name="set_primary_tunnel">Birincil tünel olarak ayarla</string>
<string name="use_tunnel_on_wifi_name">Wi-Fi adında tünel kullan</string>
<string name="no_wifi_names_configured">Bu tünel için yapılandırılmış Wi-Fi adı yok</string>
<string name="general">Genel</string>
<string name="edit_tunnel">Tüneli düzenle</string>
<string name="disabled">Devre dışı</string>
<string name="auto_on">Otomatik ayarlamayı sürdür</string>
<string name="auto_off">Otomatik ayarlamayı duraklat</string>
<string name="auto_tun_on">Otomatik tüneli sürdür</string>
<string name="auto_tun_off">Otomatik tüneli duraklat</string>
<string name="version">Sürüm</string>
<string name="mode">Mod</string>
<string name="userspace">Kullanıcı alanı</string>
<string name="settings">Ayarlar</string>
<string name="support">Destek</string>
</resources>
-7
View File
@@ -1,11 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black_background">#FF1c1b20</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_channel_background">#1D1A20</color>
</resources>
+6 -36
View File
@@ -4,32 +4,24 @@
<string name="vpn_channel_name">VPN Notification Channel</string>
<string name="watcher_channel_id">Watcher Channel</string>
<string name="watcher_channel_name">Watcher Notification Channel</string>
<string name="foreground_file">FOREGROUND_FILE</string>
<string name="github_url" translatable="false">https://github.com/zaneschepke/wgtunnel/issues</string>
<string name="docs_url" translatable="false">https://zaneschepke.com/wgtunnel-docs/overview.html</string>
<string name="privacy_policy_url" translatable="false">https://zaneschepke.com/wgtunnel-docs/privacypolicy.html</string>
<string name="error_file_extension">File is not a .conf or .zip</string>
<string name="turn_off_tunnel">Action requires tunnel off</string>
<string name="no_tunnels">No tunnels added yet!</string>
<string name="tunnel_exists">Tunnel name already exists</string>
<string name="discord_url" translatable="false">https://discord.gg/rbRRNh6H7V</string>
<string name="watcher_notification_title">Watcher Service</string>
<string name="watcher_notification_text_active">Monitoring network state changes: active</string>
<string name="watcher_notification_text_paused">Monitoring network state changes: paused</string>
<string name="tunnel_start_title">VPN connected</string>
<string name="tunnel_start_text">Connected to tunnel</string>
<string name="vpn_permission_required">VPN permission is required for the app to work properly. If this permission is not launching, please disable \"Always-on VPN\" in your phone settings for the official WireGuard mobile app and try again.</string>
<string name="notification_permission_required">Notifications permission required.</string>
<string name="open_settings">Open Settings</string>
<string name="add_trusted_ssid">Add trusted wifi name</string>
<string name="tunnels">Tunnels</string>
<string name="enable_auto_tunnel">Start auto-tunneling</string>
<string name="disable_auto_tunnel">Stop auto-tunneling</string>
<string name="tunnel_mobile_data">Tunnel on mobile data</string>
<string name="background_location_reason">\"Allow all the time\" location permission is required for retrieving Wi-Fi SSID in the background. Permission is needed for this feature.</string>
<string name="location_permission_reason">Location permission is required for this feature to work properly.</string>
<string name="one_tunnel_required">At least one tunnel required to use this feature</string>
<string name="retry">"Retry"</string>
<string name="privacy_policy">View Privacy Policy</string>
<string name="okay">Okay</string>
<string name="tunnel_on_ethernet">Tunnel on ethernet</string>
@@ -38,12 +30,10 @@
<string name="thank_you">Thank you for using WG Tunnel!</string>
<string name="trusted_ssid_empty_description">Enter SSID</string>
<string name="trusted_ssid_value_description">Submit SSID</string>
<string name="config_validation" translatable="false">[Interface]</string>
<string name="add_tunnels_text">Add from file or zip</string>
<string name="open_file">File Open</string>
<string name="add_from_qr">Add from QR code</string>
<string name="qr_scan">QR Scan</string>
<string name="tunnel_edit">Tunnel Edit</string>
<string name="tunnel_name">Tunnel Name</string>
<string name="add_tunnel">Add Tunnel</string>
<string name="exclude">Exclude</string>
@@ -55,34 +45,18 @@
<string name="no_thanks">No thanks</string>
<string name="turn_on">Turn on</string>
<string name="map">Map</string>
<string name="bad_config">Bad config. Please try again.</string>
<string name="config_interface">Interface</string>
<string name="public_key">Public key</string>
<string name="barcode_downloading">Waiting for the Barcode UI module to be downloaded.</string>
<string name="barcode_downloading_message">Barcode module downloading. Try again.</string>
<string name="addresses">Addresses</string>
<string name="dns_servers">DNS servers</string>
<string name="mtu">MTU</string>
<string name="peer">Peer</string>
<string name="allowed_ips">Allowed IPs</string>
<string name="endpoint">Endpoint</string>
<string name="transfer">Transfer</string>
<string name="last_handshake">Last handshake</string>
<string name="name">Name</string>
<string name="restart">Restart Tunnel</string>
<string name="vpn_connection_failed">Connection failed</string>
<string name="failed_connection_to">Failed connection to -</string>
<string name="initial_connection_failure_message">Attempting to connect to server after 30 seconds of no response.</string>
<string name="lost_connection_failure_message">Attempting to reconnect to server after more than one minute of no response.</string>
<string name="always_on_vpn_support">Allow Always-On VPN </string>
<string name="select_tunnel_message">Please select a tunnel first</string>
<string name="location_services_not_detected">Location Services Not Detected</string>
<string name="check_again">Check again</string>
<string name="detecting_location_services_disabled">Detecting Location Services disabled</string>
<string name="precise_location_message">This feature requires precise location to access Wi-Fi SSID name. Please enable precise location here or in the app settings.</string>
<string name="request">Request</string>
<string name="toggle_vpn">Toggle VPN</string>
<string name="no_tunnel_available">No tunnels available</string>
<string name="hint_search_packages">Search packages</string>
<string name="clear_icon">Clear Icon</string>
<string name="search_icon">Search Icon</string>
@@ -90,13 +64,9 @@
<string name="vpn_starting">VPN starting</string>
<string name="db_name">wg-tunnel-db</string>
<string name="scanning_qr">Scanning for QR</string>
<string name="qr_result_failed">QR scan failed</string>
<string name="none">No trusted wifi names</string>
<string name="never">Never</string>
<string name="stream_failed">Failed to open file stream.</string>
<string name="other">Other</string>
<string name="auto_tunneling">Auto-tunneling</string>
<string name="select_tunnel">Select tunnel to use</string>
<string name="vpn_on">VPN on</string>
<string name="vpn_off">VPN off</string>
<string name="default_vpn_on">Primary VPN on</string>
@@ -124,7 +94,6 @@
<string name="error_authorization_failed">Failed to authorize</string>
<string name="enabled_app_shortcuts">Enable app shortcuts</string>
<string name="export_configs">Export configs</string>
<string name="battery_saver">Battery saver (beta)</string>
<string name="location_services_required">Location services required</string>
<string name="background_location_required">Background location required</string>
<string name="precise_location_required">Precise location required</string>
@@ -135,7 +104,7 @@
<string name="email_subject">WG Tunnel Support</string>
<string name="email_chooser">Send an email…</string>
<string name="go">go</string>
<string name="docs_description">Read the docs (WIP)</string>
<string name="docs_description">Read the docs</string>
<string name="discord_description">Join the community</string>
<string name="email_description">Send me an email</string>
<string name="support_help_text">If you are experiencing issues, have improvement ideas, or just want to engage, the following resources are available:</string>
@@ -144,11 +113,8 @@
<string name="error_ssid_exists">SSID already exists</string>
<string name="error_root_denied">Root shell denied</string>
<string name="error_no_file_explorer">No file explorer installed</string>
<string name="error_no_scan">No code scanned</string>
<string name="error_invalid_code">Invalid QR code</string>
<string name="error_none">No error</string>
<string name="error_file_read">Failed to read file</string>
<string name="location_service_missing">Location Services Not Detected</string>
<string name="location_services_missing_message">The app is not detecting any location services enabled on your device. Depending on the device, this could cause the untrusted wifi feature to fail to read the wifi name. Would you like to continue anyways?</string>
<string name="auto_tunnel_title">Auto-tunnel Service</string>
<string name="delete_tunnel">Delete tunnel</string>
@@ -182,10 +148,14 @@
<string name="no_wifi_names_configured">No wifi names configured for this tunnel</string>
<string name="general">General</string>
<string name="edit_tunnel">Edit tunnel</string>
<string name="tunnel">Tunnel</string>
<string name="disabled">disabled</string>
<string name="auto_on">Resume auto tun</string>
<string name="auto_off">Pause auto tun</string>
<string name="auto_tun_on">Resume auto-tunnel</string>
<string name="auto_tun_off">Pause auto-tunnel</string>
<string name="version">Version</string>
<string name="mode">Mode</string>
<string name="userspace">Userspace</string>
<string name="settings">Settings</string>
<string name="support">Support</string>
</resources>
+2 -2
View File
@@ -1,7 +1,7 @@
object Constants {
const val VERSION_NAME = "3.4.0"
const val VERSION_NAME = "3.4.3-alpha"
const val JVM_TARGET = "17"
const val VERSION_CODE = 34000
const val VERSION_CODE = 34201
const val TARGET_SDK = 34
const val MIN_SDK = 26
const val APP_ID = "com.zaneschepke.wireguardautotunnel"
@@ -0,0 +1,3 @@
Verbesserungen:
- Berechtigungsfehler auf Android Versionen vor 9 behoben
- Andere Optimierungen
@@ -0,0 +1,5 @@
Verbesserungen:
- Tunnelstatistiken zum Hauptbildschirm hinzugefügt
- Navigation der Einstellungen auf AndroidTV verbessert
- Vibration von Benachrichtigungen entfernt
- Verschiedene andere Fehlerbehebungen
@@ -0,0 +1,5 @@
Verbesserungen:
- Unterstützung für Tunnelung nur bei Verwendung von Mobilen Daten
- Verbesserungen der Support Oberfläche
- Aktualisierung der Ressourcenlinks
- Verschiedene andere Fehlerbehebungen
@@ -0,0 +1,5 @@
Verbesserungen:
- Grundlegende Unterstützung für WireGuard Kernelmodus hinzugefügt
- Verbesserung des Positionsanfrage
- Behebung eines Berechtigungsfehlers bei Auto-Tunneln
- Verschiedene andere GUI Fehlerbehebungen
@@ -0,0 +1,2 @@
Fehlerbehebungen:
- Android 14 Vordergrundberechtigungen
@@ -0,0 +1,7 @@
Verbesserungen:
- Refaktorierung der Zustandsverwaltung
- Verbesserung der AndroidTV Navigation
- Verbesserung der Auto-Tunnel Effizienz
- Navigation verbessert
- Auto-Tunnel Pausefunktion
- Viele Fehlerbehebungen
@@ -0,0 +1,13 @@
Funktionen
- Hinzufügen von Tunneln über .conf Dateien, Zip, Manuelle Eingabe oder QR Codes
- Automatische Verbindung zum VPN basierend auf der Wifi-SSID, Ethernet und mobilen Daten
- Geteilter Tunnel für Anwendungen mit Suche
- Unterstützung für Wireguard Userspace- und Kernel-modus
- Always-On VPN Unterstützung
- Export von Tunneln ins Zip Format
- Quicktiles zum aktivieren/deaktivieren der VPN Verbindung
- Feste Shortcuts für den Haupttunnel für automatische Integration
- Intent basierten Automationssupport für alle Tunnel
- Automatischer Servicestart nach Geräteneustart
- Akkuerhaltungsfunktionen
@@ -0,0 +1 @@
Eine alternative VPN Client App für Wireguard mit zusätzlichen Funktionen
@@ -0,0 +1 @@
WG Tunnel
@@ -0,0 +1,5 @@
What's new:
- Improved auto tunnel reliability
- Improved tile sync
- Added AndroidTV assets
- Added apk fingerprint
@@ -0,0 +1,5 @@
What's new:
- Fix stop tunnel regression
- Add logs obfuscation
- Add hide FAB on scroll
- Add Turkish localization
@@ -0,0 +1,2 @@
What's new:
- AmneziaWG support
@@ -0,0 +1,3 @@
Mejoras:
- Corrección de fallo de permisos en < Android 9
- Otras optimizaciones
@@ -0,0 +1,5 @@
Mejoras:
- Añadidas estadísticas del túnel a la pantalla principal
- Navegación mejorada en la pantalla de ajustes para AndroidTV
- Vibración de notificación quitada
- Otras correcciones
@@ -0,0 +1,5 @@
Mejoras:
- Compatibilidad de túnel-automático cuando solo para datos móviles
- UI de la pantalla de ayuda mojorada
- Enlaces de recursos mejorados
- Otras correcciones
@@ -0,0 +1,2 @@
Mejoras:
- Añadida compatiblidad básica de Kernel WireGuard
@@ -0,0 +1,2 @@
Correcciones:
- Permisos en primer plano en Android 14
@@ -0,0 +1,13 @@
Características:
- Añadir túneles vía .conf file, zip, manualmente, o código QR
- Conexión automática a la VPN basado en el SSID Wi-Fi, ethernet, o datos móviles
- División de túnel por aplicacióno con búsqueda
- Compatibilidad WireGuard para modos kernel y userspace
- Compatibilidad con VPN Siempre-Activada
- Exportar túmeles como zip
- Añadido interruptor VPN en el Centro de Control
- Accesos directos estáticos para túnel principal para intergración con apps de automatización
- Intents de apps de automatización para todos los túneles
- Inicio automático del servicio tras reinicio
- Medidas para ahorro de batería
@@ -0,0 +1 @@
Una app cliente VPN alternativa para WireGuard con características adicionales
@@ -0,0 +1 @@
WG Tunnel
@@ -0,0 +1,13 @@
Возможности
- Добавляйте туннели через файл .conf, zip, ввод вручную или QR-код
- Автоматическое подключение к VPN основываясь на SSID Wi-Fi, подключению по Ethernet или мобильных данных
- Разделение туннелирования по приложениям с поиском
- Поддержка WireGuard для режимов ядра и пользовательского пространства
- Поддержка режима VPN Всегда-Включено
- Экспорт туннелей в zip
- Поддержка быстрой плитки для переключения VPN
- Поддержка статических ярлыков для основного туннеля для интеграции автоматизации
- Поддержка автоматизации через intent для всех туннелей
- Автоматический перезапуск службы после перезагрузки
- Меры по сохранению аккумулятора
@@ -0,0 +1 @@
Альтернативный VPN-клиент для WireGuard с дополнительными функциями
+1
View File
@@ -0,0 +1 @@
WG Тунель
@@ -0,0 +1,13 @@
Özellikler
- .conf dosyası, zip, manuel giriş veya QR kodu aracılığıyla tüneller ekleme
- Wi-Fi SSID'ye, ethernet'e veya mobil veriye dayalı VPN'ye otomatik bağlanma
- Uygulama bazında split tunneling ve arama desteği
- Kernel ve kullanıcı alanı modları için WireGuard desteği
- Her zaman açık VPN desteği
- Tünelleri zip olarak dışa aktarma
- VPN geçişleri için hızlı kısayol desteği
- Otomasyon entegrasyonu için birincil tünel için statik kısayollar desteği
- Tüm tüneller için Intent otomasyon desteği
- Yeniden başlatma sonrası otomatik olarak servisi yeniden başlatma
- Batarya koruma önlemleri
@@ -0,0 +1 @@
WireGuard için ek özelliklere sahip alternatif bir VPN istemci uygulaması
+1
View File
@@ -0,0 +1 @@
WG Tunnel
+3 -1
View File
@@ -1,6 +1,7 @@
[versions]
accompanist = "0.34.0"
activityCompose = "1.8.2"
amneziawgAndroid = "1.1.0"
androidx-junit = "1.1.5"
appcompat = "1.6.1"
biometricKtx = "1.2.0-alpha05"
@@ -20,7 +21,7 @@ pinLockCompose = "1.0.3"
roomVersion = "2.6.1"
timber = "5.0.1"
tunnel = "1.0.20230706"
androidGradlePlugin = "8.3.1"
androidGradlePlugin = "8.4.0-rc02"
kotlin = "1.9.23"
ksp = "1.9.23-1.0.19"
composeBom = "2024.03.00"
@@ -41,6 +42,7 @@ accompanist-flowlayout = { module = "com.google.accompanist:accompanist-flowlayo
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }
#room
amneziawg-android = { module = "com.zaneschepke:amneziawg-android", version.ref = "amneziawgAndroid" }
androidx-biometric-ktx = { module = "androidx.biometric:biometric-ktx", version.ref = "biometricKtx" }
androidx-core = { module = "androidx.core:core", version.ref = "coreKtx" }
androidx-core-google-shortcuts = { module = "androidx.core:core-google-shortcuts", version.ref = "coreGoogleShortcuts" }
+2 -2
View File
@@ -1,8 +1,8 @@
#Wed Oct 11 22:39:21 EDT 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
@@ -3,14 +3,29 @@ package com.zaneschepke.logcatter
import com.zaneschepke.logcatter.model.LogMessage
object Logcatter {
fun logs(callback: (input: LogMessage) -> Unit) {
private val findKeyRegex = """[A-Za-z0-9+/]{42}[AEIMQUYcgkosw480]=""".toRegex()
private val findIpv6AddressRegex = """(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))""".toRegex()
private val findIpv4AddressRegex = """((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}""".toRegex()
private val findTunnelNameRegex = """(?<=tunnel ).*?(?= UP| DOWN)""".toRegex()
fun logs(callback: (input: LogMessage) -> Unit, obfuscator: (log : String) -> String = { log -> this.obfuscator(log)}){
clear()
Runtime.getRuntime().exec("logcat -v epoch")
.inputStream
.bufferedReader()
.useLines { lines ->
lines.forEach { callback(LogMessage.from(it)) }
lines.forEach { callback(LogMessage.from(obfuscator(it))) }
}
}
private fun obfuscator(log : String) : String {
return findKeyRegex.replace(log, "<crypto-key>").let { first ->
findIpv6AddressRegex.replace(first, "<ipv6-address>").let { second ->
findTunnelNameRegex.replace(second, "<tunnel>")
}
}.let{ last -> findIpv4AddressRegex.replace(last,"<ipv4-address>") }
}
fun clear() {