feat: implement background account enforcement service and RADIUS management service for guest access control
Build and Push Docker Image to Gitea Container Registry / build-and-push (push) Successful in 1m3s

This commit is contained in:
Tygozwolle
2026-07-24 18:47:45 +02:00
parent 63082d0791
commit 926d2a1fc5
2 changed files with 14 additions and 14 deletions
@@ -107,24 +107,24 @@ public class AccountEnforcementService : BackgroundService
// Find active sessions to disconnect them instantly via RADIUS CoA (PoD) // Find active sessions to disconnect them instantly via RADIUS CoA (PoD)
var activeSessions = await db.RadAcct var activeSessions = await db.RadAcct
.Where(ra => ra.Username == profile.Username && ra.AcctStopTime == null) .Where(ra => ra.Username == profile.Username && ra.AcctStopTime == null)
.Select(ra => ra.NasIpAddress) .Select(ra => new { ra.NasIpAddress, ra.CallingStationId, ra.AcctSessionId })
.Distinct()
.ToListAsync(ct); .ToListAsync(ct);
var radiusSecret = Environment.GetEnvironmentVariable("RADIUS_SECRET") ?? "radpass"; var radiusSecret = Environment.GetEnvironmentVariable("RADIUS_SECRET") ?? "radpass";
foreach (var nasIp in activeSessions) foreach (var session in activeSessions)
{ {
if (string.IsNullOrWhiteSpace(nasIp)) continue; if (string.IsNullOrWhiteSpace(session.NasIpAddress)) continue;
try try
{ {
var payload = $"User-Name=\\\"{profile.Username}\\\"\\nCalling-Station-Id=\\\"{session.CallingStationId}\\\"\\nAcct-Session-Id=\\\"{session.AcctSessionId}\\\"\\n";
var process = new System.Diagnostics.Process var process = new System.Diagnostics.Process
{ {
StartInfo = new System.Diagnostics.ProcessStartInfo StartInfo = new System.Diagnostics.ProcessStartInfo
{ {
FileName = "sh", FileName = "sh",
Arguments = $"-c \"echo 'User-Name={profile.Username}' | radclient -x {nasIp}:3799 disconnect '{radiusSecret}'\"", Arguments = $"-c \"printf '{payload}' | radclient -x {session.NasIpAddress}:3799 disconnect '{radiusSecret}'\"",
RedirectStandardOutput = true, RedirectStandardOutput = true,
RedirectStandardError = true, RedirectStandardError = true,
UseShellExecute = false, UseShellExecute = false,
@@ -133,11 +133,11 @@ public class AccountEnforcementService : BackgroundService
}; };
process.Start(); process.Start();
await process.WaitForExitAsync(ct); await process.WaitForExitAsync(ct);
_logger.LogInformation("Sent RADIUS Disconnect-Request to NAS {NasIp} for user {Username}", nasIp, profile.Username); _logger.LogInformation("Sent RADIUS Disconnect-Request to NAS {NasIp} for user {Username} (MAC: {Mac})", session.NasIpAddress, profile.Username, session.CallingStationId);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Failed to send RADIUS Disconnect-Request to NAS {NasIp}", nasIp); _logger.LogError(ex, "Failed to send RADIUS Disconnect-Request to NAS {NasIp}", session.NasIpAddress);
} }
} }
+7 -7
View File
@@ -379,24 +379,24 @@ public class RadiusService : IRadiusService
{ {
var activeSessions = await _db.RadAcct var activeSessions = await _db.RadAcct
.Where(ra => ra.Username == username && ra.AcctStopTime == null) .Where(ra => ra.Username == username && ra.AcctStopTime == null)
.Select(ra => ra.NasIpAddress) .Select(ra => new { ra.NasIpAddress, ra.CallingStationId, ra.AcctSessionId })
.Distinct()
.ToListAsync(); .ToListAsync();
var radiusSecret = Environment.GetEnvironmentVariable("RADIUS_SECRET") ?? "radpass"; var radiusSecret = Environment.GetEnvironmentVariable("RADIUS_SECRET") ?? "radpass";
foreach (var nasIp in activeSessions) foreach (var session in activeSessions)
{ {
if (string.IsNullOrWhiteSpace(nasIp)) continue; if (string.IsNullOrWhiteSpace(session.NasIpAddress)) continue;
try try
{ {
var payload = $"User-Name=\\\"{username}\\\"\\nCalling-Station-Id=\\\"{session.CallingStationId}\\\"\\nAcct-Session-Id=\\\"{session.AcctSessionId}\\\"\\n";
var process = new System.Diagnostics.Process var process = new System.Diagnostics.Process
{ {
StartInfo = new System.Diagnostics.ProcessStartInfo StartInfo = new System.Diagnostics.ProcessStartInfo
{ {
FileName = "sh", FileName = "sh",
Arguments = $"-c \"echo 'User-Name={username}' | radclient -x {nasIp}:3799 disconnect '{radiusSecret}'\"", Arguments = $"-c \"printf '{payload}' | radclient -x {session.NasIpAddress}:3799 disconnect '{radiusSecret}'\"",
RedirectStandardOutput = true, RedirectStandardOutput = true,
RedirectStandardError = true, RedirectStandardError = true,
UseShellExecute = false, UseShellExecute = false,
@@ -405,11 +405,11 @@ public class RadiusService : IRadiusService
}; };
process.Start(); process.Start();
await process.WaitForExitAsync(); await process.WaitForExitAsync();
_logger.LogInformation("Sent manual RADIUS Disconnect-Request to NAS {NasIp} for user {Username}", nasIp, username); _logger.LogInformation("Sent manual RADIUS Disconnect-Request to NAS {NasIp} for user {Username} (MAC: {Mac})", session.NasIpAddress, username, session.CallingStationId);
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Failed to send manual RADIUS Disconnect-Request to NAS {NasIp}", nasIp); _logger.LogError(ex, "Failed to send manual RADIUS Disconnect-Request to NAS {NasIp}", session.NasIpAddress);
} }
} }
} }