Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1203369
create new VPN client session on MFA success
wojcik91 Jan 28, 2026
50f309b
handle optional enums in model derive
wojcik91 Jan 28, 2026
d67a2e0
add mfa method to session
wojcik91 Jan 28, 2026
f0bbda9
update query data
wojcik91 Jan 28, 2026
c194cce
track session state
wojcik91 Jan 29, 2026
3b317f7
mark MFA sessions as connected
wojcik91 Jan 29, 2026
bb52a1d
Merge branch 'dev' into session_manager_mfa
wojcik91 Jan 29, 2026
8765bac
clippy fix
wojcik91 Jan 29, 2026
d3b25d8
disconnect unused sessions only for MFA locations
wojcik91 Jan 29, 2026
c1dd85c
send session disconnect event to gateway handler
wojcik91 Jan 29, 2026
4a2f112
rename MFA event
wojcik91 Jan 29, 2026
492c6fd
simplify MFA-related VPN client events
wojcik91 Jan 29, 2026
244553f
update frontend messages
wojcik91 Jan 29, 2026
8576f89
remove separate peer disconnect service
wojcik91 Jan 29, 2026
e9af7b0
don't store legacy stats
wojcik91 Jan 29, 2026
846fa29
avoid fetching device from DB multiple times
wojcik91 Jan 29, 2026
3312e21
Merge branch 'dev' into session_manager_mfa
wojcik91 Jan 29, 2026
8bb115b
update query data
wojcik91 Jan 30, 2026
af9e118
remove duplicate allowed peers method
wojcik91 Jan 30, 2026
16ddec7
add dedicated gateway event for successful client MFA
wojcik91 Jan 30, 2026
93b77f3
Merge branch 'dev' into session_manager_mfa
wojcik91 Jan 30, 2026
b3eeb08
clear preshared key when disconnecting MFA device
wojcik91 Jan 30, 2026
cd23b74
Merge branch 'dev' into session_manager_mfa
wojcik91 Jan 30, 2026
5c8ffd3
move stats purge service into a separate crate
wojcik91 Jan 31, 2026
5caad8d
purge VPN sessions instead of legacy stats
wojcik91 Jan 31, 2026
59d5c74
remove legacy purge methods
wojcik91 Jan 31, 2026
1b97b54
update query data
wojcik91 Jan 31, 2026
29ee106
Merge branch 'dev' into periodic_session_purge
wojcik91 Feb 2, 2026
29eb898
update dependencies
wojcik91 Feb 2, 2026
03fa733
update deny config
wojcik91 Feb 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

43 changes: 28 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ defguard_proto = { path = "./crates/defguard_proto", version = "0.0.0" }
defguard_proxy_manager = { path = "./crates/defguard_proxy_manager", version = "0.0.0" }
defguard_session_manager = { path = "./crates/defguard_session_manager", version = "0.0.0" }
defguard_version = { path = "./crates/defguard_version", version = "0.0.0" }
defguard_vpn_stats_purge = { path = "./crates/defguard_vpn_stats_purge", version = "0.0.0" }
defguard_web_ui = { path = "./crates/defguard_web_ui", version = "0.0.0" }
defguard_certs = { path = "./crates/defguard_certs", version = "0.0.0" }
model_derive = { path = "./crates/model_derive", version = "0.0.0" }
Expand Down
1 change: 1 addition & 0 deletions crates/defguard/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ defguard_mail = { workspace = true }
defguard_proxy_manager = { workspace = true }
defguard_session_manager = { workspace = true }
defguard_version = { workspace = true }
defguard_vpn_stats_purge = { workspace = true }
defguard_certs = { workspace = true }

