BastionGuard/thirdparty/bastionguard-secure-connection/daemon/include/bsc/service/DaemonService.hpp
specialworld83 f0f913a209 Release 2.0
2026-07-15 10:52:22 +02:00

99 lines
4.4 KiB
C++

#pragma once
#include "bsc/config/Config.hpp"
#include "bsc/fw/Firewall.hpp"
#include "bsc/net/DnsResolver.hpp"
#include "bsc/netlink/ProcEventMonitor.hpp"
#include "bsc/net/SocketSnapshot.hpp"
#include "bsc/netfilter/NFQueue.hpp"
#include "bsc/proc/ProcMon.hpp"
#include "bsc/rule/Rule.hpp"
#include "bsc/stats/Statistics.hpp"
#include "bsc/task/TaskRunner.hpp"
#include "bsc/ui/UIClient.hpp"
#include <atomic>
#include <chrono>
#include <filesystem>
#include <mutex>
#include <optional>
#include <set>
#include <unordered_map>
namespace bsc::service {
class DaemonService {
public:
explicit DaemonService(bsc::config::Config config);
void run();
void stop();
private:
void scan_connections();
bool desktop_allows_activity() const;
void set_desktop_active(bool active);
void handle_proc_event(const bsc::netlink::ProcEvent& ev);
void heartbeat();
void reload_rules();
void reload_firewall();
void handle_notification(const bsc::ui::NotificationEvent& ev);
bsc::netfilter::Decision decide_connection(bsc::model::Connection conn,
bool realtime,
bool allow_blocking_ask = true);
void persist_learned_rule(const bsc::model::Connection& conn, const bsc::rule::Rule& decision);
void remember_connection(const bsc::model::Connection& conn);
void enrich_from_recent_flows(bsc::model::Connection& conn);
void enrich_from_recent_processes(bsc::model::Connection& conn,
std::chrono::milliseconds max_age = std::chrono::milliseconds(5000));
bool rules_changed() const;
static std::chrono::milliseconds parse_interval(const std::string& v, std::chrono::milliseconds def = std::chrono::seconds(5));
bsc::config::Config config_;
bsc::fw::Firewall firewall_;
bsc::net::DnsResolver dns_;
bsc::netlink::ProcEventMonitor proc_events_;
bsc::net::SocketSnapshot net_;
bsc::netfilter::NFQueue nfqueue_;
bsc::proc::ProcMon proc_;
bsc::rule::Loader rules_;
bsc::stats::Statistics stats_;
bsc::ui::UIClient ui_;
bsc::task::TaskRunner tasks_;
std::atomic_bool running_{true};
std::mutex seen_mutex_;
std::set<std::string> seen_;
mutable std::mutex rules_reload_mutex_;
mutable std::mutex flow_mutex_;
std::unordered_map<std::string, std::pair<bsc::model::Connection, std::chrono::steady_clock::time_point>> recent_flows_;
// ── Cache verdetti utente ─────────────────────────────────────────
// Chiave: "app_path|dst_host|dst_port" (dst_host se presente, altrimenti
// dst_ip). Valore: action ("allow"/"deny") + duration + scadenza.
// Evita di fare un popup per ogni connessione della stessa app verso lo
// stesso host — necessario o la UI viene sommersa.
struct CachedVerdict {
std::string action;
std::string duration; // "once" | "always" | "until.restart" | "30s" | "5m" ...
std::chrono::steady_clock::time_point expires_at;
};
mutable std::mutex verdict_cache_mutex_;
std::unordered_map<std::string, CachedVerdict> verdict_cache_;
static std::string verdict_key(const bsc::model::Connection& c);
std::optional<CachedVerdict> verdict_lookup(const bsc::model::Connection& c) const;
void verdict_store(const bsc::model::Connection& c, const bsc::rule::Rule& r);
// ── Flag isAsking ─────────────────────────────────────────────────
// Vero mentre un ask_rule e' in volo verso la UI. Le altre connessioni
// che arrivano nel frattempo NON aprono altri popup: ricevono il
// default_action cosi' il traffico non resta bloccato. Il popup per loro
// arrivera' al giro successivo, una alla volta.
std::atomic_bool is_asking_{false};
// Stato attività desktop comunicato dalla UI.
// False = desktop non pronto/bloccato/idle oppure UI non connessa:
// il daemon non scansiona, non apre popup e accetta velocemente i pacchetti.
std::atomic_bool desktop_active_{false};
std::atomic_bool inactive_notice_logged_{false};
std::filesystem::file_time_type rules_mtime_{};
std::chrono::steady_clock::time_point start_time_{std::chrono::steady_clock::now()};
};
} // namespace bsc::service