Skip to content

Set the QUIC InitialPacketSize to 1200 bytes#7886

Open
Salynn wants to merge 1 commit into
caddyserver:masterfrom
Salynn:tailscale-h3
Open

Set the QUIC InitialPacketSize to 1200 bytes#7886
Salynn wants to merge 1 commit into
caddyserver:masterfrom
Salynn:tailscale-h3

Conversation

@Salynn

@Salynn Salynn commented Jul 15, 2026

Copy link
Copy Markdown

quic-go defaults the InitialPacketSize to 1280 bytes. This is used for the size of the payload plus UDP header. When quic-go creates its initial handshake packet, it pads it to this size as an optimization for the anti-amplification limit (which does not really apply to Caddy's server connections).

Tailscale uses an MTU of 1280 (the minimum IPv6 MTU) because it is a tunnel operating in unknown environments, possibly inside other tunnels.

When wrapped in an IP header (either v4 or v6), the 1280 byte QUIC packet constructed by quic-go exceeds the Tailscale MTU and gets dropped. This makes it impossible to respond to an HTTP3 connection attempt over Tailscale when using the default InitialPacketSize.

We explicitly set the InitialPacketSize to 1200 (its minimum) to support HTTP3 connections over Tailscale and other low MTU connections.

Once the connection is established, quic-go can perform MTU discovery to increase the packet size to the maximum supported by the connection, so any throughput loss due to the lowered InitialPacketSize is short-lived.

No AI was used in making this PR.

Fixes: #7885

@CLAassistant

CLAassistant commented Jul 15, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@Salynn

Salynn commented Jul 15, 2026

Copy link
Copy Markdown
Author

I did not see any mechanism to test this with the current Caddy test code, but I am open to suggestions for how to write tests for this.
I have applied this patch to my local build of Caddy on both Windows and Linux and it has fixed HTTP3 connections over Tailscale on both.

quic-go defaults the `InitialPacketSize` to 1280 bytes. This is used for
the size of the payload plus UDP header. When quic-go creates its
initial handshake packet, it pads it to this size as an optimization
for the anti-amplification limit (which does not really apply to
Caddy's server connections).

Tailscale uses an MTU of 1280 (the minimum IPv6 MTU) because it is a
tunnel operating in unknown environments, possibly inside other
tunnels.

When wrapped in an IP header (either v4 or v6), the 1280 byte QUIC packet
constructed by quic-go exceeds the Tailscale MTU and gets dropped. This
makes it impossible to respond to an HTTP3 connection attempt over
Tailscale when using the default `InitialPacketSize`.

We explicitly set the `InitialPacketSize` to 1200 (its minimum) to support
HTTP3 connections over Tailscale and other low MTU connections.

Once the connection is established, quic-go can perform MTU discovery to
increase the packet size to the maximum supported by the connection, so
any throughput loss due to the lowered `InitialPacketSize` is
short-lived.
@francislavoie

Copy link
Copy Markdown
Member

FYI @marten-seemann in case you have any opinions on this

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.

HTTP3 does not work over Tailscale

3 participants