mirror of
https://github.com/vhaudiquet/ecrou.git
synced 2026-11-12 22:22:44 +00:00
fix(rootfs): prefer the uplink resolver, drop loopback nameservers
Copying /etc/resolv.conf verbatim gives the guest systemd-resolved's stub at 127.0.0.53, and loopback never crosses the engine's socket proxy: the name lookup dies inside the guest. Source the uplink config from /run/systemd/resolve first and strip 127.x nameserver lines from whatever is copied.
This commit is contained in:
1 parent
7d9dc6650e
commit
7adbf41f59
1 file changed
+54
-5
@@ -303,20 +303,33 @@ fn extract_prepared(
|
||||
/// guest has whatever the image shipped, which is usually nothing.
|
||||
/// Best effort: a rootfs with its own resolver config keeps it.
|
||||
fn provision_resolver(rootfs: &Path) {
|
||||
let host = match std::fs::read_to_string("/etc/resolv.conf") {
|
||||
Ok(s) if !s.trim().is_empty() => s,
|
||||
// The engine proxies guest sockets to the host's stack, so any
|
||||
// host-reachable nameserver works in the machine - but loopback
|
||||
// addresses do not cross: 127.0.0.53 stays inside the guest, where
|
||||
// nothing listens. So the source of truth is systemd-resolved's
|
||||
// uplink config when present, and loopback nameservers are dropped
|
||||
// from whatever is copied. Best effort: failures leave the
|
||||
// image's file.
|
||||
let host = match std::fs::read_to_string("/run/systemd/resolve/resolv.conf")
|
||||
.or_else(|_| std::fs::read_to_string("/etc/resolv.conf"))
|
||||
{
|
||||
Ok(s) if !s.trim().is_empty() => drop_loopback_nameservers(&s),
|
||||
Ok(_) => {
|
||||
log::debug!("host /etc/resolv.conf is empty; leaving the image's in place");
|
||||
log::debug!("host resolver config is empty; leaving the image's in place");
|
||||
return;
|
||||
}
|
||||
Err(e) => {
|
||||
log::debug!(
|
||||
"no host /etc/resolv.conf ({}); leaving the image's in place",
|
||||
"no host resolver config ({}); leaving the image's in place",
|
||||
e
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if !host.contains("nameserver ") {
|
||||
log::debug!("host resolver config has no usable nameserver; leaving the image's");
|
||||
return;
|
||||
}
|
||||
let target = rootfs.join("etc/resolv.conf");
|
||||
if let Err(e) = std::fs::remove_file(&target) {
|
||||
if e.kind() != std::io::ErrorKind::NotFound {
|
||||
@@ -328,11 +341,30 @@ fn provision_resolver(rootfs: &Path) {
|
||||
let _ = std::fs::create_dir_all(parent);
|
||||
}
|
||||
match std::fs::write(&target, host) {
|
||||
Ok(()) => log::debug!("provisioned the host resolver into {}", target.display()),
|
||||
Ok(()) => log::debug!("provisioned a resolver into {}", target.display()),
|
||||
Err(e) => log::debug!("could not write {}: {}", target.display(), e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Lines naming a loopback nameserver go: the guest's loopback is its
|
||||
/// own, and the stub resolvers live on the host's.
|
||||
fn drop_loopback_nameservers(config: &str) -> String {
|
||||
config
|
||||
.lines()
|
||||
.filter(|line| {
|
||||
let rest = match line.trim_start().strip_prefix("nameserver ") {
|
||||
Some(r) => r.trim(),
|
||||
None => return true,
|
||||
};
|
||||
!rest.starts_with("127.")
|
||||
})
|
||||
.fold(String::new(), |mut acc, line| {
|
||||
acc.push_str(line);
|
||||
acc.push('\n');
|
||||
acc
|
||||
})
|
||||
}
|
||||
|
||||
/// Write a tarball of `rootfs` at `dest`, compressed according to dest's
|
||||
/// extension (.tar.gz, .tar.xz, .tar.zst, plain .tar), atomically via a
|
||||
/// `.partial` file.
|
||||
@@ -481,6 +513,23 @@ fn get_tarball_extension(url: &str) -> &str {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::drop_loopback_nameservers;
|
||||
|
||||
#[test]
|
||||
fn loopback_nameservers_dropped() {
|
||||
let config = "# comment\nnameserver 127.0.0.53\noptions edns0\nnameserver 192.168.1.1\nnameserver 127.0.0.1\n";
|
||||
assert_eq!(
|
||||
drop_loopback_nameservers(config),
|
||||
"# comment\noptions edns0\nnameserver 192.168.1.1\n"
|
||||
);
|
||||
// A search line whose address-ish token is untouched.
|
||||
let config = "search 127.example\nnameserver 10.0.0.1\n";
|
||||
assert_eq!(
|
||||
drop_loopback_nameservers(config),
|
||||
"search 127.example\nnameserver 10.0.0.1\n"
|
||||
);
|
||||
}
|
||||
|
||||
use super::*;
|
||||
use crate::progress::NoProgress;
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
Reference in new issue
Block a user