Skip to content

Commit

Permalink
option: Add --dnsproxy-enable-transparent-mode (default false)
Browse files Browse the repository at this point in the history
[ upstream commit 35162d1 ]

Add dnsproxy-enable-transparent-mode option to enable DNS Proxy
transparent mode. If 'true', Cilium DNS proxy will use the original
source address of the source pod in the forwarded DNS requests. Local
host sources and destinations are excepted due to networking stack
compatibility reasons, but the use of the original address is typically
not significant for node local traffic.

Defaults to 'false' for backwards compatibility for upgrades, or to
'true' for Cilium 1.12 onwards.

Transparent mode is not compatible with CNI chaning modes, so if CNI
chaining is used, transparent mode will not be set unless explicitly set
with helm value 'dnsProxy.enableTransparentMode=true'.

Signed-off-by: Jarno Rajahalme <jarno@isovalent.com>
  • Loading branch information
jrajahalme authored and dylandreimerink committed Jan 16, 2024
1 parent 1cb258d commit a8fc017
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 11 deletions.
1 change: 1 addition & 0 deletions Documentation/cmdref/cilium-agent.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions daemon/cmd/daemon_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,9 @@ func initializeFlags() {
flags.Duration(option.DNSProxyConcurrencyProcessingGracePeriod, 0, "Grace time to wait when DNS proxy concurrent limit has been reached during DNS message processing")
option.BindEnv(option.DNSProxyConcurrencyProcessingGracePeriod)

flags.Bool(option.DNSProxyEnableTransparentMode, defaults.DNSProxyEnableTransparentMode, "Enable DNS proxy transparent mode")
option.BindEnv(option.DNSProxyEnableTransparentMode)

flags.Int(option.PolicyQueueSize, defaults.PolicyQueueSize, "size of queues for policy-related events")
option.BindEnv(option.PolicyQueueSize)

Expand Down Expand Up @@ -1412,6 +1415,10 @@ func initEnv(cmd *cobra.Command) {
log.Fatal("L7 proxy requires iptables rules (--install-iptables-rules=\"true\")")
}

if option.Config.EnableIPSec && option.Config.EnableL7Proxy && !option.Config.DNSProxyEnableTransparentMode {
log.Fatal("IPSec requires DNS proxy transparent mode to be enabled (--dnsproxy-enable-transparent-mode=\"true\")")
}

if option.Config.EnableIPSec && option.Config.TunnelingEnabled() {
if err := ipsec.ProbeXfrmStateOutputMask(); err != nil {
log.WithError(err).Fatal("IPSec with tunneling requires support for xfrm state output masks (Linux 4.19 or later).")
Expand Down
9 changes: 9 additions & 0 deletions install/kubernetes/cilium/templates/cilium-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
{{- $crdWaitTimeout := "5m" -}}
{{- $defaultKubeProxyReplacement := "disabled" -}}
{{- $azureUsePrimaryAddress := "true" -}}
{{- $defaultDNSProxyEnableTransparentMode := "false" -}}

{{- /* Default values when 1.8 was initially deployed */ -}}
{{- if semverCompare ">=1.8" (default "1.8" .Values.upgradeCompatibility) -}}
Expand Down Expand Up @@ -49,6 +50,7 @@
{{- $azureUsePrimaryAddress = "false" -}}
{{- end }}
{{- $defaultKubeProxyReplacement = "disabled" -}}
{{- $defaultDNSProxyEnableTransparentMode = "true" -}}
{{- end -}}

{{- $ipam := (coalesce .Values.ipam.mode $defaultIPAM) -}}
Expand Down Expand Up @@ -928,6 +930,13 @@ data:
{{- end }}

{{- if .Values.dnsProxy }}
{{- if hasKey .Values.dnsProxy "enableTransparentMode" }}
# explicit setting gets precedence
dnsproxy-enable-transparent-mode: {{ .Values.dnsProxy.enableTransparentMode | quote }}
{{- else }}
# default DNS proxy to transparent mode
dnsproxy-enable-transparent-mode: {{ $defaultDNSProxyEnableTransparentMode | quote }}
{{- end }}
{{- if .Values.dnsProxy.dnsRejectResponseCode }}
tofqdns-dns-reject-response-code: {{ .Values.dnsProxy.dnsRejectResponseCode | quote }}
{{- end }}
Expand Down
2 changes: 2 additions & 0 deletions install/kubernetes/cilium/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2297,3 +2297,5 @@ dnsProxy:
proxyPort: 0
# -- The maximum time the DNS proxy holds an allowed DNS response before sending it along. Responses are sent as soon as the datapath is updated with the new IP information.
proxyResponseMaxDelay: 100ms
# -- DNS proxy operation mode (true/false, or unset to use version dependent defaults)
# enableTransparentMode: true
2 changes: 2 additions & 0 deletions install/kubernetes/cilium/values.yaml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2294,3 +2294,5 @@ dnsProxy:
proxyPort: 0
# -- The maximum time the DNS proxy holds an allowed DNS response before sending it along. Responses are sent as soon as the datapath is updated with the new IP information.
proxyResponseMaxDelay: 100ms
# -- DNS proxy operation mode (true/false, or unset to use version dependent defaults)
# enableTransparentMode: true
3 changes: 3 additions & 0 deletions pkg/defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ const (
// endpoints that are larger than 512 Bytes or the EDNS0 option, if present.
ToFQDNsEnableDNSCompression = true

// DNSProxyEnableTransparentMode enables transparent mode for the DNS proxy.
DNSProxyEnableTransparentMode = false

// IdentityChangeGracePeriod is the default value for
// option.IdentityChangeGracePeriod
IdentityChangeGracePeriod = 5 * time.Second
Expand Down
30 changes: 19 additions & 11 deletions pkg/fqdn/dnsproxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,19 @@ func (p *DNSProxy) CheckAllowed(endpointID uint64, destPort uint16, destID ident
// for the source pod to be intercepted to the dnsproxy, which is exactly what we want but only
// until a DNS response has been received.
func setSoMarks(fd int, ipv4 bool, secId identity.NumericIdentity) error {
// Set SO_MARK to allow datapath to know these upstream packets from an egress proxy
mark := linux_defaults.MagicMarkEgress
mark |= int(uint32(secId&0xFFFF)<<16 | uint32((secId&0xFF0000)>>16))
err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_MARK, mark)
if err != nil {
return fmt.Errorf("error setting SO_MARK: %w", err)
}

// Rest of the options are only set in the transparent mode.
if !option.Config.DNSProxyEnableTransparentMode {
return nil
}

// Set IP_TRANSPARENT to be able to use a non-host address as the source address
if err := transparentSetsockopt(fd, ipv4, !ipv4); err != nil {
family := "ipv6"
Expand All @@ -649,14 +662,6 @@ func setSoMarks(fd int, ipv4 bool, secId identity.NumericIdentity) error {
return fmt.Errorf("setsockopt(IP_TRANSPARENT) for %s failed: %w", family, err)
}

// Set SO_MARK to allow datapath to know these upstream packets from an egress proxy
mark := linux_defaults.MagicMarkEgress
mark |= int(uint32(secId&0xFFFF)<<16 | uint32((secId&0xFF0000)>>16))
err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_MARK, mark)
if err != nil {
return fmt.Errorf("error setting SO_MARK: %w", err)
}

// Set SO_REUSEADDR to allow binding to an address that is already used by some other
// connection in a lingering state. This is needed in cases where we close a client
// connection but the client issues new requests re-using its source port. In that case we
Expand Down Expand Up @@ -833,9 +838,12 @@ func (p *DNSProxy) ServeDNS(w dns.ResponseWriter, request *dns.Msg) {
}

var key string
// Do not use original source address if the source is known to be in the host networking
// namespace, or the destination is known to be outside of the cluster, or is the local host
if !ep.IsHost() && !epAddr.IsLoopback() && ep.ID != uint16(identity.ReservedIdentityHost) && targetServerID.IsCluster() && targetServerID != identity.ReservedIdentityHost {
// Do not use original source address if
// - not configured, or if
// - the source is known to be in the host networking namespace, or
// - the destination is known to be outside of the cluster, or
// - is the local host
if option.Config.DNSProxyEnableTransparentMode && !ep.IsHost() && !epAddr.IsLoopback() && ep.ID != uint16(identity.ReservedIdentityHost) && targetServerID.IsCluster() && targetServerID != identity.ReservedIdentityHost {
dialer.LocalAddr = w.RemoteAddr()
key = protocol + "-" + epIPPort + "-" + targetServerAddr
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/option/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,9 @@ const (
// been reached.
DNSProxyConcurrencyProcessingGracePeriod = "dnsproxy-concurrency-processing-grace-period"

// DNSProxyEnableTransparentMode enables transparent mode for the DNS proxy.
DNSProxyEnableTransparentMode = "dnsproxy-enable-transparent-mode"

// MTUName is the name of the MTU option
MTUName = "mtu"

Expand Down Expand Up @@ -1730,6 +1733,9 @@ type DaemonConfig struct {
// been reached.
DNSProxyConcurrencyProcessingGracePeriod time.Duration

// DNSProxyEnableTransparentMode enables transparent mode for the DNS proxy.
DNSProxyEnableTransparentMode bool

// EnableXTSocketFallback allows disabling of kernel's ip_early_demux
// sysctl option if `xt_socket` kernel module is not available.
EnableXTSocketFallback bool
Expand Down Expand Up @@ -3097,6 +3103,7 @@ func (c *DaemonConfig) Populate() {
c.FQDNProxyResponseMaxDelay = viper.GetDuration(FQDNProxyResponseMaxDelay)
c.DNSProxyConcurrencyLimit = viper.GetInt(DNSProxyConcurrencyLimit)
c.DNSProxyConcurrencyProcessingGracePeriod = viper.GetDuration(DNSProxyConcurrencyProcessingGracePeriod)
c.DNSProxyEnableTransparentMode = viper.GetBool(DNSProxyEnableTransparentMode)

// Convert IP strings into net.IPNet types
subnets, invalid := ip.ParseCIDRs(viper.GetStringSlice(IPv4PodSubnets))
Expand Down

0 comments on commit a8fc017

Please sign in to comment.