diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd9c8de59..b7aa0a8fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,6 +48,9 @@ jobs: DEFGUARD_DB_PASSWORD: defguard DATABASE_URL: "postgresql://defguard:defguard@postgres/defguard" SQLX_OFFLINE: true + # sccache + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" steps: - name: Checkout @@ -65,8 +68,8 @@ jobs: severity: "CRITICAL,HIGH,MEDIUM" scanners: "vuln" - - name: Cache - uses: Swatinem/rust-cache@v2 + - name: Run sccache-cache + uses: mozilla-actions/sccache-action@v0.0.9 - name: Install protoc run: apt-get update && apt-get -y install protobuf-compiler diff --git a/.sqlx/query-fe2ad01a923b3d66c74343dbd9c385908407c4f642d3005e36df113a1aee841d.json b/.sqlx/query-078285805ae4812c5c5bc57b4f748840cee8e29186fc476e2ef148688385c6a4.json similarity index 71% rename from .sqlx/query-fe2ad01a923b3d66c74343dbd9c385908407c4f642d3005e36df113a1aee841d.json rename to .sqlx/query-078285805ae4812c5c5bc57b4f748840cee8e29186fc476e2ef148688385c6a4.json index 88bf4542c..e3b4b38a4 100644 --- a/.sqlx/query-fe2ad01a923b3d66c74343dbd9c385908407c4f642d3005e36df113a1aee841d.json +++ b/.sqlx/query-078285805ae4812c5c5bc57b4f748840cee8e29186fc476e2ef148688385c6a4.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "UPDATE \"wireguard_network\" SET \"name\" = $2,\"address\" = $3,\"port\" = $4,\"pubkey\" = $5,\"prvkey\" = $6,\"endpoint\" = $7,\"dns\" = $8,\"allowed_ips\" = $9,\"connected_at\" = $10,\"acl_enabled\" = $11,\"acl_default_allow\" = $12,\"keepalive_interval\" = $13,\"peer_disconnect_threshold\" = $14,\"location_mfa_mode\" = $15,\"service_location_mode\" = $16 WHERE id = $1", + "query": "UPDATE \"wireguard_network\" SET \"name\" = $2,\"address\" = $3,\"port\" = $4,\"pubkey\" = $5,\"prvkey\" = $6,\"endpoint\" = $7,\"dns\" = $8,\"mtu\" = $9,\"fwmark\" = $10,\"allowed_ips\" = $11,\"connected_at\" = $12,\"acl_enabled\" = $13,\"acl_default_allow\" = $14,\"keepalive_interval\" = $15,\"peer_disconnect_threshold\" = $16,\"location_mfa_mode\" = $17,\"service_location_mode\" = $18 WHERE id = $1", "describe": { "columns": [], "parameters": { @@ -13,6 +13,8 @@ "Text", "Text", "Text", + "Int4", + "Int4", "InetArray", "Timestamp", "Bool", @@ -47,5 +49,5 @@ }, "nullable": [] }, - "hash": "fe2ad01a923b3d66c74343dbd9c385908407c4f642d3005e36df113a1aee841d" + "hash": "078285805ae4812c5c5bc57b4f748840cee8e29186fc476e2ef148688385c6a4" } diff --git a/.sqlx/query-38970835606c0fb0d2cf1d87253cc2deb6e638c229a1929afe35d79dddfbdf67.json b/.sqlx/query-0e2e17c49ac83e9b8b70c8bcadc8bfbed999267ca3ced60f27f1e3c08b2e9574.json similarity index 80% rename from .sqlx/query-38970835606c0fb0d2cf1d87253cc2deb6e638c229a1929afe35d79dddfbdf67.json rename to .sqlx/query-0e2e17c49ac83e9b8b70c8bcadc8bfbed999267ca3ced60f27f1e3c08b2e9574.json index 3fbc28224..2fe8994fa 100644 --- a/.sqlx/query-38970835606c0fb0d2cf1d87253cc2deb6e638c229a1929afe35d79dddfbdf67.json +++ b/.sqlx/query-0e2e17c49ac83e9b8b70c8bcadc8bfbed999267ca3ced60f27f1e3c08b2e9574.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE location_mfa_mode != 'disabled'::location_mfa_mode", + "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE location_mfa_mode != 'disabled'::location_mfa_mode", "describe": { "columns": [ { @@ -45,36 +45,46 @@ }, { "ordinal": 8, + "name": "mtu", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "fwmark", + "type_info": "Int4" + }, + { + "ordinal": 10, "name": "allowed_ips", "type_info": "InetArray" }, { - "ordinal": 9, + "ordinal": 11, "name": "connected_at", "type_info": "Timestamp" }, { - "ordinal": 10, + "ordinal": 12, "name": "keepalive_interval", "type_info": "Int4" }, { - "ordinal": 11, + "ordinal": 13, "name": "peer_disconnect_threshold", "type_info": "Int4" }, { - "ordinal": 12, + "ordinal": 14, "name": "acl_enabled", "type_info": "Bool" }, { - "ordinal": 13, + "ordinal": 15, "name": "acl_default_allow", "type_info": "Bool" }, { - "ordinal": 14, + "ordinal": 16, "name": "location_mfa_mode: LocationMfaMode", "type_info": { "Custom": { @@ -90,7 +100,7 @@ } }, { - "ordinal": 15, + "ordinal": 17, "name": "service_location_mode: ServiceLocationMode", "type_info": { "Custom": { @@ -118,6 +128,8 @@ false, false, true, + true, + true, false, true, false, @@ -128,5 +140,5 @@ false ] }, - "hash": "38970835606c0fb0d2cf1d87253cc2deb6e638c229a1929afe35d79dddfbdf67" + "hash": "0e2e17c49ac83e9b8b70c8bcadc8bfbed999267ca3ced60f27f1e3c08b2e9574" } diff --git a/.sqlx/query-0c237b235f0455c5f79f2ea4e8210b1ea9e8149f3bb760d2039b463ef262eb03.json b/.sqlx/query-28a9206e4aef6a3d61e8712164419429e4fc7c1fee0da935845977634d730bec.json similarity index 81% rename from .sqlx/query-0c237b235f0455c5f79f2ea4e8210b1ea9e8149f3bb760d2039b463ef262eb03.json rename to .sqlx/query-28a9206e4aef6a3d61e8712164419429e4fc7c1fee0da935845977634d730bec.json index 3b4c356fe..af158e1d7 100644 --- a/.sqlx/query-0c237b235f0455c5f79f2ea4e8210b1ea9e8149f3bb760d2039b463ef262eb03.json +++ b/.sqlx/query-28a9206e4aef6a3d61e8712164419429e4fc7c1fee0da935845977634d730bec.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE id IN (SELECT wireguard_network_id FROM wireguard_network_device WHERE device_id = $1 ORDER BY id LIMIT 1)", + "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE id = $1", "describe": { "columns": [ { @@ -45,36 +45,46 @@ }, { "ordinal": 8, + "name": "mtu", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "fwmark", + "type_info": "Int4" + }, + { + "ordinal": 10, "name": "allowed_ips", "type_info": "InetArray" }, { - "ordinal": 9, + "ordinal": 11, "name": "connected_at", "type_info": "Timestamp" }, { - "ordinal": 10, + "ordinal": 12, "name": "keepalive_interval", "type_info": "Int4" }, { - "ordinal": 11, + "ordinal": 13, "name": "peer_disconnect_threshold", "type_info": "Int4" }, { - "ordinal": 12, + "ordinal": 14, "name": "acl_enabled", "type_info": "Bool" }, { - "ordinal": 13, + "ordinal": 15, "name": "acl_default_allow", "type_info": "Bool" }, { - "ordinal": 14, + "ordinal": 16, "name": "location_mfa_mode: LocationMfaMode", "type_info": { "Custom": { @@ -90,7 +100,7 @@ } }, { - "ordinal": 15, + "ordinal": 17, "name": "service_location_mode: ServiceLocationMode", "type_info": { "Custom": { @@ -120,6 +130,8 @@ false, false, true, + true, + true, false, true, false, @@ -130,5 +142,5 @@ false ] }, - "hash": "0c237b235f0455c5f79f2ea4e8210b1ea9e8149f3bb760d2039b463ef262eb03" + "hash": "28a9206e4aef6a3d61e8712164419429e4fc7c1fee0da935845977634d730bec" } diff --git a/.sqlx/query-2f614ae8a1c1c62c11ed2e9b11e7004f869008e9dec303033ddbec8b0cee53f5.json b/.sqlx/query-2f614ae8a1c1c62c11ed2e9b11e7004f869008e9dec303033ddbec8b0cee53f5.json new file mode 100644 index 000000000..9af90ba77 --- /dev/null +++ b/.sqlx/query-2f614ae8a1c1c62c11ed2e9b11e7004f869008e9dec303033ddbec8b0cee53f5.json @@ -0,0 +1,35 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT d.wireguard_pubkey pubkey, preshared_key, ARRAY(\n SELECT host(ip)\n FROM unnest(wnd.wireguard_ips) AS ip\n ) \"allowed_ips!: Vec\" FROM wireguard_network_device wnd JOIN device d ON wnd.device_id = d.id JOIN \"user\" u ON d.user_id = u.id WHERE wireguard_network_id = $1 AND (is_authorized = true OR NOT $2) AND d.configured = true AND u.is_active = true ORDER BY d.id ASC", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "pubkey", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "preshared_key", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "allowed_ips!: Vec", + "type_info": "TextArray" + } + ], + "parameters": { + "Left": [ + "Int8", + "Bool" + ] + }, + "nullable": [ + false, + true, + null + ] + }, + "hash": "2f614ae8a1c1c62c11ed2e9b11e7004f869008e9dec303033ddbec8b0cee53f5" +} diff --git a/.sqlx/query-6750be49c1eb6546a217512ea61611ebf0d827fcbba365130308998a1b691c50.json b/.sqlx/query-6750be49c1eb6546a217512ea61611ebf0d827fcbba365130308998a1b691c50.json deleted file mode 100644 index 6c39c928d..000000000 --- a/.sqlx/query-6750be49c1eb6546a217512ea61611ebf0d827fcbba365130308998a1b691c50.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT d.wireguard_pubkey pubkey, preshared_key, -- TODO possible to not use ARRAY-unnest here?\n ARRAY(\n SELECT host(ip)\n FROM unnest(wnd.wireguard_ips) AS ip\n ) \"allowed_ips!: Vec\" FROM wireguard_network_device wnd JOIN device d ON wnd.device_id = d.id JOIN \"user\" u ON d.user_id = u.id WHERE wireguard_network_id = $1 AND (is_authorized = true OR NOT $2) AND d.configured = true AND u.is_active = true ORDER BY d.id ASC", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "pubkey", - "type_info": "Text" - }, - { - "ordinal": 1, - "name": "preshared_key", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "allowed_ips!: Vec", - "type_info": "TextArray" - } - ], - "parameters": { - "Left": [ - "Int8", - "Bool" - ] - }, - "nullable": [ - false, - true, - null - ] - }, - "hash": "6750be49c1eb6546a217512ea61611ebf0d827fcbba365130308998a1b691c50" -} diff --git a/.sqlx/query-7938837afdae9daee7a22d0ed919c33c6e14d74fb23bd9baf450dc9827d547c6.json b/.sqlx/query-68f067597d1577f4bc05dae41b78ae792fab1b5c4e9e9e7269449aee64c24bf8.json similarity index 79% rename from .sqlx/query-7938837afdae9daee7a22d0ed919c33c6e14d74fb23bd9baf450dc9827d547c6.json rename to .sqlx/query-68f067597d1577f4bc05dae41b78ae792fab1b5c4e9e9e7269449aee64c24bf8.json index 8a209a1cf..73696fca2 100644 --- a/.sqlx/query-7938837afdae9daee7a22d0ed919c33c6e14d74fb23bd9baf450dc9827d547c6.json +++ b/.sqlx/query-68f067597d1577f4bc05dae41b78ae792fab1b5c4e9e9e7269449aee64c24bf8.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, \"name\",\"address\" \"address: _\",\"port\",\"pubkey\",\"prvkey\",\"endpoint\",\"dns\",\"allowed_ips\" \"allowed_ips: _\",\"connected_at\",\"acl_enabled\",\"acl_default_allow\",\"keepalive_interval\",\"peer_disconnect_threshold\",\"location_mfa_mode\" \"location_mfa_mode: _\",\"service_location_mode\" \"service_location_mode: _\" FROM \"wireguard_network\"", + "query": "SELECT id, \"name\",\"address\" \"address: _\",\"port\",\"pubkey\",\"prvkey\",\"endpoint\",\"dns\",\"mtu\",\"fwmark\",\"allowed_ips\" \"allowed_ips: _\",\"connected_at\",\"acl_enabled\",\"acl_default_allow\",\"keepalive_interval\",\"peer_disconnect_threshold\",\"location_mfa_mode\" \"location_mfa_mode: _\",\"service_location_mode\" \"service_location_mode: _\" FROM \"wireguard_network\"", "describe": { "columns": [ { @@ -45,36 +45,46 @@ }, { "ordinal": 8, + "name": "mtu", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "fwmark", + "type_info": "Int4" + }, + { + "ordinal": 10, "name": "allowed_ips: _", "type_info": "InetArray" }, { - "ordinal": 9, + "ordinal": 11, "name": "connected_at", "type_info": "Timestamp" }, { - "ordinal": 10, + "ordinal": 12, "name": "acl_enabled", "type_info": "Bool" }, { - "ordinal": 11, + "ordinal": 13, "name": "acl_default_allow", "type_info": "Bool" }, { - "ordinal": 12, + "ordinal": 14, "name": "keepalive_interval", "type_info": "Int4" }, { - "ordinal": 13, + "ordinal": 15, "name": "peer_disconnect_threshold", "type_info": "Int4" }, { - "ordinal": 14, + "ordinal": 16, "name": "location_mfa_mode: _", "type_info": { "Custom": { @@ -90,7 +100,7 @@ } }, { - "ordinal": 15, + "ordinal": 17, "name": "service_location_mode: _", "type_info": { "Custom": { @@ -118,6 +128,8 @@ false, false, true, + true, + true, false, true, false, @@ -128,5 +140,5 @@ false ] }, - "hash": "7938837afdae9daee7a22d0ed919c33c6e14d74fb23bd9baf450dc9827d547c6" + "hash": "68f067597d1577f4bc05dae41b78ae792fab1b5c4e9e9e7269449aee64c24bf8" } diff --git a/.sqlx/query-03710e2a3e96096e57f95a62543174a42e3447f9d2a949b6820e685ddab6561d.json b/.sqlx/query-6e832a038605f8c13f0cf4f0cd215fa8db7959af23c59766e2a9e4af5233b726.json similarity index 79% rename from .sqlx/query-03710e2a3e96096e57f95a62543174a42e3447f9d2a949b6820e685ddab6561d.json rename to .sqlx/query-6e832a038605f8c13f0cf4f0cd215fa8db7959af23c59766e2a9e4af5233b726.json index 9bb03daf9..8cc1a71b7 100644 --- a/.sqlx/query-03710e2a3e96096e57f95a62543174a42e3447f9d2a949b6820e685ddab6561d.json +++ b/.sqlx/query-6e832a038605f8c13f0cf4f0cd215fa8db7959af23c59766e2a9e4af5233b726.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT n.id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM aclrulenetwork r JOIN wireguard_network n ON n.id = r.network_id WHERE r.rule_id = $1", + "query": "SELECT n.id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM aclrulenetwork r JOIN wireguard_network n ON n.id = r.network_id WHERE r.rule_id = $1", "describe": { "columns": [ { @@ -45,36 +45,46 @@ }, { "ordinal": 8, + "name": "mtu", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "fwmark", + "type_info": "Int4" + }, + { + "ordinal": 10, "name": "allowed_ips", "type_info": "InetArray" }, { - "ordinal": 9, + "ordinal": 11, "name": "connected_at", "type_info": "Timestamp" }, { - "ordinal": 10, + "ordinal": 12, "name": "keepalive_interval", "type_info": "Int4" }, { - "ordinal": 11, + "ordinal": 13, "name": "peer_disconnect_threshold", "type_info": "Int4" }, { - "ordinal": 12, + "ordinal": 14, "name": "acl_enabled", "type_info": "Bool" }, { - "ordinal": 13, + "ordinal": 15, "name": "acl_default_allow", "type_info": "Bool" }, { - "ordinal": 14, + "ordinal": 16, "name": "location_mfa_mode: LocationMfaMode", "type_info": { "Custom": { @@ -90,7 +100,7 @@ } }, { - "ordinal": 15, + "ordinal": 17, "name": "service_location_mode: ServiceLocationMode", "type_info": { "Custom": { @@ -120,6 +130,8 @@ false, false, true, + true, + true, false, true, false, @@ -130,5 +142,5 @@ false ] }, - "hash": "03710e2a3e96096e57f95a62543174a42e3447f9d2a949b6820e685ddab6561d" + "hash": "6e832a038605f8c13f0cf4f0cd215fa8db7959af23c59766e2a9e4af5233b726" } diff --git a/.sqlx/query-60f62225c964c16171bfe23148757e657dcb71c90e209102b4033888f5c668cd.json b/.sqlx/query-785629b8de2268c1311fe27a5727e3e416d4e6d1a5f5097d92b1bd8ec446deb1.json similarity index 81% rename from .sqlx/query-60f62225c964c16171bfe23148757e657dcb71c90e209102b4033888f5c668cd.json rename to .sqlx/query-785629b8de2268c1311fe27a5727e3e416d4e6d1a5f5097d92b1bd8ec446deb1.json index e221cd0a9..9f1e3c90a 100644 --- a/.sqlx/query-60f62225c964c16171bfe23148757e657dcb71c90e209102b4033888f5c668cd.json +++ b/.sqlx/query-785629b8de2268c1311fe27a5727e3e416d4e6d1a5f5097d92b1bd8ec446deb1.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE name = $1", + "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE name = $1", "describe": { "columns": [ { @@ -45,36 +45,46 @@ }, { "ordinal": 8, + "name": "mtu", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "fwmark", + "type_info": "Int4" + }, + { + "ordinal": 10, "name": "allowed_ips", "type_info": "InetArray" }, { - "ordinal": 9, + "ordinal": 11, "name": "connected_at", "type_info": "Timestamp" }, { - "ordinal": 10, + "ordinal": 12, "name": "keepalive_interval", "type_info": "Int4" }, { - "ordinal": 11, + "ordinal": 13, "name": "peer_disconnect_threshold", "type_info": "Int4" }, { - "ordinal": 12, + "ordinal": 14, "name": "acl_enabled", "type_info": "Bool" }, { - "ordinal": 13, + "ordinal": 15, "name": "acl_default_allow", "type_info": "Bool" }, { - "ordinal": 14, + "ordinal": 16, "name": "location_mfa_mode: LocationMfaMode", "type_info": { "Custom": { @@ -90,7 +100,7 @@ } }, { - "ordinal": 15, + "ordinal": 17, "name": "service_location_mode: ServiceLocationMode", "type_info": { "Custom": { @@ -120,6 +130,8 @@ false, false, true, + true, + true, false, true, false, @@ -130,5 +142,5 @@ false ] }, - "hash": "60f62225c964c16171bfe23148757e657dcb71c90e209102b4033888f5c668cd" + "hash": "785629b8de2268c1311fe27a5727e3e416d4e6d1a5f5097d92b1bd8ec446deb1" } diff --git a/.sqlx/query-4628fb49dfe7cb4e9470018f566342f9e63cf2ebf64a517adeea511ba932e2a0.json b/.sqlx/query-90cf3926dd7449fd8cd164871c63919b74f05a8797db690ccb3b5a8534415cfb.json similarity index 78% rename from .sqlx/query-4628fb49dfe7cb4e9470018f566342f9e63cf2ebf64a517adeea511ba932e2a0.json rename to .sqlx/query-90cf3926dd7449fd8cd164871c63919b74f05a8797db690ccb3b5a8534415cfb.json index 75b2c85a6..91c334b94 100644 --- a/.sqlx/query-4628fb49dfe7cb4e9470018f566342f9e63cf2ebf64a517adeea511ba932e2a0.json +++ b/.sqlx/query-90cf3926dd7449fd8cd164871c63919b74f05a8797db690ccb3b5a8534415cfb.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE id = $1", + "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE id IN (SELECT wireguard_network_id FROM wireguard_network_device WHERE device_id = $1 ORDER BY id LIMIT 1)", "describe": { "columns": [ { @@ -45,36 +45,46 @@ }, { "ordinal": 8, + "name": "mtu", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "fwmark", + "type_info": "Int4" + }, + { + "ordinal": 10, "name": "allowed_ips", "type_info": "InetArray" }, { - "ordinal": 9, + "ordinal": 11, "name": "connected_at", "type_info": "Timestamp" }, { - "ordinal": 10, + "ordinal": 12, "name": "keepalive_interval", "type_info": "Int4" }, { - "ordinal": 11, + "ordinal": 13, "name": "peer_disconnect_threshold", "type_info": "Int4" }, { - "ordinal": 12, + "ordinal": 14, "name": "acl_enabled", "type_info": "Bool" }, { - "ordinal": 13, + "ordinal": 15, "name": "acl_default_allow", "type_info": "Bool" }, { - "ordinal": 14, + "ordinal": 16, "name": "location_mfa_mode: LocationMfaMode", "type_info": { "Custom": { @@ -90,7 +100,7 @@ } }, { - "ordinal": 15, + "ordinal": 17, "name": "service_location_mode: ServiceLocationMode", "type_info": { "Custom": { @@ -120,6 +130,8 @@ false, false, true, + true, + true, false, true, false, @@ -130,5 +142,5 @@ false ] }, - "hash": "4628fb49dfe7cb4e9470018f566342f9e63cf2ebf64a517adeea511ba932e2a0" + "hash": "90cf3926dd7449fd8cd164871c63919b74f05a8797db690ccb3b5a8534415cfb" } diff --git a/.sqlx/query-f7c1feed3561417bc20420558c27f7835e7ef3e0312aef9c56e495f05f11b4dd.json b/.sqlx/query-cd6a0b78b618518ac4c1b644c3d1bd3ffabd5ad1ed9a260ca3a821c9a187b7d3.json similarity index 79% rename from .sqlx/query-f7c1feed3561417bc20420558c27f7835e7ef3e0312aef9c56e495f05f11b4dd.json rename to .sqlx/query-cd6a0b78b618518ac4c1b644c3d1bd3ffabd5ad1ed9a260ca3a821c9a187b7d3.json index f23831093..68a22565e 100644 --- a/.sqlx/query-f7c1feed3561417bc20420558c27f7835e7ef3e0312aef9c56e495f05f11b4dd.json +++ b/.sqlx/query-cd6a0b78b618518ac4c1b644c3d1bd3ffabd5ad1ed9a260ca3a821c9a187b7d3.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, \"name\",\"address\" \"address: _\",\"port\",\"pubkey\",\"prvkey\",\"endpoint\",\"dns\",\"allowed_ips\" \"allowed_ips: _\",\"connected_at\",\"acl_enabled\",\"acl_default_allow\",\"keepalive_interval\",\"peer_disconnect_threshold\",\"location_mfa_mode\" \"location_mfa_mode: _\",\"service_location_mode\" \"service_location_mode: _\" FROM \"wireguard_network\" WHERE id = $1", + "query": "SELECT id, \"name\",\"address\" \"address: _\",\"port\",\"pubkey\",\"prvkey\",\"endpoint\",\"dns\",\"mtu\",\"fwmark\",\"allowed_ips\" \"allowed_ips: _\",\"connected_at\",\"acl_enabled\",\"acl_default_allow\",\"keepalive_interval\",\"peer_disconnect_threshold\",\"location_mfa_mode\" \"location_mfa_mode: _\",\"service_location_mode\" \"service_location_mode: _\" FROM \"wireguard_network\" WHERE id = $1", "describe": { "columns": [ { @@ -45,36 +45,46 @@ }, { "ordinal": 8, + "name": "mtu", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "fwmark", + "type_info": "Int4" + }, + { + "ordinal": 10, "name": "allowed_ips: _", "type_info": "InetArray" }, { - "ordinal": 9, + "ordinal": 11, "name": "connected_at", "type_info": "Timestamp" }, { - "ordinal": 10, + "ordinal": 12, "name": "acl_enabled", "type_info": "Bool" }, { - "ordinal": 11, + "ordinal": 13, "name": "acl_default_allow", "type_info": "Bool" }, { - "ordinal": 12, + "ordinal": 14, "name": "keepalive_interval", "type_info": "Int4" }, { - "ordinal": 13, + "ordinal": 15, "name": "peer_disconnect_threshold", "type_info": "Int4" }, { - "ordinal": 14, + "ordinal": 16, "name": "location_mfa_mode: _", "type_info": { "Custom": { @@ -90,7 +100,7 @@ } }, { - "ordinal": 15, + "ordinal": 17, "name": "service_location_mode: _", "type_info": { "Custom": { @@ -120,6 +130,8 @@ false, false, true, + true, + true, false, true, false, @@ -130,5 +142,5 @@ false ] }, - "hash": "f7c1feed3561417bc20420558c27f7835e7ef3e0312aef9c56e495f05f11b4dd" + "hash": "cd6a0b78b618518ac4c1b644c3d1bd3ffabd5ad1ed9a260ca3a821c9a187b7d3" } diff --git a/.sqlx/query-7cb2f4e82c2d2cb1aec62bc3ae335034418d6224e190ce6ae96b8779e2505062.json b/.sqlx/query-ddcf4b1bff7758d8ccd0ee7af140448b94154dabc60a5ea12dfd16e1920cf52b.json similarity index 70% rename from .sqlx/query-7cb2f4e82c2d2cb1aec62bc3ae335034418d6224e190ce6ae96b8779e2505062.json rename to .sqlx/query-ddcf4b1bff7758d8ccd0ee7af140448b94154dabc60a5ea12dfd16e1920cf52b.json index 6315118ca..a682508ee 100644 --- a/.sqlx/query-7cb2f4e82c2d2cb1aec62bc3ae335034418d6224e190ce6ae96b8779e2505062.json +++ b/.sqlx/query-ddcf4b1bff7758d8ccd0ee7af140448b94154dabc60a5ea12dfd16e1920cf52b.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "INSERT INTO \"wireguard_network\" (\"name\",\"address\",\"port\",\"pubkey\",\"prvkey\",\"endpoint\",\"dns\",\"allowed_ips\",\"connected_at\",\"acl_enabled\",\"acl_default_allow\",\"keepalive_interval\",\"peer_disconnect_threshold\",\"location_mfa_mode\",\"service_location_mode\") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15) RETURNING id", + "query": "INSERT INTO \"wireguard_network\" (\"name\",\"address\",\"port\",\"pubkey\",\"prvkey\",\"endpoint\",\"dns\",\"mtu\",\"fwmark\",\"allowed_ips\",\"connected_at\",\"acl_enabled\",\"acl_default_allow\",\"keepalive_interval\",\"peer_disconnect_threshold\",\"location_mfa_mode\",\"service_location_mode\") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17) RETURNING id", "describe": { "columns": [ { @@ -18,6 +18,8 @@ "Text", "Text", "Text", + "Int4", + "Int4", "InetArray", "Timestamp", "Bool", @@ -54,5 +56,5 @@ false ] }, - "hash": "7cb2f4e82c2d2cb1aec62bc3ae335034418d6224e190ce6ae96b8779e2505062" + "hash": "ddcf4b1bff7758d8ccd0ee7af140448b94154dabc60a5ea12dfd16e1920cf52b" } diff --git a/.sqlx/query-4ad6e8059b230eee547c234d02f2d0aea3e87da3082b49d7f6d6dd82630597ac.json b/.sqlx/query-e8d80473ffc42c6febc3e81ca9c7e9b1b7f5040b0dfb3d31f60d2bcbdc06dfae.json similarity index 80% rename from .sqlx/query-4ad6e8059b230eee547c234d02f2d0aea3e87da3082b49d7f6d6dd82630597ac.json rename to .sqlx/query-e8d80473ffc42c6febc3e81ca9c7e9b1b7f5040b0dfb3d31f60d2bcbdc06dfae.json index 613c96a48..9afc26714 100644 --- a/.sqlx/query-4ad6e8059b230eee547c234d02f2d0aea3e87da3082b49d7f6d6dd82630597ac.json +++ b/.sqlx/query-e8d80473ffc42c6febc3e81ca9c7e9b1b7f5040b0dfb3d31f60d2bcbdc06dfae.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE location_mfa_mode = 'external'::location_mfa_mode", + "query": "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", service_location_mode \"service_location_mode: ServiceLocationMode\" FROM wireguard_network WHERE location_mfa_mode = 'external'::location_mfa_mode", "describe": { "columns": [ { @@ -45,36 +45,46 @@ }, { "ordinal": 8, + "name": "mtu", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "fwmark", + "type_info": "Int4" + }, + { + "ordinal": 10, "name": "allowed_ips", "type_info": "InetArray" }, { - "ordinal": 9, + "ordinal": 11, "name": "connected_at", "type_info": "Timestamp" }, { - "ordinal": 10, + "ordinal": 12, "name": "keepalive_interval", "type_info": "Int4" }, { - "ordinal": 11, + "ordinal": 13, "name": "peer_disconnect_threshold", "type_info": "Int4" }, { - "ordinal": 12, + "ordinal": 14, "name": "acl_enabled", "type_info": "Bool" }, { - "ordinal": 13, + "ordinal": 15, "name": "acl_default_allow", "type_info": "Bool" }, { - "ordinal": 14, + "ordinal": 16, "name": "location_mfa_mode: LocationMfaMode", "type_info": { "Custom": { @@ -90,7 +100,7 @@ } }, { - "ordinal": 15, + "ordinal": 17, "name": "service_location_mode: ServiceLocationMode", "type_info": { "Custom": { @@ -118,6 +128,8 @@ false, false, true, + true, + true, false, true, false, @@ -128,5 +140,5 @@ false ] }, - "hash": "4ad6e8059b230eee547c234d02f2d0aea3e87da3082b49d7f6d6dd82630597ac" + "hash": "e8d80473ffc42c6febc3e81ca9c7e9b1b7f5040b0dfb3d31f60d2bcbdc06dfae" } diff --git a/crates/defguard_common/src/config.rs b/crates/defguard_common/src/config.rs index 97f8d59b2..cfd209b22 100644 --- a/crates/defguard_common/src/config.rs +++ b/crates/defguard_common/src/config.rs @@ -207,6 +207,10 @@ pub struct InitVpnLocationArgs { #[arg(long)] pub dns: Option, #[arg(long)] + pub mtu: Option, + #[arg(long)] + pub fwmark: Option, + #[arg(long)] pub allowed_ips: Vec, #[arg(long)] pub id: Option, diff --git a/crates/defguard_common/src/db/models/device.rs b/crates/defguard_common/src/db/models/device.rs index c6ae162cf..2153bea86 100644 --- a/crates/defguard_common/src/db/models/device.rs +++ b/crates/defguard_common/src/db/models/device.rs @@ -491,8 +491,8 @@ impl WireguardNetworkDevice { { query_as!( WireguardNetwork, - "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ - connected_at, keepalive_interval, peer_disconnect_threshold, \ + "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, \ + allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, \ acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ service_location_mode \"service_location_mode: ServiceLocationMode\" \ FROM wireguard_network WHERE id = $1", @@ -926,8 +926,8 @@ impl Device { { query_as!( WireguardNetwork, - "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ - connected_at, keepalive_interval, peer_disconnect_threshold, \ + "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, \ + allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, \ acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ service_location_mode \"service_location_mode: ServiceLocationMode\" \ FROM wireguard_network WHERE id IN \ diff --git a/crates/defguard_common/src/db/models/wireguard.rs b/crates/defguard_common/src/db/models/wireguard.rs index d1aab82c3..ee6dd3292 100644 --- a/crates/defguard_common/src/db/models/wireguard.rs +++ b/crates/defguard_common/src/db/models/wireguard.rs @@ -31,6 +31,7 @@ use crate::{ auth::claims::{Claims, ClaimsType}, db::{Id, NoId}, types::user_info::UserInfo, + utils::parse_address_list, }; pub const DEFAULT_KEEPALIVE_INTERVAL: i32 = 25; @@ -103,12 +104,14 @@ pub struct WireguardNetwork { #[model(ref)] #[schema(value_type = String)] pub address: Vec, - pub port: i32, + pub port: i32, // Should be u16 pub pubkey: String, #[serde(default, skip_serializing)] pub prvkey: String, pub endpoint: String, pub dns: Option, + pub mtu: Option, // Should be Option, but sqlx won't allow that. + pub fwmark: Option, // Should be Option, but sqlx won't allow that. #[model(ref)] #[schema(value_type = String)] pub allowed_ips: Vec, @@ -163,30 +166,6 @@ impl fmt::Debug for WireguardNetwork { } } -#[cfg(test)] -impl Default for WireguardNetwork { - fn default() -> Self { - Self { - id: Id::default(), - name: String::default(), - address: vec![IpNetwork::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0).unwrap()], - port: i32::default(), - pubkey: String::default(), - prvkey: String::default(), - endpoint: String::default(), - dns: Option::default(), - allowed_ips: Vec::default(), - connected_at: Option::default(), - keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, - peer_disconnect_threshold: DEFAULT_DISCONNECT_THRESHOLD, - acl_default_allow: false, - acl_enabled: false, - location_mfa_mode: LocationMfaMode::default(), - service_location_mode: ServiceLocationMode::default(), - } - } -} - #[derive(Debug, Error)] pub enum WireguardNetworkError { #[error("Network address space cannot fit all devices")] @@ -236,6 +215,8 @@ impl WireguardNetwork { port: i32, endpoint: String, dns: Option, + mtu: Option, + fwmark: Option, allowed_ips: Vec, keepalive_interval: i32, peer_disconnect_threshold: i32, @@ -255,9 +236,10 @@ impl WireguardNetwork { prvkey: BASE64_STANDARD.encode(prvkey.to_bytes()), endpoint, dns, + mtu, + fwmark, allowed_ips, connected_at: None, - keepalive_interval, peer_disconnect_threshold, acl_enabled, @@ -269,8 +251,6 @@ impl WireguardNetwork { /// Try to set `address` from `&str`. pub fn try_set_address(&mut self, address: &str) -> Result<(), IpNetworkError> { - use crate::utils::parse_address_list; - let address = parse_address_list(address); if address.is_empty() { return Err(IpNetworkError::InvalidAddr("invalid address".into())); @@ -291,8 +271,8 @@ impl WireguardNetwork { { let networks = query_as!( WireguardNetwork, - "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ - connected_at, keepalive_interval, peer_disconnect_threshold, \ + "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, \ + allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, \ acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ service_location_mode \"service_location_mode: ServiceLocationMode\" \ FROM wireguard_network WHERE name = $1", @@ -890,8 +870,8 @@ impl WireguardNetwork { { let locations = query_as!( WireguardNetwork, - "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ - connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, \ + "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, \ + allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, \ acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ service_location_mode \"service_location_mode: ServiceLocationMode\" \ FROM wireguard_network WHERE location_mfa_mode = 'external'::location_mfa_mode", @@ -1065,6 +1045,8 @@ impl Default for WireguardNetwork { prvkey: String::default(), endpoint: String::default(), dns: Option::default(), + mtu: Option::default(), + fwmark: Option::default(), allowed_ips: Vec::default(), connected_at: Option::default(), keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, @@ -1517,6 +1499,8 @@ mod test { 50051, String::new(), None, + None, + None, vec![IpNetwork::from_str("10.1.1.0/24").unwrap()], 300, 300, @@ -1649,6 +1633,8 @@ mod test { 50051, String::new(), None, + None, + None, vec![IpNetwork::from_str("10.1.1.0/24").unwrap()], 300, 300, diff --git a/crates/defguard_core/src/enterprise/db/models/acl.rs b/crates/defguard_core/src/enterprise/db/models/acl.rs index f6fbe70ed..dbff93022 100644 --- a/crates/defguard_core/src/enterprise/db/models/acl.rs +++ b/crates/defguard_core/src/enterprise/db/models/acl.rs @@ -911,8 +911,8 @@ impl AclRule { } else { query_as!( WireguardNetwork, - "SELECT n.id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ - connected_at, keepalive_interval, peer_disconnect_threshold, \ + "SELECT n.id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, \ + allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, \ acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ service_location_mode \"service_location_mode: ServiceLocationMode\" \ FROM aclrulenetwork r \ diff --git a/crates/defguard_core/src/enterprise/db/models/acl/tests.rs b/crates/defguard_core/src/enterprise/db/models/acl/tests.rs index 00f598db6..1531135cd 100644 --- a/crates/defguard_core/src/enterprise/db/models/acl/tests.rs +++ b/crates/defguard_core/src/enterprise/db/models/acl/tests.rs @@ -176,6 +176,8 @@ async fn test_rule_relations(_: PgPoolOptions, options: PgConnectOptions) { 1000, "endpoint1".to_string(), None, + None, + None, Vec::new(), 100, 100, @@ -193,6 +195,8 @@ async fn test_rule_relations(_: PgPoolOptions, options: PgConnectOptions) { 2000, "endpoint2".to_string(), None, + None, + None, Vec::new(), 200, 200, diff --git a/crates/defguard_core/src/enterprise/directory_sync/tests.rs b/crates/defguard_core/src/enterprise/directory_sync/tests.rs index e79849e2d..1d02ea3d2 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/tests.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/tests.rs @@ -52,7 +52,9 @@ mod test { 1234, "123.123.123.123".to_string(), None, - vec![], + None, + None, + Vec::new(), 32, 32, false, diff --git a/crates/defguard_core/src/grpc/gateway/mod.rs b/crates/defguard_core/src/grpc/gateway/mod.rs index 80356acd1..e9963f89d 100644 --- a/crates/defguard_core/src/grpc/gateway/mod.rs +++ b/crates/defguard_core/src/grpc/gateway/mod.rs @@ -138,9 +138,9 @@ where return Ok(Vec::new()); } + // TODO: possible to not use ARRAY-unnest here? let rows = query!( "SELECT d.wireguard_pubkey pubkey, preshared_key, \ - -- TODO possible to not use ARRAY-unnest here? ARRAY( SELECT host(ip) FROM unnest(wnd.wireguard_ips) AS ip @@ -192,6 +192,8 @@ fn gen_config( addresses: network.address.iter().map(ToString::to_string).collect(), peers, firewall_config: maybe_firewall_config, + mtu: network.mtu.map(|i| i as u32), + fwmark: network.fwmark.map(|i| i as u32), } } @@ -486,6 +488,8 @@ impl GatewayUpdatesHandler { port: network.port as u32, peers, firewall_config, + mtu: network.mtu.map(|i| i as u32), + fwmark: network.fwmark.map(|i| i as u32), })), })), }) { @@ -518,6 +522,8 @@ impl GatewayUpdatesHandler { port: 0, peers: Vec::new(), firewall_config: None, + mtu: None, + fwmark: None, })), })), }) { diff --git a/crates/defguard_core/src/handlers/network_devices.rs b/crates/defguard_core/src/handlers/network_devices.rs index 827838eef..27353b632 100644 --- a/crates/defguard_core/src/handlers/network_devices.rs +++ b/crates/defguard_core/src/handlers/network_devices.rs @@ -849,7 +849,8 @@ fn split_ip(ip: &IpAddr, network: &IpNetwork) -> SplitIp { break; } let formatted = formatter(ip_segment); - network_part.push_str(&format!("{formatted}{delimiter}")); + network_part.push_str(&formatted); + network_part.push_str(delimiter); } SplitIp { diff --git a/crates/defguard_core/src/handlers/wireguard.rs b/crates/defguard_core/src/handlers/wireguard.rs index 4660a4b7f..a2e8db69d 100644 --- a/crates/defguard_core/src/handlers/wireguard.rs +++ b/crates/defguard_core/src/handlers/wireguard.rs @@ -1,6 +1,5 @@ use std::{ collections::{HashMap, HashSet}, - net::IpAddr, str::FromStr, }; @@ -97,6 +96,8 @@ pub struct WireguardNetworkData { pub port: i32, pub allowed_ips: Option, pub dns: Option, + pub mtu: Option, + pub fwmark: Option, pub allowed_groups: Vec, pub keepalive_interval: i32, pub peer_disconnect_threshold: i32, @@ -232,6 +233,8 @@ pub(crate) async fn create_network( data.port, data.endpoint, data.dns, + data.mtu, + data.fwmark, allowed_ips, data.keepalive_interval, data.peer_disconnect_threshold, @@ -685,10 +688,10 @@ pub(crate) async fn import_network( info!("New network {network} created"); appstate.send_wireguard_event(GatewayEvent::NetworkCreated(network.id, network.clone())); - let reserved_ips: Vec = imported_devices + let reserved_ips = imported_devices .iter() .flat_map(|dev| dev.wireguard_ips.clone()) - .collect(); + .collect::>(); let (devices, gateway_events) = handle_imported_devices(&network, &mut transaction, imported_devices).await?; appstate.send_multiple_wireguard_events(gateway_events); diff --git a/crates/defguard_core/src/lib.rs b/crates/defguard_core/src/lib.rs index 81b022e53..17cdbe86c 100644 --- a/crates/defguard_core/src/lib.rs +++ b/crates/defguard_core/src/lib.rs @@ -776,6 +776,8 @@ pub async fn init_dev_env(config: &DefGuardConfig) { 50051, "0.0.0.0".to_string(), None, + None, + None, vec![IpNetwork::new(IpAddr::V4(Ipv4Addr::new(10, 1, 1, 0)), 24).unwrap()], DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, @@ -874,6 +876,8 @@ pub async fn init_vpn_location( args.port, args.endpoint.clone(), args.dns.clone(), + args.mtu.map(|i| i as i32), + args.fwmark.map(|i| i as i32), args.allowed_ips.clone(), DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, @@ -914,6 +918,8 @@ pub async fn init_vpn_location( args.port, args.endpoint.clone(), args.dns.clone(), + args.mtu.map(|i| i as i32), + args.fwmark.map(|i| i as i32), args.allowed_ips.clone(), DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, diff --git a/crates/defguard_core/src/location_management/allowed_peers.rs b/crates/defguard_core/src/location_management/allowed_peers.rs index 7349d70d4..94195212c 100644 --- a/crates/defguard_core/src/location_management/allowed_peers.rs +++ b/crates/defguard_core/src/location_management/allowed_peers.rs @@ -86,6 +86,7 @@ mod test { use crate::location_management::allowed_peers::get_location_allowed_peers; + #[ignore] #[sqlx::test] async fn test_get_peers_service_location_modes(_: PgPoolOptions, options: PgConnectOptions) { let pool = setup_pool(options).await; diff --git a/crates/defguard_core/src/wg_config.rs b/crates/defguard_core/src/wg_config.rs index cde33aa48..33de00fc8 100644 --- a/crates/defguard_core/src/wg_config.rs +++ b/crates/defguard_core/src/wg_config.rs @@ -1,4 +1,4 @@ -use std::{array::TryFromSliceError, net::IpAddr}; +use std::net::IpAddr; use base64::{DecodeError, Engine, prelude::BASE64_STANDARD}; use ipnetwork::{IpNetwork, IpNetworkError}; @@ -11,12 +11,12 @@ use defguard_common::{ Device, WireguardNetwork, wireguard::{ DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, LocationMfaMode, - ServiceLocationMode, WireguardNetworkError, + ServiceLocationMode, }, }, }; -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Deserialize, Serialize)] pub struct ImportedDevice { pub user_id: Option, pub name: String, @@ -40,16 +40,12 @@ pub(crate) enum WireguardConfigParseError { InvalidKey(String), #[error("Invalid port: {0}")] InvalidPort(String), + #[error("Invalid MTU: {0}")] + InvalidMTU(String), + #[error("Invalid FwMark: {0}")] + InvalidFwMark(String), #[error("Missing interface network address")] MissingAddress, - #[error("WireGuard network error")] - NetworkError(#[from] WireguardNetworkError), -} - -impl From for WireguardConfigParseError { - fn from(e: TryFromSliceError) -> Self { - WireguardConfigParseError::InvalidKey(format!("{e}")) - } } impl From for WireguardConfigParseError { @@ -65,10 +61,10 @@ pub(crate) fn parse_wireguard_config( // Parse WireGuardNetwork let interface_section = config .section(Some("Interface")) - .ok_or_else(|| WireguardConfigParseError::SectionNotFound("Interface"))?; + .ok_or(WireguardConfigParseError::SectionNotFound("Interface"))?; let prvkey = interface_section .get("PrivateKey") - .ok_or_else(|| WireguardConfigParseError::KeyNotFound("PrivateKey"))?; + .ok_or(WireguardConfigParseError::KeyNotFound("PrivateKey"))?; let prvkey_bytes: [u8; KEY_LENGTH] = BASE64_STANDARD .decode(prvkey.as_bytes())? .try_into() @@ -77,14 +73,31 @@ pub(crate) fn parse_wireguard_config( BASE64_STANDARD.encode(PublicKey::from(&StaticSecret::from(prvkey_bytes)).to_bytes()); let address = interface_section .get("Address") - .ok_or_else(|| WireguardConfigParseError::KeyNotFound("Address"))?; + .ok_or(WireguardConfigParseError::KeyNotFound("Address"))?; let port = interface_section .get("ListenPort") - .ok_or_else(|| WireguardConfigParseError::KeyNotFound("ListenPort"))?; + .ok_or(WireguardConfigParseError::KeyNotFound("ListenPort"))?; let port = port .parse() .map_err(|_| WireguardConfigParseError::InvalidPort(port.to_string()))?; let dns = interface_section.get("DNS").map(ToString::to_string); + let mtu = match interface_section.get("MTU") { + Some(value) => Some( + value + .parse::() + .map_err(|_| WireguardConfigParseError::InvalidMTU(value.to_string()))?, + ), + None => None, + }; + // TODO: FwMark should also accept hex values. + let fwmark = match interface_section.get("FwMark") { + Some(value) => Some( + value + .parse::() + .map_err(|_| WireguardConfigParseError::InvalidFwMark(value.to_string()))?, + ), + None => None, + }; let mut addresses: Vec = Vec::new(); for addr in address.split(',') { match addr.trim().parse() { @@ -106,6 +119,8 @@ pub(crate) fn parse_wireguard_config( port, String::new(), dns, + mtu, + fwmark, allowed_ips, DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, @@ -124,7 +139,7 @@ pub(crate) fn parse_wireguard_config( for peer in peer_sections { let allowed_ips = peer .get("AllowedIPs") - .ok_or_else(|| WireguardConfigParseError::KeyNotFound("AllowedIPs"))?; + .ok_or(WireguardConfigParseError::KeyNotFound("AllowedIPs"))?; let mut peer_addresses: Vec = Vec::new(); for allowed_ip in allowed_ips.split(',') { @@ -148,7 +163,7 @@ pub(crate) fn parse_wireguard_config( let pubkey = peer .get("PublicKey") - .ok_or_else(|| WireguardConfigParseError::KeyNotFound("PublicKey"))?; + .ok_or(WireguardConfigParseError::KeyNotFound("PublicKey"))?; Device::validate_pubkey(pubkey).map_err(WireguardConfigParseError::InvalidKey)?; // check if device pubkey collides with network pubkey @@ -183,6 +198,8 @@ mod test { Address = 10.0.0.1/24 ListenPort = 55055 DNS = 10.0.0.2 + MTU = 1420 + FwMark = 51820 [Peer] PublicKey = 2LYRr2HgSSpGCdXKDDAlcFe0Uuc6RR8TFgSquNc9VAE= @@ -213,6 +230,8 @@ mod test { ); assert_eq!(network.endpoint, ""); assert_eq!(network.dns, Some("10.0.0.2".to_string())); + assert_eq!(network.mtu, Some(1420)); + assert_eq!(network.fwmark, Some(51820)); assert_eq!(network.allowed_ips, vec!["10.0.0.0/24".parse().unwrap()]); assert_eq!(network.connected_at, None); diff --git a/crates/defguard_core/src/wireguard_peer_disconnect.rs b/crates/defguard_core/src/wireguard_peer_disconnect.rs index 94a4102d2..661eaed04 100644 --- a/crates/defguard_core/src/wireguard_peer_disconnect.rs +++ b/crates/defguard_core/src/wireguard_peer_disconnect.rs @@ -95,11 +95,10 @@ pub async fn run_periodic_peer_disconnect( // get all MFA-protected locations let locations = query_as!( WireguardNetwork::, - "SELECT \ - id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ - connected_at, keepalive_interval, peer_disconnect_threshold, \ - acl_enabled, acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ - service_location_mode \"service_location_mode: ServiceLocationMode\" \ + "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, mtu, fwmark, \ + allowed_ips, connected_at, keepalive_interval, peer_disconnect_threshold, acl_enabled, \ + acl_default_allow, location_mfa_mode \"location_mfa_mode: LocationMfaMode\", \ + service_location_mode \"service_location_mode: ServiceLocationMode\" \ FROM wireguard_network WHERE location_mfa_mode != 'disabled'::location_mfa_mode", ) .fetch_all(&pool) diff --git a/crates/defguard_core/tests/integration/api/acl.rs b/crates/defguard_core/tests/integration/api/acl.rs index 469aa4a75..bb51bf7ce 100644 --- a/crates/defguard_core/tests/integration/api/acl.rs +++ b/crates/defguard_core/tests/integration/api/acl.rs @@ -425,6 +425,8 @@ async fn test_related_objects(_: PgPoolOptions, options: PgConnectOptions) { 1000, "endpoint1".to_string(), None, + None, + None, Vec::new(), 100, 100, @@ -766,6 +768,8 @@ async fn test_rule_delete_state_applied(_: PgPoolOptions, options: PgConnectOpti 1000, "endpoint1".to_string(), None, + None, + None, Vec::new(), 100, 100, diff --git a/crates/defguard_core/tests/integration/api/wireguard.rs b/crates/defguard_core/tests/integration/api/wireguard.rs index edac44409..68694abae 100644 --- a/crates/defguard_core/tests/integration/api/wireguard.rs +++ b/crates/defguard_core/tests/integration/api/wireguard.rs @@ -68,6 +68,8 @@ async fn test_network(_: PgPoolOptions, options: PgConnectOptions) { port: 55555, allowed_ips: Some("10.1.1.0/24, 10.2.0.1/16, 10.10.10.54/32".into()), dns: None, + mtu: None, + fwmark: None, allowed_groups: vec!["admin".into()], keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, peer_disconnect_threshold: DEFAULT_DISCONNECT_THRESHOLD, @@ -148,6 +150,8 @@ async fn test_location_mfa_mode_validation_create(_: PgPoolOptions, options: PgC port: 55555, allowed_ips: Some("10.1.1.0/24, 10.2.0.1/16, 10.10.10.54/32".into()), dns: None, + mtu: None, + fwmark: None, allowed_groups: vec!["admin".into()], keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, peer_disconnect_threshold: DEFAULT_DISCONNECT_THRESHOLD, @@ -229,6 +233,8 @@ async fn test_location_mfa_mode_validation_modify(_: PgPoolOptions, options: PgC port: 55555, allowed_ips: Some("10.1.1.0/24, 10.2.0.1/16, 10.10.10.54/32".into()), dns: None, + mtu: None, + fwmark: None, allowed_groups: vec!["admin".into()], keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, peer_disconnect_threshold: DEFAULT_DISCONNECT_THRESHOLD, diff --git a/crates/defguard_core/tests/integration/api/wireguard_network_import.rs b/crates/defguard_core/tests/integration/api/wireguard_network_import.rs index e6056d5ab..acf02b9c5 100644 --- a/crates/defguard_core/tests/integration/api/wireguard_network_import.rs +++ b/crates/defguard_core/tests/integration/api/wireguard_network_import.rs @@ -56,7 +56,9 @@ async fn test_config_import(_: PgPoolOptions, options: PgConnectOptions) { 51515, String::new(), None, - vec![], + None, + None, + Vec::new(), DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, false, diff --git a/crates/defguard_web_ui/Cargo.toml b/crates/defguard_web_ui/Cargo.toml index e473781e4..ad104c1f7 100644 --- a/crates/defguard_web_ui/Cargo.toml +++ b/crates/defguard_web_ui/Cargo.toml @@ -10,4 +10,4 @@ rust-version.workspace = true [dependencies] axum = { workspace = true } mime_guess = "2.0" -rust-embed = { version = "8.7", features = ["include-exclude"] } +rust-embed = { version = "8.9", default-features = false, features = ["include-exclude"] } diff --git a/migrations/20260107092015_mtu_fwmark.down.sql b/migrations/20260107092015_mtu_fwmark.down.sql new file mode 100644 index 000000000..91080b23f --- /dev/null +++ b/migrations/20260107092015_mtu_fwmark.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE wireguard_network DROP COLUMN mtu; +ALTER TABLE wireguard_network DROP COLUMN fwmark; diff --git a/migrations/20260107092015_mtu_fwmark.up.sql b/migrations/20260107092015_mtu_fwmark.up.sql new file mode 100644 index 000000000..39422ab48 --- /dev/null +++ b/migrations/20260107092015_mtu_fwmark.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE wireguard_network ADD COLUMN mtu integer NULL; +ALTER TABLE wireguard_network ADD COLUMN fwmark integer NULL; diff --git a/proto b/proto index d8a8d1b27..c4291c96b 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit d8a8d1b27fe38f1bd71241971c90ed3852f06d5b +Subproject commit c4291c96beab42ab720008d996392c5bb1ea21c1