Skip to content

Adding robustness checks to the QUIC handshake #2613

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

alizohaib
Copy link

This change allows clients to transmit a variable number of pre-initial packets (default 1).

@alizohaib alizohaib changed the title Adding robustness checking to the QUIC handshake Adding robustness checks to the QUIC handshake May 6, 2025
Copy link
Member

@martinthomson martinthomson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@larseggert, would you mind taking a look at this as well?

I am not sure about this one: it's sending a number of datagrams, not packets. That probably isn't right. And I need to understand what the goals are for this feature.

Added: Also, I'm not seeing tests for this, which is probably why I am unable to make sense of it.

@@ -1142,6 +1153,25 @@ impl Connection {

match (&self.state, self.role) {
(State::Init, Role::Client) => {
// Before starting the client, send some noise
if self.conn_params.pre_init_noise_enabled() && self.pre_initial_pkts > 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be enough to just check the counter. The counter should be zero otherwise.

/// Maximum number of dummy datagrams to send before Client Initial packets.
const MAX_PRE_INIT_PKTS: usize = 1;
/// Payload size range (in bytes) for pre-Initial packets.
const PRE_INIT_PAYLOAD_LEN_RANGE: (usize, usize) = (1200, 1400);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the noise terminology you used; suggest to apply it more consistently, hence the rename here. Check if similar renamings make sense elsewhere?

Suggested change
const PRE_INIT_PAYLOAD_LEN_RANGE: (usize, usize) = (1200, 1400);
const PRE_INIT_NOISE_LEN_RANGE: Range<usize> = (1200, 1400);

Is the 1200-1400 range chosen for any particular reason? If so, might want to add a comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would a smaller payload, e.g. 10 bytes, do as well?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We chose that range to mimic actual Initial packet sizes. A smaller payload could work, but if it is less than the 1200-byte minimum defined in the RFC, it would be trivial to determine whether the first packet is a Client Initial.

@@ -1142,6 +1153,25 @@ impl Connection {

match (&self.state, self.role) {
(State::Init, Role::Client) => {
// Before starting the client, send some noise
if self.conn_params.pre_init_noise_enabled() && self.pre_initial_pkts > 0 {
self.pre_initial_pkts -= 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decrement after the packet was generated? Otherwise you decrement but may not send.

self.pre_initial_pkts -= 1;
if let Some(path) = self.paths.primary() {
let v = random::<1>()[0] as usize;
let len = PRE_INIT_PAYLOAD_LEN_RANGE.0 + (v % (PRE_INIT_PAYLOAD_LEN_RANGE.1 - PRE_INIT_PAYLOAD_LEN_RANGE.0 + 1));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be simplified or at least explained better? Range may have some helper functions you can use.

if let Some(path) = self.paths.primary() {
let v = random::<1>()[0] as usize;
let len = PRE_INIT_PAYLOAD_LEN_RANGE.0 + (v % (PRE_INIT_PAYLOAD_LEN_RANGE.1 - PRE_INIT_PAYLOAD_LEN_RANGE.0 + 1));
let mut dummy_buf: SmallVec<[u8; PRE_INIT_PAYLOAD_LEN_RANGE.1]> = smallvec![0u8; len];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a SmallVec really gaining us anything here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer a Vec unless a benchmark proves that a stack allocation is faster.

@larseggert
Copy link
Collaborator

And I need to understand what the goals are for this feature.

The first comment describing the commit could use some more content, agreed. (I also invited you to a related Signal chat just now.)

Added: Also, I'm not seeing tests for this, which is probably why I am unable to make sense of it.

+1 on needing tests.

Copy link

github-actions bot commented May 6, 2025

Failed Interop Tests

QUIC Interop Runner, client vs. server

neqo-latest as client

neqo-latest as server

All results

Succeeded Interop Tests

QUIC Interop Runner, client vs. server

neqo-latest as client

neqo-latest as server

Unsupported Interop Tests

QUIC Interop Runner, client vs. server

neqo-latest as client

neqo-latest as server

alizohaib and others added 2 commits May 7, 2025 12:37
Co-authored-by: Lars Eggert <lars@eggert.org>
Signed-off-by: Ali Zohaib <alizohaib1995@gmail.com>
Copy link
Collaborator

@larseggert larseggert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could I also ask that you run cargo clippy, cargo fmt and cargo test locally before you push, and fix any issues?

if self.pre_initial_noise_pkts > 0 {
if let Some(path) = self.paths.primary() {
// Choose a random payload size between the noise payload length range.
let span = PRE_INIT_NOISE_LEN_RANGE.end() - PRE_INIT_NOISE_LEN_RANGE.start() + 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let span = PRE_INIT_NOISE_LEN_RANGE.end() - PRE_INIT_NOISE_LEN_RANGE.start() + 1;
let span = PRE_INIT_NOISE_LEN_RANGE.len() + 1;

let v = usize::from(random::<1>()[0]);
let len = PRE_INIT_NOISE_LEN_RANGE.start() + (v % span);

let mut dummy_buf= vec![0u8; len];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let mut dummy_buf= vec![0u8; len];
let mut noise = vec![0u8; len];

// Before starting the client, send some noise
if self.pre_initial_noise_pkts > 0 {
if let Some(path) = self.paths.primary() {
// Choose a random payload size between the noise payload length range.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Choose a random payload size between the noise payload length range.
// Choose a random payload size in the noise payload length range.

@alizohaib
Copy link
Author

Could I also ask that you run cargo clippy, cargo fmt and cargo test locally before you push, and fix any issues?

Yes. Sorry about not doing that earlier.

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.

4 participants