fix: accept host:port in validateResolverAddr; release v0.1.8
The root helper's resolver-address validator only accepted bare IPs, so `resolvectl dns <bridge> 127.0.0.1:42069` — banger's own auto-wire call to point systemd-resolved at the in-process DNS server — was rejected before it ever reached resolvectl. The auto-wire is best-effort and only logs a warning on failure, so .vm resolution silently broke on the NSS path: dig @127.0.0.1 worked, curl <vm>.vm didn't. Validator now allows both bare IPs and IP:port (matching what `resolvectl dns` itself accepts), with new test coverage for the port'd form. Existing installs need a one-time `sudo banger system restart` after updating to v0.1.8 so the daemon re-runs the auto-wire with the fixed validator. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
403f60dbbf
commit
9400bab6fd
3 changed files with 41 additions and 7 deletions
27
CHANGELOG.md
27
CHANGELOG.md
|
|
@ -10,6 +10,30 @@ changed between versions.
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.1.8] - 2026-05-01
|
||||
|
||||
### Fixed
|
||||
|
||||
- `<vm>.vm` resolution from the host (NSS path: curl, ssh hostname,
|
||||
etc.) now works on systemd-resolved hosts. The root helper's
|
||||
`validateResolverAddr` was rejecting the `host:port` form
|
||||
(`127.0.0.1:42069`) that banger constructs to point resolved at the
|
||||
in-process DNS server, so the auto-wire silently failed at every
|
||||
daemon startup. `dig @127.0.0.1` worked because that bypasses NSS;
|
||||
any tool going through glibc's resolver chain didn't.
|
||||
- Validator now accepts both bare IPs and `IP:port` (matching what
|
||||
`resolvectl dns` itself accepts) with new test coverage for the
|
||||
port'd form.
|
||||
|
||||
### Notes
|
||||
|
||||
- Existing v0.1.x installs that already booted with the broken
|
||||
validator have stale per-link resolved state. After updating to
|
||||
v0.1.8, run `sudo banger system restart` once to re-trigger the
|
||||
auto-wire, or restart the host. systemd-resolved restarts also
|
||||
wipe per-link state — banger restores it on its own daemon
|
||||
startup but won't re-run for an already-running daemon.
|
||||
|
||||
## [v0.1.7] - 2026-05-01
|
||||
|
||||
### Added
|
||||
|
|
@ -250,7 +274,8 @@ root filesystem and network, and exits on demand.
|
|||
the swap rather than starting up against an incompatible store.
|
||||
- Linux only. amd64 only. KVM required.
|
||||
|
||||
[Unreleased]: https://git.thaloco.com/thaloco/banger/compare/v0.1.7...HEAD
|
||||
[Unreleased]: https://git.thaloco.com/thaloco/banger/compare/v0.1.8...HEAD
|
||||
[v0.1.8]: https://git.thaloco.com/thaloco/banger/releases/tag/v0.1.8
|
||||
[v0.1.7]: https://git.thaloco.com/thaloco/banger/releases/tag/v0.1.7
|
||||
[v0.1.6]: https://git.thaloco.com/thaloco/banger/releases/tag/v0.1.6
|
||||
[v0.1.5]: https://git.thaloco.com/thaloco/banger/releases/tag/v0.1.5
|
||||
|
|
|
|||
|
|
@ -1296,18 +1296,24 @@ func validateIPv4(ip string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// validateResolverAddr confirms s parses as an IP address (v4 or v6).
|
||||
// resolvectl accepts either; reject anything that doesn't parse so a
|
||||
// compromised daemon can't wedge resolved with garbage input.
|
||||
// validateResolverAddr confirms s parses as an IP address, optionally
|
||||
// with a ":port" suffix. resolvectl accepts both bare IPs and the
|
||||
// "IP:port" form (used to point at a non-default DNS port — banger's
|
||||
// in-process server binds to 127.0.0.1:42069). Reject anything that
|
||||
// doesn't parse so a compromised daemon can't wedge resolved with
|
||||
// garbage input.
|
||||
func validateResolverAddr(s string) error {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return errors.New("resolver address is required")
|
||||
}
|
||||
if net.ParseIP(s) == nil {
|
||||
return fmt.Errorf("invalid resolver address %q", s)
|
||||
if net.ParseIP(s) != nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
if host, _, err := net.SplitHostPort(s); err == nil && net.ParseIP(host) != nil {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid resolver address %q", s)
|
||||
}
|
||||
|
||||
func validateTapName(tapName string) error {
|
||||
|
|
|
|||
|
|
@ -566,8 +566,11 @@ func TestValidateResolverAddr(t *testing.T) {
|
|||
}{
|
||||
{name: "ipv4", arg: "192.168.1.1", ok: true},
|
||||
{name: "ipv6", arg: "fe80::1", ok: true},
|
||||
{name: "ipv4_with_port", arg: "127.0.0.1:42069", ok: true},
|
||||
{name: "ipv6_with_port", arg: "[fe80::1]:42069", ok: true},
|
||||
{name: "empty", arg: "", ok: false},
|
||||
{name: "garbage", arg: "resolver.example", ok: false},
|
||||
{name: "garbage_with_port", arg: "resolver.example:53", ok: false},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue