daemon: doctor passes vm dns when banger itself owns the port

The previous check tried to bind 127.0.0.1:42069 and warned on
'address already in use' — which is exactly the state when the
banger daemon is running, the case the user ran 'doctor' to
confirm. The warning was actively misleading.

Now, on 'address already in use', probe the listener with a
*.vm DNS query that only banger's vmdns server answers
authoritatively (NXDOMAIN with Authoritative=true). If the shape
matches we pass; if the port is held by something else we still
warn. Tests cover both branches: a real vmdns server is accepted,
and a silent UDP listener on the same port is rejected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Thales Maciel 2026-04-26 18:57:27 -03:00
parent 35bfac3f13
commit 3ec357090a
No known key found for this signature in database
GPG key ID: 33112E6833C34679
2 changed files with 56 additions and 1 deletions

View file

@ -3,6 +3,7 @@ package daemon
import (
"context"
"errors"
"net"
"reflect"
"testing"
@ -10,6 +11,7 @@ import (
"banger/internal/guestconfig"
"banger/internal/model"
"banger/internal/system"
"banger/internal/vmdns"
)
type testCapability struct {
@ -146,6 +148,32 @@ func TestContributeHooksPopulateGuestAndMachineConfig(t *testing.T) {
}
}
func TestProbeBangerDNSAcceptsRealServer(t *testing.T) {
server, err := vmdns.New("127.0.0.1:0", nil)
if err != nil {
t.Fatalf("vmdns.New: %v", err)
}
t.Cleanup(func() { _ = server.Close() })
if !probeBangerDNS(server.Addr()) {
t.Fatal("probeBangerDNS rejected the real banger DNS server")
}
}
func TestProbeBangerDNSRejectsSilentListener(t *testing.T) {
// A UDP listener that drops every datagram. The probe should
// time out and return false — i.e. "this is not banger".
conn, err := net.ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatalf("ListenPacket: %v", err)
}
t.Cleanup(func() { _ = conn.Close() })
if probeBangerDNS(conn.LocalAddr().String()) {
t.Fatal("probeBangerDNS accepted a silent non-DNS listener")
}
}
func TestDefaultCapabilitiesInOrder(t *testing.T) {
d := &Daemon{}
wireServices(d)