1. Overview
Daemon orchestration implementation. Starts all subsystems, selects monitoring fallbacks, handles UI notifications, evaluates real-time and polled connections, persists permanent decisions, reloads configuration and performs orderly shutdown.
The original source path is:
src/service/DaemonService.cpp
2. Role in the Daemon
This file participates in the privileged BastionGuard Secure Connection daemon. It uses the shared bsc models and follows the daemon-wide fallback strategy: optional high-fidelity backends are used when available, while portable polling or stub behavior preserves service startup.
3. Namespaces
bsc::servicefs
4. Dependencies and Included Interfaces
bsc/service/DaemonService.hppbsc/logging/Logger.hppcctypechronofilesystemfstreamnlohmann/json.hppsstreamthread
5. API and Functions
The file declares or implements the following callable entry points:
lower_copy(std::string s)looks_like_browser_thread_comm(const std::string& comm)has_process_identity(const bsc::model::Connection& c)merge_process_info(bsc::model::Connection& conn, const bsc::model::ProcessInfo& p)same_process_signature(const bsc::model::ProcessInfo& a, const bsc::model::ProcessInfo& b)DaemonService::parse_interval(const std::string& v, std::chrono::milliseconds def)DaemonService::DaemonService(bsc::config::Config config) : config_(std::move(config)), firewall_(config_.firewall), stats_(config_.stats.max_events), ui_(config_.server.address)DaemonService::run()DaemonService::stop()DaemonService::desktop_allows_activity()DaemonService::set_desktop_active(bool active)DaemonService::rules_changed()DaemonService::reload_rules()DaemonService::reload_firewall()DaemonService::handle_notification(const bsc::ui::NotificationEvent& ev)parse_interval(config_.fw_options.monitor_interval, std::chrono::seconds(15)), [this]()DaemonService::handle_proc_event(const bsc::netlink::ProcEvent& ev)DaemonService::persist_learned_rule(const bsc::model::Connection& conn, const bsc::rule::Rule& decision)DaemonService::remember_connection(const bsc::model::Connection& conn)DaemonService::enrich_from_recent_flows(bsc::model::Connection& conn)DaemonService::enrich_from_recent_processes(bsc::model::Connection& conn, std::chrono::milliseconds max_age)DaemonService::verdict_key(const bsc::model::Connection& c)DaemonService::verdict_lookup(const bsc::model::Connection& c)DaemonService::verdict_store(const bsc::model::Connection& c, const bsc::rule::Rule& r)DaemonService::decide_connection(bsc::model::Connection conn, bool realtime, bool allow_blocking_ask)DaemonService::scan_connections()DaemonService::heartbeat()
6. Constants and Compile-Time Controls
auto kRecentFlowTtl = std::chrono::seconds(10)auto s = lower_copy(comm)auto aliases = std::filesystem::path(config_.rules.path).parent_path() / "network_aliases.json"fs::path tasks_file = fs::path(config_.tasks.config_path) / "tasks.json"auto name = task.value("name", std::string{})auto interval = parse_interval(task.value("interval", std::string{"5s"}), std::chrono::seconds(5))auto proc_method = [&]() { auto method = config_.proc_monitor_methodauto ebpf_obj = config_.ebpf_obj_path.empty() ? std::string{"/usr/lib/bastionguard-sc/bsc_ebpf.o"} : config_.ebpf_obj_pathbool nft_ok = firewall_.install_nfqueue_rule( config_.fw_options.queue_num, config_.fw_options.queue_bypass)bool previous = desktop_active_.exchange(active)bool changed = latest != rules_mtime_auto name = j.value("Name", std::string{})auto interval = parse_interval(j.value("Interval", std::string{"5s"}), std::chrono::seconds(5))auto target = config_.source_path.empty() ? std::string{"/etc/bastionguard-secure-connectiond/default-config.json"} : config_.source_pathauto pid = ev.tgid ? ev.tgid : ev.pidauto now = std::chrono::steady_clock::now()auto& cached = it->second.firstbool same_direct = conn.protocol == cached.protocol && conn.src_ip == cached.src_ip && conn.src_port == cached.src_port && conn.dst_ip == cached.dst_ip && conn.dst_port == cached.dst_portbool same_reverse = conn.protocol == cached.protocol && conn.src_ip == cached.dst_ip && conn.src_port == cached.dst_port && conn.dst_ip == cached.src_ip && conn.dst_port == cached.src_portauto& best = candidates.front()std::string host = !c.dst_host.empty() ? c.dst_host : c.dst_ipauto key = verdict_key(c)auto key = conn.key()
7. Operational Flow
- Load aliases and rules, start the UI client and apply the firewall configuration.
- Schedule connection scans, heartbeat, rule reload and firewall reload tasks.
- Start netlink and/or eBPF process monitoring, then attempt nftables plus NFQUEUE interception.
- For every connection, enrich process and DNS information, consult cached verdicts and loaded rules, optionally ask the UI, record statistics and persist permanent decisions.
- On shutdown, close NFQUEUE, remove the temporary nftables diversion, stop monitors/tasks and close the UI socket.
8. Decision Pipeline
The policy pipeline first validates desktop/UI availability, enriches process information, checks the permanent verdict cache, evaluates loaded rules, and may ask the UI for an unknown connection. The selected action is converted into an NFQUEUE verdict, recorded in statistics and optionally persisted as an automatically generated rule.
9. External Resources and Protocol Values
Relevant paths, endpoints, command names or policy values referenced by this file include:
bsc/service/DaemonService.hppbsc/logging/Logger.hppnetlinkprocebpf/usr/lib/bastionguard-sc/bsc_ebpf.oeBPF non disponibile — fallback NFQUEUE+/procrichiesto: uso netlink/proc come fallback runtime nel port C++proc event monitor non disponibile, resto in modalità on-demand /procNFQUEUE non disponibile: uso polling /proc come fallbackNFQUEUE non disponibile: fallback su /proc snapshotDesktop inattivo/bloccato: sospendo scansione e popup connessioni/etc/bastionguard-secure-connectiond/default-config.json
10. Security Considerations
- Runs with capabilities sufficient for nftables, NFQUEUE, netlink/eBPF and cross-user /proc inspection.
- When the desktop UI is unavailable, policy fallback behavior must fail in the configured direction rather than block indefinitely.
- Permanent decisions create rule files and therefore require safe administrative directory ownership and permissions.
11. Implementation Considerations
- Shared state is protected by mutexes; callers should avoid holding external locks while invoking callbacks.
- Linux /proc data can disappear between reads because processes and sockets are inherently short-lived.
- JSON input is an administrative trust boundary; type errors and malformed documents must remain contained.
12. Source Metrics
| Metric | Value |
|---|---|
| File size | 32056 bytes |
| Lines | 674 |
| Detected API entries | 27 |
| Detected types | 0 |
