Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nym-vpn-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- Change default entry and exit points to random (https://github.com/nymtech/nym-vpn-client/pull/5378)
- Enable secure DNS for requests forwarded by local resolver (https://github.com/nymtech/nym-vpn-client/pull/5458)

### Fixed

Expand Down
37 changes: 36 additions & 1 deletion nym-vpn-core/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions nym-vpn-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,6 @@ make -C nym-vpn-core -f Android.mk
- `netsh`: use the `netsh` program
- `tcpip`: set TCP/IP parameters in the registry

- `NYM_DISABLE_LOCAL_DNS_RESOLVER` - Set this variable to `1` to disable the local DNS resolver
(macOS only).

- `NYM_DISABLE_OFFLINE_MONITOR` - Set to `1` to forces the daemon to always assume the host is online.

- `NYM_USE_PATH_MONITOR` - Set to `1` to use Apple Network framework for offline monitoring. (macOS only)
Expand Down
8 changes: 2 additions & 6 deletions nym-vpn-core/crates/nym-dns/src/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright 2024 Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only

use crate::ResolvedDnsConfig;
use crate::DnsConfig;

/// Stub error type for DNS errors on Android.
#[derive(Debug, thiserror::Error)]
Expand All @@ -18,11 +18,7 @@ impl super::DnsMonitorT for DnsMonitor {
Ok(DnsMonitor)
}

async fn set(
&mut self,
_interface: &str,
_servers: ResolvedDnsConfig,
) -> Result<(), Self::Error> {
async fn set(&mut self, _interface: &str, _servers: DnsConfig) -> Result<(), Self::Error> {
Ok(())
}

Expand Down
146 changes: 8 additions & 138 deletions nym-vpn-core/crates/nym-dns/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright 2024 Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only

use std::{fmt, net::IpAddr};
use std::net::IpAddr;

#[cfg(target_os = "linux")]
use nym_routing::RouteManagerHandle;
Expand Down Expand Up @@ -31,142 +31,13 @@ pub use self::imp::Error;
pub use imp::flush_resolver_cache;

/// DNS configuration
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DnsConfig {
config: InnerDnsConfig,
}

impl Default for DnsConfig {
fn default() -> Self {
Self {
config: InnerDnsConfig::Default,
}
}
}

impl DnsConfig {
/// Use the specified addresses for DNS resolution
pub fn from_addresses(tunnel_config: &[IpAddr], non_tunnel_config: &[IpAddr]) -> Self {
DnsConfig {
config: InnerDnsConfig::Override {
tunnel_config: tunnel_config.to_owned(),
non_tunnel_config: non_tunnel_config.to_owned(),
},
}
}
}
/// DNS server addresses
pub addresses: Vec<IpAddr>,

impl DnsConfig {
pub fn resolve(
&self,
default_tun_config: &[IpAddr],
#[cfg(not(any(target_os = "android", target_os = "ios")))] port: u16,
) -> ResolvedDnsConfig {
match &self.config {
InnerDnsConfig::Default => ResolvedDnsConfig {
tunnel_config: default_tun_config.to_owned(),
non_tunnel_config: vec![],
#[cfg(not(any(target_os = "android", target_os = "ios")))]
port,
},
InnerDnsConfig::Override {
tunnel_config,
non_tunnel_config,
} => ResolvedDnsConfig {
tunnel_config: tunnel_config.to_owned(),
non_tunnel_config: non_tunnel_config.to_owned(),
#[cfg(not(any(target_os = "android", target_os = "ios")))]
port,
},
}
}
}

#[derive(Debug, Clone, PartialEq)]
enum InnerDnsConfig {
/// Use gateway addresses from the tunnel config
Default,
/// Use the specified addresses for DNS resolution
Override {
/// Addresses to configure on the tunnel interface
tunnel_config: Vec<IpAddr>,
/// Addresses to allow on non-tunnel interface.
/// For the most part, the tunnel state machine will not handle any of this configuration
/// on non-tunnel interface, only allow them in the firewall.
non_tunnel_config: Vec<IpAddr>,
},
}

/// DNS configuration with `DnsConfig::Default` resolved
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ResolvedDnsConfig {
/// Addresses to configure on the tunnel interface
tunnel_config: Vec<IpAddr>,
/// Addresses to allow on non-tunnel interface.
/// For the most part, the tunnel state machine will not handle any of this configuration
/// on non-tunnel interface, only allow them in the firewall.
non_tunnel_config: Vec<IpAddr>,
/// Port to use
#[cfg(not(any(target_os = "android", target_os = "ios")))]
port: u16,
}

impl fmt::Display for ResolvedDnsConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Tunnel DNS: ")?;
Self::fmt_addr_set(f, &self.tunnel_config)?;

f.write_str(" Non-tunnel DNS: ")?;
Self::fmt_addr_set(f, &self.non_tunnel_config)?;

#[cfg(not(any(target_os = "android", target_os = "ios")))]
write!(f, " Port: {}", self.port)?;

Ok(())
}
}

impl ResolvedDnsConfig {
fn fmt_addr_set(f: &mut fmt::Formatter<'_>, addrs: &[IpAddr]) -> fmt::Result {
f.write_str("{")?;
for (i, addr) in addrs.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}
write!(f, "{addr}")?;
}
f.write_str("}")
}

