-
Notifications
You must be signed in to change notification settings - Fork 7
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
Proxy-Chosen Virtual Client Connection ID #104
Conversation
As described in ietf-wg-masque#88, loop attacks are possible when clients pick the virtual connection ID. This change moves the responsibility of generating a Virtual Client Connection ID to the proxy and requires the proxy to generate unpredictable virtual connection IDs. Unfortunately, this change complicates the capsule exchange. Specifically, the proxy cannot send forwarded mode packets in the Target->Client direction until it knows that the client is ready to receive them. Previously, when the client chose the vcid, we could require that the client not share the vcid unless it's ready to receive with it. Now that the proxy chooses the client vcid, we need the client to signal it's ready to receive forwarded mode packets. To accomplish this, ACK_CLIENT_VCID is introduced. The ACK_CLIENT_VCID capsule solves the rule-readiness problem and maintains that the client can supply a Stateless Reset Token for resetting the client<->target tunnel.
| ACK_TARGET_CID | 0xffe403 | This Document | | ||
| CLOSE_CLIENT_CID | 0xffe404 | This Document | | ||
| CLOSE_TARGET_CID | 0xffe405 | This Document | | ||
| REGISTER_CLIENT_CID | 0xffe500 | This Document | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for updating the values!
If the virtual client CID is chosen by the proxy, doesn't that mean that the client can no longer multiplex multiple connections on the same socket? |
I don't think so. The difference here is that the client has to create a demultiplexing rule with a value that the proxy chooses as opposed to one it chose itself. And the proxy can't send forwarded mode packets until the client signals that the rule is created. Maybe I'm missing something, can you elaborate? |
In general the mindset of QUIC CIDs is that they're picked by the receiver. That allows among other things the receiver to pick their CID length (a length 1 might be sufficient for a client that's only multiplexing two connections, but a server multiplexing hundreds would want more bytes). If you let someone else pick the CIDs, you could end up with a conflict on the client if it's talking to two proxies and the first proxy picks |
@DavidSchinazi what do you think about 98b876e? |
I like that. We'll probably want to add some implementation considerations that
but in general this should work |
@DavidSchinazi, how does the language added in 4a2dc21 sound? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the latest updates, I think this is good
I have two concerns with this approach:
|
@marten-seemann, to address your second point, one option could be to change this from a SHOULD to a MUST
Your first point is well taken. For what it's worth, this requirement mirrors the requirement for the proxy - it must receive QUIC packets (with CIDs it did not choose) from the target and demultiplex them. As mentioned at 119, I see three options for addressing the loop issue:
While certainly not perfect, I think this option is the best of those three. Do you disagree? Do you see a another alternative? |
This is already a property of the design, before this PR, unless I'm missing something. Proxies are not able to choose the client CID that the target writes into packets, except for an ability to veto ones that collide. There is no ability to propose a routable connection ID for use on the target-facing interface. |
@martinduke, if I'm understanding @marten-seemann correctly, I think he's referring to the fact that, with this change, the client can no longer choose the virtual client connection IDs that it receives with in forwarding mode. I do agree with you that the proxy has never been able to influence the real client connection IDs beyond rejecting collisions - and this PR doesn't change that. |
I agree with your statement of the facts. But my point is that we've already negated the idea of connection-ID based load balancing on the client side. Since QUIC (modulo MPQUIC) doesn't allow changes to server address anyway, this is not much of a problem. |
@marten-seemann, thoughts? |
Sorry for the late response, I'll get back to this later today or tomorrow. |
I spent some more time thinking about this point, and I'm wondering if I'm missing something here. Compared to a simple map lookup, looking up a variable-length CID is way slower. I implemented a prefix trie with (up to) 20 levels, and its performance is terrible. At 100k CIDs, a CID lookup takes up to 40x longer:
In these cases, it would be faster to do a map lookup for all 20 possible CID lengths, until a match is found. Admittedly, this problem exists on the proxy side already, but now we're moving it to the client as well. There are probably faster algorithms than a prefix trie (prefix b-trees), but I'd be curious to learn what kind of data structure people are planning to use for this in practice. |
I'm not sure if this is a nice solution, but an alternative could be using a bloom filter. I described the idea in more detail in #108. |
@marten-seemann, one way of avoiding variable length lookups is to use a minimum client cid size and reject conflicts. Let's say you want to use N-byte CIDs. You would send a REGISTER_CLIENT_CID capsule with your N-byte CID and receive a virtual client connection ID back that's N+M bytes long. For the purposes of connection lookup, just use the first N bytes. If the first N bytes conflicts with some other connection, don't proceed with forwarding mode or send another REGISTER_CLIENT_CID capsule to solicit a new virtual client connection ID. |
Would it be possible to let the client choose between the method initially described in the draft and the mechanism proposed by @ehaydenr ? |
If I'm not mistaken, if the proxy allows the client to choose the connection ID, it is open to the attack that is the reason for this PR. |
I understand the wish to mitigate loop attacks, but at the same time it complicates the connection setup with one additional message. Besides, we can argue that not answering the ACK_CLIENT_ID sent by the proxy can be used as an attack vector if clients coordinate to sent a high number of REGISTER_CLIENT_CID to the same proxy. Letting the client choose whether he wants to let the proxy choose its virtual connection ID would allow to either ease the capsule exchange at connection setup, or fallback in a mode which protects the proxy against loop attacks. |
I would argue the additional message is cheap since it requires no additional round trip.
The proxy can reject the CID registration with the corresponding CLOSE_CLIENT_CID/CLOSE_TARGET_CID capsule. For adding guidance here, I created #109
Are you suggesting we keep the capsule exchange as-is and for deployments that wish to mitigate loop attacks, they simply don't implement forwarding mode? |
@marten-seemann , does my comment about skipping variable length lookups address your concern? |
This makes sense to me. It assumes that there's not too much structure to CIDs issued (e.g. if the proxy's CID allocation strategy would be to use an N byte prefix, this method wouldn't work), but I think that's guaranteed by the fact that CIDs MUST be unlinkable to an on-path observer. |
If you can send the ACK_CLIEN_VCID together with the first bytes of data, then, I agree, you "only" loose the overhead of the ACK message.
Not exactly. I had in mind a mechanism in which the client starts with sending a REGISTER_CLIENT_ID with either a VCCID or not in it (or a bit stating the VCCID is proposed but can be overridden).
|
As described in #88, loop attacks are possible when clients pick the virtual connection ID. This change moves the responsibility of generating a Virtual Client Connection ID to the proxy and requires the proxy to generate unpredictable virtual connection IDs.
Unfortunately, this change complicates the capsule exchange. Specifically, the proxy cannot send forwarded mode packets in the Target->Client direction until it knows that the client is ready to receive them. Previously, when the client chose the vcid, we could require that the client not share the vcid unless it's ready to receive with it. Now that the proxy chooses the client vcid, we need the client to signal it's ready to receive forwarded mode packets. To accomplish this, ACK_CLIENT_VCID is introduced.
The ACK_CLIENT_VCID capsule solves the rule-readiness problem and maintains that the client can supply a Stateless Reset Token for resetting the client<->target tunnel.