This commit adds a new --block option to the server example to
illustate in a simplified way the general structure one would use to
implement IP address blocking with the new accept/reject/retry API.
For example:
cargo run --example server ./ --listen 127.0.0.1:4433 --stateless-retry --block 127.0.0.1:8065
cargo run --example client https://127.0.0.1:4433/Cargo.toml --host localhost --bind 127.0.0.1:8065
One thing to note is that that example places the reject condition
before the retry condition. This expends slightly less effort rejecting
connections, but does create a blocked IP address oracle for an attacker
who can do address spoofing.
This commit removes use_retry from the server config and provides a
public API for the user to manually accept/reject/retry incoming
connections before a handshake begins, and inspect properties such as
an incoming connection's remote address and whether that address is
validated when doing so.
In quinn-proto, Incoming is made public, as well as Endpoint's accept/
reject/retry methods which operate on it. The
DatagramEvent::NewConnection event is modified to return an incoming
but not yet accepted connection.
In quinn, awaiting Endpoint::accept now yields a new
quinn::Incoming type, rather than quinn::Connecting. The new
quinn::Incoming type has all the methods its quinn_proto equivalent has,
as well as an accept method to (fallibly) transition it into a
Connecting, and also reject, retry, and ignore methods.
Furthermore, quinn::Incoming implements IntoFuture with the output type
Result<Connection, ConnectionError>>, which is the same as the Future
output type of Connecting. This lets server code which was
straightforwardly awaiting the result of quinn::Endpoint::accept work
with little to no modification.
The test accept_after_close was removed because the functionality it
was testing for no longer exists.
This commit refactors the logic for a quinn_proto::Endpoint accepting
an incoming connection so that it constructs an explicit Incoming struct
containing all the necessary state to accept/reject/retry the
connection-creating packet. However, the external API stays the same.
The bulk of this code change is just moving around existing code.
Additionally, adds some gitignore lines I was using for coverage
testing.
This commit factors out the two fields of a quinn::Endpoint's State
necessary to process a proto::Transmit into a new sub-struct,
TransmitState. This is to alleviate borrowing issues, because
proto::Transmit will soon be called from more call sites than
previously.
The bulk of this code change is just moving around existing code.
This commit factors out the connection limit check from
quinn_proto::Endpoint::early_validate_first_packet to a new method. This
commit also adds a new ConnectionLimitExceeded variant to
ConnectionError, although it is not yet instantiated. These changes are
made because this exception case will soon be possible to encounter at
more points than previously.
PacketBuilder::max_size previously subtracted out the start index and
header size of the packet, and therefore described the admissible size
of the packet's frames. However, most of our logic operates in terms
of absolute buffer positions instead. This was confusing, and led to
erroneous double-counting of space use in close packets.
Currently, when trying to run the client example with an IPV6 address
URL, such as by running:
cargo run --example client https://[::1]:4433/Cargo.toml --host localhost
A "failed to lookup address information: Name or service not known"
error is raised. This is because `url.host_str()` is `"[::1]"`, which
is wrapped in brackets. These brackets, specified by by RFC 2732, are
part of the URL syntax, not the IP address syntax.
Although this code succeeds, because the standard library treats this
like a URL:
use std::net::ToSocketAddrs;
"[::1]:4433".to_socket_addrs()
This code does not:
use std::net::Ipv6Addr;
"[::1]".parse::<Ipv6Addr>()
As the stdlib expects to just receive "::1". Consequentially, this
does not succeed, counterintuitively:
use std::net::ToSocketAddrs;
("[::1]", 4433).to_socket_addrs()
This code fixes the client example's URL parsing behavior by
stripping out such brackets in the same way as [is done in
tokio-tungstenite][1].
[1]: https://github.com/snapview/tokio-tungstenite/blob/052d085aff4708b924b92becaa83923b15045841/src/lib.rs#L404