From: Yeonggi Kim <[email protected]>

Hi Amaury, Frederic,

Following your comment on github issue #3503, here is a series which
sets the source address of the three packets emitted without connection
(Retry, stateless reset and Version Negotiation), as qc_snd_buf()
already does for connections using the listener socket. As you
suggested, each send function gets an extra source address parameter
next to the destination one, and each one is fixed in its own patch.

  1/5 MINOR: prerequisite, adds quic_sock_sendto(), a sendto()-like
      function with an optional source address relying on the existing
      cmsg_set_saddr(), and two inline helpers. The wildcard-only rule
      of qc_may_use_saddr() (EINVAL on FreeBSD for a specific bind) is
      moved into one of them so that it is shared.
  2/5 BUG/MEDIUM: Retry
  3/5 BUG/MINOR: stateless reset
  4/5 BUG/MINOR: Version Negotiation
  5/5 REGTESTS: new reg-tests/quic/retry_wildcard.vtc

Testing was done on Linux (Debian 13, OpenSSL 3.5.7, aarch64) :

  - retry_wildcard.vtc: a QUIC backend connects to 127.0.0.2 on a server
    bound on 0.0.0.0 with quic-force-retry. It fails on current master
    (Retry sent from 127.0.0.1 and dropped by the connected backend
    socket, confirmed with a capture), and passes with the series. The
    same test targeting 127.0.0.1 passes on master. It is limited to
    Linux, where all of 127.0.0.0/8 is local, and I checked that it is
    skipped on an osx build.

  - stateless reset and Version Negotiation cannot be triggered from
    vtest, so they were checked manually in network namespaces with the
    VIPs on the server loopback and the client routing them through a
    veth, which is the IPVS direct routing layout where we first hit the
    issue. One datagram per packet type (Initial without token, unknown
    version, short header with an unknown DCID), checking the source of
    the reply, on [email protected], [email protected] with sock-per-conn
    force-off, quic6@:::443 and quic6@:::443 v4v6. On master all replies
    come from the route source address. Each patch fixes exactly its own
    packet type, and all replies come from the VIP after the series. A
    specific bind (quic4@<VIP>:443) is unchanged. With quic-force-retry
    on the wildcard bind, a client with a connected socket (emulated
    with aioquic and a firewall rule) cannot complete the handshake on
    master, and completes it with the series.

  - reg-tests/quic and reg-tests/qmux: 30/30 on master, 31/31 with the
    series. Each commit builds with ERR=1 and USE_QUIC=1. The whole
    series also builds with USE_QUIC_OPENSSL_COMPAT, without QUIC, and
    on macOS.

FreeBSD was not tested. The source address is only set when the listener
is bound on a wildcard address, which is the same rule as the one used
by qc_snd_buf() since 1c33756f78.

Regards,
Yeonggi Kim

Yeonggi Kim (5):
  MINOR: quic: define a function to emit a datagram without connection
  BUG/MEDIUM: quic: use datagram destination as source for Retry
  BUG/MINOR: quic: use datagram destination as source for stateless
    reset
  BUG/MINOR: quic: use datagram destination as source for version
    negotiation
  REGTESTS: quic: check Retry source address on a wildcard listener

 include/haproxy/quic_sock.h       | 30 +++++++++++++
 include/haproxy/quic_tx.h         |  3 ++
 reg-tests/quic/retry_wildcard.vtc | 75 +++++++++++++++++++++++++++++++
 src/quic_rx.c                     | 17 +++++--
 src/quic_sock.c                   | 64 +++++++++++++++++++++++---
 src/quic_tx.c                     | 28 +++++++-----
 6 files changed, 195 insertions(+), 22 deletions(-)
 create mode 100644 reg-tests/quic/retry_wildcard.vtc


base-commit: 04456142e3ed1d8b5a7d3d39861ee6529458fca7
-- 
2.50.1 (Apple Git-155)



Reply via email to