diff --git a/src/app/pages/admin/interface.vue b/src/app/pages/admin/interface.vue
index fd4d7eeb..f14ad60d 100644
--- a/src/app/pages/admin/interface.vue
+++ b/src/app/pages/admin/interface.vue
@@ -69,6 +69,30 @@
:label="$t('awg.s4Label')"
:description="$t('awg.s4Description')"
/>
+
+
+
+
-
-
-
-
{{ $t('form.actions') }}
diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index 17fc3f7f..dbed156d 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -183,6 +183,7 @@
"generic": {
"required": "{0} is required",
"validNumber": "{0} must be a valid number",
+ "validNumberRange": "{0} must be a valid number or number range",
"validString": "{0} must be a valid string",
"validBoolean": "{0} must be a valid boolean",
"validArray": "{0} must be a valid array",
@@ -262,6 +263,14 @@
"s3Description": "Cookie reply packet junk size",
"s4Label": "Transport packet junk size (S4)",
"s4Description": "Transport packet junk size",
+ "h1Label": "Init magic header (H1)",
+ "h1Description": "Init packet header value or range (X or X-Y, where X",
"i2Label": "Special junk packet 2 (I2)",
@@ -272,14 +281,6 @@
"i4Description": "Protocol mimic packet in hex format: ",
"i5Label": "Special junk packet 5 (I5)",
"i5Description": "Protocol mimic packet in hex format: ",
- "h1Label": "Init magic header (H1)",
- "h1Description": "Init packet header value (5-2147483647, must be unique from H2-H4)",
- "h2Label": "Response magic header (H2)",
- "h2Description": "Response packet header value (5-2147483647, must be unique from H1, H3, H4)",
- "h3Label": "Cookie reply magic header (H3)",
- "h3Description": "Cookie reply packet header value (5-2147483647, must be unique from H1, H2, H4)",
- "h4Label": "Transport magic header (H4)",
- "h4Description": "Transport packet header value (5-2147483647, must be unique from H1-H3)",
"mtuNote": "Values depend on the MTU",
"obfuscationParameters": "AmneziaWG Obfuscation Parameters"
}
diff --git a/src/server/database/migrations/0003_breezy_colossus.sql b/src/server/database/migrations/0003_breezy_colossus.sql
new file mode 100644
index 00000000..b5987a13
--- /dev/null
+++ b/src/server/database/migrations/0003_breezy_colossus.sql
@@ -0,0 +1,36 @@
+PRAGMA foreign_keys=OFF;--> statement-breakpoint
+CREATE TABLE `__new_interfaces_table` (
+ `name` text PRIMARY KEY NOT NULL,
+ `device` text NOT NULL,
+ `port` integer NOT NULL,
+ `private_key` text NOT NULL,
+ `public_key` text NOT NULL,
+ `ipv4_cidr` text NOT NULL,
+ `ipv6_cidr` text NOT NULL,
+ `mtu` integer NOT NULL,
+ `j_c` integer DEFAULT 7,
+ `j_min` integer DEFAULT 10,
+ `j_max` integer DEFAULT 1000,
+ `s1` integer DEFAULT 128,
+ `s2` integer DEFAULT 56,
+ `s3` integer,
+ `s4` integer,
+ `h1` text,
+ `h2` text,
+ `h3` text,
+ `h4` text,
+ `i1` text,
+ `i2` text,
+ `i3` text,
+ `i4` text,
+ `i5` text,
+ `enabled` integer NOT NULL,
+ `created_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
+ `updated_at` text DEFAULT (CURRENT_TIMESTAMP) NOT NULL
+);
+--> statement-breakpoint
+INSERT INTO `__new_interfaces_table`("name", "device", "port", "private_key", "public_key", "ipv4_cidr", "ipv6_cidr", "mtu", "j_c", "j_min", "j_max", "s1", "s2", "s3", "s4", "h1", "h2", "h3", "h4", "i1", "i2", "i3", "i4", "i5", "enabled", "created_at", "updated_at") SELECT "name", "device", "port", "private_key", "public_key", "ipv4_cidr", "ipv6_cidr", "mtu", "j_c", "j_min", "j_max", "s1", "s2", "s3", "s4", "h1", "h2", "h3", "h4", "i1", "i2", "i3", "i4", "i5", "enabled", "created_at", "updated_at" FROM `interfaces_table`;--> statement-breakpoint
+DROP TABLE `interfaces_table`;--> statement-breakpoint
+ALTER TABLE `__new_interfaces_table` RENAME TO `interfaces_table`;--> statement-breakpoint
+PRAGMA foreign_keys=ON;--> statement-breakpoint
+CREATE UNIQUE INDEX `interfaces_table_port_unique` ON `interfaces_table` (`port`);
\ No newline at end of file
diff --git a/src/server/database/migrations/meta/0003_snapshot.json b/src/server/database/migrations/meta/0003_snapshot.json
new file mode 100644
index 00000000..708657e8
--- /dev/null
+++ b/src/server/database/migrations/meta/0003_snapshot.json
@@ -0,0 +1,972 @@
+{
+ "version": "6",
+ "dialect": "sqlite",
+ "id": "68c43b7a-772d-4c34-8278-e9fce5b53df1",
+ "prevId": "e09bc17a-dab6-45a3-a09c-57af222b08fb",
+ "tables": {
+ "clients_table": {
+ "name": "clients_table",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "interface_id": {
+ "name": "interface_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "ipv4_address": {
+ "name": "ipv4_address",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "ipv6_address": {
+ "name": "ipv6_address",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "pre_up": {
+ "name": "pre_up",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "''"
+ },
+ "post_up": {
+ "name": "post_up",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "''"
+ },
+ "pre_down": {
+ "name": "pre_down",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "''"
+ },
+ "post_down": {
+ "name": "post_down",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "''"
+ },
+ "private_key": {
+ "name": "private_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "public_key": {
+ "name": "public_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "pre_shared_key": {
+ "name": "pre_shared_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "allowed_ips": {
+ "name": "allowed_ips",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "server_allowed_ips": {
+ "name": "server_allowed_ips",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "persistent_keepalive": {
+ "name": "persistent_keepalive",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "mtu": {
+ "name": "mtu",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "j_c": {
+ "name": "j_c",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "j_min": {
+ "name": "j_min",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "j_max": {
+ "name": "j_max",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i1": {
+ "name": "i1",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i2": {
+ "name": "i2",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i3": {
+ "name": "i3",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i4": {
+ "name": "i4",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i5": {
+ "name": "i5",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "dns": {
+ "name": "dns",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "server_endpoint": {
+ "name": "server_endpoint",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "enabled": {
+ "name": "enabled",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ }
+ },
+ "indexes": {
+ "clients_table_ipv4_address_unique": {
+ "name": "clients_table_ipv4_address_unique",
+ "columns": [
+ "ipv4_address"
+ ],
+ "isUnique": true
+ },
+ "clients_table_ipv6_address_unique": {
+ "name": "clients_table_ipv6_address_unique",
+ "columns": [
+ "ipv6_address"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {
+ "clients_table_user_id_users_table_id_fk": {
+ "name": "clients_table_user_id_users_table_id_fk",
+ "tableFrom": "clients_table",
+ "tableTo": "users_table",
+ "columnsFrom": [
+ "user_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "cascade"
+ },
+ "clients_table_interface_id_interfaces_table_name_fk": {
+ "name": "clients_table_interface_id_interfaces_table_name_fk",
+ "tableFrom": "clients_table",
+ "tableTo": "interfaces_table",
+ "columnsFrom": [
+ "interface_id"
+ ],
+ "columnsTo": [
+ "name"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "general_table": {
+ "name": "general_table",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 1
+ },
+ "setup_step": {
+ "name": "setup_step",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "session_password": {
+ "name": "session_password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "session_timeout": {
+ "name": "session_timeout",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "metrics_prometheus": {
+ "name": "metrics_prometheus",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "metrics_json": {
+ "name": "metrics_json",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "metrics_password": {
+ "name": "metrics_password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "hooks_table": {
+ "name": "hooks_table",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "pre_up": {
+ "name": "pre_up",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "post_up": {
+ "name": "post_up",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "pre_down": {
+ "name": "pre_down",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "post_down": {
+ "name": "post_down",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "hooks_table_id_interfaces_table_name_fk": {
+ "name": "hooks_table_id_interfaces_table_name_fk",
+ "tableFrom": "hooks_table",
+ "tableTo": "interfaces_table",
+ "columnsFrom": [
+ "id"
+ ],
+ "columnsTo": [
+ "name"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "interfaces_table": {
+ "name": "interfaces_table",
+ "columns": {
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "device": {
+ "name": "device",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "port": {
+ "name": "port",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "private_key": {
+ "name": "private_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "public_key": {
+ "name": "public_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "ipv4_cidr": {
+ "name": "ipv4_cidr",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "ipv6_cidr": {
+ "name": "ipv6_cidr",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "mtu": {
+ "name": "mtu",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "j_c": {
+ "name": "j_c",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 7
+ },
+ "j_min": {
+ "name": "j_min",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 10
+ },
+ "j_max": {
+ "name": "j_max",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 1000
+ },
+ "s1": {
+ "name": "s1",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 128
+ },
+ "s2": {
+ "name": "s2",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 56
+ },
+ "s3": {
+ "name": "s3",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "s4": {
+ "name": "s4",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "h1": {
+ "name": "h1",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "h2": {
+ "name": "h2",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "h3": {
+ "name": "h3",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "h4": {
+ "name": "h4",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i1": {
+ "name": "i1",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i2": {
+ "name": "i2",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i3": {
+ "name": "i3",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i4": {
+ "name": "i4",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "i5": {
+ "name": "i5",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "enabled": {
+ "name": "enabled",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ }
+ },
+ "indexes": {
+ "interfaces_table_port_unique": {
+ "name": "interfaces_table_port_unique",
+ "columns": [
+ "port"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "one_time_links_table": {
+ "name": "one_time_links_table",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "one_time_link": {
+ "name": "one_time_link",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ }
+ },
+ "indexes": {
+ "one_time_links_table_one_time_link_unique": {
+ "name": "one_time_links_table_one_time_link_unique",
+ "columns": [
+ "one_time_link"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {
+ "one_time_links_table_id_clients_table_id_fk": {
+ "name": "one_time_links_table_id_clients_table_id_fk",
+ "tableFrom": "one_time_links_table",
+ "tableTo": "clients_table",
+ "columnsFrom": [
+ "id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "users_table": {
+ "name": "users_table",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "integer",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "username": {
+ "name": "username",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "role": {
+ "name": "role",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "totp_key": {
+ "name": "totp_key",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "totp_verified": {
+ "name": "totp_verified",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "enabled": {
+ "name": "enabled",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ }
+ },
+ "indexes": {
+ "users_table_username_unique": {
+ "name": "users_table_username_unique",
+ "columns": [
+ "username"
+ ],
+ "isUnique": true
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ },
+ "user_configs_table": {
+ "name": "user_configs_table",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "default_mtu": {
+ "name": "default_mtu",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "default_persistent_keepalive": {
+ "name": "default_persistent_keepalive",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "default_dns": {
+ "name": "default_dns",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "default_allowed_ips": {
+ "name": "default_allowed_ips",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "default_j_c": {
+ "name": "default_j_c",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 7
+ },
+ "default_j_min": {
+ "name": "default_j_min",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 10
+ },
+ "default_j_max": {
+ "name": "default_j_max",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false,
+ "default": 1000
+ },
+ "default_i1": {
+ "name": "default_i1",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "default_i2": {
+ "name": "default_i2",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "default_i3": {
+ "name": "default_i3",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "default_i4": {
+ "name": "default_i4",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "default_i5": {
+ "name": "default_i5",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "host": {
+ "name": "host",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "port": {
+ "name": "port",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(CURRENT_TIMESTAMP)"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "user_configs_table_id_interfaces_table_name_fk": {
+ "name": "user_configs_table_id_interfaces_table_name_fk",
+ "tableFrom": "user_configs_table",
+ "tableTo": "interfaces_table",
+ "columnsFrom": [
+ "id"
+ ],
+ "columnsTo": [
+ "name"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "checkConstraints": {}
+ }
+ },
+ "views": {},
+ "enums": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "indexes": {}
+ }
+}
\ No newline at end of file
diff --git a/src/server/database/migrations/meta/_journal.json b/src/server/database/migrations/meta/_journal.json
index 9e4a5f4c..8a95d1af 100644
--- a/src/server/database/migrations/meta/_journal.json
+++ b/src/server/database/migrations/meta/_journal.json
@@ -22,6 +22,13 @@
"when": 1761298328460,
"tag": "0002_keen_sleepwalker",
"breakpoints": true
+ },
+ {
+ "idx": 3,
+ "version": "6",
+ "when": 1770902426367,
+ "tag": "0003_breezy_colossus",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/src/server/database/repositories/interface/schema.ts b/src/server/database/repositories/interface/schema.ts
index c0ee71c0..d465ebf3 100644
--- a/src/server/database/repositories/interface/schema.ts
+++ b/src/server/database/repositories/interface/schema.ts
@@ -20,15 +20,15 @@ export const wgInterface = sqliteTable('interfaces_table', {
s2: int().default(56),
s3: int(),
s4: int(),
+ h1: text(),
+ h2: text(),
+ h3: text(),
+ h4: text(),
i1: text(),
i2: text(),
i3: text(),
i4: text(),
i5: text(),
- h1: int().default(0),
- h2: int().default(0),
- h3: int().default(0),
- h4: int().default(0),
// does nothing yet
enabled: int({ mode: 'boolean' }).notNull(),
createdAt: text('created_at')
diff --git a/src/server/database/repositories/interface/types.ts b/src/server/database/repositories/interface/types.ts
index 3051d3b3..306f6546 100644
--- a/src/server/database/repositories/interface/types.ts
+++ b/src/server/database/repositories/interface/types.ts
@@ -38,15 +38,15 @@ export const InterfaceUpdateSchema = schemaForType()(
s2: SSchema,
s3: SSchema,
s4: SSchema,
+ h1: HSchema,
+ h2: HSchema,
+ h3: HSchema,
+ h4: HSchema,
i1: ISchema,
i2: ISchema,
i3: ISchema,
i4: ISchema,
i5: ISchema,
- h1: HSchema,
- h2: HSchema,
- h3: HSchema,
- h4: HSchema,
port: PortSchema,
device: device,
enabled: EnabledSchema,
diff --git a/src/server/utils/WireGuard.ts b/src/server/utils/WireGuard.ts
index 8b4ade14..c73b8fdc 100644
--- a/src/server/utils/WireGuard.ts
+++ b/src/server/utils/WireGuard.ts
@@ -213,7 +213,7 @@ class WireGuard {
WG_DEBUG('New Wireguard Keys generated successfully.');
}
- if (wgInterface.h1 === 0) {
+ if (!wgInterface.h1) {
WG_DEBUG('Generating random AmneziaWG obfuscation parameters...');
const headers = new Set();
@@ -222,10 +222,10 @@ class WireGuard {
}
const [h1, h2, h3, h4] = Array.from(headers);
- wgInterface.h1 = h1!;
- wgInterface.h2 = h2!;
- wgInterface.h3 = h3!;
- wgInterface.h4 = h4!;
+ wgInterface.h1 = String(h1)!;
+ wgInterface.h2 = String(h2)!;
+ wgInterface.h3 = String(h3)!;
+ wgInterface.h4 = String(h4)!;
Database.interfaces.update(wgInterface);
}
diff --git a/src/server/utils/types.ts b/src/server/utils/types.ts
index 46eb80e2..b604c47b 100644
--- a/src/server/utils/types.ts
+++ b/src/server/utils/types.ts
@@ -34,7 +34,33 @@ export const JmaxSchema = z.number().max(1280).nullable();
export const SSchema = z.number().max(1132).nullable();
-export const HSchema = z.number().min(5).max(2147483647).nullable();
+const H_MIN = 5;
+const H_MAX = 2 ** 31 - 1;
+
+export const HSchema = z
+ .string()
+ .transform(v => v.replace(/\s+/g, ''))
+ .refine(v => v === '' || /^\d+(-\d+)?$/.test(v), {
+ message: t('zod.generic.validNumberRange')
+ })
+ .refine(v => {
+ // if single number
+ if (!v.includes('-')) {
+ const num = Number(v);
+ if ( num < H_MIN || num > H_MAX )
+ return false;
+ return `${num}`;
+ }
+
+ // if number range
+ const [min, max] = v.split('-').map(Number);
+ if ( min < H_MIN || max > H_MAX || min > max )
+ return false;
+ return min === max ? `${min}` : `${min}-${max}`;
+ }, {
+ message: t('zod.generic.validNumberRange')
+ })
+ .nullable();
export const ISchema = z.string().nullable();
diff --git a/src/server/utils/wgHelper.ts b/src/server/utils/wgHelper.ts
index 607a0c51..7f69d6c5 100644
--- a/src/server/utils/wgHelper.ts
+++ b/src/server/utils/wgHelper.ts
@@ -63,15 +63,15 @@ AllowedIPs = ${allowedIps.join(', ')}${extraLines.length ? `\n${extraLines.join(
S2: wgInterface.s2,
S3: wgInterface.s3,
S4: wgInterface.s4,
+ H1: wgInterface.h1,
+ H2: wgInterface.h2,
+ H3: wgInterface.h3,
+ H4: wgInterface.h4,
I1: wgInterface.i1,
I2: wgInterface.i2,
I3: wgInterface.i3,
I4: wgInterface.i4,
I5: wgInterface.i5,
- H1: wgInterface.h1,
- H2: wgInterface.h2,
- H3: wgInterface.h3,
- H4: wgInterface.h4,
} as const;
awgLines = Object.entries(parameters)
@@ -131,15 +131,15 @@ PostDown = ${iptablesTemplate(hooks.postDown, wgInterface)}`;
S2: wgInterface.s2,
S3: wgInterface.s3,
S4: wgInterface.s4,
+ H1: wgInterface.h1,
+ H2: wgInterface.h2,
+ H3: wgInterface.h3,
+ H4: wgInterface.h4,
I1: client.i1,
I2: client.i2,
I3: client.i3,
I4: client.i4,
I5: client.i5,
- H1: wgInterface.h1,
- H2: wgInterface.h2,
- H3: wgInterface.h3,
- H4: wgInterface.h4,
} as const;
awgLines = Object.entries(parameters)