dnsmasq_backend.hpp

1. Overview

The DnsmasqBackend.hpp header defines the BastionGuard::DnsmasqBackend class, which provides an abstraction layer for managing domain-based filtering rules in dnsmasq. This component enables BastionGuard to enforce blacklist and whitelist policies at the DNS level by generating and maintaining dnsmasq-compatible configuration files and reloading the service when changes occur.

Functionally, DnsmasqBackend provides:

  • Programmatic management of dnsmasq blacklist and whitelist entries
  • Atomic replacement of configuration files
  • Safe addition and removal of individual domains
  • Automatic reload of the dnsmasq service
  • Filesystem path and permission abstraction

2. Dependencies and Includes

#include <string>
#include <vector>
  • <string> – storage of file paths, domain names, and generated configuration
  • <vector> – container for domain lists

3. Namespace Declaration and Scope

namespace BastionGuard { ... }

The DnsmasqBackend class is scoped under the BastionGuard namespace, indicating its role as part of the system-level enforcement layer.


4. Class Declaration and Construction

class DnsmasqBackend

Instances of DnsmasqBackend are configured at construction time with explicit paths for blacklist and whitelist files and with the target dnsmasq user.


4.1 Constructor

DnsmasqBackend(const std::string& blacklist_path = "/etc/dnsmasq.d/BastionGuard-blacklist.conf",
               const std::string& whitelist_path = "/etc/dnsmasq.d/BastionGuard-whitelist.conf",
               const std::string& dnsmasq_user = "dnsmasq");

Initializes the backend with default system paths and user identity. Custom paths may be supplied for non-standard deployments or testing environments.


5. Public Interface

5.1 Incremental Domain Management

bool add_to_blacklist(const std::string& domain);
bool remove_from_blacklist(const std::string& domain);
bool add_to_whitelist(const std::string& domain);
bool remove_from_whitelist(const std::string& domain);

Adds or removes individual domain entries from the corresponding dnsmasq configuration file. Domains must be normalized and sanitized prior to invocation.


5.2 Atomic List Replacement

bool write_blacklist(const std::vector<std::string>& domains);
bool write_whitelist(const std::vector<std::string>& domains);

Replaces the entire blacklist or whitelist with the provided domain set using an atomic write strategy to avoid partial or corrupted configuration files.


5.3 Service Reload

bool reload_dnsmasq();

Reloads the dnsmasq service to apply updated configuration. The method first attempts to send a SIGHUP signal to the running daemon and falls back to systemctl reload if required.


6. Internal Utilities

6.1 Atomic File Writer

bool atomic_write(const std::string& path,
                   const std::string& content);

Writes configuration content to a temporary file and replaces the target file using an atomic rename operation to guarantee consistency.


6.2 dnsmasq Entry Generator

std::string make_dnsmasq_entries(const std::vector<std::string>& domains);

Converts a list of normalized domain names into dnsmasq-compatible configuration entries (e.g., address=/example.com/0.0.0.0 or equivalent directives).


7. Configuration File Model

The generated configuration files typically contain:

  • One rule per domain
  • Consistent formatting for readability and auditability
  • Optional metadata comments identifying BastionGuard ownership

8. Operational Workflow

A typical management cycle consists of:

  • Sanitizing and validating domain input
  • Updating in-memory domain lists (if applicable)
  • Generating dnsmasq configuration entries
  • Writing files atomically to disk
  • Reloading the dnsmasq service

9. Security and Deployment Considerations

  • Privilege requirements: writing to /etc/dnsmasq.d and reloading dnsmasq typically requires root privileges or appropriate sudo policies
  • Domain sanitization: input domains must be strictly validated to prevent configuration injection or malformed rules
  • Atomicity guarantees: atomic file replacement prevents dnsmasq from loading incomplete configurations during updates
  • Rollback strategy: consider backing up previous configurations to enable rapid recovery from misconfiguration
  • Compatibility: ensure generated directives match the dnsmasq version deployed on target systems
  • Audit logging: configuration changes should be logged for traceability and compliance