Skip to content

proxyproto: add UDP session tracking for Cloudflare Spectrum PPv2#7967

Merged
yongtang merged 1 commit into
coredns:masterfrom
hunts:proxyproto-udp-session-tracking
Mar 28, 2026
Merged

proxyproto: add UDP session tracking for Cloudflare Spectrum PPv2#7967
yongtang merged 1 commit into
coredns:masterfrom
hunts:proxyproto-udp-session-tracking

Conversation

@hunts

@hunts hunts commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

1. Why is this pull request needed and what does it do?

Cloudflare Spectrum's PROXY Protocol v2 for UDP sends the PPv2 header only in the first datagram. Subsequent datagrams from the same client arrive without any header. The existing PacketConn in plugin/pkg/proxyproto processes each UDP packet independently with no session state, so it never associates the real client IP with subsequent packets. This means plugins like whoami report the Spectrum proxy address rather than the actual client address for UDP queries.

This PR adds opt-in UDP session tracking to PacketConn: when a header-only datagram arrives, the parsed source address is cached keyed by the proxy-side remote address in a fixed-capacity expirable LRU (github.com/hashicorp/golang-lru/v2/expirable, default 10,240 entries). Subsequent headerless datagrams from the same remote address are assigned the cached source address until the configurable TTL expires. The TTL is refreshed on every matching packet.

The feature is enabled via a new Corefile directive:

proxyproto {
    udp_session_tracking <ttl> [max_sessions]
}

For example, udp_session_tracking 28s uses a 28-second TTL matching Spectrum's 30-second UDP idle timeout with headroom.

TCP is unaffected — proxyproto.Listener already handles TCP correctly since the header is at the start of the stream.

2. Which issues (if any) are related?

Client IPs are lost for UDP DNS queries behind Spectrum after start using proxyproto plugin via CoreDNS 1.14.2.

3. Which documentation changes (if any) need to be made?

plugin/proxyproto/README.md has been updated in this PR to document the new udp_session_tracking directive, its parameters, and usage examples.

4. Does this introduce a backward incompatible change or deprecation?

No. The feature is entirely opt-in. When udp_session_tracking is absent from the Corefile, behavior is identical to before. No existing fields, methods, or directive syntax have been changed or removed.

Cloudflare Spectrum's PROXY Protocol v2 for UDP sends the PPv2 header only
in first datagram. Subsequent datagrams from the same client arrive without
any header. The existing `PacketConn` processes each packet independently
with no session state, so it never associates the real client IP with
subsequent packets.

Add opt-in UDP session tracking to `PacketConn`: when a header-only datagram
arrives, cache the parsed source address keyed by the Spectrum-side remote
address in a fixed-capacity expirable LRU (hashicorp/golang-lru/v2/expirable,
default 10,240 entries). Subsequent headerless datagrams from the same
remote address are assigned the cached source address until the configurable
TTL expires. The TTL is refreshed on every matching packet.

The feature is enabled via a new Corefile directive:

```
    proxyproto {
        udp_session_tracking <ttl> [max_sessions]
    }
```

For example, `udp_session_tracking 28s` uses a 28-second TTL matching
Spectrum's 30-second UDP idle timeout with headroom.

Signed-off-by: Minghang Chen <chen@minghang.dev>
@hunts hunts force-pushed the proxyproto-udp-session-tracking branch from 21bbc42 to f0f11b7 Compare March 24, 2026 22:35
@yongtang yongtang merged commit 34acf83 into coredns:master Mar 28, 2026
11 checks passed
@hunts hunts deleted the proxyproto-udp-session-tracking branch April 7, 2026 03:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants