Skip to content

Commit

Permalink
option: Add --dnsproxy-enable-transparent-mode (default false)
Browse files Browse the repository at this point in the history
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 committed Jan 10, 2024
1 parent 824e969 commit 35162d1
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 8 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 @@ -879,6 +879,9 @@ func InitGlobalFlags(cmd *cobra.Command, vp *viper.Viper) {
flags.MarkHidden(option.DNSProxyLockTimeout)
option.BindEnv(vp, option.DNSProxyLockTimeout)

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

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

Expand Down Expand Up @@ -1364,6 +1367,10 @@ func initEnv(vp *viper.Viper) {
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.EnableIPv4 {
log.Fatal("IPSec requires IPv4 addressing to be enabled (--enable-ipv4=\"true\")")
}
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 @@
{{- $azureUsePrimaryAddress := "true" -}}
{{- $defaultK8sClientQPS := 5 -}}
{{- $defaultK8sClientBurst := 10 -}}
{{- $defaultDNSProxyEnableTransparentMode := "false" -}}

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

{{- /* Default values when 1.14 was initially deployed */ -}}
Expand Down Expand Up @@ -1157,6 +1159,13 @@ data:
{{- end }}

{{- if .Values.dnsProxy }}
{{- if hasKey .Values.dnsProxy "enableTransparentMode" }}
# explicit setting gets precedence
dnsproxy-enable-transparent-mode: {{ .Values.dnsProxy.enableTransparentMode | quote }}
{{- else if eq $cniChainingMode "none" }}
# default DNS proxy to transparent mode in non-chaining modes
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

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

2 changes: 2 additions & 0 deletions install/kubernetes/cilium/values.yaml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3315,6 +3315,8 @@ 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

# -- SCTP Configuration Values
sctp:
Expand Down
3 changes: 3 additions & 0 deletions pkg/defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,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
24 changes: 16 additions & 8 deletions pkg/fqdn/dnsproxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -808,11 +808,6 @@ 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, ipFamily ipfamily.IPFamily, secId identity.NumericIdentity) error {
// Set IP_TRANSPARENT to be able to use a non-host address as the source address
if err := unix.SetsockoptInt(fd, ipFamily.SocketOptsFamily, ipFamily.SocketOptsTransparent, 1); err != nil {
return fmt.Errorf("setsockopt(IP_TRANSPARENT) for %s failed: %w", ipFamily.Name, 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))
Expand All @@ -821,6 +816,16 @@ func setSoMarks(fd int, ipFamily ipfamily.IPFamily, secId identity.NumericIdenti
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 := unix.SetsockoptInt(fd, ipFamily.SocketOptsFamily, ipFamily.SocketOptsTransparent, 1); err != nil {
return fmt.Errorf("setsockopt(IP_TRANSPARENT) for %s failed: %w", ipFamily.Name, 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 @@ -1009,9 +1014,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 + "-" + targetServerAddrStr
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/option/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,9 @@ const (
// DNSProxyLockCount.
DNSProxyLockTimeout = "dnsproxy-lock-timeout"

// 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 @@ -1856,6 +1859,9 @@ type DaemonConfig struct {
// been reached.
DNSProxyConcurrencyProcessingGracePeriod time.Duration

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

// DNSProxyLockCount is the array size containing mutexes which protect
// against parallel handling of DNS response names.
DNSProxyLockCount int
Expand Down Expand Up @@ -3305,6 +3311,7 @@ func (c *DaemonConfig) Populate(vp *viper.Viper) {
c.FQDNProxyResponseMaxDelay = vp.GetDuration(FQDNProxyResponseMaxDelay)
c.DNSProxyConcurrencyLimit = vp.GetInt(DNSProxyConcurrencyLimit)
c.DNSProxyConcurrencyProcessingGracePeriod = vp.GetDuration(DNSProxyConcurrencyProcessingGracePeriod)
c.DNSProxyEnableTransparentMode = vp.GetBool(DNSProxyEnableTransparentMode)
c.DNSProxyLockCount = vp.GetInt(DNSProxyLockCount)
c.DNSProxyLockTimeout = vp.GetDuration(DNSProxyLockTimeout)
c.FQDNRejectResponse = vp.GetString(FQDNRejectResponseCode)
Expand Down

0 comments on commit 35162d1

Please sign in to comment.