"QUIC makes network monitoring harder, not easier. That is not a side effect; in some deployment contexts it is a feature. For defenders, it is a challenge." -- IETF QUIC Working Group, RFC 9000 Security Considerations
Lecture (90 min)
9.1 QUIC Protocol Mechanics
QUIC (RFC 9000, 2021) is a multiplexed, secure transport protocol that runs over UDP and provides the reliability, ordering, and congestion control properties that TCP provides -- but with integrated TLS 1.3 and several architectural improvements over TCP+TLS.
Why QUIC exists: Three TCP-era problems drove its design.
| Problem | TCP+TLS behavior | QUIC solution |
|---|---|---|
| Head-of-line blocking | A lost packet in any TCP stream stalls all HTTP/2 streams sharing the connection | QUIC streams are independent; a lost packet in stream 3 does not stall stream 5 |
| Connection establishment latency | TCP 3-way handshake + TLS 1.2 handshake = 3 RTT minimum; TLS 1.3 = 2 RTT | QUIC 1-RTT for new connections; 0-RTT for session resumption |
| Connection migration | TCP connections are identified by 4-tuple (src IP, src port, dst IP, dst port); changing IP breaks the connection | QUIC uses Connection IDs; a UE moving from WiFi to cellular keeps the QUIC connection alive |
QUIC packet number spaces and encryption levels:
Every QUIC packet is encrypted. There are four encryption levels:
- Initial packets -- encrypted with keys derived from the destination Connection ID (known standard; eavesdropper can decrypt Initial packets with the published derivation)
- 0-RTT packets -- encrypted with keys from a previous session (session resumption without a full handshake; replay attack surface)
- Handshake packets -- encrypted with keys from the TLS 1.3 Handshake
- 1-RTT packets -- encrypted with keys from the completed TLS 1.3 handshake (application data)
For NSM purposes: Initial packets are decodable (Wireshark does this automatically). Everything above Initial requires the session keys, which are ephemeral TLS 1.3 keys.
Connection establishment (1-RTT):
Client Server
| |
|-- Initial (CRYPTO: ClientHello) -->|
|<- Initial (CRYPTO: ServerHello) --|
|<- Handshake (CRYPTO: Cert+Fin) --|
|-- Handshake (CRYPTO: ClientFin) -->|
|-- 1-RTT (application data)-------->|
|<- 1-RTT (application data)---------|
Total: 1 RTT for application data to begin flowing (vs. 2 RTT for TCP + TLS 1.3).
9.2 HTTP/3 over QUIC
HTTP/3 (RFC 9114) runs over QUIC streams. Each HTTP request/response pair occupies a dedicated QUIC stream. The elimination of head-of-line blocking at the transport layer makes HTTP/3's stream multiplexing genuinely parallel, unlike HTTP/2's multiplexing over a single TCP connection.
QPACK header compression (RFC 9204): HTTP/3's header compression scheme. HTTP/2 uses HPACK, which maintains a shared dynamic table between client and server -- vulnerable to CRIME/BEAST-style attacks and tied to single-connection sequencing. QPACK uses separate encoder/decoder streams to avoid HOL blocking in the dynamic table updates.
NSM impact of HTTP/3:
- HTTP/3 uses UDP port 443 (QUIC Alt-Svc advertisement in HTTP/2 responses routes clients to HTTP/3)
- QUIC's encrypted headers hide the HTTP method, URL, and response code from passive inspection
- The TLS SNI in the Initial CRYPTO ClientHello is visible in plaintext (until Encrypted ClientHello / ECH is deployed)
- No
http.login Zeek for HTTP/3 traffic -- onlyssl.logandconn.logentries
9.3 MASQUE and QUIC as a Tunneling Substrate
MASQUE (RFC 9297, 2022) uses HTTP/3 CONNECT method extended with the connect-udp and connect-ip upgrade tokens to proxy arbitrary UDP or IP datagrams over an HTTP/3 session. This makes QUIC/HTTP3 a VPN substrate that:
- Looks like normal HTTPS traffic to a firewall (destination port 443)
- Carries arbitrary UDP datagrams or IP packets inside
- Encrypts all metadata above the TLS SNI level
C2 implications: Red teams have adopted QUIC/MASQUE for command-and-control because:
- QUIC port 443 passes through most enterprise egress policies
- The TLS SNI can point to a legitimate CDN that fronts the C2 server
- Connection migration makes source IP attribution harder
- Zeek and Suricata lose their Layer-7 visibility
9.4 Detection Challenges: The NSM Visibility Gap
Mapping the visibility loss vs. TCP+TLS:
| NSM field | TCP + TLS 1.2 | QUIC + TLS 1.3 |
|---|---|---|
| TLS SNI (server name) | Visible in ClientHello | Visible in QUIC Initial CRYPTO (until ECH deployed) |
| JA3 fingerprint | Available from TLS ClientHello cipher list | Partial -- QUIC transport parameters interact with TLS; JA3 for QUIC is non-standard |
| HTTP method (GET/POST) | Visible (unencrypted in HTTP/1.1; exposed via HPACK tables in HTTP/2) | Not visible -- HTTP/3 is encrypted end-to-end |
| HTTP URL path | Visible in HTTP/1.1; mostly visible in HTTP/2 | Not visible |
| Response code | Visible | Not visible |
| X-Forwarded-For header | Visible in proxy scenarios | Not visible |
| Connection duration | Available via conn.log |
Available via conn.log |
| Byte counts | Available | Available |
What detection remains:
- Zeek dpd.log: Zeek's Dynamic Protocol Detection identifies QUIC by protocol signature on UDP/443. Zeek logs
quicas the service inconn.log. - Suricata
quickeyword (Suricata 7+): detects QUIC Initial packets; can match on the QUIC SNI extracted from the Initial CRYPTO frame. - Flow-level metadata: connection duration, byte totals, packet counts remain available. Beaconing detection via RITA still works on QUIC flows.
- JA3 for QUIC (emerging): browser-specific TLS parameter fingerprints are partially preserved in QUIC Initial CRYPTO frames. Not as reliable as TCP JA3.
Example Suricata rule for QUIC SNI detection:
alert quic any any -> any any (
msg:"NET-301 QUIC C2 SNI indicator";
quic.sni; content:"suspicious-domain.com";
classtype:command-and-control;
sid:9000001; rev:1;
)
Example Zeek QUIC identification:
# QUIC connections appear in conn.log with service=quic
zeek-cut id.orig_h id.orig_p id.resp_h id.resp_p service proto < conn.log \
| awk '$6 == "quic"' | head -20
9.5 Defensive Options and Documentation
Option 1: TLS 1.3 downgrade for internal traffic. Internal east-west traffic (within a datacenter or VPN perimeter) can be forced to TLS 1.2 or TLS 1.3 over TCP via policy. This preserves JA3 fingerprinting and HTTP-level logging for internal flows. Not applicable to egress internet traffic.
Option 2: Explicit QUIC blocking at the egress. Some organizations block UDP/443 at the perimeter firewall, forcing all HTTPS traffic to TCP/443. This recovers full Zeek/Suricata visibility for egress flows. Cost: legitimate HTTP/3 performance benefits are lost; some applications may experience degraded performance.
Option 3: Decrypt-and-inspect via TLS inspection proxy. A TLS/QUIC-aware decryption proxy can terminate QUIC connections and forward decrypted HTTP/3 to the backend. Cost: requires deploying an enterprise proxy that speaks QUIC (as of 2026, supported by major vendors including Palo Alto, Zscaler, Cisco Secure); certificate transparency considerations apply.
Option 4: Coverage-gap documentation. Accept the visibility gap and document it formally in the NSM policy. This is the correct answer for organizations that cannot deploy QUIC inspection: document what cannot be detected, design compensating controls (flow analysis, DNS monitoring, endpoint telemetry), and review quarterly as QUIC detection tooling matures.
Architecture Comparison Sidebar: TCP+TLS vs. QUIC+TLS — NSM Visibility Matrix
| Property | TCP + TLS 1.2 | TCP + TLS 1.3 | QUIC + TLS 1.3 |
|---|---|---|---|
| TLS SNI | Plaintext | Plaintext (until ECH) | Plaintext in Initial (until ECH) |
| JA3/JA3S | Full | Full | Partial/experimental |
| HTTP method | Visible (HTTP/1.1) | Visible (HTTP/1.1) | Not visible (HTTP/3) |
| HTTP response code | Visible | Visible | Not visible |
| Session resumption detection | Visible (Session Ticket) | Visible (Session Ticket) | Partially (0-RTT indicator) |
| Connection migration tracking | N/A (4-tuple fixed) | N/A | Connection ID required |
Zeek ssl.log |
Full | Full | Partial (Initial frame only) |
Zeek http.log |
Full (HTTP/1.1/2) | Full | None |
| Suricata content match | Full | Full | Initial frame content only |
| Flow metadata | Full | Full | Full |
Design evolution framing: TCP+TLS was designed for a world where network operators had strong incentives to inspect traffic (enterprise security, CDN optimization, content filtering). QUIC was designed for a world where end-to-end encryption is the default and network operator visibility is explicitly deprioritized. The NSM community is adapting to a deployment reality where the assumption "I can see Layer-7 metadata on my own network" is progressively less true.
Reflection Prompts
- An organization blocks UDP/443 at its perimeter to preserve Zeek/Suricata HTTP-level visibility. What is the operational cost of this policy? Name two classes of applications that would degrade in performance and explain why.
- QUIC's 0-RTT session resumption reduces connection latency but introduces a replay attack surface. What conditions must an attacker meet to exploit 0-RTT replay? What does the QUIC specification say about what servers are permitted to do with 0-RTT data?
- The JA3 fingerprinting technique for QUIC is described as "partial/experimental" in the NSM visibility matrix. What specific information does JA3 for TCP extract from the TLS ClientHello, and which of those fields is or is not preserved in a QUIC Initial packet?