diff --git a/pkg/transparentproxy/config/config.go b/pkg/transparentproxy/config/config.go index ee3c0867c640..2ce67bfe9f0d 100644 --- a/pkg/transparentproxy/config/config.go +++ b/pkg/transparentproxy/config/config.go @@ -69,11 +69,14 @@ type TrafficFlow struct { } type DNS struct { - Enabled bool - CaptureAll bool - Port uint16 - ConntrackZoneSplit bool - ResolvConfigPath string + Enabled bool + CaptureAll bool + Port uint16 + // The iptables chain where the upstream DNS requests should be directed to. + // It is only applied for IP V4. Use with care. (default "RETURN") + UpstreamTargetChain string + ConntrackZoneSplit bool + ResolvConfigPath string } type VNet struct { @@ -153,6 +156,13 @@ func (c Config) ShouldRedirectDNS() bool { return c.Redirect.DNS.Enabled } +// ShouldFallbackDNSToUpstreamChain is just a convenience function which can be used in +// iptables conditional command generations instead of inlining anonymous functions +// i.e. AppendIf(ShouldFallbackDNSToUpstreamChain, Match(...), Jump(Drop())) +func (c Config) ShouldFallbackDNSToUpstreamChain() bool { + return c.Redirect.DNS.UpstreamTargetChain != "" +} + // ShouldCaptureAllDNS is just a convenience function which can be used in // iptables conditional command generations instead of inlining anonymous functions // i.e. AppendIf(ShouldCaptureAllDNS, Match(...), Jump(Drop())) @@ -309,6 +319,10 @@ func MergeConfigWithDefaults(cfg Config) Config { result.Redirect.DNS.ResolvConfigPath = cfg.Redirect.DNS.ResolvConfigPath } + if cfg.Redirect.DNS.UpstreamTargetChain != "" { + result.Redirect.DNS.UpstreamTargetChain = cfg.Redirect.DNS.UpstreamTargetChain + } + if cfg.Redirect.DNS.Port != 0 { result.Redirect.DNS.Port = cfg.Redirect.DNS.Port } diff --git a/pkg/transparentproxy/iptables/builder/builder_nat.go b/pkg/transparentproxy/iptables/builder/builder_nat.go index 0aa75323bdbe..7c85430661bf 100644 --- a/pkg/transparentproxy/iptables/builder/builder_nat.go +++ b/pkg/transparentproxy/iptables/builder/builder_nat.go @@ -225,13 +225,19 @@ func addOutputRules(cfg config.Config, dnsServers []string, nat *table.NatTable) } if cfg.ShouldRedirectDNS() { + jumpTarget := Return() + if cfg.ShouldFallbackDNSToUpstreamChain() { + jumpTarget = ToUserDefinedChain(cfg.Redirect.DNS.UpstreamTargetChain) + } + nat.Output().Insert( rulePosition, Protocol(Udp(DestinationPort(DNSPort))), Match(Owner(Uid(uid))), - Jump(Return()), + Jump(jumpTarget), ) rulePosition++ + if cfg.ShouldCaptureAllDNS() { nat.Output().Insert( rulePosition, diff --git a/pkg/transparentproxy/transparentproxy_experimental.go b/pkg/transparentproxy/transparentproxy_experimental.go index 344fce1a7efb..7af7e8b98ba9 100644 --- a/pkg/transparentproxy/transparentproxy_experimental.go +++ b/pkg/transparentproxy/transparentproxy_experimental.go @@ -161,10 +161,11 @@ func (tp *ExperimentalTransparentProxy) Setup(tpConfig *config.TransparentProxyC ExcludePortsForUIDs: excludePortsForUIDs, }, DNS: config.DNS{ - Enabled: tpConfig.RedirectDNS, - CaptureAll: tpConfig.RedirectAllDNSTraffic, - Port: agentDNSListenerPort, - ConntrackZoneSplit: !tpConfig.SkipDNSConntrackZoneSplit, + Enabled: tpConfig.RedirectDNS, + CaptureAll: tpConfig.RedirectAllDNSTraffic, + Port: agentDNSListenerPort, + UpstreamTargetChain: tpConfig.DNSUpstreamTargetChain, + ConntrackZoneSplit: !tpConfig.SkipDNSConntrackZoneSplit, }, VNet: config.VNet{ Networks: tpConfig.VnetNetworks, diff --git a/test/framework/universal_app.go b/test/framework/universal_app.go index 427a90a846e9..aea0aff62cd5 100644 --- a/test/framework/universal_app.go +++ b/test/framework/universal_app.go @@ -490,6 +490,7 @@ func (s *UniversalApp) setupTransparent(cpIp string, builtindns bool, experiment if builtindns { args = append(args, "--redirect-dns", + "--redirect-dns-upstream-target-chain", "DOCKER_OUTPUT", ) }