Conversation
A proxy can refuse a CONNECT tunnel with a keep-alive response, such as a 407 with a Content-Length body. Connection records the failed tunnel and the client skips sending the request, but the connection stayed keep-alive, so a persistent client reused it. The flag is never cleared, so the next request skipped sending again and returned a response read from the same socket without contacting the proxy: the old refusal if its body was still unread, or a response with status 0 once it had been read, whose body read then blocks until the read timeout. The socket can't carry another request, since the proxy never opened the tunnel. Mark the connection as not keep-alive when CONNECT fails. The client then closes it before the next request, and finish_response closes it once the refusal's body has been read, so every request asks the proxy again on a new connection. AuthProxyServer closes the socket after its 407, so no test kept a refused tunnel open. RefusingProxyServer answers every CONNECT with a keep-alive 407 and counts connections.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
A proxy can refuse a CONNECT tunnel with a keep-alive response, like a 407 with a
Content-Lengthbody. The connection stays marked keep-alive and@failed_proxy_connectis never cleared, so the next request on a persistent client skips sending and reads whatever is left on that socket without contacting the proxy.Local proxy that answers every CONNECT with a keep-alive 407,
HTTP.timeout(3).via(proxy).persistent("https://example.com"), two GETs:"deny"HTTP::TimeoutErrorafter 3 s reading its bodyThe fix is one line in
handle_proxy_connect_response: a refused tunnel sets@keep_alive = false. The client then closes the connection before the next request, andfinish_responsecloses it once the refusal's body is read.AuthProxyServercloses its socket after the 407, so no test kept a refused tunnel open. The newRefusingProxyServerkeeps it open and counts connections. The 3 new tests fail on main.Repro script
ruby -Ilib proxy407_run.rb unreadand... read: