Skip to content

Commit 53f5489

Browse files
committed
fix: increase host dns packet ttl for pods
This PR fixes incorrect packet TTL if `forwardKubeDNSToHost` is enabled. Credits go to Julian Wiedmann. Closes #8698. Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
1 parent dedb6d3 commit 53f5489

File tree

3 files changed

+73
-63
lines changed

3 files changed

+73
-63
lines changed

internal/app/machined/pkg/controllers/network/dns_resolve_cache.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func (ctrl *DNSResolveCacheController) Run(ctx context.Context, r controller.Run
130130
runnerCfg := runnerConfig{net: netwk, addr: addr}
131131

132132
if _, ok := ctrl.runners[runnerCfg]; !ok {
133-
runner, rErr := newDNSRunner(runnerCfg, ctrl.cache, ctrl.Logger)
133+
runner, rErr := newDNSRunner(runnerCfg, ctrl.cache, ctrl.Logger, cfg.TypedSpec().ServiceHostDNSAddress.IsValid())
134134
if rErr != nil {
135135
return fmt.Errorf("error creating dns runner: %w", rErr)
136136
}
@@ -256,7 +256,7 @@ type runnerConfig struct {
256256
addr netip.AddrPort
257257
}
258258

259-
func newDNSRunner(cfg runnerConfig, cache *dns.Cache, logger *zap.Logger) (*dns.Server, error) {
259+
func newDNSRunner(cfg runnerConfig, cache *dns.Cache, logger *zap.Logger, forwardEnabled bool) (*dns.Server, error) {
260260
if cfg.addr.Addr().Is6() {
261261
cfg.net += "6"
262262
}
@@ -265,9 +265,14 @@ func newDNSRunner(cfg runnerConfig, cache *dns.Cache, logger *zap.Logger) (*dns.
265265

266266
var serverOpts dns.ServerOptions
267267

268+
controlFn, ctrlErr := dns.MakeControl(cfg.net, forwardEnabled)
269+
if ctrlErr != nil {
270+
return nil, fmt.Errorf("error creating %q control function: %w", cfg.net, ctrlErr)
271+
}
272+
268273
switch cfg.net {
269274
case "udp", "udp6":
270-
packetConn, err := dns.NewUDPPacketConn(cfg.net, cfg.addr.String())
275+
packetConn, err := dns.NewUDPPacketConn(cfg.net, cfg.addr.String(), controlFn)
271276
if err != nil {
272277
return nil, fmt.Errorf("error creating %q packet conn: %w", cfg.net, err)
273278
}
@@ -279,7 +284,7 @@ func newDNSRunner(cfg runnerConfig, cache *dns.Cache, logger *zap.Logger) (*dns.
279284
}
280285

281286
case "tcp", "tcp6":
282-
listener, err := dns.NewTCPListener(cfg.net, cfg.addr.String())
287+
listener, err := dns.NewTCPListener(cfg.net, cfg.addr.String(), controlFn)
283288
if err != nil {
284289
return nil, fmt.Errorf("error creating %q listener: %w", cfg.net, err)
285290
}

internal/pkg/dns/dns.go

Lines changed: 62 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -338,88 +338,76 @@ func (s *Server) Start(onDone func(err error)) (stop func(), stopped <-chan stru
338338
}
339339

340340
// NewTCPListener creates a new TCP listener.
341-
func NewTCPListener(network, addr string) (net.Listener, error) {
342-
var opts []controlOptions
343-
344-
switch network {
345-
case "tcp", "tcp4":
346-
network = "tcp4"
347-
opts = tcpOptions
348-
349-
case "tcp6":
350-
opts = tcpOptionsV6
351-
352-
default:
341+
func NewTCPListener(network, addr string, control ControlFn) (net.Listener, error) {
342+
network, ok := networkNames[network]
343+
if !ok {
353344
return nil, fmt.Errorf("unsupported network: %s", network)
354345
}
355346

356-
lc := net.ListenConfig{Control: makeControl(opts)}
347+
lc := net.ListenConfig{Control: control}
357348

358349
return lc.Listen(context.Background(), network, addr)
359350
}
360351

361352
// NewUDPPacketConn creates a new UDP packet connection.
362-
func NewUDPPacketConn(network, addr string) (net.PacketConn, error) {
363-
var opts []controlOptions
364-
365-
switch network {
366-
case "udp", "udp4":
367-
network = "udp4"
368-
opts = udpOptions
369-
370-
case "udp6":
371-
opts = udpOptionsV6
372-
373-
default:
353+
func NewUDPPacketConn(network, addr string, control ControlFn) (net.PacketConn, error) {
354+
network, ok := networkNames[network]
355+
if !ok {
374356
return nil, fmt.Errorf("unsupported network: %s", network)
375357
}
376358

377-
lc := net.ListenConfig{
378-
Control: makeControl(opts),
379-
}
359+
lc := net.ListenConfig{Control: control}
380360

381361
return lc.ListenPacket(context.Background(), network, addr)
382362
}
383363

384-
var (
385-
tcpOptions = []controlOptions{
386-
{unix.IPPROTO_IP, unix.IP_RECVTTL, 1, "failed to set IP_RECVTTL"},
387-
{unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 5, "failed to set TCP_FASTOPEN"}, // tcp specific stuff from systemd
388-
{unix.IPPROTO_TCP, unix.TCP_NODELAY, 1, "failed to set TCP_NODELAY"}, // tcp specific stuff from systemd
389-
{unix.IPPROTO_IP, unix.IP_TTL, 1, "failed to set IP_TTL"},
390-
}
364+
// ControlFn is an alias to [net.ListenConfig.Control] function.
365+
type ControlFn = func(string, string, syscall.RawConn) error
391366

392-
tcpOptionsV6 = []controlOptions{
393-
{unix.IPPROTO_IPV6, unix.IPV6_RECVHOPLIMIT, 1, "failed to set IPV6_RECVHOPLIMIT"},
394-
{unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 5, "failed to set TCP_FASTOPEN"}, // tcp specific stuff from systemd
395-
{unix.IPPROTO_TCP, unix.TCP_NODELAY, 1, "failed to set TCP_NODELAY"}, // tcp specific stuff from systemd
396-
{unix.IPPROTO_IPV6, unix.IPV6_UNICAST_HOPS, 1, "failed to set IPV6_UNICAST_HOPS"},
397-
}
367+
// MakeControl creates a control function for setting socket options.
368+
func MakeControl(network string, forwardEnabled bool) (ControlFn, error) {
369+
maxHops := 1
398370

399-
udpOptions = []controlOptions{
400-
{unix.IPPROTO_IP, unix.IP_RECVTTL, 1, "failed to set IP_RECVTTL"},
401-
{unix.IPPROTO_IP, unix.IP_TTL, 1, "failed to set IP_TTL"},
371+
if forwardEnabled {
372+
maxHops = 2
402373
}
403374

404-
udpOptionsV6 = []controlOptions{
405-
{unix.IPPROTO_IPV6, unix.IPV6_RECVHOPLIMIT, 1, "failed to set IPV6_RECVHOPLIMIT"},
406-
{unix.IPPROTO_IPV6, unix.IPV6_UNICAST_HOPS, 1, "failed to set IPV6_UNICAST_HOPS"},
407-
}
408-
)
375+
var options []controlOptions
409376

410-
type controlOptions struct {
411-
level int
412-
opt int
413-
val int
414-
errorMessage string
415-
}
377+
switch network {
378+
case "tcp", "tcp4":
379+
options = []controlOptions{
380+
{unix.IPPROTO_IP, unix.IP_RECVTTL, maxHops, "failed to set IP_RECVTTL"},
381+
{unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 5, "failed to set TCP_FASTOPEN"}, // tcp specific stuff from systemd
382+
{unix.IPPROTO_TCP, unix.TCP_NODELAY, 1, "failed to set TCP_NODELAY"}, // tcp specific stuff from systemd
383+
{unix.IPPROTO_IP, unix.IP_TTL, maxHops, "failed to set IP_TTL"},
384+
}
385+
case "tcp6":
386+
options = []controlOptions{
387+
{unix.IPPROTO_IPV6, unix.IPV6_RECVHOPLIMIT, maxHops, "failed to set IPV6_RECVHOPLIMIT"},
388+
{unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 5, "failed to set TCP_FASTOPEN"}, // tcp specific stuff from systemd
389+
{unix.IPPROTO_TCP, unix.TCP_NODELAY, 1, "failed to set TCP_NODELAY"}, // tcp specific stuff from systemd
390+
{unix.IPPROTO_IPV6, unix.IPV6_UNICAST_HOPS, maxHops, "failed to set IPV6_UNICAST_HOPS"},
391+
}
392+
case "udp", "udp4":
393+
options = []controlOptions{
394+
{unix.IPPROTO_IP, unix.IP_RECVTTL, maxHops, "failed to set IP_RECVTTL"},
395+
{unix.IPPROTO_IP, unix.IP_TTL, maxHops, "failed to set IP_TTL"},
396+
}
397+
case "udp6":
398+
options = []controlOptions{
399+
{unix.IPPROTO_IPV6, unix.IPV6_RECVHOPLIMIT, maxHops, "failed to set IPV6_RECVHOPLIMIT"},
400+
{unix.IPPROTO_IPV6, unix.IPV6_UNICAST_HOPS, maxHops, "failed to set IPV6_UNICAST_HOPS"},
401+
}
402+
default:
403+
return nil, fmt.Errorf("unsupported network: %s", network)
404+
}
416405

417-
func makeControl(opts []controlOptions) func(string, string, syscall.RawConn) error {
418406
return func(_ string, _ string, c syscall.RawConn) error {
419407
var resErr error
420408

421409
err := c.Control(func(fd uintptr) {
422-
for _, opt := range opts {
410+
for _, opt := range options {
423411
opErr := unix.SetsockoptInt(int(fd), opt.level, opt.opt, opt.val)
424412
if opErr != nil {
425413
resErr = fmt.Errorf(opt.errorMessage+": %w", opErr)
@@ -437,5 +425,21 @@ func makeControl(opts []controlOptions) func(string, string, syscall.RawConn) er
437425
}
438426

439427
return nil
440-
}
428+
}, nil
429+
}
430+
431+
type controlOptions struct {
432+
level int
433+
opt int
434+
val int
435+
errorMessage string
436+
}
437+
438+
var networkNames = map[string]string{
439+
"tcp": "tcp4",
440+
"tcp4": "tcp4",
441+
"tcp6": "tcp6",
442+
"udp": "udp4",
443+
"udp4": "udp4",
444+
"udp6": "udp6",
441445
}

internal/pkg/dns/dns_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"github.com/coredns/coredns/plugin/pkg/proxy"
1515
dnssrv "github.com/miekg/dns"
16+
"github.com/siderolabs/gen/ensure"
1617
"github.com/siderolabs/gen/xslices"
1718
"github.com/siderolabs/gen/xtesting/check"
1819
"github.com/stretchr/testify/require"
@@ -120,7 +121,7 @@ func newServer(t *testing.T, nameservers ...string) func() {
120121

121122
handler.SetProxy(pxs)
122123

123-
pc, err := dns.NewUDPPacketConn("udp", "127.0.0.53:10700")
124+
pc, err := dns.NewUDPPacketConn("udp", "127.0.0.53:10700", ensure.Value(dns.MakeControl("udp", false)))
124125
require.NoError(t, err)
125126

126127
nodeHandler := dns.NewNodeHandler(handler, &testResolver{}, l)

0 commit comments

Comments
 (0)