summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2020-08-06 11:47:32 +0100
committerEmīls <emils@mullvad.net>2020-08-06 11:47:32 +0100
commit502d93565fe8dad97117b0e01e3ddf9e4d67474e (patch)
tree7fda6d67a4bbbeb2b1222e9f23242695d3ac1007
parent61d14531b61cc78d951add7b3cdfd3623e45410b (diff)
parent9b64aadc2e610fafb19b2118af9f03e9a4d3fdb7 (diff)
downloadmullvadvpn-502d93565fe8dad97117b0e01e3ddf9e4d67474e.tar.xz
mullvadvpn-502d93565fe8dad97117b0e01e3ddf9e4d67474e.zip
Merge branch 'fix-systemd-resolved-parsing'
-rw-r--r--CHANGELOG.md3
-rw-r--r--talpid-core/src/dns/linux/systemd_resolved.rs53
2 files changed, 18 insertions, 38 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 51da6a86d5..323592a39b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -72,6 +72,9 @@ Line wrap the file at 100 chars. Th
connecting.
- Fix notification sometimes not being dismissible.
+#### Linux
+- Fix `systemd-resolved` DNS management by not parsing `/etc/resolv.conf`.
+
## [2020.5] - 2020-06-25
### Added
diff --git a/talpid-core/src/dns/linux/systemd_resolved.rs b/talpid-core/src/dns/linux/systemd_resolved.rs
index f4466ac231..ee0ad7e793 100644
--- a/talpid-core/src/dns/linux/systemd_resolved.rs
+++ b/talpid-core/src/dns/linux/systemd_resolved.rs
@@ -6,11 +6,7 @@ use dbus::{
};
use lazy_static::lazy_static;
use libc::{AF_INET, AF_INET6};
-use std::{
- fs, io,
- net::{IpAddr, Ipv4Addr},
- path::Path,
-};
+use std::{fs, io, net::IpAddr, path::Path};
use talpid_types::ErrorExt as _;
pub type Result<T> = std::result::Result<T, Error>;
@@ -24,9 +20,6 @@ pub enum Error {
#[error(display = "/etc/resolv.conf is not a symlink to Systemd resolved")]
NotSymlinkedToResolvConf,
- #[error(display = "Systemd resolved DNS 127.0.0.53, is not currently configured")]
- NoDnsPointsToResolved,
-
#[error(display = "Systemd resolved not detected")]
NoSystemdResolved(#[error(source)] dbus::Error),
@@ -56,13 +49,12 @@ pub enum Error {
}
lazy_static! {
- static ref RESOLVED_PATHS: Vec<&'static Path> = vec![
+ static ref RESOLVED_STUB_PATHS: Vec<&'static Path> = vec![
Path::new("/run/systemd/resolve/stub-resolv.conf"),
- Path::new("/run/systemd/resolve/resolv.conf"),
+ Path::new("/var/run/systemd/resolve/stub-resolv.conf"),
];
}
-const RESOLVED_DNS_SERVER_ADDRESS: [u8; 4] = [127, 0, 0, 53];
const RESOLVED_BUS: &str = "org.freedesktop.resolve1";
const RPC_TIMEOUT_MS: i32 = 1000;
@@ -94,7 +86,6 @@ impl SystemdResolved {
systemd_resolved.ensure_resolved_exists()?;
Self::ensure_resolv_conf_is_resolved_symlink()?;
- Self::ensure_resolv_conf_has_resolved_dns()?;
Ok(systemd_resolved)
}
@@ -109,21 +100,26 @@ impl SystemdResolved {
}
fn ensure_resolv_conf_is_resolved_symlink() -> Result<()> {
- let is_correct_symlink = fs::read_link(RESOLV_CONF_PATH)
- .map(|resolv_conf_target| Self::compare_resolvconf_symlink(&resolv_conf_target))
- .unwrap_or_else(|_| false);
- if is_correct_symlink {
+ let link_target =
+ fs::read_link(RESOLV_CONF_PATH).map_err(|_| Error::NotSymlinkedToResolvConf)?;
+
+ // if /etc/resolv.conf is not symlinked to the stub resolve.conf file , managing DNS
+ // through systemd-resolved will not ensure that our resolver is given priority - sometimes
+ // this will mean adding 1 and 2 seconds of latency to DNS queries, other times our
+ // resolver won't be considered at all. In this case, it's better to fall back to cruder
+ // management methods.
+ if Self::path_is_resolvconf_stub(&link_target) {
Ok(())
} else {
Err(Error::NotSymlinkedToResolvConf)
}
}
- fn compare_resolvconf_symlink(link_path: &Path) -> bool {
+ fn path_is_resolvconf_stub(link_path: &Path) -> bool {
// if link path is relative to /etc/resolv.conf, resolve the path and compare it.
if link_path.is_relative() {
match Path::new("/etc/").join(link_path).canonicalize() {
- Ok(link_destination) => RESOLVED_PATHS.contains(&link_destination.as_ref()),
+ Ok(link_destination) => RESOLVED_STUB_PATHS.contains(&link_destination.as_ref()),
Err(e) => {
log::error!(
"Failed to canonicalize resolv conf path {} - {}",
@@ -134,26 +130,7 @@ impl SystemdResolved {
}
}
} else {
- RESOLVED_PATHS.contains(&link_path)
- }
- }
-
- fn ensure_resolv_conf_has_resolved_dns() -> Result<()> {
- let resolv_conf_contents =
- fs::read_to_string(RESOLV_CONF_PATH).map_err(Error::ReadResolvConfFailed)?;
- let parsed_resolv_conf = resolv_conf::Config::parse(resolv_conf_contents)
- .map_err(Error::ParseResolvConfFailed)?;
- let resolved_dns_server =
- resolv_conf::ScopedIp::V4(Ipv4Addr::from(RESOLVED_DNS_SERVER_ADDRESS));
-
- if parsed_resolv_conf
- .nameservers
- .into_iter()
- .any(|nameserver| nameserver == resolved_dns_server)
- {
- Ok(())
- } else {
- Err(Error::NoDnsPointsToResolved)
+ RESOLVED_STUB_PATHS.contains(&link_path)
}
}