Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Setting Up HTTP/3 with Caddy Server

Tech Aug 20 17

Prerequisites

HTTP/3 operates over QUIC (UDP-based) instead of TCP, making the setup more demanding than HTTP/2.

HTPS Certificate

HTTP/3 requires a valid security certificate. Unlike HTTP/2, insecure certificates will not work at all.

Install mkcert for local development:

winget install mkcert

Initialize the local certificate authority:

mkcert -install

Generate a certificate for localhost:

mkcert localhost 127.0.0.1 ::1

Configure Caddyfile:

tls ./localhost+2.pem ./localhost+2-key.pem

Alt-Svc Header

The server must announce the UDP port via the Alt-Svc response header:

header Alt-Svc `h3=":8443"; ma=2592000, h3-29=":8443"; ma=2592000`

UDP Port Accesibility

Caddy may open only IPv6 UDP ports by default. Verify open UDP endpoints using PowerShell:

Get-NetUDPEndpoint | Select-Object LocalAddress, LocalPort, OwningProcess

Filter by specific port:

PS D:\www> Get-NetUDPEndpoint -LocalPort 8443 | Select-Object LocalAddress, LocalPort, OwningProcess

LocalAddress LocalPort OwningProcess
------------ --------- -------------
::                8443         81976

Browser Configuration

Chrome requires explicit flags to enable HTTP/3. Launch Chrome with QUIC forcing enabled:

& "C:\Users\32956\AppData\Local\Google\Chrome\Application\chrome.exe" `
    --user-data-dir="$env:TEMP\chrome_h3_test" `
    --origin-to-force-quic-on=127.0.0.1:8443 `
    --force-quic `
    --ignore-certificate-errors `
    "https://127.0.0.1:8443/image-hosts"

If HTTP/3 fails, the browser will not fallback to HTTP/2.

Testing HTTP/3 Connectivity

Use the aioquic library to verify QUIC handshake:

# /// script
# dependencies = ["aioquic"]
# ///
import asyncio
from aioquic.quic.configuration import QuicConfiguration
from aioquic.asyncio import connect

async def test_quic_connection():
    config = QuicConfiguration(is_client=True, alpn_protocols=["h3"])
    config.verify_mode = 0
    
    try:
        async with connect("127.0.0.1", 8443, configuration=config) as client:
            print("QUIC handshake successful - HTTP/3 is working")
    except Exception as err:
        print(f"Connection failed: {err}")

if __name__ == "__main__":
    asyncio.run(test_quic_connection())

Protocol Compatibility

Protocol Transport Requirements
HTTP/1.1 TCP Minimal
HTTP/2 TCP HTTPS recommended
HTTP/3 UDP Valid certificate + Alt-Svc header

HTTP/3 has the strictest requirements among all HTTP verisons.

Network Considerations

When using reverse proxy services or tunnel forwarding, separate tunnels are needed for TCP and UDP traffic. This adds complexity to the configuration compared to traditional HTTP setups.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.