Addiing listener for DNS resolution in envoy sidecar#23698
Conversation
There was a problem hiding this comment.
Pull request overview
This PR extends the xDS listener generation for Connect proxies to include UDP DNS listeners backed by Envoy’s dns_filter, enabling (1) inline resolution of Consul virtual service names to VIPs and (2) optional forwarding to configured upstream DNS recursors.
Changes:
- Add an inline “virtual DNS” UDP listener (127.0.0.1:8653) that serves an in-memory FQDN→VIP table derived from the proxy snapshot.
- Add an optional “egress DNS” UDP listener (127.0.0.1:8654) that forwards queries to agent-configured DNS recursors via c-ares when recursors are present.
- Extend the xDS ConfigFetcher interface (and agent implementation) to expose DNS recursors; add unit tests for the new DNS listener/table builders.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| agent/xds/listeners.go | Appends inline and (optionally) egress DNS listeners to LDS resources for Connect proxies. |
| agent/xds/listeners_test.go | Updates a test config fetcher stub to satisfy the expanded ConfigFetcher interface. |
| agent/xds/listeners_dns.go | Implements virtual DNS table construction and the two UDP dns_filter listeners (inline + egress). |
| agent/xds/listeners_dns_test.go | Adds unit tests for DNS domain table generation and both DNS listeners. |
| agent/xds/configfetcher/config_fetcher.go | Adds DNSRecursors() to the ConfigFetcher interface. |
| agent/xds/clusters_test.go | Updates a mock config fetcher stub to satisfy the expanded ConfigFetcher interface. |
| agent/agent.go | Adds Agent.DNSRecursors() to provide pre-resolved recursor addresses for xDS. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -7,4 +7,5 @@ package configfetcher | |||
| // for the xDS server to fetch agent config, currently only one field is fetched | |||
| // Auto-assigned and manually-configured virtual IPs for the upstream service. | ||
| // These are Consul-allocated, cluster-unique addresses (e.g. 240.0.0.0/4), so | ||
| // they are safe to advertise regardless of the upstream's partition. This is | ||
| // required for cross-partition upstreams, whose VIPs are otherwise not present | ||
| // on the locally-watched endpoints. | ||
| for _, ip := range chain.AutoVirtualIPs { | ||
| for _, fqdn := range fqdns { | ||
| addEntry(fqdn, ip) | ||
| } | ||
| } | ||
| for _, ip := range chain.ManualVirtualIPs { | ||
| for _, fqdn := range fqdns { | ||
| addEntry(fqdn, ip) | ||
| } | ||
| } |
| // virtualIPsForNodes extracts the unique virtual IP addresses advertised by the | ||
| // given service nodes, matching the same VIP tags used to build tproxy filter chains. | ||
| func virtualIPsForNodes(cfgSnap *proxycfg.ConfigSnapshot, nodes structs.CheckServiceNodes) []string { | ||
| uniqueAddrs := make(map[string]struct{}) | ||
| for _, e := range nodes { |
Go Test Coverage: 64.4%See the workflow run for the full per-package breakdown and downloadable HTML report. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #23698 +/- ##
==========================================
- Coverage 60.36% 59.75% -0.61%
==========================================
Files 613 952 +339
Lines 86073 115124 +29051
==========================================
+ Hits 51956 68790 +16834
- Misses 28884 39946 +11062
- Partials 5233 6388 +1155 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…nsul into mansi_localized_dns
| // Configure the inline virtual DNS listener. When enabled, this builds a | ||
| // dns_filter listener with an inline FQDN->VIP table from catalog data and | ||
| // binds it on 127.0.0.1:8653. It is part of the LDS resources so it is | ||
| // recomputed and re-pushed whenever upstream VIPs change. |
| // virtualDNSListenerAddr is the loopback address the inline DNS listener binds to. | ||
| virtualDNSListenerAddr = "127.0.0.1" | ||
|
|
||
| // virtualDNSListenerPort is the UDP port the inline DNS listener binds to. | ||
| // Envoy resolves virtual service FQDNs locally from the inline table. | ||
| virtualDNSListenerPort = 8653 |
| dc := uid.Datacenter | ||
| if dc == "" { | ||
| dc = cfgSnap.Datacenter | ||
| } | ||
|
|
| // Configure the inline virtual DNS listener. When enabled, this builds a | ||
| // dns_filter listener with an inline FQDN->VIP table from catalog data and | ||
| // binds it on 127.0.0.1:8653. It is part of the LDS resources so it is | ||
| // recomputed and re-pushed whenever upstream VIPs change. | ||
| dnsListener, err := s.makeInlineDNSListener(cfgSnap) |
| if s.CfgFetcher != nil { | ||
| dnsRecursors = s.CfgFetcher.DNSRecursors() | ||
| } | ||
| if len(dnsRecursors) > 0 { |
There was a problem hiding this comment.
creating egress listener only if recursors are configures in consul server
Description
This PR extends the xDS listener generation for Connect proxies to include UDP DNS listeners backed by Envoy’s dns_filter, enabling (1) inline resolution of Consul virtual service names to VIPs and (2) optional forwarding to configured upstream DNS recursors.
Add an inline “virtual DNS” UDP listener (127.0.0.1:8653) that serves an in-memory FQDN→VIP table derived from the proxy snapshot.
-Included FQDNs(suppose for service A):
Explicit upstreams — services A is directly configured to reach.
Implicit/intention-allowed upstreams — in transparent proxy mode, services A is permitted to reach via intentions (discovered through discovery chains).
Peer upstreams — services A reaches through a cluster peering connection (their VIPs come from the peer's endpoints).
For each of those, the VIPs added are:
The service's own auto-assigned and manually-configured VIPs — but only if the service is in A's own partition.
The VIP of the upstream service itself (the discovery chain's primary target), not the addresses of other targets in its chain.
Excluded (skipped):
Cross-partition services' configured auto/manual VIPs — A's tproxy won't intercept those.
Stale/unauthorized discovery chains — e.g. a chain lingering after an intention was removed, or pulled in by a wildcard watch but not actually an upstream (GetUpstream returns skip=true).
Any entry with an empty FQDN or a non-IP address.
The guiding rule: the DNS table advertises a VIP only if A's transparent-proxy listener has a filter chain that will actually intercept traffic to that VIP — so DNS and interception always stay in sync.
Add an optional “egress DNS” UDP listener (127.0.0.1:8654) that forwards queries to agent-configured DNS recursors via c-ares when recursors are present.
Extend the xDS ConfigFetcher interface (and agent implementation) to expose DNS recursors;
It is assumed that port 8654 and 8653 are not occupied
Testing & Reproduction steps
Links
PR Checklist
PCI review checklist
I have documented a clear reason for, and description of, the change I am making.
If applicable, I've documented a plan to revert these changes if they require more than reverting the pull request.
If applicable, I've documented the impact of any changes to security controls.
Examples of changes to security controls include using new access control methods, adding or removing logging pipelines, etc.