From 346988f30fb47fb32d804554ba8767e06315bf80 Mon Sep 17 00:00:00 2001 From: Hemant Date: Wed, 13 Nov 2024 22:52:59 +0530 Subject: [PATCH] initial commit for implementing minTTL Signed-off-by: Hemant --- build/yamls/antrea-aks.yml | 7 ++++++- build/yamls/antrea-eks.yml | 7 ++++++- build/yamls/antrea-gke.yml | 7 ++++++- build/yamls/antrea-ipsec.yml | 7 ++++++- build/yamls/antrea.yml | 7 ++++++- cmd/antrea-agent/agent.go | 1 + cmd/antrea-agent/options.go | 5 +++++ pkg/agent/controller/networkpolicy/fqdn.go | 15 ++++++++++++--- pkg/agent/controller/networkpolicy/fqdn_test.go | 1 + .../networkpolicy/networkpolicy_controller.go | 4 ++-- .../networkpolicy_controller_test.go | 3 ++- pkg/config/agent/config.go | 4 ++++ 12 files changed, 57 insertions(+), 11 deletions(-) diff --git a/build/yamls/antrea-aks.yml b/build/yamls/antrea-aks.yml index e30c8c27f9b..571c29c0689 100644 --- a/build/yamls/antrea-aks.yml +++ b/build/yamls/antrea-aks.yml @@ -4233,7 +4233,12 @@ data: # Defaults to "". It must be a host string or a host:port pair of the DNS server (e.g. 10.96.0.10, # 10.96.0.10:53, [fd00:10:96::a]:53). dnsServerOverride: "" - + + # The minTTL setting helps address the problem of applications caching DNS response IPs indefinitely. + # Cluster administrators should configure this value, ideally setting it to be equal to or greater than the maximum TTL + # value of the application's DNS cache. + minTTL: "" + # Comma-separated list of Cipher Suites. If omitted, the default Go Cipher Suites will be used. # https://golang.org/pkg/crypto/tls/#pkg-constants # Note that TLS1.3 Cipher Suites cannot be added to the list. But the apiserver will always diff --git a/build/yamls/antrea-eks.yml b/build/yamls/antrea-eks.yml index 32e4cd34bb7..c4aa2257a1b 100644 --- a/build/yamls/antrea-eks.yml +++ b/build/yamls/antrea-eks.yml @@ -4233,7 +4233,12 @@ data: # Defaults to "". It must be a host string or a host:port pair of the DNS server (e.g. 10.96.0.10, # 10.96.0.10:53, [fd00:10:96::a]:53). dnsServerOverride: "" - + + # The minTTL setting helps address the problem of applications caching DNS response IPs indefinitely. + # Cluster administrators should configure this value, ideally setting it to be equal to or greater than the maximum TTL + # value of the application's DNS cache. + minTTL: "" + # Comma-separated list of Cipher Suites. If omitted, the default Go Cipher Suites will be used. # https://golang.org/pkg/crypto/tls/#pkg-constants # Note that TLS1.3 Cipher Suites cannot be added to the list. But the apiserver will always diff --git a/build/yamls/antrea-gke.yml b/build/yamls/antrea-gke.yml index a1733ffd279..59c6a318dfd 100644 --- a/build/yamls/antrea-gke.yml +++ b/build/yamls/antrea-gke.yml @@ -4233,7 +4233,12 @@ data: # Defaults to "". It must be a host string or a host:port pair of the DNS server (e.g. 10.96.0.10, # 10.96.0.10:53, [fd00:10:96::a]:53). dnsServerOverride: "" - + + # The minTTL setting helps address the problem of applications caching DNS response IPs indefinitely. + # Cluster administrators should configure this value, ideally setting it to be equal to or greater than the maximum TTL + # value of the application's DNS cache. + minTTL: "" + # Comma-separated list of Cipher Suites. If omitted, the default Go Cipher Suites will be used. # https://golang.org/pkg/crypto/tls/#pkg-constants # Note that TLS1.3 Cipher Suites cannot be added to the list. But the apiserver will always diff --git a/build/yamls/antrea-ipsec.yml b/build/yamls/antrea-ipsec.yml index 92d831c2263..c915dd3c068 100644 --- a/build/yamls/antrea-ipsec.yml +++ b/build/yamls/antrea-ipsec.yml @@ -4246,7 +4246,12 @@ data: # Defaults to "". It must be a host string or a host:port pair of the DNS server (e.g. 10.96.0.10, # 10.96.0.10:53, [fd00:10:96::a]:53). dnsServerOverride: "" - + + # The minTTL setting helps address the problem of applications caching DNS response IPs indefinitely. + # Cluster administrators should configure this value, ideally setting it to be equal to or greater than the maximum TTL + # value of the application's DNS cache. + minTTL: "" + # Comma-separated list of Cipher Suites. If omitted, the default Go Cipher Suites will be used. # https://golang.org/pkg/crypto/tls/#pkg-constants # Note that TLS1.3 Cipher Suites cannot be added to the list. But the apiserver will always diff --git a/build/yamls/antrea.yml b/build/yamls/antrea.yml index deea6342fdf..2d0b73cf090 100644 --- a/build/yamls/antrea.yml +++ b/build/yamls/antrea.yml @@ -4233,7 +4233,12 @@ data: # Defaults to "". It must be a host string or a host:port pair of the DNS server (e.g. 10.96.0.10, # 10.96.0.10:53, [fd00:10:96::a]:53). dnsServerOverride: "" - + + # The minTTL setting helps address the problem of applications caching DNS response IPs indefinitely. + # Cluster administrators should configure this value, ideally setting it to be equal to or greater than the maximum TTL + # value of the application's DNS cache. + minTTL: "" + # Comma-separated list of Cipher Suites. If omitted, the default Go Cipher Suites will be used. # https://golang.org/pkg/crypto/tls/#pkg-constants # Note that TLS1.3 Cipher Suites cannot be added to the list. But the apiserver will always diff --git a/cmd/antrea-agent/agent.go b/cmd/antrea-agent/agent.go index 9b0ab2db775..2c6c8f434a0 100644 --- a/cmd/antrea-agent/agent.go +++ b/cmd/antrea-agent/agent.go @@ -528,6 +528,7 @@ func run(o *Options) error { nodeConfig, podNetworkWait, l7Reconciler, + o.minTTL, ) if err != nil { return fmt.Errorf("error creating new NetworkPolicy controller: %v", err) diff --git a/cmd/antrea-agent/options.go b/cmd/antrea-agent/options.go index a091fdd7068..c68a2e3d00f 100644 --- a/cmd/antrea-agent/options.go +++ b/cmd/antrea-agent/options.go @@ -90,6 +90,7 @@ type Options struct { nplEndPort int dnsServerOverride string nodeType config.NodeType + minTTL uint32 // enableEgress represents whether Egress should run or not, calculated from its feature gate configuration and // whether the traffic mode supports it. @@ -604,6 +605,10 @@ func (o *Options) validateK8sNodeOptions() error { } o.dnsServerOverride = hostPort } + // If minTTL is greater than 1, it indicates that the value has been set externally by a cluster admin, and should be respected. + if o.config.MinTTL > 1 { + o.minTTL = o.config.MinTTL + } if err := o.validateSecondaryNetworkConfig(); err != nil { return fmt.Errorf("failed to validate secondary network config: %v", err) diff --git a/pkg/agent/controller/networkpolicy/fqdn.go b/pkg/agent/controller/networkpolicy/fqdn.go index 8c077c707fe..8a05129e68d 100644 --- a/pkg/agent/controller/networkpolicy/fqdn.go +++ b/pkg/agent/controller/networkpolicy/fqdn.go @@ -127,6 +127,7 @@ type fqdnController struct { ofClient openflow.Client // dnsServerAddr stores the coreDNS server address, or the user provided DNS server address. dnsServerAddr string + minTTL uint32 // dirtyRuleHandler is a callback that is run upon finding a rule out-of-sync. dirtyRuleHandler func(string) @@ -160,7 +161,7 @@ type fqdnController struct { clock clock.Clock } -func newFQDNController(client openflow.Client, allocator *idAllocator, dnsServerOverride string, dirtyRuleHandler func(string), v4Enabled, v6Enabled bool, gwPort uint32, clock clock.WithTicker) (*fqdnController, error) { +func newFQDNController(client openflow.Client, allocator *idAllocator, dnsServerOverride string, dirtyRuleHandler func(string), v4Enabled, v6Enabled bool, gwPort uint32, clock clock.WithTicker, minTTL uint32) (*fqdnController, error) { controller := &fqdnController{ ofClient: client, dirtyRuleHandler: dirtyRuleHandler, @@ -182,6 +183,7 @@ func newFQDNController(client openflow.Client, allocator *idAllocator, dnsServer ipv6Enabled: v6Enabled, gwPort: gwPort, clock: clock, + minTTL: minTTL, } if controller.ofClient != nil { if err := controller.ofClient.NewDNSPacketInConjunction(dnsInterceptRuleID); err != nil { @@ -636,6 +638,13 @@ func (f *fqdnController) parseDNSResponse(msg *dns.Msg) (string, map[string]ipWi } fqdn := strings.ToLower(msg.Question[0].Name) responseIPs := map[string]ipWithExpiration{} + getMaxTTL := func(ttl1, ttl2 uint32) uint32 { + if ttl1 > ttl2 { + return ttl1 + } else { + return ttl2 + } + } currentTime := f.clock.Now() for _, ans := range msg.Answer { switch r := ans.(type) { @@ -643,7 +652,7 @@ func (f *fqdnController) parseDNSResponse(msg *dns.Msg) (string, map[string]ipWi if f.ipv4Enabled { responseIPs[r.A.String()] = ipWithExpiration{ ip: r.A, - expirationTime: currentTime.Add(time.Duration(r.Header().Ttl) * time.Second), + expirationTime: currentTime.Add(time.Duration(getMaxTTL(f.minTTL, r.Header().Ttl)) * time.Second), } } @@ -651,7 +660,7 @@ func (f *fqdnController) parseDNSResponse(msg *dns.Msg) (string, map[string]ipWi if f.ipv6Enabled { responseIPs[r.AAAA.String()] = ipWithExpiration{ ip: r.AAAA, - expirationTime: currentTime.Add(time.Duration(r.Header().Ttl) * time.Second), + expirationTime: currentTime.Add(time.Duration(getMaxTTL(f.minTTL, r.Header().Ttl)) * time.Second), } } } diff --git a/pkg/agent/controller/networkpolicy/fqdn_test.go b/pkg/agent/controller/networkpolicy/fqdn_test.go index 55e6a21a058..b6f970ae21e 100644 --- a/pkg/agent/controller/networkpolicy/fqdn_test.go +++ b/pkg/agent/controller/networkpolicy/fqdn_test.go @@ -52,6 +52,7 @@ func newMockFQDNController(t *testing.T, controller *gomock.Controller, dnsServe false, config.DefaultHostGatewayOFPort, clockToInject, + 0, ) require.NoError(t, err) return f, mockOFClient diff --git a/pkg/agent/controller/networkpolicy/networkpolicy_controller.go b/pkg/agent/controller/networkpolicy/networkpolicy_controller.go index 9b5308e549f..35504e5f514 100644 --- a/pkg/agent/controller/networkpolicy/networkpolicy_controller.go +++ b/pkg/agent/controller/networkpolicy/networkpolicy_controller.go @@ -196,7 +196,7 @@ func NewNetworkPolicyController(antreaClientGetter client.AntreaClientProvider, gwPort, tunPort uint32, nodeConfig *config.NodeConfig, podNetworkWait *utilwait.Group, - l7Reconciler *l7engine.Reconciler) (*Controller, error) { + l7Reconciler *l7engine.Reconciler, minTTL uint32) (*Controller, error) { idAllocator := newIDAllocator(asyncRuleDeleteInterval, dnsInterceptRuleID) c := &Controller{ antreaClientProvider: antreaClientGetter, @@ -227,7 +227,7 @@ func NewNetworkPolicyController(antreaClientGetter client.AntreaClientProvider, var err error if antreaPolicyEnabled { - if c.fqdnController, err = newFQDNController(ofClient, idAllocator, dnsServerOverride, c.enqueueRule, v4Enabled, v6Enabled, gwPort, clock.RealClock{}); err != nil { + if c.fqdnController, err = newFQDNController(ofClient, idAllocator, dnsServerOverride, c.enqueueRule, v4Enabled, v6Enabled, gwPort, clock.RealClock{}, minTTL); err != nil { return nil, err } diff --git a/pkg/agent/controller/networkpolicy/networkpolicy_controller_test.go b/pkg/agent/controller/networkpolicy/networkpolicy_controller_test.go index 50b2fc3a16c..64eb5c97972 100644 --- a/pkg/agent/controller/networkpolicy/networkpolicy_controller_test.go +++ b/pkg/agent/controller/networkpolicy/networkpolicy_controller_test.go @@ -105,7 +105,8 @@ func newTestController() (*Controller, *fake.Clientset, *mockReconciler) { config.DefaultTunOFPort, &config.NodeConfig{}, wait.NewGroup(), - l7reconciler) + l7reconciler, + 0) reconciler := newMockReconciler() controller.podReconciler = reconciler controller.auditLogger = nil diff --git a/pkg/config/agent/config.go b/pkg/config/agent/config.go index 79fdf48b644..0b87971696a 100644 --- a/pkg/config/agent/config.go +++ b/pkg/config/agent/config.go @@ -155,6 +155,10 @@ type AgentConfig struct { // Defaults to "". It must be a host string or a host:port pair of the DNS server (e.g. 10.96.0.10, // 10.96.0.10:53, [fd00:10:96::a]:53). DNSServerOverride string `yaml:"dnsServerOverride,omitempty"` + // The minTTL setting helps address the problem of applications caching DNS response IPs indefinitely. + // The Cluster administrators should configure this value, ideally setting it to be equal to or greater than the maximum TTL + // value of the application's DNS cache. + MinTTL uint32 `yaml:"minTTL,omitempty"` // Cipher suites to use. TLSCipherSuites string `yaml:"tlsCipherSuites,omitempty"` // TLS min version.