Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0b4192cbd | |||
| 32a055093a | |||
| 51558c7027 | |||
| b85286f0ab | |||
| 48f3fbd715 | |||
| 458f66818a | |||
| 7964dc7993 | |||
| 0ac5d7d461 | |||
| 826914a4f3 | |||
| 261da431e7 | |||
| 94b33abf5e | |||
| 8325056ccc | |||
| 81a1b2c907 | |||
| fc8f89fb83 | |||
| d846c7745f | |||
| 61c6fd6c02 | |||
| abe5708058 | |||
| 626339bddb | |||
| 381ae23c07 | |||
| 52382d1d7a | |||
| 68e5216d4b |
@@ -18,8 +18,8 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
os: ubuntu-24.04-arm
|
||||
- platform: linux/arm/v7
|
||||
os: ubuntu-24.04-arm
|
||||
# - platform: linux/arm/v7
|
||||
# os: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
needs: docker-build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-*
|
||||
|
||||
@@ -25,8 +25,8 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
os: ubuntu-24.04-arm
|
||||
- platform: linux/arm/v7
|
||||
os: ubuntu-24.04-arm
|
||||
# - platform: linux/arm/v7
|
||||
# os: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
@@ -94,7 +94,7 @@ jobs:
|
||||
needs: docker-build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-*
|
||||
|
||||
@@ -21,8 +21,8 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
os: ubuntu-24.04-arm
|
||||
- platform: linux/arm/v7
|
||||
os: ubuntu-24.04-arm
|
||||
# - platform: linux/arm/v7
|
||||
# os: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ jobs:
|
||||
os: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
os: ubuntu-24.04-arm
|
||||
- platform: linux/arm/v7
|
||||
os: ubuntu-24.04-arm
|
||||
# - platform: linux/arm/v7
|
||||
# os: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
needs: docker-build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-*
|
||||
|
||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
||||
"aaron-bond.better-comments",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"antfu.goto-alias",
|
||||
"esbenp.prettier-vscode",
|
||||
"prettier.prettier-vscode",
|
||||
"yoavbls.pretty-ts-errors",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"vue.volar",
|
||||
|
||||
Vendored
+5
-5
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"editor.tabSize": 2,
|
||||
"editor.useTabStops": false,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.defaultFormatter": "prettier.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "always"
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "prettier.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "prettier.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "prettier.prettier-vscode"
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.defaultFormatter": "prettier.prettier-vscode",
|
||||
"editor.tabSize": 4,
|
||||
"editor.useTabStops": false
|
||||
},
|
||||
|
||||
+17
-5
@@ -7,7 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## Added
|
||||
## [15.2.1] - 2026-01-14
|
||||
|
||||
### Fixed
|
||||
|
||||
- Icon in Searchbar (https://github.com/wg-easy/wg-easy/commit/458f66818a400f181e2c6326ede077c8793d71f2)
|
||||
- Interface save not working (https://github.com/wg-easy/wg-easy/commit/48f3fbd715a889e2425702a8a46332f2752aef91)
|
||||
- Error Messages in Setup (https://github.com/wg-easy/wg-easy/commit/32a055093a76342c40858d8dcf563b0700a8bd48)
|
||||
|
||||
## [15.2.0] - 2026-01-12
|
||||
|
||||
### Added
|
||||
|
||||
- AmneziaWG integration (https://github.com/wg-easy/wg-easy/pull/2102, https://github.com/wg-easy/wg-easy/pull/2226)
|
||||
- Search / filter box (https://github.com/wg-easy/wg-easy/pull/2170)
|
||||
@@ -15,13 +25,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Show client endpoint (https://github.com/wg-easy/wg-easy/pull/2058)
|
||||
- Add option to view and copy config (https://github.com/wg-easy/wg-easy/pull/2289)
|
||||
|
||||
## Fixed
|
||||
### Fixed
|
||||
|
||||
- Fix download as conf.txt (https://github.com/wg-easy/wg-easy/pull/2269)
|
||||
- Clean filename for OTL download (https://github.com/wg-easy/wg-easy/pull/2253)
|
||||
- Text color in admin menu in light mode (https://github.com/wg-easy/wg-easy/pull/2307)
|
||||
|
||||
## Changed
|
||||
### Changed
|
||||
|
||||
- Allow lower MTU (https://github.com/wg-easy/wg-easy/pull/2228)
|
||||
- Use /32 and /128 for client Cidr (https://github.com/wg-easy/wg-easy/pull/2217)
|
||||
@@ -30,11 +40,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Allow empty DNS (https://github.com/wg-easy/wg-easy/pull/2052, https://github.com/wg-easy/wg-easy/pull/2057)
|
||||
- Don't include keys in API responses (https://github.com/wg-easy/wg-easy/pull/2015)
|
||||
- Try all QR ecc levels (https://github.com/wg-easy/wg-easy/pull/2288)
|
||||
- Update OneTimeLink expiry on reuse (https://github.com/wg-easy/wg-easy/pull/2370)
|
||||
- Removed ARMv7 support (https://github.com/wg-easy/wg-easy/pull/2369)
|
||||
|
||||
## Docs
|
||||
### Docs
|
||||
|
||||
- Add AdGuard Home (https://github.com/wg-easy/wg-easy/pull/2175)
|
||||
- Add Routed (No NAT) docs (https://github.com/wg-easy/wg-easy/pull/2181)
|
||||
- Add Routed (No NAT) docs (https://github.com/wg-easy/wg-easy/pull/2181, https://github.com/wg-easy/wg-easy/pull/2380)
|
||||
- Add AmneziaWG docs (https://github.com/wg-easy/wg-easy/pull/2108, https://github.com/wg-easy/wg-easy/pull/2292)
|
||||
|
||||
## [15.1.0] - 2025-07-01
|
||||
|
||||
@@ -7,7 +7,7 @@ This guide will help you migrate from `v14` to version `v15` of `wg-easy`.
|
||||
## Changes
|
||||
|
||||
- This is a complete rewrite of the `wg-easy` project, therefore the configuration files and the way you interact with the project have changed.
|
||||
- If you use armv6, you unfortunately won't be able to migrate to `v15`.
|
||||
- If you use armv6 or armv7, you unfortunately won't be able to migrate to `v15`.
|
||||
- If you are connecting to the Web UI via HTTP, you need to set the `INSECURE` environment variable to `true` in the new container.
|
||||
|
||||
## Migration
|
||||
|
||||
@@ -8,7 +8,7 @@ title: Basic Installation
|
||||
|
||||
1. You need to have a host that you can manage
|
||||
2. You need to have a domain name or a public IP address
|
||||
3. You need a supported architecture (x86_64, arm64, armv7)
|
||||
3. You need a supported architecture (x86_64, arm64)
|
||||
4. You need curl installed on your host
|
||||
|
||||
## Install Docker
|
||||
|
||||
@@ -93,3 +93,19 @@ PostDown
|
||||
```shell
|
||||
iptables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; ip6tables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT
|
||||
```
|
||||
|
||||
/// warning | Important: When using nftables use the following hooks instead.
|
||||
|
||||
PostUp
|
||||
|
||||
```shell
|
||||
nft add chain ip filter WG_EASY; nft add rule ip filter DOCKER-USER jump WG_EASY; nft add rule ip filter WG_EASY iifname {{device}} accept; nft add rule ip filter WG_EASY oifname {{device}} accept; nft add chain ip6 filter WG_EASY; nft add rule ip6 filter DOCKER-USER jump WG_EASY; nft add rule ip6 filter WG_EASY iifname {{device}} accept; nft add rule ip6 filter WG_EASY oifname {{device}} accept;
|
||||
```
|
||||
|
||||
PostDown
|
||||
|
||||
```shell
|
||||
nft delete rule ip filter DOCKER-USER handle $(nft -a list chain ip filter DOCKER-USER | awk '/jump WG_EASY/ {print $NF}'); nft flush chain ip filter WG_EASY; nft delete chain ip filter WG_EASY; nft delete rule ip6 filter DOCKER-USER handle $(nft -a list chain ip6 filter DOCKER-USER | awk '/jump WG_EASY/ {print $NF}'); nft flush chain ip6 filter WG_EASY; nft delete chain ip6 filter WG_EASY
|
||||
```
|
||||
|
||||
///
|
||||
|
||||
@@ -12,7 +12,7 @@ Before you can get started with deploying your own VPN, there are some requireme
|
||||
|
||||
1. You need to have a host that you can manage
|
||||
2. You need to have a domain name or a public IP address
|
||||
3. You need a supported architecture (x86_64, arm64, armv7)
|
||||
3. You need a supported architecture (x86_64, arm64)
|
||||
|
||||
### Host Setup
|
||||
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@
|
||||
"format:check:docs": "prettier --check docs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^3.7.3"
|
||||
"prettier": "^3.7.4"
|
||||
},
|
||||
"packageManager": "pnpm@10.24.0"
|
||||
"packageManager": "pnpm@10.28.0"
|
||||
}
|
||||
|
||||
Generated
+5
-5
@@ -9,16 +9,16 @@ importers:
|
||||
.:
|
||||
devDependencies:
|
||||
prettier:
|
||||
specifier: ^3.7.3
|
||||
version: 3.7.3
|
||||
specifier: ^3.7.4
|
||||
version: 3.7.4
|
||||
|
||||
packages:
|
||||
|
||||
prettier@3.7.3:
|
||||
resolution: {integrity: sha512-QgODejq9K3OzoBbuyobZlUhznP5SKwPqp+6Q6xw6o8gnhr4O85L2U915iM2IDcfF2NPXVaM9zlo9tdwipnYwzg==}
|
||||
prettier@3.7.4:
|
||||
resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
|
||||
snapshots:
|
||||
|
||||
prettier@3.7.3: {}
|
||||
prettier@3.7.4: {}
|
||||
|
||||
@@ -30,6 +30,7 @@ echo "Updated package.json to version $new_version"
|
||||
|
||||
echo "----"
|
||||
echo "If you changed the major version, remember to update the docker-compose.yml file and docs (search for: ref: major version)"
|
||||
echo "Make sure to stage any changes before proceeding (e.g. Changelog updates)."
|
||||
echo "----"
|
||||
|
||||
echo "If you did everything press 'y' to commit the changes and create a new tag"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="relative w-60 md:mr-2">
|
||||
<div class="relative flex h-full items-center">
|
||||
<MagnifyingGlassIcon
|
||||
<IconsMagnifyingGlass
|
||||
class="absolute left-2.5 h-4 w-4 text-gray-400 dark:text-neutral-500"
|
||||
/>
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="$t('client.search')"
|
||||
class="w-full rounded bg-white py-2 pr-8 text-sm text-gray-900 shadow-sm ring-1 ring-gray-300 transition-all placeholder:text-gray-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-red-600 dark:bg-neutral-800 dark:text-white dark:ring-neutral-700 dark:placeholder:text-neutral-500 dark:focus:ring-red-700"
|
||||
class="w-full rounded bg-white px-8 py-2 text-sm text-gray-900 shadow-sm ring-1 ring-gray-300 transition-all placeholder:text-gray-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-red-600 dark:bg-neutral-800 dark:text-white dark:ring-neutral-700 dark:placeholder:text-neutral-500 dark:focus:ring-red-700"
|
||||
@input="updateSearch"
|
||||
/>
|
||||
<button
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<MagnifyingGlassIcon />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MagnifyingGlassIcon from '@heroicons/vue/24/outline/esm/MagnifyingGlassIcon';
|
||||
</script>
|
||||
@@ -4,25 +4,27 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const event = useRequestEvent();
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const userData = await authStore.getSession();
|
||||
authStore.userData = await authStore.getSession(event);
|
||||
|
||||
// skip login if already logged in
|
||||
if (to.path === '/login') {
|
||||
if (userData?.username) {
|
||||
if (authStore.userData?.username) {
|
||||
return navigateTo('/', { redirectCode: 302 });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Require auth for every page other than Login
|
||||
if (!userData?.username) {
|
||||
if (!authStore.userData?.username) {
|
||||
return navigateTo('/login', { redirectCode: 302 });
|
||||
}
|
||||
|
||||
// Check for admin access
|
||||
if (to.path.startsWith('/admin')) {
|
||||
if (!hasPermissions(userData, 'admin', 'any')) {
|
||||
if (!hasPermissions(authStore.userData, 'admin', 'any')) {
|
||||
return abortNavigation('Not allowed to access Admin Panel');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,9 +38,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const authStore = useAuthStore();
|
||||
authStore.update();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
@@ -206,9 +206,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const authStore = useAuthStore();
|
||||
const globalStore = useGlobalStore();
|
||||
authStore.update();
|
||||
|
||||
const route = useRoute();
|
||||
const id = route.params.id as string;
|
||||
|
||||
@@ -29,9 +29,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const authStore = useAuthStore();
|
||||
authStore.update();
|
||||
|
||||
const globalStore = useGlobalStore();
|
||||
const clientsStore = useClientsStore();
|
||||
|
||||
|
||||
@@ -67,9 +67,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const authStore = useAuthStore();
|
||||
authStore.update();
|
||||
|
||||
const toast = useToast();
|
||||
const { t } = useI18n();
|
||||
|
||||
|
||||
@@ -120,7 +120,6 @@
|
||||
import { encodeQR } from 'qr';
|
||||
|
||||
const authStore = useAuthStore();
|
||||
authStore.update();
|
||||
|
||||
const name = ref(authStore.userData?.name);
|
||||
const email = ref(authStore.userData?.email);
|
||||
|
||||
+14
-7
@@ -1,18 +1,25 @@
|
||||
export const useAuthStore = defineStore('Auth', () => {
|
||||
const { data: userData, refresh: update } = useFetch('/api/session', {
|
||||
method: 'get',
|
||||
});
|
||||
import type { H3Event } from 'h3';
|
||||
import type { SharedPublicUser } from '~~/shared/utils/permissions';
|
||||
|
||||
async function getSession() {
|
||||
export const useAuthStore = defineStore('Auth', () => {
|
||||
const userData = useState<SharedPublicUser | null>('user-data', () => null);
|
||||
|
||||
async function getSession(event?: H3Event) {
|
||||
const fetch = event?.$fetch || $fetch;
|
||||
try {
|
||||
const { data } = await useFetch('/api/session', {
|
||||
const data = await fetch('/api/session', {
|
||||
method: 'get',
|
||||
});
|
||||
return data.value;
|
||||
return data;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function update() {
|
||||
const data = await getSession();
|
||||
userData.value = data;
|
||||
}
|
||||
|
||||
return { userData, update, getSession };
|
||||
});
|
||||
|
||||
+74
-25
@@ -11,12 +11,12 @@
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"email": "Email"
|
||||
"email": "E-Mail"
|
||||
},
|
||||
"me": {
|
||||
"currentPassword": "Aktuelles Passwort",
|
||||
"enable2fa": "Zwei-Faktor-Authentifizierunng aktivieren",
|
||||
"enable2faDesc": "Scannen Sie den QR-Code mit ihrer Authentifizierungs-App oder geben Sie den Schlüssel manuell ein.",
|
||||
"enable2fa": "Zwei-Faktor-Authentifizierung aktivieren",
|
||||
"enable2faDesc": "Scannen Sie den QR-Code mit Ihrer Authentifizierungs-App oder geben Sie den Schlüssel manuell ein.",
|
||||
"2faKey": "TOTP-Schlüssel",
|
||||
"2faCodeDesc": "Geben Sie den Code aus Ihrer Authentifizierungs-App ein.",
|
||||
"disable2fa": "Zwei-Faktor-Authentifizierung deaktivieren",
|
||||
@@ -45,26 +45,26 @@
|
||||
},
|
||||
"setup": {
|
||||
"welcome": "Willkommen zur Ersteinrichtung von wg-easy",
|
||||
"welcomeDesc": "Das ist der einfachste Weg, um Wireguard auf jedem Linux-Server zu installieren und zu betreiben.",
|
||||
"welcomeDesc": "Sie haben den einfachsten Weg gefunden, WireGuard auf jedem Linux-Server zu installieren und zu verwalten.",
|
||||
"existingSetup": "Haben Sie eine bestehende Einrichtung?",
|
||||
"createAdminDesc": "Bitte geben Sie zuerst einen Admin-Benutzernamen sowie ein starkes, sicheres Passwort ein. Diese Anmeldedaten benötigen Sie, um sich im Admin-Panel anzumelden.",
|
||||
"createAdminDesc": "Bitte geben Sie zuerst einen Admin-Benutzernamen sowie ein starkes, sicheres Passwort ein. Diese Anmeldedaten benötigen Sie, um sich in der Admin-Konsole anzumelden.",
|
||||
"setupConfigDesc": "Bitte geben Sie die Host- und Portinformationen ein. Diese werden für die Client-Konfiguration verwendet, wenn Sie WireGuard auf Ihren Geräten einrichten.",
|
||||
"setupMigrationDesc": "Bitte halten Sie die Sicherungsdatei bereit, wenn Sie Ihre Daten von Ihrer vorherigen wg-easy Version auf ihre neue Einrichtung migrieren möchten.",
|
||||
"upload": "Hochladen",
|
||||
"migration": "Sicherung wiederherstellen:",
|
||||
"migration": "Backup wiederherstellen:",
|
||||
"createAccount": "Konto erstellen",
|
||||
"successful": "Einrichtung erfolgreich",
|
||||
"hostDesc": "Öffentlicher Hostname mit dem sich die Clients verbinden",
|
||||
"portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden und auf dem Wireguard läuft"
|
||||
"portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden und auf dem WireGuard läuft"
|
||||
},
|
||||
"update": {
|
||||
"updateAvailable": "Es ist ein neue Aktualisierung verfügbar!",
|
||||
"updateAvailable": "Ein neues Update ist verfügbar!",
|
||||
"update": "Aktualisieren"
|
||||
},
|
||||
"theme": {
|
||||
"dark": "Dunkles Thema",
|
||||
"light": "Helles Thema",
|
||||
"system": "System-Thema"
|
||||
"system": "System Thema"
|
||||
},
|
||||
"layout": {
|
||||
"toggleCharts": "Statistiken ein-/ausblenden",
|
||||
@@ -84,16 +84,16 @@
|
||||
"sort": "Sortieren",
|
||||
"create": "Client erstellen",
|
||||
"created": "Client wurde erstellt",
|
||||
"new": "Neuer client",
|
||||
"new": "Neuer Client",
|
||||
"name": "Name",
|
||||
"expireDate": "Ablaufdatum",
|
||||
"expireDateDesc": "Datum, an dem der Client deaktiviert wird. Leer lassen, damit dies nie passiert.",
|
||||
"expireDateDesc": "Datum, an dem der Client deaktiviert wird. Leer lassen für dauerhaft aktiv.",
|
||||
"deleteClient": "Client löschen",
|
||||
"deleteDialog1": "Sind Sie sicher, dass Sie diesen Client löschen wollen",
|
||||
"deleteDialog1": "Sind Sie sicher, dass Sie diesen Client löschen möchten",
|
||||
"deleteDialog2": "Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"enabled": "Aktiviert",
|
||||
"address": "Adresse",
|
||||
"serverAllowedIps": "serverseitig erlaubte IP-Adressen",
|
||||
"serverAllowedIps": "Serverseitig erlaubte IP-Adressen",
|
||||
"otlDesc": "Einen kurzen Einmal-Link erzeugen",
|
||||
"permanent": "Dauerhaft",
|
||||
"createdOn": "Angelegt am ",
|
||||
@@ -112,8 +112,15 @@
|
||||
"persistentKeepaliveDesc": "Legt das Intervall (in Sekunden) für Keepalive-Pakete fest. 0 deaktiviert es",
|
||||
"hooks": "Hooks",
|
||||
"hooksDescription": "Hooks funktionieren nur mit wg-quick",
|
||||
"hooksLeaveEmpty": "Nur für wg-quick. Sonst leer lassen",
|
||||
"dnsDesc": "DNS-Server, den die Clients benutzen (überschreibt die globale Konfiguration)"
|
||||
"hooksLeaveEmpty": "Nur für wg-quick. Andernfalls leer lassen",
|
||||
"dnsDesc": "DNS-Server, den die Clients benutzen (überschreibt die globale Konfiguration)",
|
||||
"delete": "Löschen",
|
||||
"notConnected": "Client nicht verbunden",
|
||||
"endpoint": "Endpunkt",
|
||||
"endpointDesc": "IP-Adresse des Clients, von dem aus die WireGuard-Verbindung hergestellt wird",
|
||||
"search": "Suche Clients...",
|
||||
"config": "Konfiguration",
|
||||
"viewConfig": "Konfiguration anzeigen"
|
||||
},
|
||||
"dialog": {
|
||||
"change": "Ändern",
|
||||
@@ -150,24 +157,24 @@
|
||||
"config": {
|
||||
"connection": "Verbindung",
|
||||
"hostDesc": "Öffentlicher Hostname mit dem sich die Clients verbinden (überschreibt die Konfiguration)",
|
||||
"portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden (überschreibt die Konfiguration, vermutlich wollen Sie ebenfalls den Port der Weboberfläche ändern)",
|
||||
"portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden (überschreibt die Konfiguration, vermutlich wollen Sie auch den Interface-Port ändern)",
|
||||
"allowedIpsDesc": "Erlaubte IP-Adressen, die die Clients nutzen werden (Globale Konfiguration)",
|
||||
"dnsDesc": "DNS-Server, den die Clients nutzen werden (Globale Konfiguration)",
|
||||
"mtuDesc": "MTU, den die Clients benutzen werden (nur für neue Clients)",
|
||||
"persistentKeepaliveDesc": "Intervall in Sekunden, in dem Keepalive-Packete an den Server gesendet werden. 0 = deaktiviert (nur für neue Clients)",
|
||||
"persistentKeepaliveDesc": "Intervall in Sekunden, in dem Keepalive-Pakete an den Server gesendet werden. 0 = deaktiviert (nur für neue Clients)",
|
||||
"suggest": "Vorschlagen",
|
||||
"suggestDesc": "Wählen Sie eine IP-Adresse oder einen Hostnamen für das Host-Feld aus"
|
||||
},
|
||||
"interface": {
|
||||
"cidrSuccess": "CIDR wurde geändert",
|
||||
"device": "Gerät",
|
||||
"deviceDesc": "Ethernet-Gerät, durch das der Wireguard-Datenverkehr geleitet werden soll",
|
||||
"deviceDesc": "Ethernet-Gerät, durch das der WireGuard-Datenverkehr geleitet werden soll",
|
||||
"mtuDesc": "MTU, den WireGuard benutzen wird",
|
||||
"portDesc": "UDP Port, auf dem WireGuard lauschen wird (Sie wollen wahrscheinlich auch den Config-Port ändern)",
|
||||
"portDesc": "UDP-Port, auf dem WireGuard lauschen wird (Sie wollen wahrscheinlich auch den Interface-Port ändern)",
|
||||
"changeCidr": "CIDR ändern",
|
||||
"restart": "Interface neu starten",
|
||||
"restartDesc": "Das WireGuard-Interface neu starten",
|
||||
"restartWarn": "Sind Sie sicher, dass Sie das Interface neu starten wollen? Dies wird die Verbindungen aller Clients trennen.",
|
||||
"restartWarn": "Sind Sie sicher, dass Sie das Interface neu starten möchten? Dies wird die Verbindungen aller Clients trennen.",
|
||||
"restartSuccess": "Interface neu gestartet"
|
||||
},
|
||||
"introText": "Willkommen in der Admin-Konsole.\n\nHier können Sie die allgemeinen Einstellungen, die Konfiguration, die Schnittstelleneinstellungen und die Hooks verwalten.\n\nBeginnen Sie, indem Sie einen der Bereiche in der Seitenleiste auswählen."
|
||||
@@ -188,15 +195,15 @@
|
||||
"expiresAt": "Läuft ab am",
|
||||
"address4": "IPv4-Adresse",
|
||||
"address6": "IPv6-Adresse",
|
||||
"serverAllowedIps": "serverseitig erlaubte IP-Adressen"
|
||||
"serverAllowedIps": "Serverseitig erlaubte IP-Adressen"
|
||||
},
|
||||
"user": {
|
||||
"username": "Benutzername",
|
||||
"password": "Passwort",
|
||||
"remember": "Merken",
|
||||
"name": "Name",
|
||||
"email": "Email",
|
||||
"emailInvalid": "Die Email-Adresse muss valide sein",
|
||||
"email": "E-Mail",
|
||||
"emailInvalid": "Die E-Mail-Adresse muss gültig sein",
|
||||
"passwordMatch": "Die Passwörter müssen übereinstimmen",
|
||||
"totpEnable": "TOTP aktivieren",
|
||||
"totpEnableTrue": "\"TOTP aktivieren\" muss ausgewählt sein",
|
||||
@@ -212,8 +219,8 @@
|
||||
},
|
||||
"interface": {
|
||||
"cidr": "CIDR",
|
||||
"device": "Geräte",
|
||||
"cidrValid": "CIDR muss valide sein"
|
||||
"device": "Gerät",
|
||||
"cidrValid": "CIDR muss gültig sein"
|
||||
},
|
||||
"otl": "Einmal-Link",
|
||||
"stringMalformed": "Zeichenkette ist fehlerhaft",
|
||||
@@ -233,5 +240,47 @@
|
||||
"postUp": "PostUp",
|
||||
"preDown": "PreDown",
|
||||
"postDown": "PostDown"
|
||||
},
|
||||
"copy": {
|
||||
"notSupported": "Kopieren ist nicht unterstützt",
|
||||
"copied": "Kopiert!",
|
||||
"failed": "Kopieren fehlgeschlagen",
|
||||
"copy": "Kopieren"
|
||||
},
|
||||
"awg": {
|
||||
"jCLabel": "Anzahl der Junk-Pakete (Jc)",
|
||||
"jCDescription": "Anzahl der zu sendenden Junk-Pakete (1-128, empfohlen: 4-12)",
|
||||
"jMinLabel": "Minimale Junk-Paketgröße (Jmin)",
|
||||
"jMinDescription": "Mindestgröße von Junk-Paketen (0-1279*, empfohlen: 8, muss < Jmax sein)",
|
||||
"jMaxLabel": "Maximale Junk-Paketgröße (Jmax)",
|
||||
"jMaxDescription": "Maximalgröße von Junk-Paketen (1-1280*, empfohlen: 80, muss > Jmin sein)",
|
||||
"s1Label": "Junk-Paketgröße des Init-Pakets (S1)",
|
||||
"s1Description": "Junk-Paketgröße des Init-Pakets (0-1132[1280* - 148 = 1132], empfohlen: 15-150, S1+56 ≠ S2)",
|
||||
"s2Label": "Junk-Paketgröße des Antwort-Pakets (S2)",
|
||||
"s2Description": "Junk-Paketgröße des Antwort-Pakets (0-1188[1280* - 92 = 1188], empfohlen: 15-150)",
|
||||
"s3Label": "Junk-Paketgröße des Cookie-Antwort-Pakets (S3)",
|
||||
"s3Description": "Junk-Paketgröße des Cookie-Antwort-Pakets",
|
||||
"s4Label": "Junk-Paketgröße des Transport-Pakets (S4)",
|
||||
"s4Description": "Junk-Paketgröße des Transport-Pakets",
|
||||
"i1Label": "Spezial-Junk-Paket 1 (I1)",
|
||||
"i1Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
|
||||
"i2Label": "Spezial-Junk-Paket 2 (I2)",
|
||||
"i2Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
|
||||
"i3Label": "Spezial-Junk-Paket 3 (I3)",
|
||||
"i3Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
|
||||
"i4Label": "Spezial-Junk-Paket 4 (I4)",
|
||||
"i4Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
|
||||
"i5Label": "Spezial-Junk-Paket 5 (I5)",
|
||||
"i5Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
|
||||
"h1Label": "Init-Magic-Header (H1)",
|
||||
"h1Description": "Wert des Init-Paket-Headers (5-2147483647, muss eindeutig zu H2-H4 sein)",
|
||||
"h2Label": "Antwort-Magic-Header (H2)",
|
||||
"h2Description": "Wert des Antwort-Paket-Headers (5-2147483647, muss eindeutig zu H1, H3, H4 sein)",
|
||||
"h3Label": "Cookie-Antwort-Magic-Header (H3)",
|
||||
"h3Description": "Wert des Cookie-Antwort-Paket-Headers (5-2147483647, muss eindeutig zu H1, H2, H4 sein)",
|
||||
"h4Label": "Transport-Magic-Header (H4)",
|
||||
"h4Description": "Wert des Transport-Paket-Headers (5-2147483647, muss eindeutig zu H1-H3 sein)",
|
||||
"mtuNote": "Werte hängen von der MTU ab",
|
||||
"obfuscationParameters": "AmneziaWG Verschleierungsparameter"
|
||||
}
|
||||
}
|
||||
|
||||
+59
-13
@@ -15,12 +15,12 @@
|
||||
},
|
||||
"me": {
|
||||
"currentPassword": "Mot de passe actuel",
|
||||
"enable2fa": "Activer l'authentification à double facteur",
|
||||
"enable2fa": "Activer l'authentification à deux facteurs",
|
||||
"enable2faDesc": "Scannez le code QR avec votre application d'authentification ou saisissez la clé manuellement.",
|
||||
"2faKey": "Clé TOTP",
|
||||
"2faCodeDesc": "Saisissez le code de votre application d'authentification.",
|
||||
"disable2fa": "Désactiver l'authentification à double facteur",
|
||||
"disable2faDesc": "Saisissez votre mot de passe pour désactiver l'authentification à double facteur"
|
||||
"disable2fa": "Désactiver l'authentification à deux facteurs",
|
||||
"disable2faDesc": "Saisissez votre mot de passe pour désactiver l'authentification à deux facteurs."
|
||||
},
|
||||
"general": {
|
||||
"name": "Nom",
|
||||
@@ -40,7 +40,7 @@
|
||||
"no": "Non",
|
||||
"confirmPassword": "Confirmer le mot de passe",
|
||||
"loading": "Chargement...",
|
||||
"2fa": "Authentification à double facteur",
|
||||
"2fa": "Authentification à deux facteurs",
|
||||
"2faCode": "Code TOTP"
|
||||
},
|
||||
"setup": {
|
||||
@@ -75,8 +75,8 @@
|
||||
"rememberMe": "Se souvenir de moi",
|
||||
"rememberMeDesc": "Rester connecté après avoir fermé le navigateur",
|
||||
"insecure": "Vous ne pouvez pas vous connecter avec une connexion non sécurisée. Utilisez HTTPS.",
|
||||
"2faRequired": "Une authentification à double facteur est requise",
|
||||
"2faWrong": "L'authentification à double facteur est incorrecte"
|
||||
"2faRequired": "L'authentification à deux facteurs est requise",
|
||||
"2faWrong": "Le code d'authentification à deux facteurs est incorrect"
|
||||
},
|
||||
"client": {
|
||||
"empty": "Il n'y a pas encore de clients.",
|
||||
@@ -108,7 +108,7 @@
|
||||
"downloadConfig": "Télécharger la configuration",
|
||||
"allowedIpsDesc": "Quelles IPs seront acheminées par le VPN (remplace la configuration globale)",
|
||||
"serverAllowedIpsDesc": "Les IPs que le serveur acheminera vers le client",
|
||||
"mtuDesc": "Définit le nombre maximum d'unités de transmission (taille des paquets) pour le tunnel VPN.",
|
||||
"mtuDesc": "Définit l'unité de transmission maximale (taille des paquets) pour le tunnel VPN",
|
||||
"persistentKeepaliveDesc": "Définit l'intervalle (en secondes) pour les paquets keep-alive. 0 le désactive",
|
||||
"hooks": "Hooks",
|
||||
"hooksDescription": "Les hooks ne fonctionnent qu'avec wg-quick",
|
||||
@@ -116,7 +116,11 @@
|
||||
"dnsDesc": "Serveur DNS que les clients utiliseront (remplace la configuration globale)",
|
||||
"notConnected": "Client non connecté",
|
||||
"endpoint": "Endpoint",
|
||||
"endpointDesc": "Adresse IP du client à partir duquel la connexion WireGuard est établie"
|
||||
"endpointDesc": "Adresse IP du client à partir duquel la connexion WireGuard est établie",
|
||||
"search": "Rechercher des clients...",
|
||||
"config": "Configuration",
|
||||
"viewConfig": "Voir la configuration",
|
||||
"delete": "Supprimer"
|
||||
},
|
||||
"dialog": {
|
||||
"change": "Modifier",
|
||||
@@ -146,9 +150,9 @@
|
||||
"metricsPassword": "Mot de passe",
|
||||
"metricsPasswordDesc": "Mot de passe Bearer pour le endpoint des métriques (mot de passe ou argon2 hash)",
|
||||
"json": "JSON",
|
||||
"jsonDesc": "Acheminement pour les métriques au format JSON",
|
||||
"jsonDesc": "Route pour les métriques au format JSON",
|
||||
"prometheus": "Prometheus",
|
||||
"prometheusDesc": "Acheminement pour les métriques de Prometheus"
|
||||
"prometheusDesc": "Route pour les métriques Prometheus"
|
||||
},
|
||||
"config": {
|
||||
"connection": "Connexion",
|
||||
@@ -180,13 +184,13 @@
|
||||
"required": "{0} est requis",
|
||||
"validNumber": "{0} doit être un nombre valide",
|
||||
"validString": "{0} doit être une chaîne de caractères valide",
|
||||
"validBoolean": "{0} doit être une variable valide",
|
||||
"validBoolean": "{0} doit être un booléen valide",
|
||||
"validArray": "{0} doit être un tableau valide",
|
||||
"stringMin": "{0} doit être d'au moins {1} Caractère",
|
||||
"stringMin": "{0} doit comporter au moins {1} caractère(s)",
|
||||
"numberMin": "{0} doit être d'au moins {1}"
|
||||
},
|
||||
"client": {
|
||||
"id": "Client ID",
|
||||
"id": "ID du client",
|
||||
"name": "Nom",
|
||||
"expiresAt": "Expire le",
|
||||
"address4": "Adresse IPv4",
|
||||
@@ -236,5 +240,47 @@
|
||||
"postUp": "PostUp",
|
||||
"preDown": "PreDown",
|
||||
"postDown": "PostDown"
|
||||
},
|
||||
"copy": {
|
||||
"notSupported": "La copie n'est pas prise en charge",
|
||||
"copied": "Copié !",
|
||||
"failed": "Échec de la copie",
|
||||
"copy": "Copier"
|
||||
},
|
||||
"awg": {
|
||||
"jCLabel": "Nombre de paquets parasites (Jc)",
|
||||
"jCDescription": "Nombre de paquets parasites à envoyer (1-128, recommandé : 4-12)",
|
||||
"jMinLabel": "Taille min des paquets parasites (Jmin)",
|
||||
"jMinDescription": "Taille minimale des paquets parasites (0-1279*, recommandé : 8, doit être < Jmax)",
|
||||
"jMaxLabel": "Taille max des paquets parasites (Jmax)",
|
||||
"jMaxDescription": "Taille maximale des paquets parasites (1-1280*, recommandé : 80, doit être > Jmin)",
|
||||
"s1Label": "Taille parasite du paquet init (S1)",
|
||||
"s1Description": "Taille parasite du paquet d'initialisation (0-1132[1280* - 148 = 1132], recommandé : 15-150, S1+56 ≠ S2)",
|
||||
"s2Label": "Taille parasite du paquet réponse (S2)",
|
||||
"s2Description": "Taille parasite du paquet de réponse (0-1188[1280* - 92 = 1188], recommandé : 15-150)",
|
||||
"s3Label": "Taille parasite du paquet cookie reply (S3)",
|
||||
"s3Description": "Taille parasite du paquet de réponse cookie",
|
||||
"s4Label": "Taille parasite du paquet transport (S4)",
|
||||
"s4Description": "Taille parasite du paquet de transport",
|
||||
"i1Label": "Paquet parasite spécial 1 (I1)",
|
||||
"i1Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
|
||||
"i2Label": "Paquet parasite spécial 2 (I2)",
|
||||
"i2Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
|
||||
"i3Label": "Paquet parasite spécial 3 (I3)",
|
||||
"i3Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
|
||||
"i4Label": "Paquet parasite spécial 4 (I4)",
|
||||
"i4Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
|
||||
"i5Label": "Paquet parasite spécial 5 (I5)",
|
||||
"i5Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
|
||||
"h1Label": "En-tête magique init (H1)",
|
||||
"h1Description": "Valeur d'en-tête du paquet init (5-2147483647, doit être unique par rapport à H2-H4)",
|
||||
"h2Label": "En-tête magique réponse (H2)",
|
||||
"h2Description": "Valeur d'en-tête du paquet réponse (5-2147483647, doit être unique par rapport à H1, H3, H4)",
|
||||
"h3Label": "En-tête magique cookie reply (H3)",
|
||||
"h3Description": "Valeur d'en-tête du paquet cookie reply (5-2147483647, doit être unique par rapport à H1, H2, H4)",
|
||||
"h4Label": "En-tête magique transport (H4)",
|
||||
"h4Description": "Valeur d'en-tête du paquet transport (5-2147483647, doit être unique par rapport à H1-H3)",
|
||||
"mtuNote": "Les valeurs dépendent du MTU",
|
||||
"obfuscationParameters": "Paramètres d'obfuscation AmneziaWG"
|
||||
}
|
||||
}
|
||||
|
||||
+117
-71
@@ -3,8 +3,8 @@
|
||||
"me": "Аккаунт",
|
||||
"clients": "Клиенты",
|
||||
"admin": {
|
||||
"panel": "Админ панель",
|
||||
"general": "Общие",
|
||||
"panel": "Админ-панель",
|
||||
"general": "Общие настройки",
|
||||
"config": "Конфигурация",
|
||||
"interface": "Интерфейс",
|
||||
"hooks": "Хуки"
|
||||
@@ -16,11 +16,11 @@
|
||||
"me": {
|
||||
"currentPassword": "Текущий пароль",
|
||||
"enable2fa": "Включить двухфакторную аутентификацию",
|
||||
"enable2faDesc": "Отсканируйте QR-код приложением-аутентификатором или введите ключ вручную.",
|
||||
"2faKey": "TOTP-ключ",
|
||||
"2faCodeDesc": "Введите код из приложения-аутентификатора.",
|
||||
"enable2faDesc": "Отсканируйте QR‑код с помощью приложения‑аутентификатора или введите ключ вручную.",
|
||||
"2faKey": "Ключ TOTP",
|
||||
"2faCodeDesc": "Введите код из приложения‑аутентификатора.",
|
||||
"disable2fa": "Отключить двухфакторную аутентификацию",
|
||||
"disable2faDesc": "Введите пароль, чтобы отключить двухфакторную аутентификацию"
|
||||
"disable2faDesc": "Введите пароль, чтобы отключить двухфакторную аутентификацию."
|
||||
},
|
||||
"general": {
|
||||
"name": "Имя",
|
||||
@@ -29,9 +29,9 @@
|
||||
"newPassword": "Новый пароль",
|
||||
"updatePassword": "Обновить пароль",
|
||||
"mtu": "MTU",
|
||||
"allowedIps": "Разрешённые IP",
|
||||
"allowedIps": "Разрешённые IP‑адреса",
|
||||
"dns": "DNS",
|
||||
"persistentKeepalive": "Постоянный keepalive",
|
||||
"persistentKeepalive": "Постоянное поддержание соединения",
|
||||
"logout": "Выйти",
|
||||
"continue": "Продолжить",
|
||||
"host": "Хост",
|
||||
@@ -41,21 +41,21 @@
|
||||
"confirmPassword": "Подтвердите пароль",
|
||||
"loading": "Загрузка...",
|
||||
"2fa": "Двухфакторная аутентификация",
|
||||
"2faCode": "TOTP‑код"
|
||||
"2faCode": "Код TOTP"
|
||||
},
|
||||
"setup": {
|
||||
"welcome": "Добро пожаловать в первичную настройку wg-easy",
|
||||
"welcomeDesc": "Вы нашли самый простой способ установить и управлять WireGuard на любом Linux-хосте",
|
||||
"existingSetup": "У вас уже есть существующая установка?",
|
||||
"createAdminDesc": "Сначала введите имя администратора и надёжный пароль. Эти данные понадобятся для входа в панель управления",
|
||||
"setupConfigDesc": "Введите информацию о хосте и порте. Она будет использоваться в конфигурации клиента при установке WireGuard на устройствах",
|
||||
"setupMigrationDesc": "Укажите файл резервной копии, если хотите перенести данные из предыдущей версии wg-easy",
|
||||
"welcomeDesc": "Вы нашли самый простой способ установить и управлять WireGuard на любом Linux‑хосте",
|
||||
"existingSetup": "У вас уже есть существующая настройка?",
|
||||
"createAdminDesc": "Сначала введите имя администратора и надёжный пароль. Эти данные будут использоваться для входа в Админ-панель.",
|
||||
"setupConfigDesc": "Введите данные хоста и порта. Они будут использоваться для настройки клиента при установке WireGuard на устройствах.",
|
||||
"setupMigrationDesc": "Укажите файл резервной копии, если хотите перенести данные из предыдущей версии wg-easy.",
|
||||
"upload": "Загрузить",
|
||||
"migration": "Восстановить из резервной копии:",
|
||||
"createAccount": "Создать аккаунт",
|
||||
"successful": "Настройка успешна",
|
||||
"successful": "Настройка завершена успешно",
|
||||
"hostDesc": "Публичное имя хоста, к которому будут подключаться клиенты",
|
||||
"portDesc": "Публичный UDP‑порт для подключения клиентов и прослушивания WireGuard"
|
||||
"portDesc": "Публичный UDP‑порт, к которому будут подключаться клиенты и на котором будет слушать WireGuard"
|
||||
},
|
||||
"update": {
|
||||
"updateAvailable": "Доступно обновление!",
|
||||
@@ -68,7 +68,7 @@
|
||||
},
|
||||
"layout": {
|
||||
"toggleCharts": "Показать/скрыть графики",
|
||||
"donate": "Пожертвовать"
|
||||
"donate": "Поддержать"
|
||||
},
|
||||
"login": {
|
||||
"signIn": "Войти",
|
||||
@@ -87,18 +87,19 @@
|
||||
"new": "Новый клиент",
|
||||
"name": "Имя",
|
||||
"expireDate": "Дата отключения",
|
||||
"expireDateDesc": "Дата, когда клиент будет отключён. Пусто — бессрочно",
|
||||
"expireDateDesc": "Дата, когда клиент будет отключён. Оставьте пустым для бессрочного доступа",
|
||||
"delete": "Удалить",
|
||||
"deleteClient": "Удалить клиента",
|
||||
"deleteDialog1": "Вы уверены, что хотите удалить",
|
||||
"deleteDialog2": "Это действие необратимо.",
|
||||
"enabled": "Включен",
|
||||
"deleteDialog2": "Это действие нельзя отменить.",
|
||||
"enabled": "Включён",
|
||||
"address": "Адрес",
|
||||
"serverAllowedIps": "Разрешённые IP сервера",
|
||||
"otlDesc": "Сгенерировать одноразовую короткую ссылку",
|
||||
"permanent": "Постоянный",
|
||||
"serverAllowedIps": "Разрешённые IP‑адреса сервера",
|
||||
"otlDesc": "Сгенерировать короткую одноразовую ссылку",
|
||||
"permanent": "Бессрочный",
|
||||
"createdOn": "Создан ",
|
||||
"lastSeen": "Последнее подключение ",
|
||||
"totalDownload": "Всего загружено: ",
|
||||
"totalDownload": "Всего скачано: ",
|
||||
"totalUpload": "Всего отправлено: ",
|
||||
"newClient": "Новый клиент",
|
||||
"disableClient": "Отключить клиента",
|
||||
@@ -106,25 +107,28 @@
|
||||
"noPrivKey": "У этого клиента нет приватного ключа. Невозможно создать конфигурацию.",
|
||||
"showQR": "Показать QR‑код",
|
||||
"downloadConfig": "Скачать конфигурацию",
|
||||
"allowedIpsDesc": "Какие IP будут маршрутизироваться через VPN (перезаписывает общую конфигурацию)",
|
||||
"serverAllowedIpsDesc": "Какие IP сервер будет отправлять клиенту",
|
||||
"mtuDesc": "Максимальный размер пакета для VPN‑туннеля",
|
||||
"persistentKeepaliveDesc": "Интервал пакетов для поддержания соединения (в секундах). 0 — отключено.",
|
||||
"allowedIpsDesc": "Какие IP‑адреса будут маршрутизироваться через VPN (переопределяет глобальную конфигурацию)",
|
||||
"serverAllowedIpsDesc": "Какие IP‑адреса сервер будет отправлять клиенту",
|
||||
"mtuDesc": "Максимальный размер пакета (MTU) для VPN‑туннеля",
|
||||
"persistentKeepaliveDesc": "Устанавливает интервал (в секундах) для пакетов поддержания соединения. 0 — отключить",
|
||||
"hooks": "Хуки",
|
||||
"hooksDescription": "Хуки работают только с wg-quick",
|
||||
"hooksLeaveEmpty": "Только для wg-quick. Иначе оставьте пустым",
|
||||
"dnsDesc": "DNS‑сервер, который будут использовать клиенты (перезаписывает общую конфигурацию)",
|
||||
"hooksDescription": "Хуки работают только с wg‑quick",
|
||||
"hooksLeaveEmpty": "Только для wg‑quick. В остальных случаях оставьте пустым",
|
||||
"dnsDesc": "DNS‑сервер, который будут использовать клиенты (переопределяет глобальную конфигурацию)",
|
||||
"notConnected": "Клиент не подключен",
|
||||
"endpoint": "Конечная точка",
|
||||
"endpointDesc": "IP-адрес клиента, с которого установлено соединение WireGuard"
|
||||
"endpoint": "Точка подключения",
|
||||
"endpointDesc": "IP‑адрес клиента, с которого установлено соединение WireGuard",
|
||||
"search": "Поиск клиентов...",
|
||||
"config": "Конфигурация",
|
||||
"viewConfig": "Просмотреть конфигурацию"
|
||||
},
|
||||
"dialog": {
|
||||
"change": "Изменить",
|
||||
"cancel": "Отмена",
|
||||
"cancel": "Отменить",
|
||||
"create": "Создать"
|
||||
},
|
||||
"toast": {
|
||||
"success": "Успех",
|
||||
"success": "Успешно",
|
||||
"saved": "Сохранено",
|
||||
"error": "Ошибка"
|
||||
},
|
||||
@@ -133,18 +137,18 @@
|
||||
"save": "Сохранить",
|
||||
"revert": "Отменить",
|
||||
"sectionGeneral": "Общие",
|
||||
"sectionAdvanced": "Дополнительно",
|
||||
"sectionAdvanced": "Расширенные",
|
||||
"noItems": "Нет элементов",
|
||||
"nullNoItems": "Нет элементов. Используется глобальная конфигурация",
|
||||
"add": "Добавить"
|
||||
},
|
||||
"admin": {
|
||||
"general": {
|
||||
"sessionTimeout": "Тайм-аут сессии",
|
||||
"sessionTimeoutDesc": "Длительность сеанса для \"Запомнить меня\" (секунды)",
|
||||
"sessionTimeout": "Время жизни сессии",
|
||||
"sessionTimeoutDesc": "Длительность сессии для «Запомнить меня» (в секундах)",
|
||||
"metrics": "Метрики",
|
||||
"metricsPassword": "Пароль",
|
||||
"metricsPasswordDesc": "Пароль Bearer для эндпоинта метрик (пароль или хеш argon2)",
|
||||
"metricsPasswordDesc": "Пароль Bearer для конечной точки метрик (пароль или хэш argon2)",
|
||||
"json": "JSON",
|
||||
"jsonDesc": "Путь для метрик в формате JSON",
|
||||
"prometheus": "Prometheus",
|
||||
@@ -152,83 +156,83 @@
|
||||
},
|
||||
"config": {
|
||||
"connection": "Соединение",
|
||||
"hostDesc": "Публичное имя хоста для подключения клиентов (сбросит конфигурацию)",
|
||||
"portDesc": "Публичный UDP‑порт для подключения клиентов (также стоит изменить порт интерфейса)",
|
||||
"allowedIpsDesc": "Разрешённые IP для клиентов (общая конфигурация)",
|
||||
"dnsDesc": "DNS‑сервер для клиентов (общая конфигурация)",
|
||||
"hostDesc": "Публичное имя хоста для подключения клиентов(обнуляет конфигурацию)",
|
||||
"portDesc": "Публичный UDP‑порт для подключения клиентов (также рекомендуется изменить порт интерфейса)",
|
||||
"allowedIpsDesc": "Разрешённые IP‑адреса для клиентов(глобальная конфигурация)",
|
||||
"dnsDesc": "DNS‑сервер для клиентов (глобальная конфигурация)",
|
||||
"mtuDesc": "MTU для клиентов (только для новых)",
|
||||
"persistentKeepaliveDesc": "Интервал отправки keepalive на сервер (секунды). 0 = отключено (только для новых)",
|
||||
"suggest": "Определить",
|
||||
"suggestDesc": "Выберите IP‑адрес или имя хоста для поля Host"
|
||||
"persistentKeepaliveDesc": "Интервал в секундах для отправки пакетов поддержания соединения на сервер. 0 = отключено (только для новых клиентов)",
|
||||
"suggest": "Предложить",
|
||||
"suggestDesc": "Выберите IP‑адрес или имя хоста для поля «Хост»"
|
||||
},
|
||||
"interface": {
|
||||
"cidrSuccess": "CIDR изменён",
|
||||
"device": "Устройство",
|
||||
"deviceDesc": "Сетевое устройство, через которое должен проходить трафик WireGuard",
|
||||
"mtuDesc": "MTU, который использует WireGuard",
|
||||
"portDesc": "UDP‑порт, на котором WireGuard будет слушать (возможно, нужно изменить и порт конфигурации)",
|
||||
"deviceDesc": "Сетевое устройство Ethernet, через которое должен проходить трафик WireGuard",
|
||||
"mtuDesc": "MTU, который будет использовать WireGuard",
|
||||
"portDesc": "UDP‑порт, на котором будет слушать WireGuard (возможно, нужно также изменить порт конфигурации)",
|
||||
"changeCidr": "Изменить CIDR",
|
||||
"restart": "Перезапустить интерфейс",
|
||||
"restartDesc": "Перезапустить интерфейс WireGuard",
|
||||
"restartWarn": "Вы уверены, что хотите перезапустить интерфейс? Все клиенты будут отключены.",
|
||||
"restartWarn": "Вы уверены, что хотите перезапустить интерфейс? Это приведёт к отключению всех клиентов.",
|
||||
"restartSuccess": "Интерфейс перезапущен"
|
||||
},
|
||||
"introText": "Добро пожаловать в панель администратора.\n\nЗдесь вы можете управлять общими настройками, конфигурацией, параметрами интерфейса и хуками.\n\nНачните с выбора раздела в боковой панели."
|
||||
"introText": "Добро пожаловать в панель администратора.\n\nЗдесь вы можете управлять общими настройками, конфигурацией, настройками интерфейса и хуками.\n\nНачните с выбора одного из разделов на боковой панели."
|
||||
},
|
||||
"zod": {
|
||||
"generic": {
|
||||
"required": "{0} обязательное поле",
|
||||
"validNumber": "{0} должен быть числом",
|
||||
"validString": "{0} должна быть строкой",
|
||||
"validBoolean": "{0} должен быть булевым значением",
|
||||
"validArray": "{0} должен быть массивом",
|
||||
"stringMin": "{0} должен содержать не менее {1} символов",
|
||||
"numberMin": "{0} должен быть не меньше {1}"
|
||||
"required": "{0} обязательно для заполнения",
|
||||
"validNumber": "{0} должно быть числом",
|
||||
"validString": "{0} должно быть строкой",
|
||||
"validBoolean": "{0} должно быть логическим значением",
|
||||
"validArray": "{0} должно быть массивом",
|
||||
"stringMin": "{0} должно содержать не менее {1} символа",
|
||||
"numberMin": "{0} должно быть не менее {1}"
|
||||
},
|
||||
"client": {
|
||||
"id": "ID клиента",
|
||||
"name": "Имя",
|
||||
"expiresAt": "Действителен до",
|
||||
"address4": "IPv4 адрес",
|
||||
"address6": "IPv6 адрес",
|
||||
"serverAllowedIps": "Разрешённые IP сервера"
|
||||
"expiresAt": "Дата окончания действия",
|
||||
"address4": "IPv4‑адрес",
|
||||
"address6": "IPv6‑адрес",
|
||||
"serverAllowedIps": "Разрешённые IP‑адреса сервера"
|
||||
},
|
||||
"user": {
|
||||
"username": "Имя пользователя",
|
||||
"password": "Пароль",
|
||||
"remember": "Запомнить",
|
||||
"name": "Имя",
|
||||
"email": "Email",
|
||||
"emailInvalid": "Email должен быть валидным",
|
||||
"email": "Электронная почта",
|
||||
"emailInvalid": "Адрес электронной почты должен быть корректным",
|
||||
"passwordMatch": "Пароли должны совпадать",
|
||||
"totpEnable": "Включить TOTP",
|
||||
"totpEnableTrue": "Необходимо включить TOTP",
|
||||
"totpCode": "TOTP‑код"
|
||||
"totpEnableTrue": "TOTP должен быть включён",
|
||||
"totpCode": "Код TOTP"
|
||||
},
|
||||
"userConfig": {
|
||||
"host": "Хост"
|
||||
},
|
||||
"general": {
|
||||
"sessionTimeout": "Тайм-аут сессии",
|
||||
"sessionTimeout": "Время жизни сессии",
|
||||
"metricsEnabled": "Метрики",
|
||||
"metricsPassword": "Пароль для метрик"
|
||||
},
|
||||
"interface": {
|
||||
"cidr": "CIDR",
|
||||
"device": "Устройство",
|
||||
"cidrValid": "CIDR должен быть валидным"
|
||||
"cidrValid": "CIDR должен быть корректным"
|
||||
},
|
||||
"otl": "Одноразовая ссылка",
|
||||
"stringMalformed": "Строка имеет неверный формат",
|
||||
"body": "Тело должно быть объектом",
|
||||
"body": "Тело должно быть корректным объектом",
|
||||
"hook": "Хук",
|
||||
"enabled": "Включено",
|
||||
"mtu": "MTU",
|
||||
"port": "Порт",
|
||||
"persistentKeepalive": "Поддерживать соединение",
|
||||
"persistentKeepalive": "Постоянное поддержание соединения",
|
||||
"address": "IP‑адрес",
|
||||
"dns": "DNS",
|
||||
"allowedIps": "Разрешённые IP",
|
||||
"allowedIps": "Разрешённые IP‑адреса",
|
||||
"file": "Файл"
|
||||
},
|
||||
"hooks": {
|
||||
@@ -236,5 +240,47 @@
|
||||
"postUp": "PostUp",
|
||||
"preDown": "PreDown",
|
||||
"postDown": "PostDown"
|
||||
},
|
||||
"copy": {
|
||||
"notSupported": "Копирование не поддерживается",
|
||||
"copied": "Скопировано!",
|
||||
"failed": "Ошибка копирования",
|
||||
"copy": "Копировать"
|
||||
},
|
||||
"awg": {
|
||||
"jCLabel": "Количество шумовых пакетов (Jc)",
|
||||
"jCDescription": "Число шумовых пакетов для отправки (1-128, рекомендуется: 4-12)",
|
||||
"jMinLabel": "Минимальный размер шумовых пакетов (Jmin)",
|
||||
"jMinDescription": "Минимальный размер шумовых пакетов (0-1279*, рекомендуется: 8, должен быть < Jmax)",
|
||||
"jMaxLabel": "Максимальный размер шумовых пакетов (Jmax)",
|
||||
"jMaxDescription": "Максимальный размер шумовых пакетов (1-1280*, рекомендуется: 80, должен быть > Jmin)",
|
||||
"s1Label": "Размер шумовых данных в init-пакете (S1)",
|
||||
"s1Description": "Размер шумовых данных в init-пакете (0-1132[1280* - 148 = 1132], рекомендуется: 15-150, S1+56 ≠ S2)",
|
||||
"s2Label": "Размер шумовых данных в ответном пакете (S2)",
|
||||
"s2Description": "Размер шумовых данных в ответном пакете (0-1188[1280* - 92 = 1188], рекомендуется: 15-150)",
|
||||
"s3Label": "Размер шумовых данных в cookie-reply пакете (S3)",
|
||||
"s3Description": "Размер шумовых данных в cookie-reply пакете",
|
||||
"s4Label": "Размер шумовых данных в транспортном пакете (S4)",
|
||||
"s4Description": "Размер шумовых данных в транспортном пакете",
|
||||
"i1Label": "Специальный шумовой пакет 1 (I1)",
|
||||
"i1Description": "Пакет имитации протокола в hex формате: <b 0x...>",
|
||||
"i2Label": "Специальный шумовой пакет 2 (I2)",
|
||||
"i2Description": "Пакет имитации протокола в hex формате: <b 0x...>",
|
||||
"i3Label": "Специальный шумовой пакет 3 (I3)",
|
||||
"i3Description": "Пакет имитации протокола в hex формате: <b 0x...>",
|
||||
"i4Label": "Специальный шумовой пакет 4 (I4)",
|
||||
"i4Description": "Пакет имитации протокола в hex формате: <b 0x...>",
|
||||
"i5Label": "Специальный шумовой пакет 5 (I5)",
|
||||
"i5Description": "Пакет имитации протокола в hex формате: <b 0x...>",
|
||||
"h1Label": "Init magic заголовок (H1)",
|
||||
"h1Description": "Значение заголовка init-пакета (5-2147483647, должно отличаться от H2-H4)",
|
||||
"h2Label": "Response magic заголовок (H2)",
|
||||
"h2Description": "Значение заголовка ответного пакета (5-2147483647, должно отличаться от H1, H3, H4)",
|
||||
"h3Label": "Cookie reply magic заголовок (H3)",
|
||||
"h3Description": "Значение заголовка cookie-reply пакета (5-2147483647, должно отличаться от H1, H2, H4)",
|
||||
"h4Label": "Transport magic заголовок (H4)",
|
||||
"h4Description": "Значение заголовка транспортного пакета (5-2147483647, должно отличаться от H1-H3)",
|
||||
"mtuNote": "Значения зависят от MTU",
|
||||
"obfuscationParameters": "Параметры обфускации AmneziaWG"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"name": "Ім'я",
|
||||
"expireDate": "Термін дії",
|
||||
"expireDateDesc": "Дата, коли клієнт буде відключений. Порожнє для постійного користування",
|
||||
"delete": "Видалити",
|
||||
"deleteClient": "Видалити клієнта",
|
||||
"deleteDialog1": "Ви впевнені, що бажаєте видалити",
|
||||
"deleteDialog2": "Цю дію неможливо скасувати.",
|
||||
|
||||
+16
-16
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wg-easy",
|
||||
"version": "15.2.0-beta.3",
|
||||
"version": "15.2.1",
|
||||
"description": "The easiest way to run WireGuard VPN + Web-based Admin UI.",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -22,12 +22,12 @@
|
||||
"dependencies": {
|
||||
"@eschricht/nuxt-color-mode": "^1.2.0",
|
||||
"@heroicons/vue": "^2.2.0",
|
||||
"@libsql/client": "^0.15.15",
|
||||
"@libsql/client": "^0.17.0",
|
||||
"@nuxtjs/i18n": "^10.2.1",
|
||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||
"@phc/format": "^1.0.0",
|
||||
"@pinia/nuxt": "^0.11.3",
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"@tailwindcss/forms": "^0.5.11",
|
||||
"@vueuse/core": "^14.1.0",
|
||||
"@vueuse/nuxt": "^14.1.0",
|
||||
"apexcharts": "^5.3.6",
|
||||
@@ -37,37 +37,37 @@
|
||||
"consola": "^3.4.2",
|
||||
"crc-32": "^1.2.2",
|
||||
"debug": "^4.4.3",
|
||||
"drizzle-orm": "^0.44.7",
|
||||
"drizzle-orm": "^0.45.1",
|
||||
"ip-bigint": "^8.2.2",
|
||||
"is-cidr": "^6.0.1",
|
||||
"is-ip": "^5.0.1",
|
||||
"js-sha256": "^0.11.1",
|
||||
"nuxt": "^3.20.1",
|
||||
"nuxt": "^3.20.2",
|
||||
"otpauth": "^9.4.1",
|
||||
"pinia": "^3.0.4",
|
||||
"qr": "^0.5.3",
|
||||
"qr": "^0.5.4",
|
||||
"radix-vue": "^1.9.17",
|
||||
"semver": "^7.7.3",
|
||||
"tailwindcss": "^3.4.18",
|
||||
"tailwindcss": "^3.4.19",
|
||||
"timeago.js": "^4.0.2",
|
||||
"vue": "latest",
|
||||
"vue3-apexcharts": "^1.10.0",
|
||||
"zod": "^4.1.13"
|
||||
"zod": "^4.3.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/eslint": "^1.11.0",
|
||||
"@nuxt/eslint": "^1.12.1",
|
||||
"@types/debug": "^4.1.12",
|
||||
"@types/phc__format": "^1.0.1",
|
||||
"@types/semver": "^7.7.1",
|
||||
"drizzle-kit": "^0.31.7",
|
||||
"esbuild": "^0.27.0",
|
||||
"eslint": "^9.39.1",
|
||||
"drizzle-kit": "^0.31.8",
|
||||
"esbuild": "^0.27.2",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"prettier": "^3.7.3",
|
||||
"prettier-plugin-tailwindcss": "^0.7.1",
|
||||
"prettier": "^3.7.4",
|
||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vue-tsc": "^3.1.5"
|
||||
"vue-tsc": "^3.2.2"
|
||||
},
|
||||
"packageManager": "pnpm@10.24.0"
|
||||
"packageManager": "pnpm@10.28.0"
|
||||
}
|
||||
|
||||
Generated
+1597
-1457
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,14 @@
|
||||
import type { SharedPublicUser } from '~~/shared/utils/permissions';
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const session = await useWGSession(event);
|
||||
|
||||
if (!session.data.userId) {
|
||||
// not logged in
|
||||
return null;
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
statusMessage: 'Not authenticated',
|
||||
});
|
||||
}
|
||||
|
||||
const user = await Database.users.get(session.data.userId);
|
||||
@@ -21,5 +26,5 @@ export default defineEventHandler(async (event) => {
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
totpVerified: user.totpVerified,
|
||||
};
|
||||
} satisfies SharedPublicUser;
|
||||
});
|
||||
|
||||
@@ -16,6 +16,12 @@ function createPreparedStatement(db: DBType) {
|
||||
oneTimeLink: sql.placeholder('oneTimeLink'),
|
||||
expiresAt: sql.placeholder('expiresAt'),
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: oneTimeLink.id,
|
||||
set: {
|
||||
expiresAt: sql.placeholder('expiresAt') as never as string,
|
||||
},
|
||||
})
|
||||
.prepare(),
|
||||
erase: db
|
||||
.update(oneTimeLink)
|
||||
|
||||
@@ -3,7 +3,7 @@ export default defineEventHandler(async (event) => {
|
||||
const url = getRequestURL(event);
|
||||
|
||||
// User can't be logged in, and public routes can be accessed whenever
|
||||
if (url.pathname.startsWith('/api/')) {
|
||||
if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/_i18n/')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ class WireGuard {
|
||||
WG_DEBUG('New Wireguard Keys generated successfully.');
|
||||
}
|
||||
|
||||
if (WG_ENV.WG_EXECUTABLE === 'awg' && wgInterface.h1 === 0) {
|
||||
if (wgInterface.h1 === 0) {
|
||||
WG_DEBUG('Generating random AmneziaWG obfuscation parameters...');
|
||||
const headers = new Set<number>();
|
||||
|
||||
|
||||
@@ -45,6 +45,11 @@ type SharedUserType =
|
||||
| Pick<UserType, 'id' | 'role'>
|
||||
| (Pick<UserType, 'id'> & { role: BrandedNumber });
|
||||
|
||||
export type SharedPublicUser = Pick<
|
||||
UserType,
|
||||
'id' | 'username' | 'name' | 'email' | 'totpVerified'
|
||||
> & { role: BrandedNumber };
|
||||
|
||||
type PermissionCheck<Key extends keyof Permissions> =
|
||||
| boolean
|
||||
| ((user: SharedUserType, data: Permissions[Key]['dataType']) => boolean);
|
||||
|
||||
Reference in New Issue
Block a user