Open nibanks opened 5 years ago
I would suggest the following:
serverId = packet.destCid.ExtractServerId()
if (serverId is not in pool) || (cid is too short to extract) {
if (pkt.isInitial() || pkt.is0RTT()) {
serverId = hash(key, packet.destCid)
} else {
drop
}
This design also cleanly handles Initial DCIDs that came from RETRY.
I agree it would be nice to explain what LBs should do about this. Section 3 is not very good: ... The load balancer SHOULD route Initial and 0-RTT packets from the client using an alternate algorithm. Note that the SCID in these packets may not be long enough to represent all the routing bits. This algorithm SHOULD generate consistent results for Initial and 0RTT packets that arrive with the same source and destination connection ID. The load balancer algorithms below apply to all incoming Handshake and 1-RTT packets. ...
Actually, after discussing with the WG, I'd prefer:
int serverId;
if (packet.IsLongHeader()) {
serverId = hash(key, packet.tuple + packet.srcCid)
} else {
serverId = packet.destCid.ExtractServerId()
}
@nibanks You mean the following, right?
if (packet.IsLongHeader()) {
Yes. You are correct. Very important distinction! Thanks for catching that. I will update that comment.
You may want to be more tricky than serverId = hash(key, packet.tuple + packet.srcCid)
. I am not sure what you mean by packet.tuple
, but even if it is a 4-tuple, an attacker sitting on an IPv6 address foo::/96 can generate MANY srcCids that hash to the same host.
Maybe you want something like serverId = hash(key, hash(key, packet.tuple) + packet.srcCid)
or, if your key can be arbitrary, serverId = hash(key+packet.tuple, packet.srcCid)
I've been looking at load balancing more lately and specifically trying to figure out an algorithm to use to statelessly load balance new connections that doesn't expose any type of attack surface.
The closest thing I've come up with is something like this:
ExtractServerId
will rely on whatever encoding scheme was chosen and get the server ID from that.My problem with the above pseudocode is post initial Initial packets. The first Initial packet will use the client chosen CID, but after that it uses the server CID. That change in CID will break the above logic. Because of this, I've actually been considering opening a transport issue recommending all Initial packets use the client CID.
Is there another way to achieve this goal? And how much of this kind of stuff should be included in the QUIC-LB spec?
P.S. How would unknown (experimental?) version numbers factor into the above pseudocode? Just go to the
else
?