DNS Resolver Override

1. Overview

This component provides a low-level helper function used to generate a deterministic resolv.conf file for sandboxed or isolated execution environments. It is designed to bypass system-level DNS interception (e.g. dnsmasq, NetworkManager, or local resolvers) by explicitly defining trusted public DNS servers.

The resulting file is typically bind-mounted into a restricted namespace (e.g. via bwrap) to enforce predictable DNS resolution behavior.


2. Function Signature

static std::string write_resolv_conf();

3. Responsibilities

  • Create a temporary resolv.conf file under /tmp.
  • Write a fixed set of trusted public DNS resolvers.
  • Ensure correct permissions and atomic overwrite semantics.
  • Return the path to the generated file on success.
  • Fail safely and return an empty string on error.

4. Output File

The function always writes to:

/tmp/bastionguard-resolv.conf

File permissions:

  • Mode: 0644
  • Owner: current user

5. DNS Configuration

The following resolvers are hardcoded to ensure reliability and neutrality:

  • 1.1.1.1 – Cloudflare DNS
  • 9.9.9.9 – Quad9 DNS
  • 8.8.8.8 – Google Public DNS

Additional resolver options:

options timeout:2 attempts:3 rotate

These options improve responsiveness and reduce the impact of slow or failing resolvers, which is particularly important for Chromium/CEF-based network stacks.


6. Implementation Details

  • Uses POSIX system calls (open, write, close) instead of C++ streams.
  • Ensures explicit file descriptor handling for sandbox compatibility.
  • Truncates existing file contents on each invocation.
  • No reliance on libc resolver helpers or external tools.

7. Error Handling

  • If open() fails, the function logs the error via perror.
  • If write() fails, the file descriptor is closed immediately.
  • On any failure, an empty std::string is returned.

The caller is expected to treat an empty return value as a hard failure and skip any DNS override logic.


8. Security Considerations

  • The file is written to /tmp, which is assumed to be private per-user in sandboxed contexts.
  • No user-controlled input is written to the file.
  • DNS servers are fixed and non-configurable to avoid injection or policy bypass.
  • The function does not modify the host system configuration.

9. Typical Usage

const std::string resolv_path = write_resolv_conf();
if (!resolv_path.empty()) {
    // bind-mount resolv_path to /etc/resolv.conf
}

This pattern is commonly used before re-executing the process inside a sandbox (e.g. Bubblewrap) with a controlled filesystem namespace.


10. Summary

This helper provides a minimal, deterministic, and sandbox-friendly mechanism to override DNS resolution behavior without requiring elevated privileges or persistent system changes.

It is a foundational building block for secure browsing and network isolation within BastionGuard.