chore: listen for dns requests on 127.0.0.53

Turns out there is actually no black magic in systemd, they simply listen on 127.0.0.53 and forward dns requests there in resolv.conf.
Reason is the same as ours — to preserve compatibility with other applications. So we do the same in our code.

This PR also does two things:
- Adds `::1` into resolv.conf for IPv6 only resolvers.
- Drops `SO_REUSEPORT` from control options (it works without them).

Closes #8328

Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
This commit is contained in:
Dmitriy Matrenichev 2024-02-26 14:27:43 +03:00
parent 8872a7a210
commit f8c556a1ce
No known key found for this signature in database
GPG Key ID: D3363CF894E68892
7 changed files with 18 additions and 18 deletions

View File

@ -160,6 +160,8 @@ func (ctrl *DNSResolveCacheController) runServer(originCtx context.Context, r co
MaxTCPQueries: -1, MaxTCPQueries: -1,
} }
} }
l.Info("dns listener created")
} }
for netwk, opt := range serverOpts { for netwk, opt := range serverOpts {
@ -227,6 +229,8 @@ func closeListener(lis io.Closer, l *zap.Logger) {
if err := lis.Close(); err != nil && !errors.Is(err, net.ErrClosed) { if err := lis.Close(); err != nil && !errors.Is(err, net.ErrClosed) {
l.Error("error closing listener", zap.Error(err)) l.Error("error closing listener", zap.Error(err))
} }
l.Info("dns listener closed")
} }
func dropResolveResources(ctx context.Context, r controller.Runtime, nets ...resource.ID) error { func dropResolveResources(ctx context.Context, r controller.Runtime, nets ...resource.ID) error {

View File

@ -77,7 +77,7 @@ func (suite *DNSServer) TestResolving() {
var res *dns.Msg var res *dns.Msg
err := retry.Constant(2*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(func() error { err := retry.Constant(2*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(func() error {
r, err := dns.Exchange(msg, "127.0.0.1:10700") r, err := dns.Exchange(msg, "127.0.0.53:10700")
res = r res = r
@ -148,7 +148,7 @@ func TestDNSServer(t *testing.T) {
AfterSetup: func(suite *ctest.DefaultSuite) { AfterSetup: func(suite *ctest.DefaultSuite) {
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.DNSUpstreamController{})) suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.DNSUpstreamController{}))
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.DNSResolveCacheController{ suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.DNSResolveCacheController{
Addr: "127.0.0.1:10700", Addr: "127.0.0.53:10700",
AddrV6: "[::1]:10700", AddrV6: "[::1]:10700",
Logger: zaptest.NewLogger(t), Logger: zaptest.NewLogger(t),
})) }))

View File

@ -176,12 +176,12 @@ func (ctrl *EtcFileController) Run(ctx context.Context, r controller.Runtime, lo
} }
} }
var localDNS = netip.MustParseAddr("127.0.0.1") var localDNS = []netip.Addr{netip.MustParseAddr("127.0.0.53"), netip.MustParseAddr("::1")}
func pickNameservers(list safe.List[*network.DNSResolveCache], resolverStatus *network.ResolverStatus) []netip.Addr { func pickNameservers(list safe.List[*network.DNSResolveCache], resolverStatus *network.ResolverStatus) []netip.Addr {
if list.Len() > 0 { if list.Len() > 0 {
// local dns resolve cache enabled, route host dns requests to 127.0.0.1 // local dns resolve cache enabled, route host dns requests to 127.0.0.1
return []netip.Addr{localDNS} return localDNS
} }
return resolverStatus.TypedSpec().DNSServers return resolverStatus.TypedSpec().DNSServers

View File

@ -221,7 +221,7 @@ func (suite *EtcFileConfigSuite) TestComplete() {
[]resource.Resource{suite.cfg, suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus, suite.dnsServer}, []resource.Resource{suite.cfg, suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus, suite.dnsServer},
etcFileContents{ etcFileContents{
hosts: "127.0.0.1 localhost\n33.11.22.44 foo.example.com foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n10.0.0.1 a b\n10.0.0.2 c d\n", //nolint:lll hosts: "127.0.0.1 localhost\n33.11.22.44 foo.example.com foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n10.0.0.1 a b\n10.0.0.2 c d\n", //nolint:lll
resolvConf: "nameserver 127.0.0.1\n\nsearch example.com\n", resolvConf: "nameserver 127.0.0.53\nnameserver ::1\n\nsearch example.com\n",
resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n\nsearch example.com\n", resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n\nsearch example.com\n",
}, },
) )
@ -232,7 +232,7 @@ func (suite *EtcFileConfigSuite) TestNoExtraHosts() {
[]resource.Resource{suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus, suite.dnsServer}, []resource.Resource{suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus, suite.dnsServer},
etcFileContents{ etcFileContents{
hosts: "127.0.0.1 localhost\n33.11.22.44 foo.example.com foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n", hosts: "127.0.0.1 localhost\n33.11.22.44 foo.example.com foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n",
resolvConf: "nameserver 127.0.0.1\n\nsearch example.com\n", resolvConf: "nameserver 127.0.0.53\nnameserver ::1\n\nsearch example.com\n",
resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n\nsearch example.com\n", resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n\nsearch example.com\n",
}, },
) )
@ -255,7 +255,7 @@ func (suite *EtcFileConfigSuite) TestNoSearchDomain() {
[]resource.Resource{cfg, suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus, suite.dnsServer}, []resource.Resource{cfg, suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus, suite.dnsServer},
etcFileContents{ etcFileContents{
hosts: "127.0.0.1 localhost\n33.11.22.44 foo.example.com foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n", hosts: "127.0.0.1 localhost\n33.11.22.44 foo.example.com foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n",
resolvConf: "nameserver 127.0.0.1\n", resolvConf: "nameserver 127.0.0.53\nnameserver ::1\n",
resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n", resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n",
}, },
) )
@ -268,7 +268,7 @@ func (suite *EtcFileConfigSuite) TestNoDomainname() {
[]resource.Resource{suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus, suite.dnsServer}, []resource.Resource{suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus, suite.dnsServer},
etcFileContents{ etcFileContents{
hosts: "127.0.0.1 localhost\n33.11.22.44 foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n", hosts: "127.0.0.1 localhost\n33.11.22.44 foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n",
resolvConf: "nameserver 127.0.0.1\n", resolvConf: "nameserver 127.0.0.53\nnameserver ::1\n",
resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n", resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n",
}, },
) )
@ -279,7 +279,7 @@ func (suite *EtcFileConfigSuite) TestOnlyResolvers() {
[]resource.Resource{suite.resolverStatus, suite.dnsServer}, []resource.Resource{suite.resolverStatus, suite.dnsServer},
etcFileContents{ etcFileContents{
hosts: "", hosts: "",
resolvConf: "nameserver 127.0.0.1\n", resolvConf: "nameserver 127.0.0.53\nnameserver ::1\n",
resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n", resolvGlobalConf: "nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n",
}, },
) )