/// Addresses to configure on the tunnel interface
pub fn tunnel_config(&self) -> &[IpAddr] {
&self.tunnel_config
}

/// Addresses to allow on non-tunnel interface.
/// For the most part, the tunnel state machine will not handle any of this configuration
/// on non-tunnel interface, only allow them in the firewall.
pub fn non_tunnel_config(&self) -> &[IpAddr] {
&self.non_tunnel_config
}

/// Consume `self` and return a vector of all addresses
pub fn addresses(self) -> impl Iterator<Item = IpAddr> {
self.non_tunnel_config.into_iter().chain(self.tunnel_config)
}

/// Return whether the config contains only (and at least one) loopback addresses, and zero
/// non-loopback addresses
pub fn is_loopback(&self) -> bool {
let (loopback_addrs, non_loopback_addrs) = self
.tunnel_config
.iter()
.chain(self.non_tunnel_config.iter())
.copied()
.partition::<Vec<_>, _>(|ip| ip.is_loopback());

!loopback_addrs.is_empty() && non_loopback_addrs.is_empty()
}
pub port: u16,
}

/// Sets and monitors system DNS settings. Makes sure the desired DNS servers are being used.
Expand All @@ -188,8 +59,8 @@ impl DnsMonitor {
}

/// Set DNS to the given servers. And start monitoring the system for changes.
pub async fn set(&mut self, interface: &str, config: ResolvedDnsConfig) -> Result<(), Error> {
tracing::info!("Setting DNS servers on interface '{interface}': {config}");
pub async fn set(&mut self, interface: &str, config: DnsConfig) -> Result<(), Error> {
tracing::info!("Setting DNS servers on interface '{interface}': {config:?}");
self.inner.set(interface, config).await
}

Expand All @@ -216,8 +87,7 @@ trait DnsMonitorT: Sized {
#[cfg(target_os = "linux")] route_manager: RouteManagerHandle,
) -> Result<Self, Self::Error>;

async fn set(&mut self, interface: &str, servers: ResolvedDnsConfig)
-> Result<(), Self::Error>;
async fn set(&mut self, interface: &str, servers: DnsConfig) -> Result<(), Self::Error>;

async fn reset(&mut self) -> Result<(), Self::Error>;

Expand Down
6 changes: 3 additions & 3 deletions nym-vpn-core/crates/nym-dns/src/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use tokio::sync::Mutex;

use nym_routing::debounce::BurstGuard;

use super::ResolvedDnsConfig;
use super::DnsConfig;

pub type Result<T> = std::result::Result<T, Error>;

Expand Down Expand Up @@ -402,9 +402,9 @@ impl super::DnsMonitorT for DnsMonitor {
})
}

async fn set(&mut self, interface: &str, config: ResolvedDnsConfig) -> Result<()> {
async fn set(&mut self, interface: &str, config: DnsConfig) -> Result<()> {
let port = config.port;
let servers: Vec<_> = config.addresses().collect();
let servers: Vec<_> = config.addresses;

let mut state = self.state.lock().await;
state.apply_new_config(&self.store, interface, &servers, port)
Expand Down
1 change: 0 additions & 1 deletion nym-vpn-core/crates/nym-firewall/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ libc.workspace = true
thiserror.workspace = true
tracing.workspace = true

nym-dns.workspace = true
nym-common.workspace = true
nym-firewall-config.workspace = true

Expand Down
Loading
Loading