DaemonService.cpp

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::service
  • fs

4. Dependencies and Included Interfaces

  • bsc/service/DaemonService.hpp
  • bsc/logging/Logger.hpp
  • cctype
  • chrono
  • filesystem
  • fstream
  • nlohmann/json.hpp
  • sstream
  • thread

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_method
  • auto ebpf_obj = config_.ebpf_obj_path.empty() ? std::string{"/usr/lib/bastionguard-sc/bsc_ebpf.o"} : config_.ebpf_obj_path
  • bool 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_path
  • auto pid = ev.tgid ? ev.tgid : ev.pid
  • auto now = std::chrono::steady_clock::now()
  • auto& cached = it->second.first
  • bool 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_port
  • bool 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_port
  • auto& best = candidates.front()
  • std::string host = !c.dst_host.empty() ? c.dst_host : c.dst_ip
  • auto key = verdict_key(c)
  • auto key = conn.key()

7. Operational Flow

  1. Load aliases and rules, start the UI client and apply the firewall configuration.
  2. Schedule connection scans, heartbeat, rule reload and firewall reload tasks.
  3. Start netlink and/or eBPF process monitoring, then attempt nftables plus NFQUEUE interception.
  4. For every connection, enrich process and DNS information, consult cached verdicts and loaded rules, optionally ask the UI, record statistics and persist permanent decisions.
  5. 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.hpp
  • bsc/logging/Logger.hpp
  • netlink
  • proc
  • ebpf
  • /usr/lib/bastionguard-sc/bsc_ebpf.o
  • eBPF non disponibile — fallback NFQUEUE+/proc
  • richiesto: uso netlink/proc come fallback runtime nel port C++
  • proc event monitor non disponibile, resto in modalità on-demand /proc
  • NFQUEUE non disponibile: uso polling /proc come fallback
  • NFQUEUE non disponibile: fallback su /proc snapshot
  • Desktop 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

MetricValue
File size32056 bytes
Lines674
Detected API entries27
Detected types0