nvpn 4.1.9

CLI and daemon for Nostr VPN private mesh networks
Documentation
use std::sync::Arc;

use anyhow::{Context as _, Result};
use nostr_vpn_core::config::ExitDnsResolverConfig;
use nostr_vpn_core::secure_dns::{
    SecureDnsError, SecureDnsLookup, SecureDnsResolver, WireGuardDnsResolver,
};

use super::{FIPS_DNS_TTL_SECS, ResolverState, SharedResolver};

pub(super) fn dns_resolver(config: &ExitDnsResolverConfig) -> Result<SharedResolver> {
    match config {
        ExitDnsResolverConfig::Doh { .. } => Ok(Arc::new(
            SecureDnsResolver::from_resolver_config(config)
                .context("failed to initialize encrypted DNS")?,
        )),
        ExitDnsResolverConfig::ThroughExit { servers } => Ok(Arc::new(
            WireGuardDnsResolver::new(servers)
                .context("failed to initialize DNS through the selected exit")?,
        )),
        ExitDnsResolverConfig::FailClosed => Ok(Arc::new(FailClosedDnsResolver)),
    }
}

struct FailClosedDnsResolver;

#[async_trait::async_trait]
impl SecureDnsLookup for FailClosedDnsResolver {
    async fn resolve(&self, _query: &[u8]) -> Result<Vec<u8>, SecureDnsError> {
        Err(SecureDnsError::ExitNotReady)
    }
}

pub(super) fn current_resolver(resolver: &ResolverState) -> Option<SharedResolver> {
    resolver.read().ok().map(|resolver| Arc::clone(&*resolver))
}

pub(super) fn resolve_fips_dns_if_handled(
    query: &[u8],
) -> Option<(Vec<u8>, Option<fips_core::upper::dns::DnsResolvedIdentity>)> {
    let request = hickory_proto::op::Message::from_vec(query).ok()?;
    let name = request.queries.first()?.name.to_utf8();
    let name = name.trim_end_matches('.');
    if !name.to_ascii_lowercase().ends_with(".fips") {
        return None;
    }
    fips_core::upper::dns::handle_dns_packet(
        query,
        FIPS_DNS_TTL_SECS,
        &fips_core::upper::hosts::HostMap::new(),
    )
}