Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 protocol: new feature auto-detect proxy protocol #18951
proxy protocol: new feature auto-detect proxy protocol #18951
Changes from 16 commits
278ce7e
121e87d
2d43ae3
de6b7f2
3a36695
409f94c
ae19e1f
ed4fb54
bcc7aef
8c87bcd
4aa520e
91c9a1b
c45ecc7
4259f1a
2b4a89a
f105c3d
6a0d49b
f47232f
fa9746a
a37ad43
6f19883
0927000
b5cbfc1
a7ef68f
9495853
ffb56d1
ac2982f
2a66a01
c9e086f
af6f88d
7f17660
59206da
b416242
4e4638a
354a365
86ad288
899f199
887d0bc
a23ac5f
6075b67
4d6f75f
2cb4526
1667461
a0c977f
85706e6
c86edef
6031151
a09bb1b
cfeda5a
5a660a0
e92a8a4
84cdc32
f3d65e9
b2d467e
45e9c24
056f74f
39e7b50
392124e
307df1c
5c50e23
36bbfa2
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
In the doc comment a couple lines up, it references version 2.1's copy of the doc. Please use the same url as that one (or update both of them), so the user isn't left wondering if there's a significant difference between the two links.
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.
addressed in fa9746a
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.
Please add a link to the new config setting.
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.
addressed in 392124e
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.
I don't think this handles the case where there is no PROXY header, but the number of bytes read is larger than
PROXY_PROTO_V2_HEADER_LEN
, eg the filter reads an entire HTTP/1 request header.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.
good catch, thanks! addressed in fa9746a
i went ahead and wrote a test that failed (the new one), then removed the faulty logic. now there are two tests (for small and large requests that get passed through the filter) that hit the exact same code path. happy to remove either one, what do you think?
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.
Please leave both tests in
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.
Although it is rare case, there still have the chance of receiving the partial v1 signature, like just a 'P' char, the left of the signature received by the second
recv
call. But this check will just skip the left of signature checking.we could return
SkipFilterError
at https://github.com/envoyproxy/envoy/pull/18951/files#diff-a35fc10b1ce97239d02ac1791aac05069eaf253d8efc77cefe93749f901e36abL446Then it will got all the data, and compared the signature of v1 and v2.
But if we only receive very short data from the client (short than both v1 and v2 signature), then I feel we only can waiting for a timeout of listener filter. But that is bad for the usecase of issue.
Another idea is if the
nread
is less than v1 and v2 signature, then we compare part of signature, like if the first byte isX', then compare to the first byte of v1 signature, it is
P`. Also compare the first byte of v2 signature, then we know it can't be the proxy protocol.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.
@soulxu can you update the link from
to a link to main / a commit and where you're proposing this change? I think with the recent commits to this PR that the link provided is dated, I'm not sure where you're proposing we return the error
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.
also related #18951 (comment)
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.
it should be
((nread < PROXY_PROTO_V2_SIGNATURE_LEN || memcmp(buf_, PROXY_PROTO_V2_SIGNATURE, nread)) && memcmp(buf_, PROXY_PROTO_V1_SIGNATURE, nread))
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.
this is actually fine as is. the first if statement in this block ensures that by the time we get here we know
nread
>=PROXY_PROTO_V1_SIGNATURE_LEN
. then in this if statement thenread < PROXY_PROTO_V2_SIGNATURE_LEN
case short-circuits if needed, so in the secondmemcmp
we knownread
>=PROXY_PROTO_V2_SIGNATURE_LEN
. in short, we knownread
is >= both signature lengths before we domemcmp
with the signature, and we want to check at most the signature lengthif it helps with readability I'm happy to add
std::min
onnread
and the signature lengths, but I do not think there is a logic error hereThere 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.
sorry, you are right.
I was based on the logic we want to exam more bytes.
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.
const
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.
Why did you rename
TryAgainLater
?I think
SkipFilterError
should be renamed toSkipFilter
. It isn't an error.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.
addressed in fa9746a
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.
Also worth testing a case that we have correct v1 or v2 header signature, but invalid data in the rest of header, then ensure we disconnect the connection, and not let the connection passthrough.
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.
addressed in 6031151
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.
nit, useless space line
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.
addressed in 1667461
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.
We should test the case of the first write is not full v1 protocol signature, like just one char 'P'
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.
Addressed in 6a0d49b
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.
I'm actually not sure this is possible simultaneously with the fragmented/partial protocol without the possibility for false positive, e.g.
this is why in the initial implementation I required that the initial read from
recv
have enough bytes available on the initialMSG_PEEK
to make the determination on the v1/v2 proxy header.We can leave the PR as it is (or perhaps preferably throw a hard error if we consumed some bytes and then realize we had a false positive?) with the understanding that there could be false positives on identifying proxy protocol, additionally with the understanding that this is quite rare and will not likely happen in practice (except perhaps for single byte reads of
P
and HTTP POST/PUT request?). In exchange, we get support for fragmented/partial reads. Thoughts?Also willing to go back to my original version (before 6a0d49b which addresses the initial concern with partial reads) which addresses the potential false positive here
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.
I'm not following. How would the filter consume the
P
only?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.
Running the test above, we do
recv
withMSG_PEEK
and just getP
here.Then before we continue the loop, we read that byte for real (no
MSG_PEEK
) here. Thus when we do our secondrecv
and we getBOGUS
we have already consumedP
. We correctly identify that the request is not proxy protocol, but the request forwarded upstream has a missing byte(s) (in this case, justP
).The only way I see to avoid false positives identifying the header and always send the correct response up the filter chain is to require that the initial
MSG_PEEK
has enough bytes to detect v1/v2 header (at most 16, which seems reasonable for this opt-in only codepath)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.
Oh, I see.
I think you need to fix this case. You may have to restructure the code such that no bytes are read (without MSG_PEEK) until we've decided 100% whether this is a proxy header or not.
I think it's probably good enough to look for either
PROXY_PROTO_V1_SIGNATURE
orPROXY_PROTO_V2_SIGNATURE
. If the connections starts with either of those, but then doesn't have a valid full proxy protocol header, abort the connection as we currently do. If the connection starts with bytes that match neither of those signatures, and the new option is enabled, don'tread()
any bytes and continue the filter chain. Will that work?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.
I think it will work. Implemented in 6f19883 and 0927000