Skip to content

Commit

Permalink
fix(transparent-proxy): fix IPv6 iptables rules when no IPv6 DNS serv…
Browse files Browse the repository at this point in the history
…ers (kumahq#10800)

When the `--redirect-dns` flag is present during the execution of
`kumactl install transparent-proxy`, the `/etc/resolv.conf` file is
parsed to obtain DNS servers. However, when the transparent proxy is
configured to include IPv6 and no valid IPv6 servers are found,
incorrect iptables rules were generated.

This commit fixes this when in such situation logs warning and skip
IPv6 DNS traffic redirection.

Signed-off-by: Bart Smykla <[email protected]>
  • Loading branch information
bartsmykla committed Jul 5, 2024
1 parent ddef32c commit 7def52d
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 17 deletions.
36 changes: 28 additions & 8 deletions pkg/transparentproxy/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ type InitializedDNS struct {
ServersIPv6 []string
ConntrackZoneSplitIPv4 bool
ConntrackZoneSplitIPv6 bool
EnabledIPv4 bool
EnabledIPv6 bool
}

// Initialize initializes the ServersIPv4 and ServersIPv6 fields by parsing
Expand All @@ -70,7 +72,11 @@ func (c DNS) Initialize(
cfg Config,
executables InitializedExecutablesIPvX,
) (InitializedDNS, error) {
initialized := InitializedDNS{DNS: c}
initialized := InitializedDNS{
DNS: c,
EnabledIPv4: c.Enabled,
EnabledIPv6: c.Enabled,
}

// We don't have to continue initialization if the DNS traffic shouldn't be
// redirected
Expand Down Expand Up @@ -123,6 +129,27 @@ func (c DNS) Initialize(
}
}

warning := func(ipvx string) string {
return fmt.Sprintf(
"couldn't find any %s servers in %s file. Capturing %[1]s DNS "+
"traffic will be disabled",
ipvx,
c.ResolvConfigPath,
)
}

if len(initialized.ServersIPv4) == 0 {
initialized.EnabledIPv4 = false
initialized.ConntrackZoneSplitIPv4 = false
l.Warn(warning("IPv4"))
}

if cfg.IPv6 && len(initialized.ServersIPv6) == 0 {
initialized.EnabledIPv6 = false
initialized.ConntrackZoneSplitIPv6 = false
l.Warn(warning("IPv6"))
}

return initialized, nil
}

Expand Down Expand Up @@ -326,13 +353,6 @@ func (c InitializedConfig) ShouldDropInvalidPackets(ipv6 bool) bool {
return c.DropInvalidPackets && mangleTablePresent
}

// ShouldRedirectDNS is just a convenience function which can be used in
// iptables conditional command generations instead of inlining anonymous functions
// i.e. AddRuleIf(ShouldRedirectDNS, Match(...), Jump(Drop()))
func (c InitializedConfig) ShouldRedirectDNS() bool {
return c.Redirect.DNS.Enabled
}

// ShouldCaptureAllDNS is just a convenience function which can be used in
// iptables conditional command generations instead of inlining anonymous functions
// i.e. AddRuleIf(ShouldCaptureAllDNS, Match(...), Jump(Drop()))
Expand Down
15 changes: 11 additions & 4 deletions pkg/transparentproxy/iptables/builder/builder_table_nat.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ func buildMeshOutbound(

localhost := LocalhostCIDRIPv4
inboundPassthroughSourceAddress := InboundPassthroughSourceAddressCIDRIPv4
shouldRedirectDNS := cfg.Redirect.DNS.EnabledIPv4
if ipv6 {
inboundPassthroughSourceAddress = InboundPassthroughSourceAddressCIDRIPv6
localhost = LocalhostCIDRIPv6
shouldRedirectDNS = cfg.Redirect.DNS.EnabledIPv6
}

meshOutbound, err := NewChain(TableNat, outboundChainName)
Expand Down Expand Up @@ -131,14 +133,14 @@ func buildMeshOutbound(
Jump(Return()),
).
AddRule(
Protocol(Tcp(NotDestinationPortIf(cfg.ShouldRedirectDNS, DNSPort))),
Protocol(Tcp(NotDestinationPortIfBool(shouldRedirectDNS, DNSPort))),
OutInterface(cfg.LoopbackInterfaceName),
NotDestination(localhost),
Match(Owner(Uid(uid))),
Jump(ToUserDefinedChain(inboundRedirectChainName)),
).
AddRule(
Protocol(Tcp(NotDestinationPortIf(cfg.ShouldRedirectDNS, DNSPort))),
Protocol(Tcp(NotDestinationPortIfBool(shouldRedirectDNS, DNSPort))),
OutInterface(cfg.LoopbackInterfaceName),
Match(Owner(NotUid(uid))),
Jump(Return()),
Expand All @@ -147,7 +149,7 @@ func buildMeshOutbound(
Match(Owner(Uid(uid))),
Jump(Return()),
)
if cfg.ShouldRedirectDNS() {
if shouldRedirectDNS {
if cfg.ShouldCaptureAllDNS() {
meshOutbound.AddRule(
Protocol(Tcp(DestinationPort(DNSPort))),
Expand Down Expand Up @@ -220,6 +222,11 @@ func addOutputRules(
// Initial position for the first rule in the NAT table.
rulePosition := uint(1)

shouldRedirectDNS := cfg.Redirect.DNS.EnabledIPv4
if ipv6 {
shouldRedirectDNS = cfg.Redirect.DNS.EnabledIPv6
}

// Add logging rule if logging is enabled in the configuration.
if cfg.Log.Enabled {
nat.Output().AddRuleAtPosition(
Expand Down Expand Up @@ -256,7 +263,7 @@ func addOutputRules(
}

// Conditionally add DNS redirection rules if DNS redirection is enabled.
if cfg.ShouldRedirectDNS() {
if shouldRedirectDNS {
// Default jump target for DNS rules.
jumpTarget := Return()
// Determine if DockerOutput chain should be targeted based on IPv4/IPv6
Expand Down
5 changes: 1 addition & 4 deletions pkg/transparentproxy/iptables/builder/builder_table_raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@ func buildRawTable(cfg config.InitializedConfig, ipv6 bool) *tables.RawTable {
raw := tables.Raw()

dnsServers := cfg.Redirect.DNS.ServersIPv4
if ipv6 {
dnsServers = cfg.Redirect.DNS.ServersIPv6
}

conntractZoneSplit := cfg.Redirect.DNS.ConntrackZoneSplitIPv4
if ipv6 {
dnsServers = cfg.Redirect.DNS.ServersIPv6
conntractZoneSplit = cfg.Redirect.DNS.ConntrackZoneSplitIPv6
}

Expand Down
6 changes: 5 additions & 1 deletion pkg/transparentproxy/iptables/parameters/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,11 @@ func NotDestinationPort(port uint16) *TcpUdpParameter {
}

func NotDestinationPortIf(predicate func() bool, port uint16) *TcpUdpParameter {
if predicate() {
return NotDestinationPortIfBool(predicate(), port)
}

func NotDestinationPortIfBool(condition bool, port uint16) *TcpUdpParameter {
if condition {
return destinationPort(port, true)
}

Expand Down

0 comments on commit 7def52d

Please sign in to comment.