View File

@ -189,7 +189,7 @@ func (ctrl *Controller) Run(ctx context.Context, drainer *runtime.Drainer) error
&network.AddressStatusController{}, &network.AddressStatusController{},
&network.DeviceConfigController{}, &network.DeviceConfigController{},
&network.DNSResolveCacheController{ &network.DNSResolveCacheController{
Addr: "127.0.0.1:53", Addr: "127.0.0.53:53",
AddrV6: "[::1]:53", AddrV6: "[::1]:53",
Logger: dnsCacheLogger, Logger: dnsCacheLogger,
}, },

View File

@ -274,7 +274,6 @@ func NewUDPPacketConn(network, addr string) (net.PacketConn, error) {
var ( var (
tcpOptions = []controlOptions{ tcpOptions = []controlOptions{
{unix.SOL_SOCKET, unix.SO_REUSEPORT, 1, "failed to set SO_REUSEADDR"},
{unix.IPPROTO_IP, unix.IP_RECVTTL, 1, "failed to set IP_RECVTTL"}, {unix.IPPROTO_IP, unix.IP_RECVTTL, 1, "failed to set IP_RECVTTL"},
{unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 5, "failed to set TCP_FASTOPEN"}, // tcp specific stuff from systemd {unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 5, "failed to set TCP_FASTOPEN"}, // tcp specific stuff from systemd
{unix.IPPROTO_TCP, unix.TCP_NODELAY, 1, "failed to set TCP_NODELAY"}, // tcp specific stuff from systemd {unix.IPPROTO_TCP, unix.TCP_NODELAY, 1, "failed to set TCP_NODELAY"}, // tcp specific stuff from systemd
@ -282,7 +281,6 @@ var (
} }
tcpOptionsV6 = []controlOptions{ tcpOptionsV6 = []controlOptions{
{unix.SOL_SOCKET, unix.SO_REUSEPORT, 1, "failed to set SO_REUSEADDR"},
{unix.IPPROTO_IPV6, unix.IPV6_RECVHOPLIMIT, 1, "failed to set IPV6_RECVHOPLIMIT"}, {unix.IPPROTO_IPV6, unix.IPV6_RECVHOPLIMIT, 1, "failed to set IPV6_RECVHOPLIMIT"},
{unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 5, "failed to set TCP_FASTOPEN"}, // tcp specific stuff from systemd {unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 5, "failed to set TCP_FASTOPEN"}, // tcp specific stuff from systemd
{unix.IPPROTO_TCP, unix.TCP_NODELAY, 1, "failed to set TCP_NODELAY"}, // tcp specific stuff from systemd {unix.IPPROTO_TCP, unix.TCP_NODELAY, 1, "failed to set TCP_NODELAY"}, // tcp specific stuff from systemd
@ -290,13 +288,11 @@ var (
} }
udpOptions = []controlOptions{ udpOptions = []controlOptions{
{unix.SOL_SOCKET, unix.SO_REUSEPORT, 1, "failed to set SO_REUSEADDR"},
{unix.IPPROTO_IP, unix.IP_RECVTTL, 1, "failed to set IP_RECVTTL"}, {unix.IPPROTO_IP, unix.IP_RECVTTL, 1, "failed to set IP_RECVTTL"},
{unix.IPPROTO_IP, unix.IP_TTL, 1, "failed to set IP_TTL"}, {unix.IPPROTO_IP, unix.IP_TTL, 1, "failed to set IP_TTL"},
} }
udpOptionsV6 = []controlOptions{ udpOptionsV6 = []controlOptions{
{unix.SOL_SOCKET, unix.SO_REUSEPORT, 1, "failed to set SO_REUSEADDR"},
{unix.IPPROTO_IPV6, unix.IPV6_RECVHOPLIMIT, 1, "failed to set IPV6_RECVHOPLIMIT"}, {unix.IPPROTO_IPV6, unix.IPV6_RECVHOPLIMIT, 1, "failed to set IPV6_RECVHOPLIMIT"},
{unix.IPPROTO_IPV6, unix.IPV6_UNICAST_HOPS, 1, "failed to set IPV6_UNICAST_HOPS"}, {unix.IPPROTO_IPV6, unix.IPV6_UNICAST_HOPS, 1, "failed to set IPV6_UNICAST_HOPS"},
} }

View File

@ -60,7 +60,7 @@ func TestDNS(t *testing.T) {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
r, err := dnssrv.Exchange(createQuery(), "127.0.0.1:10700") r, err := dnssrv.Exchange(createQuery(), "127.0.0.53:10700")
test.errCheck(t, err) test.errCheck(t, err)
if r != nil { if r != nil {
@ -86,11 +86,11 @@ func TestDNSEmptyDestinations(t *testing.T) {
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
r, err := dnssrv.Exchange(createQuery(), "127.0.0.1:10700") r, err := dnssrv.Exchange(createQuery(), "127.0.0.53:10700")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, dnssrv.RcodeServerFailure, r.Rcode, r) require.Equal(t, dnssrv.RcodeServerFailure, r.Rcode, r)
r, err = dnssrv.Exchange(createQuery(), "127.0.0.1:10700") r, err = dnssrv.Exchange(createQuery(), "127.0.0.53:10700")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, dnssrv.RcodeServerFailure, r.Rcode, r) require.Equal(t, dnssrv.RcodeServerFailure, r.Rcode, r)
@ -118,7 +118,7 @@ func newServer(t *testing.T, nameservers ...string) (context.Context, func()) {
handler.SetProxy(pxs) handler.SetProxy(pxs)
pc, err := dns.NewUDPPacketConn("udp", "127.0.0.1:10700") pc, err := dns.NewUDPPacketConn("udp", "127.0.0.53:10700")
require.NoError(t, err) require.NoError(t, err)
runner := dns.NewRunner(dns.NewServer(dns.ServerOptins{ runner := dns.NewRunner(dns.NewServer(dns.ServerOptins{