# external dependencies
Expand Down
2 changes: 1 addition & 1 deletion crates/defguard/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ use defguard_core::{
init_dev_env, init_vpn_location, run_web_server,
utility_thread::run_utility_thread,
version::IncompatibleComponents,
wireguard_stats_purge::run_periodic_stats_purge,
};
use defguard_event_logger::{message::EventLoggerMessage, run_event_logger};
use defguard_event_router::{RouterReceiverSet, run_event_router};
use defguard_mail::{Mail, run_mail_handler};
use defguard_proxy_manager::{ProxyManager, ProxyTxSet};
use defguard_session_manager::{events::SessionManagerEvent, run_session_manager};
use defguard_vpn_stats_purge::run_periodic_stats_purge;
use secrecy::ExposeSecret;
use tokio::sync::{
broadcast,
Expand Down
94 changes: 4 additions & 90 deletions crates/defguard_common/src/db/models/wireguard_peer_stats.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
use std::time::Duration;

use chrono::{DateTime, NaiveDateTime, TimeDelta, Utc};
use humantime::format_duration;
use chrono::NaiveDateTime;
use ipnetwork::IpNetwork;
use model_derive::Model;
use serde::{Deserialize, Serialize};
use sqlx::{PgExecutor, PgPool, query, query_as, query_scalar};
use tracing::{debug, info};
use sqlx::{PgPool, query_as};

use crate::db::{Id, NoId};

Expand All @@ -28,90 +24,6 @@ pub struct WireguardPeerStats<I = NoId> {
pub allowed_ips: Option<String>,
}

impl WireguardPeerStats {
/// Delete stats older than a configured threshold.
/// This is done to prevent unnecessary table growth.
/// At least one record is retained for each device and network combination,
/// even when older than set threshold.
pub async fn purge_old_stats(
pool: &PgPool,
stats_purge_threshold: Duration,
) -> Result<(), sqlx::Error> {
let start = Utc::now();
info!(
"Purging stats older than {}",
format_duration(stats_purge_threshold)
);

let threshold = (Utc::now()
- TimeDelta::from_std(stats_purge_threshold).expect("Failed to parse duration"))
.naive_utc();
let result = query!(
"DELETE FROM wireguard_peer_stats \
WHERE collected_at < $1 \
AND (device_id, network, collected_at) NOT IN ( \
SELECT device_id, network, MAX(collected_at) \
FROM wireguard_peer_stats \
GROUP BY device_id, network)",
threshold
)
.execute(pool)
.await?;

let end = Utc::now();
let rows_count = result.rows_affected();

info!("Removed {rows_count} old records from wireguard_peer_stats",);

// Store successful stats purge in database.
Self::record_stats_purge(pool, start, end, threshold, rows_count as i64).await?;

Ok(())
}

// Check how much time has elapsed since last recorded stats purge
pub async fn time_since_last_purge<'e, E>(executor: E) -> Result<Option<Duration>, sqlx::Error>
where
E: PgExecutor<'e>,
{
debug!("Checking time since last stats purge");

let timestamp = query_scalar!("SELECT MAX(started_at) FROM wireguard_stats_purge")
.fetch_one(executor)
.await?;

match timestamp {
Some(timestamp) => {
let time_since = Utc::now().signed_duration_since(timestamp.and_utc());
let time_since = time_since.to_std().expect("Failed to parse duration");
debug!(
"Time since last stats purge: {}",
format_duration(time_since)
);
Ok(Some(time_since))
}
None => Ok(None),
}
}

async fn record_stats_purge<'e, E>(
executor: E,
start: DateTime<Utc>,
end: DateTime<Utc>,
removal_threshold: NaiveDateTime,
records_removed: i64,
) -> Result<(), sqlx::Error>
where
E: PgExecutor<'e>,
{
debug!("Recording successful stats purge in database");
query!("INSERT INTO wireguard_stats_purge (started_at, finished_at, removal_threshold, records_removed) VALUES ($1, $2, $3, $4)",
start.naive_utc(), end.naive_utc(), removal_threshold, records_removed).execute(executor).await?;

Ok(())
}
}

impl WireguardPeerStats<Id> {
pub async fn fetch_latest(
conn: &PgPool,
Expand Down Expand Up @@ -167,6 +79,8 @@ impl WireguardPeerStats<Id> {

#[cfg(test)]
mod test {
use chrono::Utc;

use super::*;

#[test]
Expand Down
1 change: 0 additions & 1 deletion crates/defguard_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ pub mod user_management;
pub mod utility_thread;
pub mod version;
pub mod wg_config;
pub mod wireguard_stats_purge;

#[macro_use]
extern crate tracing;
Expand Down
54 changes: 0 additions & 54 deletions crates/defguard_core/src/wireguard_stats_purge.rs

This file was deleted.

18 changes: 18 additions & 0 deletions crates/defguard_vpn_stats_purge/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "defguard_vpn_stats_purge"
version = "0.0.0"
edition.workspace = true
license-file.workspace = true
homepage.workspace = true
repository.workspace = true
rust-version.workspace = true

[dependencies]
defguard_common.workspace = true

chrono.workspace = true
humantime.workspace = true
sqlx.workspace = true
tokio.workspace = true
tracing.workspace = true

Loading
Loading