Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-16 Thread Micha Lenk
Hi Yann,

Am 09.12.2013 00:30, schrieb Yann Ylavic:
 Now, if trying to send the first bytes of the request immediately fails
 because the socket isn't connected anymore (e.g. EPIPE), you *know* that
 exactly *none* bits of your current request reached the server. For this
 reason it should be safe to retry by establishing a new connection to
 the server and to try to send the request again over the newly
 established connection.
 
 
 The send() will never fail at this point if the peer FIN-closed the
 connection (EPIPE or whatever on non-unixes), since it is only half-closed.
 You can't read anymore, but you still can write, and this is precisely
 why the error log is error *reading* status line and not error
 writing 
 A second send() could fail however, though possibly with ECONNRESET, and
 you are no better here.
 
 The point is that mod_proxy already checks whether the connection is
 alive before trying to send a (successive) request on the kept alive
 connection, by using a recv(MSG_PEEK) (see ap_proxy_is_socket_connected).
 If that fails, a new connection is established and the request is sent
 on it, this is already the current behaviour.
 The race condition is when this check succeeds, but the peer closes the
 connection before the request reaches it (in the meantime).

Okay, got that. If it really works like it should then I don't know how
to improve the code. So the remaining question is, whether the checks
whether the connection is alive are sufficient. Unfortunately I have no
resources to investigate this any further.

Regards,
Micha


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-08 Thread Micha Lenk
Hi all,

Am 05.12.2013 22:03, schrieb Yann Ylavic:
 I'm not talking about retrying requests but retrying writing on the
 socket after trying to re-open a connection. When mod_proxy tries
 to forward the client request to the backends and encounters a
 closed connection due to the described race condition it will fail
 back to the client. Instead, I suggest trying to re-open the
 connection once and then either send the client request over that
 connection or go back to the client with an error. No double-sending
 requests anywhere.
 
 I must be missing something.
 
 When mod_proxy encounters a closed (reused) connection while forwarding
 the client's request, it has just sent the request once, right?

That depends on the actual state. What Thomas is talking about (I know
because I worked with him on the same product he is referring to here)
is the state where you have everything in place to send out the next
request headers on a connection that was established by a previous
request and that was kept open using HTTP Keep-Alive. Let me stress the
fact that in this state you haven't sent a single bit of the current
request over the wire yet.

Now, if trying to send the first bytes of the request immediately fails
because the socket isn't connected anymore (e.g. EPIPE), you *know* that
exactly *none* bits of your current request reached the server. For this
reason it should be safe to retry by establishing a new connection to
the server and to try to send the request again over the newly
established connection. To avoid an endless retry loop, you certainly
should do this retry approach only once per request.

In the sense of getting the reverse proxy request correctly processed by
the backend server, this approach *does* fix the keep-alive race
condition issue where the server closes the backend connection because
it sees no (new) client request for too long time -- IIRC this is what
this discussion started with.

I hope I could shed some more some light on this issue and on the idea
how to possibly tackle it in Apache httpd.

Regards,
Micha


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-08 Thread Yann Ylavic
On Sun, Dec 8, 2013 at 11:51 AM, Micha Lenk mi...@lenk.info wrote:


 Am 05.12.2013 22:03, schrieb Yann Ylavic:
  When mod_proxy encounters a closed (reused) connection while forwarding
  the client's request, it has just sent the request once, right?

 That depends on the actual state. What Thomas is talking about (I know
 because I worked with him on the same product he is referring to here)
 is the state where you have everything in place to send out the next
 request headers on a connection that was established by a previous
 request and that was kept open using HTTP Keep-Alive. Let me stress the
 fact that in this state you haven't sent a single bit of the current
 request over the wire yet.


Yes, here we are.




 Now, if trying to send the first bytes of the request immediately fails
 because the socket isn't connected anymore (e.g. EPIPE), you *know* that
 exactly *none* bits of your current request reached the server. For this
 reason it should be safe to retry by establishing a new connection to
 the server and to try to send the request again over the newly
 
 established connection.


The send() will never fail at this point if the peer FIN-closed the
connection (EPIPE or whatever on non-unixes), since it is only half-closed.
You can't read anymore, but you still can write, and this is precisely why
the error log is error *reading* status line and not error writing 
A second send() could fail however, though possibly with ECONNRESET, and
you are no better here.

The point is that mod_proxy already checks whether the connection is alive
before trying to send a (successive) request on the kept alive connection,
by using a recv(MSG_PEEK) (see ap_proxy_is_socket_connected).
If that fails, a new connection is established and the request is sent on
it, this is already the current behaviour.
The race condition is when this check succeeds, but the peer closes the
connection before the request reaches it (in the meantime).



 In the sense of getting the reverse proxy request correctly processed by
 the backend server, this approach *does* fix the keep-alive race
 condition issue where the server closes the backend connection because
 it sees no (new) client request for too long time -- IIRC this is what
 this discussion started with.


It does *not* fix the race, nothing can, and the proxy can't know whether
its request as been processed by the peer based on the (second) send()
error.

IMHO, the best that can be done is HTTP ping for POST requests (using
Expect: 100-continue, already implemented), retry idempotent requests
(TODO), reduce the race time (my proposal/patch), and let client client
decide for others (proxy-initial-not-pooled can help it).
 


 I hope I could shed some more some light on this issue and on the idea
 how to possibly tackle it in Apache httpd.


Thanks, I really wish it could be, and Thomas prove me wrong!

Regards,
Yann.


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-06 Thread Yann Ylavic
I don't want to overdo this thread (apologies if it is already), last
comment yet...

On Thu, Dec 5, 2013 at 10:03 PM, Yann Ylavic ylavic@gmail.com wrote:

 Is sending a partial request first what you'd like to (be) implement(ed),
 and only if that succeeds send the remaining data?


The issue would still be there for the remaining data since nothing
guarantees the partial (initial) sending has reached the backend, which
might still have closed the connection in the meantime (error reading
status line from remote server is the proof, the failure occurs on the
recv(), not the send()).

Maybe one (other than me) facing the race condition can give my patch a
chance (no more error reading status line... here with TTL  KA-timeout,
pretetch, and slow clients).

No noticeable slow-down either, although statements like this are worthless
without measure...
I plan to do that soon (and keep you informed, for those who still care :)

Regards,
Yann.


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-05 Thread Jan Kaluža

Hi,

should this be fixed in trunk already? I see some commits in proxy code 
based on your ideas Yann, but I'm not sure if they address this 
particular problem too.


Jan Kaluza

On 10/17/2013 04:52 PM, Yann Ylavic wrote:


On Thu, Oct 17, 2013 at 11:36 AM, Thomas Eckert
thomas.r.w.eck...@gmail.com mailto:thomas.r.w.eck...@gmail.com wrote:

  Hence,
why cannot mod_proxy_http prefetch the client's body *before* trying
anything with the backend connection, and only if it's all good,
connect (or reuse a connection to) the
  backend and then start forwarding the data immediatly (flushing
the prefetched ones) ?

Now I'm confused. Are we talking about flushing everything
immediately from client to backend (that's what I understood from
your first patch proposal in this thread) or are we talking about
pre fetching the whole request body from the client and then passing
it on to the backend as a whole ?


Sorry, I really should not have proposed 2 patches in the same thread
without being clear about their different purposes.

I first thought flushing everything received from the client to the
backend immediatly, and disabling *retries* in the 16K-prefetch, would
address the issue (my first patch,
httpd-trunk-mod_proxy_http_flushall.patch). But as you said in a
previous message, that did not address the case where the client and/or
an input filter retain the very first body bytes, and mod_proxy_http
blocks, and the backend timeouts...

Hence the second patch (httpd-trunk-mod_proxy_http_prefetch.patch),
which does prefetch *before* establishing/checking the backend's
connection, so to minimize (to the minimum) the future delay between
that and the first bytes sent to the backend (hence the chances for it
to timeout). The prefetch is still up to 16K (same as existing), and not
the whole body of course.

Then, when it's time to forward (what is available from) the client's
request, the patched mod_proxy_http will establish or check+reuse a
backend connection and always flush immediatly what it has  already
(headers + prefetch, see stream_reqbody_* functions).

For the remaining request's body chunks (if any), I intentionally did
not change the current behaviour of letting the output filters choose
when to flush, this is not the keep-alive timeout anymore, so it becomes
out of the issue's scope. But I'm definitively +1 to flush-all here too
(optionaly), since mod_proxy may retain small chunks and can then face
another backend timeout later! That's where patch1 meets patch2, and
comes patch3 (httpd-trunk-mod_proxy_http_prefetch+flushall.patch,
attached here).

There is still the potential (minimal) race condition, the backend could
have closed in the (short) meantime, that's indeed *not* addressed by my
patch(es).


The problem I mentioned in the first message is about treating the
backend connection in an error prone way. By not ensuring the
connection is still valid - e.g. as seen by the peer - we risk
running into this problem no matter what we do elsewhere. So I
really think the proper way to handle this is to reopen the
connection if necessary - be this with a filter or integrated into
the connection handling itself - and only fail after we tried at
least once.


IMHO this is hardly feasible for non-idempotent (and no body) requests
(without disabling connection reuse, or using proxy-initial-not-pooled
to let the client choose), even if mod_proxy takes care of not sending
the full request in one time to be able to detect connection problems
before it's too late (to retry), there is still a possibility that it
won't know before sending the last chunk, and the issue remain.
mod_proxy_http addresses retries for requests *with body* by the ping
parameter, maybe it could also retry idempotent requests (like
mod_proxy_ajp does), but this is still not an overall solution, is there
one?


Re-thinking the proposed flush mechanism, I don't think using the
flushing will really solve the problem, albeit it probably narrowing
down the window of opportunity for the problem significantly in most
scenarios. I mention this because I'm getting the feeling two
different discussions are being mixed up: Solving the
keep-alive time out problem and introducing the
flush-all-immediately option. While the latter might improve the
situation with the first, it is no complete solution and there are a
lot of scenarios where it does not apply due to other factors like
filters (as discussed previously).


See above, the flushall does not resolve the issue (filters...), but the
early prefetch + flushall reduces it considerably, IMHO.


The flush option itself sounds like a good idea, so I see no reason
why not to put it in. I just don't want to loose focus on the actual
problem ;-)


I don't see either...

Please consider the new (yet) patch attached, can you still encounter
some proxy: error reading status line from 

Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-05 Thread Yann Ylavic
Hi Jan,

I don't think it is fixed in trunk, but I may have missed the commits.
Which ones are you talking about?

Regards,
Yann.


On Thu, Dec 5, 2013 at 1:51 PM, Jan Kaluža jkal...@redhat.com wrote:

 Hi,

 should this be fixed in trunk already? I see some commits in proxy code
 based on your ideas Yann, but I'm not sure if they address this particular
 problem too.

 Jan Kaluza


 On 10/17/2013 04:52 PM, Yann Ylavic wrote:


 On Thu, Oct 17, 2013 at 11:36 AM, Thomas Eckert
 thomas.r.w.eck...@gmail.com mailto:thomas.r.w.eck...@gmail.com wrote:

   Hence,
 why cannot mod_proxy_http prefetch the client's body *before* trying
 anything with the backend connection, and only if it's all good,
 connect (or reuse a connection to) the
   backend and then start forwarding the data immediatly (flushing
 the prefetched ones) ?

 Now I'm confused. Are we talking about flushing everything
 immediately from client to backend (that's what I understood from
 your first patch proposal in this thread) or are we talking about
 pre fetching the whole request body from the client and then passing
 it on to the backend as a whole ?


 Sorry, I really should not have proposed 2 patches in the same thread
 without being clear about their different purposes.

 I first thought flushing everything received from the client to the
 backend immediatly, and disabling *retries* in the 16K-prefetch, would
 address the issue (my first patch,
 httpd-trunk-mod_proxy_http_flushall.patch). But as you said in a
 previous message, that did not address the case where the client and/or
 an input filter retain the very first body bytes, and mod_proxy_http
 blocks, and the backend timeouts...

 Hence the second patch (httpd-trunk-mod_proxy_http_prefetch.patch),
 which does prefetch *before* establishing/checking the backend's
 connection, so to minimize (to the minimum) the future delay between
 that and the first bytes sent to the backend (hence the chances for it
 to timeout). The prefetch is still up to 16K (same as existing), and not
 the whole body of course.

 Then, when it's time to forward (what is available from) the client's
 request, the patched mod_proxy_http will establish or check+reuse a
 backend connection and always flush immediatly what it has  already
 (headers + prefetch, see stream_reqbody_* functions).

 For the remaining request's body chunks (if any), I intentionally did
 not change the current behaviour of letting the output filters choose
 when to flush, this is not the keep-alive timeout anymore, so it becomes
 out of the issue's scope. But I'm definitively +1 to flush-all here too
 (optionaly), since mod_proxy may retain small chunks and can then face
 another backend timeout later! That's where patch1 meets patch2, and
 comes patch3 (httpd-trunk-mod_proxy_http_prefetch+flushall.patch,
 attached here).

 There is still the potential (minimal) race condition, the backend could
 have closed in the (short) meantime, that's indeed *not* addressed by my
 patch(es).


 The problem I mentioned in the first message is about treating the
 backend connection in an error prone way. By not ensuring the
 connection is still valid - e.g. as seen by the peer - we risk
 running into this problem no matter what we do elsewhere. So I
 really think the proper way to handle this is to reopen the
 connection if necessary - be this with a filter or integrated into
 the connection handling itself - and only fail after we tried at
 least once.


 IMHO this is hardly feasible for non-idempotent (and no body) requests
 (without disabling connection reuse, or using proxy-initial-not-pooled
 to let the client choose), even if mod_proxy takes care of not sending
 the full request in one time to be able to detect connection problems
 before it's too late (to retry), there is still a possibility that it
 won't know before sending the last chunk, and the issue remain.
 mod_proxy_http addresses retries for requests *with body* by the ping
 parameter, maybe it could also retry idempotent requests (like
 mod_proxy_ajp does), but this is still not an overall solution, is there
 one?


 Re-thinking the proposed flush mechanism, I don't think using the
 flushing will really solve the problem, albeit it probably narrowing
 down the window of opportunity for the problem significantly in most
 scenarios. I mention this because I'm getting the feeling two
 different discussions are being mixed up: Solving the
 keep-alive time out problem and introducing the
 flush-all-immediately option. While the latter might improve the
 situation with the first, it is no complete solution and there are a
 lot of scenarios where it does not apply due to other factors like
 filters (as discussed previously).


 See above, the flushall does not resolve the issue (filters...), but the
 early prefetch + flushall reduces it considerably, IMHO.


 The flush 

Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-05 Thread Jim Jagielski
There hardly seemed any consensus on the patch... It also
seems that it adds more cycles to Apache on the front to
reduce a race condition that can't really be removed.
IMO, a reverse proxy should get out of the way as
quickly as possible.

Plus, if we do this here, shouldn't we do it for
all proxy protocol submodules (fcgi, etc...)?

Plus, as mentioned, this single patch includes 2 fixes
which can be/should be independent.

On Dec 5, 2013, at 8:06 AM, Yann Ylavic ylavic@gmail.com wrote:

 Hi Jan,
 
 I don't think it is fixed in trunk, but I may have missed the commits.
 Which ones are you talking about?
 
 Regards,
 Yann.
 
 
 On Thu, Dec 5, 2013 at 1:51 PM, Jan Kaluža jkal...@redhat.com wrote:
 Hi,
 
 should this be fixed in trunk already? I see some commits in proxy code based 
 on your ideas Yann, but I'm not sure if they address this particular problem 
 too.
 
 Jan Kaluza
 
 
 On 10/17/2013 04:52 PM, Yann Ylavic wrote:
 
 On Thu, Oct 17, 2013 at 11:36 AM, Thomas Eckert
 thomas.r.w.eck...@gmail.com mailto:thomas.r.w.eck...@gmail.com wrote:
 
   Hence,
 why cannot mod_proxy_http prefetch the client's body *before* trying
 anything with the backend connection, and only if it's all good,
 connect (or reuse a connection to) the
   backend and then start forwarding the data immediatly (flushing
 the prefetched ones) ?
 
 Now I'm confused. Are we talking about flushing everything
 immediately from client to backend (that's what I understood from
 your first patch proposal in this thread) or are we talking about
 pre fetching the whole request body from the client and then passing
 it on to the backend as a whole ?
 
 
 Sorry, I really should not have proposed 2 patches in the same thread
 without being clear about their different purposes.
 
 I first thought flushing everything received from the client to the
 backend immediatly, and disabling *retries* in the 16K-prefetch, would
 address the issue (my first patch,
 httpd-trunk-mod_proxy_http_flushall.patch). But as you said in a
 previous message, that did not address the case where the client and/or
 an input filter retain the very first body bytes, and mod_proxy_http
 blocks, and the backend timeouts...
 
 Hence the second patch (httpd-trunk-mod_proxy_http_prefetch.patch),
 which does prefetch *before* establishing/checking the backend's
 connection, so to minimize (to the minimum) the future delay between
 that and the first bytes sent to the backend (hence the chances for it
 to timeout). The prefetch is still up to 16K (same as existing), and not
 the whole body of course.
 
 Then, when it's time to forward (what is available from) the client's
 request, the patched mod_proxy_http will establish or check+reuse a
 backend connection and always flush immediatly what it has  already
 (headers + prefetch, see stream_reqbody_* functions).
 
 For the remaining request's body chunks (if any), I intentionally did
 not change the current behaviour of letting the output filters choose
 when to flush, this is not the keep-alive timeout anymore, so it becomes
 out of the issue's scope. But I'm definitively +1 to flush-all here too
 (optionaly), since mod_proxy may retain small chunks and can then face
 another backend timeout later! That's where patch1 meets patch2, and
 comes patch3 (httpd-trunk-mod_proxy_http_prefetch+flushall.patch,
 attached here).
 
 There is still the potential (minimal) race condition, the backend could
 have closed in the (short) meantime, that's indeed *not* addressed by my
 patch(es).
 
 
 The problem I mentioned in the first message is about treating the
 backend connection in an error prone way. By not ensuring the
 connection is still valid - e.g. as seen by the peer - we risk
 running into this problem no matter what we do elsewhere. So I
 really think the proper way to handle this is to reopen the
 connection if necessary - be this with a filter or integrated into
 the connection handling itself - and only fail after we tried at
 least once.
 
 
 IMHO this is hardly feasible for non-idempotent (and no body) requests
 (without disabling connection reuse, or using proxy-initial-not-pooled
 to let the client choose), even if mod_proxy takes care of not sending
 the full request in one time to be able to detect connection problems
 before it's too late (to retry), there is still a possibility that it
 won't know before sending the last chunk, and the issue remain.
 mod_proxy_http addresses retries for requests *with body* by the ping
 parameter, maybe it could also retry idempotent requests (like
 mod_proxy_ajp does), but this is still not an overall solution, is there
 one?
 
 
 Re-thinking the proposed flush mechanism, I don't think using the
 flushing will really solve the problem, albeit it probably narrowing
 down the window of opportunity for the problem significantly in most
 scenarios. I mention this because I'm getting the feeling 

Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-05 Thread Thomas Eckert
 It also seems that it adds more cycles to Apache on the front to
 reduce a race condition that can't really be removed.

While it's true that the race condition itself cannot be avoided we can
definitely work around the resulting problem situation, e.g. by trying to
open the connection again once and then either send the data or fail back
to the client as we do right now. The approach itself is not theoretical: I
know that's exactly how certain forward proxies solve the problem.


 Plus, if we do this here, shouldn't we do it for
 all proxy protocol submodules (fcgi, etc...)?

I go with my original suggestion: Have the above mentioned retry-once
mechanism apply on connection level so that request modules don't even
notice. Otherwise I would agree in having it added to the appropriate
modules. I would like to come up with the appropriate patch but I doubt
I'll have the time for it anytime soon :-(


As it stands I think Yann's approach in flushing through the reverse
proxy is better then doing nothing. Though I expect that to be useless for
a lot of deployments where stuff like AV scanning or mod_security will need
to buffer the request bodies - then you will have the original problem
again.


On Thu, Dec 5, 2013 at 4:05 PM, Jim Jagielski j...@jagunet.com wrote:

 There hardly seemed any consensus on the patch... It also
 seems that it adds more cycles to Apache on the front to
 reduce a race condition that can't really be removed.
 IMO, a reverse proxy should get out of the way as
 quickly as possible.

 Plus, if we do this here, shouldn't we do it for
 all proxy protocol submodules (fcgi, etc...)?

 Plus, as mentioned, this single patch includes 2 fixes
 which can be/should be independent.

 On Dec 5, 2013, at 8:06 AM, Yann Ylavic ylavic@gmail.com wrote:

  Hi Jan,
 
  I don't think it is fixed in trunk, but I may have missed the commits.
  Which ones are you talking about?
 
  Regards,
  Yann.
 
 
  On Thu, Dec 5, 2013 at 1:51 PM, Jan Kaluža jkal...@redhat.com wrote:
  Hi,
 
  should this be fixed in trunk already? I see some commits in proxy code
 based on your ideas Yann, but I'm not sure if they address this particular
 problem too.
 
  Jan Kaluza
 
 
  On 10/17/2013 04:52 PM, Yann Ylavic wrote:
 
  On Thu, Oct 17, 2013 at 11:36 AM, Thomas Eckert
  thomas.r.w.eck...@gmail.com mailto:thomas.r.w.eck...@gmail.com
 wrote:
 
Hence,
  why cannot mod_proxy_http prefetch the client's body *before* trying
  anything with the backend connection, and only if it's all good,
  connect (or reuse a connection to) the
backend and then start forwarding the data immediatly (flushing
  the prefetched ones) ?
 
  Now I'm confused. Are we talking about flushing everything
  immediately from client to backend (that's what I understood from
  your first patch proposal in this thread) or are we talking about
  pre fetching the whole request body from the client and then passing
  it on to the backend as a whole ?
 
 
  Sorry, I really should not have proposed 2 patches in the same thread
  without being clear about their different purposes.
 
  I first thought flushing everything received from the client to the
  backend immediatly, and disabling *retries* in the 16K-prefetch, would
  address the issue (my first patch,
  httpd-trunk-mod_proxy_http_flushall.patch). But as you said in a
  previous message, that did not address the case where the client and/or
  an input filter retain the very first body bytes, and mod_proxy_http
  blocks, and the backend timeouts...
 
  Hence the second patch (httpd-trunk-mod_proxy_http_prefetch.patch),
  which does prefetch *before* establishing/checking the backend's
  connection, so to minimize (to the minimum) the future delay between
  that and the first bytes sent to the backend (hence the chances for it
  to timeout). The prefetch is still up to 16K (same as existing), and not
  the whole body of course.
 
  Then, when it's time to forward (what is available from) the client's
  request, the patched mod_proxy_http will establish or check+reuse a
  backend connection and always flush immediatly what it has  already
  (headers + prefetch, see stream_reqbody_* functions).
 
  For the remaining request's body chunks (if any), I intentionally did
  not change the current behaviour of letting the output filters choose
  when to flush, this is not the keep-alive timeout anymore, so it becomes
  out of the issue's scope. But I'm definitively +1 to flush-all here too
  (optionaly), since mod_proxy may retain small chunks and can then face
  another backend timeout later! That's where patch1 meets patch2, and
  comes patch3 (httpd-trunk-mod_proxy_http_prefetch+flushall.patch,
  attached here).
 
  There is still the potential (minimal) race condition, the backend could
  have closed in the (short) meantime, that's indeed *not* addressed by my
  patch(es).
 
 
  The problem I mentioned in the first message is about treating the
  

Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-05 Thread Yann Ylavic
On Thu, Dec 5, 2013 at 4:05 PM, Jim Jagielski j...@jagunet.com wrote:

 There hardly seemed any consensus on the patch... It also
 seems that it adds more cycles to Apache on the front to
 reduce a race condition that can't really be removed.


I don't think more cycles are added by this patch.
What is done is that ap_proxy_http_request() is split in two functions,
the prefetch part is now in ap_proxy_http_prefetch(), and
ap_proxy_http_prefetch()+ap_proxy_http_request() has no more cycles than
the previous ap_proxy_http_request().
Unless you consider dereferencing pointer arguments a cycles-overhead
compared to using local variables...

I agree the race condition can't really be removed, mod_proxy can (must?)
strive for limiting it.
With this patch and the reslist's TTL below the backend's KeepAliveTimeout,
the race should not occur unless the backend closed before the timeout
(which may indeed be the case when, say, mpm_event is busy).



 IMO, a reverse proxy should get out of the way as
 quickly as possible.


I'm not sure to understand this but, IMHO, a reverse proxy should not
reserve a backend connection

(possibly) far before using it, and presume it will still be alive when
it's time to use it.




 Plus, if we do this here, shouldn't we do it for
 all proxy protocol submodules (fcgi, etc...)?


Agreed.





 Plus, as mentioned, this single patch includes 2 fixes
 which can be/should be independent.


This was just to show that early prefetch and flushall can work
together, but they are indeed 2 different things.
I can split them into different patches, should there be an interest in one
or/and the other.

Regards,
Yann.


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-05 Thread Yann Ylavic
On Thu, Dec 5, 2013 at 5:04 PM, Thomas Eckert
thomas.r.w.eck...@gmail.comwrote:

  It also seems that it adds more cycles to Apache on the front to
  reduce a race condition that can't really be removed.

 While it's true that the race condition itself cannot be avoided we can
 definitely work around the resulting problem situation, e.g. by trying to
 open the connection again once and then either send the data or fail back
 to the client as we do right now. The approach itself is not theoretical: I
 know that's exactly how certain forward proxies solve the problem.


You can't retry all the requests (particularly non idempotent ones), not
even once.
Suppose it is a charged $100 order, you wouldn't like any proxy to double
that because of network problems...





  Plus, if we do this here, shouldn't we do it for
  all proxy protocol submodules (fcgi, etc...)?

 I go with my original suggestion: Have the above mentioned retry-once
 mechanism apply on connection level so that request modules don't even
 notice. Otherwise I would agree in having it added to the appropriate
 modules. I would like to come up with the appropriate patch but I doubt
 I'll have the time for it anytime soon :-(


Same as above, this can't be done (even less at the connection level).
There is really no overall solution, IMHO.



 As it stands I think Yann's approach in flushing through the reverse
 proxy is better then doing nothing. Though I expect that to be useless for
 a lot of deployments where stuff like AV scanning or mod_security will need
 to buffer the request bodies - then you will have the original problem
 again.


My first approach was to flush only, but the latest patch take also care
about buffered request, the backend won't be connected/reused until the
bytes are in mod_proxy.


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-05 Thread Yann Ylavic
On Thu, Dec 5, 2013 at 5:45 PM, Yann Ylavic ylavic@gmail.com wrote:

 On Thu, Dec 5, 2013 at 5:07 PM, Yann Ylavic ylavic@gmail.com wrote:

 On Thu, Dec 5, 2013 at 4:05 PM, Jim Jagielski j...@jagunet.com wrote:

 There hardly seemed any consensus on the patch... It also
 seems that it adds more cycles to Apache on the front to
 reduce a race condition that can't really be removed.


 I don't think more cycles are added by this patch.
 What is done is that ap_proxy_http_request() is split in two functions,
 the prefetch part is now in ap_proxy_http_prefetch(), and
 ap_proxy_http_prefetch()+ap_proxy_http_request() has no more cycles than
 the previous ap_proxy_http_request().
 Unless you consider dereferencing pointer arguments a cycles-overhead
 compared to using local variables...


 That's not totally true, maybe you refer to this cycles :


 +/* Preserve the header/input brigades since they may be retried.
 */
 +input_bb = apr_brigade_create(p, backconn-bucket_alloc);
 +header_bb = apr_brigade_create(p, backconn-bucket_alloc);

 +proxy_buckets_lifetime_transform(r, input_brigade, input_bb);
 +proxy_buckets_lifetime_transform(r, header_brigade, header_bb);

 mod_proxy may need to setaside these buckets.


Oups, I meant, since input_brigade has already been setaside 
during prefetch, reading its buckets in
proxy_buckets_lifetime_transform() shouldn't take much time (though a few
more cycles).


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-05 Thread Thomas Eckert
 You can't retry all the requests (particularly non idempotent ones), not
even once.
 Suppose it is a charged $100 order, you wouldn't like any proxy to double
that because of network problems...

I'm not talking about retrying requests but retrying writing on the socket
after trying to re-open a connection. When mod_proxy tries to forward the
client request to the backends and encounters a closed connection due to
the described race condition it will fail back to the client. Instead, I
suggest trying to re-open the connection once and then either send the
client request over that connection or go back to the client with an error.
No double-sending requests anywhere.

 Same as above, this can't be done (even less at the connection level).
 There is really no overall solution, IMHO.

I doubt that statement is correct. As I said before, I've seen it work with
another proxy so the basic approach is no problem. You might be correct in
that it's not possible with apache but I cannot confirm or disconfirm this
until I have tried adding it.


Anyway, this is getting us nowhere until I (or anyone) come(s) up with a
corresponding patch. I hope I'll get around for it sometime until January.
Until then I'll just see this as declined.


On Thu, Dec 5, 2013 at 5:26 PM, Yann Ylavic ylavic@gmail.com wrote:

 On Thu, Dec 5, 2013 at 5:04 PM, Thomas Eckert thomas.r.w.eck...@gmail.com
  wrote:

  It also seems that it adds more cycles to Apache on the front to
  reduce a race condition that can't really be removed.

 While it's true that the race condition itself cannot be avoided we can
 definitely work around the resulting problem situation, e.g. by trying to
 open the connection again once and then either send the data or fail back
 to the client as we do right now. The approach itself is not theoretical: I
 know that's exactly how certain forward proxies solve the problem.


 You can't retry all the requests (particularly non idempotent ones), not
 even once.
 Suppose it is a charged $100 order, you wouldn't like any proxy to double
 that because of network problems...





  Plus, if we do this here, shouldn't we do it for
  all proxy protocol submodules (fcgi, etc...)?

 I go with my original suggestion: Have the above mentioned retry-once
 mechanism apply on connection level so that request modules don't even
 notice. Otherwise I would agree in having it added to the appropriate
 modules. I would like to come up with the appropriate patch but I doubt
 I'll have the time for it anytime soon :-(


 Same as above, this can't be done (even less at the connection level).
 There is really no overall solution, IMHO.



 As it stands I think Yann's approach in flushing through the reverse
 proxy is better then doing nothing. Though I expect that to be useless for
 a lot of deployments where stuff like AV scanning or mod_security will need
 to buffer the request bodies - then you will have the original problem
 again.


 My first approach was to flush only, but the latest patch take also care
 about buffered request, the backend won't be connected/reused until the
 bytes are in mod_proxy.




Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-12-05 Thread Yann Ylavic
On Thu, Dec 5, 2013 at 7:03 PM, Thomas Eckert
thomas.r.w.eck...@gmail.comwrote:

 I'm not talking about retrying requests but retrying writing on the socket
 after trying to re-open a connection. When mod_proxy tries to forward the
 client request to the backends and encounters a closed connection due to
 the described race condition it will fail back to the client. Instead, I
 suggest trying to re-open the connection once and then either send the
 client request over that connection or go back to the client with an error.
 No double-sending requests anywhere.


I must be missing something.

When mod_proxy encounters a closed (reused) connection while forwarding the
client's request, it has just sent the request once, right?
If, in that case, it opens a new connection and send that same request on
it, this is the second time, still right?

Unless it didn't send the complete request the first time, I mean
deliberately by sending only part of the request (incomplete body if any,
or incomplete header otherwise), how can the proxy be sure the first
request has not been interpreted by the backend already?
This is not because the send() failed on the proxy side the backend has not
recv()ed all the bytes (there might be a problem with the ack of the last
bytes for example), hence the request could be valid from the backend side.

Is sending a partial request first what you'd like to (be) implement(ed),
and only if that succeeds send the remaining data?


  Same as above, this can't be done (even less at the connection level).
  There is really no overall solution, IMHO.

 I doubt that statement is correct. As I said before, I've seen it work
 with another proxy so the basic approach is no problem. You might be
 correct in that it's not possible with apache but I cannot confirm or
 disconfirm this until I have tried adding it.


A proxy that re-sends the same non-idempotent request twice is simply not
HTTP compliant (
http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-25, 6.3.1.
Retrying Requests).

However, the RFC does not talk about incomplete requests.

Regards,
Yann.


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-17 Thread Thomas Eckert
Sorry for the delayed reply. At the moment I don't have time to look at the
patch proposal in detail, sorry about that too. I'll get back to it soon, I
hope.

 Pre-fetching 16K (or waiting for input filters to provide these) is not
always a fast operation, and the case where the backend closes its
connection in the meantime is easy to
 reproduce (and even likely to happen with some applications).

I absolutely agree. That's why I proposed to solve this more systematically
then trial-and-error-like in the first place.


 Hence, why cannot mod_proxy_http prefetch the client's body *before*
trying anything with the backend connection, and only if it's all good,
connect (or reuse a connection to) the
 backend and then start forwarding the data immediatly (flushing the
prefetched ones) ?

Now I'm confused. Are we talking about flushing everything immediately from
client to backend (that's what I understood from your first patch proposal
in this thread) or are we talking about pre fetching the whole request body
from the client and then passing it on to the backend as a whole ?


The problem I mentioned in the first message is about treating the backend
connection in an error prone way. By not ensuring the connection is still
valid - e.g. as seen by the peer - we risk running into this problem no
matter what we do elsewhere. So I really think the proper way to handle
this is to reopen the connection if necessary - be this with a filter or
integrated into the connection handling itself - and only fail after we
tried at least once.

Re-thinking the proposed flush mechanism, I don't think using the flushing
will really solve the problem, albeit it probably narrowing down the window
of opportunity for the problem significantly in most scenarios. I mention
this because I'm getting the feeling two different discussions are being
mixed up: Solving the keep-alive time out problem and introducing the
flush-all-immediately option. While the latter might improve the
situation with the first, it is no complete solution and there are a lot of
scenarios where it does not apply due to other factors like filters (as
discussed previously).

The flush option itself sounds like a good idea, so I see no reason why not
to put it in. I just don't want to loose focus on the actual problem ;-)

Cheers,
  Thomas







On Mon, Oct 7, 2013 at 6:49 PM, Yann Ylavic ylavic@gmail.com wrote:

 Sorry to insist about this issue but I don't see how the current
 mod_proxy_http's behaviour of connecting the backend (or checking
 established connection reusability) before prefetching the client's body is
 not a problem.

 Pre-fetching 16K (or waiting for input filters to provide these) is not
 always a fast operation, and the case where the backend closes its
 connection in the meantime is easy to reproduce (and even likely to happen
 with some applications).

 Hence, why cannot mod_proxy_http prefetch the client's body *before*
 trying anything with the backend connection, and only if it's all good,
 connect (or reuse a connection to) the backend and then start forwarding
 the data immediatly (flushing the prefetched ones) ?

 By doing this, the time between the connect (or check) and the first bytes
 sent to the backend is minimal.

 It does not require to disable the prefetch since this one can really help
 the decision about forwarding Content-Length vs chunked (which may not be
 handled by the backend, IFAIK this is not a HTTP/1.1 requirement to handle
 it for requests).

 That was the purpose of the first patch I proposed ealier, but had no
 feedback...
 Maybe this message and the following patch could have more chance.

 This patch is quite the same as the previous one (ap_proxy_http_request
 split in 2, ap_proxy_http_prefetch to prefetch before connect and
 ap_proxy_http_request to forward using the relevent
 stream_reqbody_cl/chunked once prefetched and connected). It just fixes the
 immediate flush of the prefetched bytes when it's time to forward, and the
 handling of backend-close set by ap_proxy_create_hdrbrgd (or
 ap_proxy_http_prefetch) before the connection even exist (or the previous
 one to be reused).

 Regards,
 Yann.

 Index: modules/proxy/mod_proxy_http.c
 ===
 --- modules/proxy/mod_proxy_http.c(revision 1529127)
 +++ modules/proxy/mod_proxy_http.c(working copy)
 @@ -251,6 +251,7 @@ static int stream_reqbody_chunked(apr_pool_t *p,
  while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
  {
  char chunk_hdr[20];  /* must be here due to transient bucket. */
 +int flush = 0;

  /* If this brigade contains EOS, either stop or remove it. */
  if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
 @@ -299,13 +300,14 @@ static int stream_reqbody_chunked(apr_pool_t *p,
  }

  header_brigade = NULL;
 +flush = 1;
  }
  else {
  bb = input_brigade;


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-17 Thread Yann Ylavic
On Thu, Oct 17, 2013 at 11:36 AM, Thomas Eckert thomas.r.w.eck...@gmail.com
 wrote:

  Hence,
 
 why cannot mod_proxy_http prefetch the client's body *before* trying
 anything with the backend connection, and only if it's all good, connect
 (or reuse a connection to) the
  backend and then start forwarding the data immediatly (flushing the
 prefetched ones) ?

 Now I'm confused. Are we talking about flushing everything immediately
 from client to backend (that's what I understood from your first patch
 proposal in this thread) or are we talking about pre fetching the whole
 request body from the client and then passing it on to the backend as a
 whole ?


Sorry, I really should not have proposed 2 patches in the same thread
without being clear about their different purposes.

I first thought flushing everything received from the client to the backend
immediatly, and disabling *retries* in the 16K-prefetch, would address the
issue (my first patch, httpd-trunk-mod_proxy_http_flushall.patch). But as
you said in a previous message, that did not address the case where the
client and/or an input filter retain the very first body bytes, and
mod_proxy_http blocks, and the backend timeouts...

Hence the second patch (httpd-trunk-mod_proxy_http_prefetch.patch), which
does prefetch *before* establishing/checking the backend's connection, so
to minimize (to the minimum) the future delay between that and the first
bytes sent to the backend (hence the chances for it to timeout). The
prefetch is still up to 16K (same as existing), and not the whole body of
course.

Then, when it's time to forward (what is available from) the client's
request, the patched mod_proxy_http will establish or check+reuse a backend
connection and always flush immediatly what it has  already (headers +
prefetch, see stream_reqbody_* functions).

For the remaining request's body chunks (if any), I intentionally did not
change the current behaviour of letting the output filters choose when to
flush, this is not the keep-alive timeout anymore, so it becomes out of the
issue's scope. But I'm definitively +1 to flush-all here too (optionaly),
since mod_proxy may retain small chunks and can then face another backend
timeout later! That's where patch1 meets patch2, and comes patch3
(httpd-trunk-mod_proxy_http_prefetch+flushall.patch, attached here).

There is still the potential (minimal) race condition, the backend could
have closed in the (short) meantime, that's indeed *not* addressed by my
patch(es).



 The problem I mentioned in the first message is about treating the backend
 connection in an error prone way. By not ensuring the connection is still
 valid - e.g. as seen by the peer - we risk running into this problem no
 matter what we do elsewhere. So I really think the proper way to handle
 this is to reopen the connection if necessary - be this with a filter or
 integrated into the connection handling itself - and only fail after we
 tried at least once.


IMHO this is hardly feasible for non-idempotent (and no body) requests
(without disabling connection reuse, or using proxy-initial-not-pooled to
let the client choose), even if mod_proxy takes care of not sending the
full request in one time to be able to detect connection problems before
it's too late (to retry), there is still a possibility that it won't know
before sending the last chunk, and the issue remain. mod_proxy_http
addresses retries for requests *with body* by the ping parameter, maybe
it could also retry idempotent requests (like mod_proxy_ajp does), but this
is still not an overall solution, is there one?




 Re-thinking the proposed flush mechanism, I don't think using the flushing
 will really solve the problem, albeit it probably narrowing down the window
 of opportunity for the problem significantly in most scenarios. I mention
 this because I'm getting the feeling two different discussions are being
 mixed up: Solving the
 
 keep-alive time out problem and introducing the
 
 flush-all-immediately option. While the latter might improve the
 situation with the first, it is no complete solution and there are a lot of
 scenarios where it does not apply due to other factors like filters (as
 discussed previously).


See above, the flushall does not resolve the issue (filters...), but the
early prefetch + flushall reduces it considerably, IMHO.



 The flush option itself sounds like a good idea, so I see no reason why
 not to put it in. I just don't want to loose focus on the actual problem ;-)


I don't see either...

Please consider the new (yet) patch attached, can you still encounter some
proxy: error reading status line from remote server with it?
Even without proxy-flushall set, you shouldn't, whatever the time taken
to read the request first 16K bytes...

Regards,
Yann.


httpd-trunk-mod_proxy_http_prefetch+flushall.patch
Description: Binary data


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-08 Thread Micha Lenk
Hi Yann,

Am 03.10.2013 15:33, schrieb Yann Ylavic:
 On Thu, Oct 3, 2013 at 2:07 PM, Micha Lenk mi...@lenk.info wrote:
Independent from how the HRS issue (CVE-2005-2088) was fixed at that
time, I still believe that it is a bad idea in terms of security to
flush the buffer and forward its content to the backend before the
*whole* request body has been received.
 
 mod_proxy won't forward anything before the whole request *header* is
 received (it isn't even called before), with or without my patch(es),
 and that prevent HRS provided the httpd checks
 Content-Length/Transfer-Encoding against
 http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23#page-31
 (which is the case, at least in trunk).

 mod_proxy will also prevent HRS by checking that the received data do
 not exceed the announced size, again my patch(es) don't change that.

Well, assessing HRS alike issues, you need to not only look at the first
HTTP request, but more importantly at a possible subsequent HTTP request
sent on the same connection. So, if you flush the buffer and forward its
content to the backend, you need to make sure to not accidentally
forwarding the next request without parsing it. That is all I wanted to
stress when talking about a potential HRS issue.

 It currently prefetches 16K of the body (if any) and forwards that and
 everything after to the backend from there, it won't retain the
 *whole* body unless one plays with the proxy-sendcl env.

If this is the same behavior as with current unpatched httpd, I am fine
with it. But then I guess this behavior is unrelated to your patch, right?

 Do you mean you always setenv proxy-sendcl to force mod_proxy in
 full-fetching mode because of security issues ?

No.

 I'm not sure what changes you are talking about, though.
 Is it about the flushall or the prefetch before connect patch ?

It is about the flushall patch.

Regards,
Micha


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-07 Thread Yann Ylavic

Sorry to insist about this issue but I don't see how the current
mod_proxy_http's behaviour of connecting the backend (or checking
established connection reusability) before prefetching the client's body is
not a problem.

Pre-fetching 16K (or waiting for input filters to provide these) is not
always a fast operation, and the case where the backend closes its
connection in the meantime is easy to reproduce (and even likely to happen
with some applications).

Hence, why cannot mod_proxy_http prefetch the client's body *before* trying
anything with the backend connection, and only if it's all good, connect
(or reuse a connection to) the backend and then start forwarding the data
immediatly (flushing the prefetched ones) ?

By doing this, the time between the connect (or check) and the first bytes
sent to the backend is minimal.

It does not require to disable the prefetch since this one can really help
the decision about forwarding Content-Length vs chunked (which may not be
handled by the backend, IFAIK this is not a HTTP/1.1 requirement to handle
it for requests).

That was the purpose of the first patch I proposed ealier, but had no
feedback...
Maybe this message and the following patch could have more chance.

This patch is quite the same as the previous one (ap_proxy_http_request
split in 2, ap_proxy_http_prefetch to prefetch before connect and
ap_proxy_http_request to forward using the relevent
stream_reqbody_cl/chunked once prefetched and connected). It just fixes the
immediate flush of the prefetched bytes when it's time to forward, and the
handling of backend-close set by ap_proxy_create_hdrbrgd (or
ap_proxy_http_prefetch) before the connection even exist (or the previous
one to be reused).

Regards,
Yann.

Index: modules/proxy/mod_proxy_http.c
===
--- modules/proxy/mod_proxy_http.c(revision 1529127)
+++ modules/proxy/mod_proxy_http.c(working copy)
@@ -251,6 +251,7 @@ static int stream_reqbody_chunked(apr_pool_t *p,
 while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
 {
 char chunk_hdr[20];  /* must be here due to transient bucket. */
+int flush = 0;

 /* If this brigade contains EOS, either stop or remove it. */
 if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
@@ -299,13 +300,14 @@ static int stream_reqbody_chunked(apr_pool_t *p,
 }

 header_brigade = NULL;
+flush = 1;
 }
 else {
 bb = input_brigade;
 }

 /* The request is flushed below this loop with chunk EOS header */
-rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, 0);
+rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb,
flush);
 if (rv != OK) {
 return rv;
 }
@@ -389,12 +391,14 @@ static int stream_reqbody_cl(apr_pool_t *p,

 while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
 {
+int flush = 0;
+
 apr_brigade_length(input_brigade, 1, bytes);
 bytes_streamed += bytes;

 /* If this brigade contains EOS, either stop or remove it. */
 if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
-seen_eos = 1;
+seen_eos = flush = 1;

 /* We can't pass this EOS to the output_filters. */
 e = APR_BRIGADE_LAST(input_brigade);
@@ -444,13 +448,14 @@ static int stream_reqbody_cl(apr_pool_t *p,
 }

 header_brigade = NULL;
+flush = 1;
 }
 else {
 bb = input_brigade;
 }

 /* Once we hit EOS, we are ready to flush. */
-rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb,
seen_eos);
+rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb,
flush);
 if (rv != OK) {
 return rv ;
 }
@@ -677,29 +682,33 @@ static apr_status_t proxy_buckets_lifetime_transfo
 return rv;
 }

+enum rb_methods {
+RB_INIT,
+RB_STREAM_CL,
+RB_STREAM_CHUNKED,
+RB_SPOOL_CL
+};
+
 static
-int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
+int ap_proxy_http_prefetch(apr_pool_t *p, request_rec *r,
proxy_conn_rec *p_conn, proxy_worker
*worker,
proxy_server_conf *conf,
apr_uri_t *uri,
-   char *url, char *server_portstr)
+   char *url, char *server_portstr,
+   apr_bucket_brigade *header_brigade,
+   apr_bucket_brigade *input_brigade,
+   char **old_cl_val, char **old_te_val,
+   enum rb_methods *rb_method)
 {
 conn_rec *c = r-connection;
 apr_bucket_alloc_t *bucket_alloc = c-bucket_alloc;
-apr_bucket_brigade *header_brigade;
-

Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-03 Thread Yann Ylavic
Having a look at MPM event's doc (

http://httpd.apache.org/docs/current/mod/event.html#asyncrequestworkerfactor),
I found this :
 [...] if all workers are busy, [mpm_event] will close connections in
keep-alive state even if the keep-alive timeout has not expired
.


On Fri, Aug 2, 2013 at 2:33 PM, Plüm, Rüdiger, Vodafone Group 
ruediger.pl...@vodafone.com wrote:

 The typical way to solve this today is to know the keepalive timeout of
 the backend and set ttl for this worker to a value a few seconds below.


So it might not work if the backend is a busy mpm_event...



 Regards

 Rüdiger

  -Ursprüngliche Nachricht-
  Von: Jim Jagielski
  Gesendet: Freitag, 2. August 2013 14:29
  An: dev@httpd.apache.org
  Betreff: Re: mod_proxy, oooled backend connections and the keep-alive
  race condition
 
  +1 for the theory, but I'm not sure if it's feasible or not.
 
  On Aug 2, 2013, at 5:28 AM, Thomas Eckert thomas.r.w.eck...@gmail.com
  wrote:
 
   So I've been seeing lots of proxy: error reading status line from
  remote server by mod_proxy lately. Usually this is caused by the race
  condition between checking the connection state and the backend closing
  the connection due to the keep-alive timeout. As Covener pointed out to
  me in IRC, using mod_proxy_http's env variable proxy-initial-not-
  pooled does offer a solution to the problem albeit at the cost of
  performance.
  
   The call to ap_proxy_http_process_response() in mod_proxy_http.c
  eventually boils down to ap_rgetline_core() which calls ap_get_brigade()
  on r-input_filters. This looks to me like a simple input filter might
  do the trick if it only checked for a possibility to read on the socket
  and reopens the connection upon failure type reset by peer. I took a
  short look at core_create_proxy_req() in server/core.c to see how
  connections are set up and I wonder if it's possible to recreate/reuse
  that logic in an input filter. If so, this input filter would offer a
  nice alternative if hard coding this behavior into mod_proxy/core is
  frowned upon. Simply make the filter dependant on an env variable, just
  like proxy-initial-not-pooled.
  




Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-03 Thread Micha Lenk
Hi Yann,

Am 01.10.2013 17:08, schrieb Yann Ylavic:
 As far as I understand the issue, the main point of prefetch was to fix
 CVE-2005-2088, a HTTP Request Smuggling attack (see also
 http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-2088).
 
 This is discussed in PR40029 and is not related to HRS, the real fix
 regarding HRS was about both CL/TE sent by th client
 (https://issues.apache.org/bugzilla/show_bug.cgi?id=40029#c4).

Independent from how the HRS issue (CVE-2005-2088) was fixed at that
time, I still believe that it is a bad idea in terms of security to
flush the buffer and forward its content to the backend before the
*whole* request body has been received. At least I would recommend to
carefully review this change to make sure you don't create a new
security issue similar to the HRS issue.

Regards,
Micha


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-03 Thread Yann Ylavic
Hi Micha,

On Thu, Oct 3, 2013 at 2:07 PM, Micha Lenk mi...@lenk.info wrote:

 Independent from how the HRS issue (CVE-2005-2088) was fixed at that
 time, I still believe that it is a bad idea in terms of security to
 flush the buffer and forward its content to the backend before the
 *whole* request body has been received.


mod_proxy won't forward anything before the whole request *header* is
received (it isn't even called before), with or without my patch(es), and
that prevent HRS provided the httpd checks Content-Length/Transfer-Encoding
against
http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23#page-31(which
is the case, at least in trunk).

mod_proxy will also prevent HRS by checking that the received data do not
exceed the announced size, again my patch(es) don't change that.

It currently prefetches 16K of the body (if any) and forwards that and
everything after to the backend from there, it won't retain the *whole*
body unless one plays with the proxy-sendcl env.

Do you mean you always setenv proxy-sendcl to force mod_proxy in
full-fetching mode because of security issues ?


 At least I would recommend to
 carefully review this change to make sure you don't create a new
 security issue similar to the HRS issue.


Sure, review and more testing is very welcome.

I'm not sure what changes you are talking about, though.
Is it about the flushall or the prefetch before connect patch ?

For the first patch I don't see (as explained above) the changes about
security, it is more about small network packet now vs big ones later. The
latter case (the current default behaviour) also raises a backend timeout
issue, when the client sends small but regular data fetched-but-not-flushed
by the proxy (whether or not the bytes are the first ones) and the backend
timeouts because it hasn't received anything since a while...

For the second patch, do you mean pre-fetching (part of) the request body
before connecting/reusing a backend could introduce a flaw ?
You may be right but, IMHO, not for a HRS vulnerability (httpd/mod_proxy
checks haven't been changed).

Contrariwise, it avoids a DOS attempt on both the proxy and the backend
(whose connections are requisitioned) should a client be slow (or Alice).



 Regards,
 Micha



Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-02 Thread Thomas Eckert
-sendchunked))) {
 +   !apr_table_get(r-subprocess_env,
 proxy-sendchunked)
 +   !flushall)) {
  rb_method = RB_SPOOL_CL;
  }
  else {
 @@ -889,7 +908,8 @@ int ap_proxy_http_request(apr_pool_t *p, request_r
  }
  else if (!force10
 (apr_table_get(r-subprocess_env, proxy-sendchunks)
 -  || apr_table_get(r-subprocess_env,
 proxy-sendchunked))
 +  || apr_table_get(r-subprocess_env,
 proxy-sendchunked)
 +  || flushall)
 !apr_table_get(r-subprocess_env, proxy-sendcl)) {
  rb_method = RB_STREAM_CHUNKED;
  }
 [/patch]

 Regards,
 Yann.



 On Tue, Oct 1, 2013 at 2:36 PM, Plüm, Rüdiger, Vodafone Group 
 ruediger.pl...@vodafone.com wrote:



  -Ursprüngliche Nachricht-
  Von: Joe Orton
  Gesendet: Dienstag, 1. Oktober 2013 14:23
  An: Plüm, Rüdiger, Vodafone Group
  Cc: dev@httpd.apache.org
  Betreff: Re: mod_proxy, oooled backend connections and the keep-alive
  race condition
 
  On Fri, Aug 02, 2013 at 12:33:58PM +, Plüm, Rüdiger, Vodafone Group
  wrote:
   The typical way to solve this today is to know the keepalive timeout
   of the backend and set ttl for this worker to a value a few seconds
   below.
 
  I just looked at a case where the user is hitting this problem and does
  already have the ttl  keepalive-timeout configured like that; and a few
  seconds difference is not necessarily enough.  The problem is that the
  prefetch of the 16K request body is making it a lot worse - the worst
  case is (16K/packet size) * Timeout seconds to complete the prefetch.

 True.

 
  That's time when the proxy *thinks* the connection is valid but the
  backend thinks the connection is idle.  And in most reverse-proxy cases
  that prefetch is adding basically no value AFAICT - the backend is a
  known vintage and probably HTTP/1.1.  So... could we make the prefetch
  stuff configurable away?

 IMHO no issue with this. Let's hear what others say.
 I guess the main point of prefetch was to make better decisions whether
 to use chunked
 encoding when sending to the backend. Or provide a CL to the backend when
 the real client does not.

 Regards

 Rüdiger





Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-02 Thread Yann Ylavic

On Wed, Oct 2, 2013 at 9:40 AM, Thomas Eckert
thomas.r.w.eck...@gmail.comwrote:

 Yann, although I do expect it to solve the issue discussed here, I  don't
 think simply flushing everything instantly is the right way to go. For
 example, how do the proposed changes work with modules which scan the
 request body like mod_security ? A lot of scanning/parsing can only be done
 in a senseful way if the entity to be scanned/parsed is available in full.


Indeed, this patch won't help if an input filter in the chain does spool
the body.

Maybe mod_proxy_http can partially prefetch the request body before the
acquire/determine/connect backend logic so that the is_socket_connected()
runs just before the first byte is sent (regardless of the time taken by
the first input filters call) ?

The flushall flag would still (optionally) be welcome :p



 Passing through everything immediately will probably cause the SlowHTTP to
 bybass the reverse proxy and harm the web server direclty. (I haven't had
 time to appl the changes to a test environment)


SlowHTTP does currently eat Apache resources (the thread won't do anything
else until all is forwarded to the backend, or even back to the client),
though I don't know much about mpm_event still...

IMHO that cannot be avoided without mod_reqtimeout (mod_security?).

Regards,
Yann.


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-02 Thread Yann Ylavic
A late (little) fix below...


On Thu, Oct 3, 2013 at 12:14 AM, Yann Ylavic ylavic@gmail.com wrote:


 Index: modules/proxy/proxy_util.c
 ===
 --- modules/proxy/proxy_util.c(revision 1528615)
 +++ modules/proxy/proxy_util.c(working copy)
 @@ -3092,7 +3092,9 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
  buf = apr_pstrcat(p, r-method,  , url,  HTTP/1.1 CRLF, NULL);
  }
  if (apr_table_get(r-subprocess_env, proxy-nokeepalive)) {
 -origin-keepalive = AP_CONN_CLOSE;
 +if (origin) {
 +origin-keepalive = AP_CONN_CLOSE;
 +}
  p_conn-close = 1;
  }
  ap_xlate_proto_to_ascii(buf, strlen(buf));
 Index: modules/proxy/mod_proxy_http.c
 ===
 --- modules/proxy/mod_proxy_http.c(revision 1528615)
 +++ modules/proxy/mod_proxy_http.c(working copy)
 @@ -677,30 +677,41 @@ static apr_status_t proxy_buckets_lifetime_transfo
  return rv;
  }

 +enum rb_methods {
 +RB_INIT,
 +RB_STREAM_CL,
 +RB_STREAM_CHUNKED,
 +RB_SPOOL_CL
 +};
 +
  static
 -int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
 +int ap_proxy_http_prefetch(apr_pool_t *p, request_rec *r,
 proxy_conn_rec *p_conn, proxy_worker
 *worker,
 proxy_server_conf *conf,
 apr_uri_t *uri,
 -   char *url, char *server_portstr)
 +   char *url, char *server_portstr,
 +   apr_bucket_brigade *header_brigade,
 +   apr_bucket_brigade *input_brigade,
 +   char **old_cl_val, char **old_te_val,
 +   enum rb_methods *rb_method, int
 *keepalive)
  {
  conn_rec *c = r-connection;
  apr_bucket_alloc_t *bucket_alloc = c-bucket_alloc;
 -apr_bucket_brigade *header_brigade;
 -apr_bucket_brigade *input_brigade;
  apr_bucket_brigade *temp_brigade;
  apr_bucket *e;
  char *buf;
  apr_status_t status;
 -enum rb_methods {RB_INIT, RB_STREAM_CL, RB_STREAM_CHUNKED,
 RB_SPOOL_CL};
 -enum rb_methods rb_method = RB_INIT;
 -char *old_cl_val = NULL;
 -char *old_te_val = NULL;
  apr_off_t bytes_read = 0;

  apr_off_t bytes;
  int force10, rv;
 -conn_rec *origin = p_conn-connection;

 +/* XXX: This somehow should be fixed in the API.
 + * Assumes p_conn-close is 0 here since ap_proxy_create_hdrbrgd and
 code
 + * below will use it to disable keep-alive and not for the connection
 to
 + * be closed before reuse.
 + */
 +AP_DEBUG_ASSERT(!p_conn-close);

 +
  if (apr_table_get(r-subprocess_env, force-proxy-request-1.0)) {
  if (r-expecting_100) {
  return HTTP_EXPECTATION_FAILED;
 @@ -710,17 +721,13 @@ static
  force10 = 0;
  }

 -header_brigade = apr_brigade_create(p, origin-bucket_alloc);

  rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
   worker, conf, uri, url, server_portstr,
 - old_cl_val, old_te_val);
 + old_cl_val, old_te_val);

  if (rv != OK) {
  return rv;
  }

 -/* We have headers, let's figure out our request body... */
 -input_brigade = apr_brigade_create(p, bucket_alloc);
 -
  /* sub-requests never use keepalives, and mustn't pass request bodies.
   * Because the new logic looks at input_brigade, we will
 self-terminate
   * input_brigade and jump past all of the request body logic...
 @@ -733,15 +740,15 @@ static
  if (!r-kept_body  r-main) {
  /* XXX: Why DON'T sub-requests use keepalives? */
  p_conn-close = 1;
 -if (old_cl_val) {
 -old_cl_val = NULL;
 +if (*old_cl_val) {
 +*old_cl_val = NULL;
  apr_table_unset(r-headers_in, Content-Length);
  }
 -if (old_te_val) {
 -old_te_val = NULL;
 +if (*old_te_val) {
 +*old_te_val = NULL;
  apr_table_unset(r-headers_in, Transfer-Encoding);
  }
 -rb_method = RB_STREAM_CL;
 +*rb_method = RB_STREAM_CL;
  e = apr_bucket_eos_create(input_brigade-bucket_alloc);
  APR_BRIGADE_INSERT_TAIL(input_brigade, e);
  goto skip_body;
 @@ -755,20 +762,19 @@ static
   * encoding has been done by the extensions' handler, and
   * do not modify add_te_chunked's logic
   */
 -if (old_te_val  strcasecmp(old_te_val, chunked) != 0) {
 +if (*old_te_val  strcasecmp(*old_te_val, chunked) != 0) {
  ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01093)
%s Transfer-Encoding is not supported,
 old_te_val);
  return 

Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-02 Thread Yann Ylavic
Is the Step Three-and-a-Half really required since
ap_proxy_connect_backend() (that does the same is_socket_connected() check)
is run almost before? May the ap_proxy_connection_create() function in
between take some time or is it a last chance to catch the race?

Regards


On Thu, Oct 3, 2013 at 12:38 AM, Yann Ylavic ylavic@gmail.com wrote:

 A late (little) fix below...


 On Thu, Oct 3, 2013 at 12:14 AM, Yann Ylavic ylavic@gmail.com wrote:


 Index: modules/proxy/proxy_util.c
 ===
 --- modules/proxy/proxy_util.c(revision 1528615)
 +++ modules/proxy/proxy_util.c(working copy)
 @@ -3092,7 +3092,9 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
  buf = apr_pstrcat(p, r-method,  , url,  HTTP/1.1 CRLF,
 NULL);
  }
  if (apr_table_get(r-subprocess_env, proxy-nokeepalive)) {
 -origin-keepalive = AP_CONN_CLOSE;
 +if (origin) {
 +origin-keepalive = AP_CONN_CLOSE;
 +}
  p_conn-close = 1;
  }
  ap_xlate_proto_to_ascii(buf, strlen(buf));
 Index: modules/proxy/mod_proxy_http.c
 ===
 --- modules/proxy/mod_proxy_http.c(revision 1528615)
 +++ modules/proxy/mod_proxy_http.c(working copy)
 @@ -677,30 +677,41 @@ static apr_status_t proxy_buckets_lifetime_transfo
  return rv;
  }

 +enum rb_methods {
 +RB_INIT,
 +RB_STREAM_CL,
 +RB_STREAM_CHUNKED,
 +RB_SPOOL_CL
 +};
 +
  static
 -int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
 +int ap_proxy_http_prefetch(apr_pool_t *p, request_rec *r,
 proxy_conn_rec *p_conn, proxy_worker
 *worker,
 proxy_server_conf *conf,
 apr_uri_t *uri,
 -   char *url, char *server_portstr)
 +   char *url, char *server_portstr,
 +   apr_bucket_brigade *header_brigade,
 +   apr_bucket_brigade *input_brigade,
 +   char **old_cl_val, char **old_te_val,
 +   enum rb_methods *rb_method, int
 *keepalive)
  {
  conn_rec *c = r-connection;
  apr_bucket_alloc_t *bucket_alloc = c-bucket_alloc;
 -apr_bucket_brigade *header_brigade;
 -apr_bucket_brigade *input_brigade;
  apr_bucket_brigade *temp_brigade;
  apr_bucket *e;
  char *buf;
  apr_status_t status;
 -enum rb_methods {RB_INIT, RB_STREAM_CL, RB_STREAM_CHUNKED,
 RB_SPOOL_CL};
 -enum rb_methods rb_method = RB_INIT;
 -char *old_cl_val = NULL;
 -char *old_te_val = NULL;
  apr_off_t bytes_read = 0;

  apr_off_t bytes;
  int force10, rv;
 -conn_rec *origin = p_conn-connection;

 +/* XXX: This somehow should be fixed in the API.
 + * Assumes p_conn-close is 0 here since ap_proxy_create_hdrbrgd and
 code
 + * below will use it to disable keep-alive and not for the
 connection to
 + * be closed before reuse.
 + */
 +AP_DEBUG_ASSERT(!p_conn-close);

 +
  if (apr_table_get(r-subprocess_env, force-proxy-request-1.0)) {
  if (r-expecting_100) {
   return HTTP_EXPECTATION_FAILED;
 @@ -710,17 +721,13 @@ static
  force10 = 0;
  }

 -header_brigade = apr_brigade_create(p, origin-bucket_alloc);

  rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
   worker, conf, uri, url, server_portstr,
 - old_cl_val, old_te_val);
 + old_cl_val, old_te_val);

  if (rv != OK) {
  return rv;
  }

 -/* We have headers, let's figure out our request body... */
 -input_brigade = apr_brigade_create(p, bucket_alloc);
 -
  /* sub-requests never use keepalives, and mustn't pass request
 bodies.
   * Because the new logic looks at input_brigade, we will
 self-terminate
   * input_brigade and jump past all of the request body logic...
 @@ -733,15 +740,15 @@ static
  if (!r-kept_body  r-main) {
  /* XXX: Why DON'T sub-requests use keepalives? */
  p_conn-close = 1;
 -if (old_cl_val) {
 -old_cl_val = NULL;
 +if (*old_cl_val) {
 +*old_cl_val = NULL;
  apr_table_unset(r-headers_in, Content-Length);
  }
 -if (old_te_val) {
 -old_te_val = NULL;
 +if (*old_te_val) {
 +*old_te_val = NULL;
  apr_table_unset(r-headers_in, Transfer-Encoding);
  }
 -rb_method = RB_STREAM_CL;
 +*rb_method = RB_STREAM_CL;
  e = apr_bucket_eos_create(input_brigade-bucket_alloc);
  APR_BRIGADE_INSERT_TAIL(input_brigade, e);
  goto skip_body;
 @@ -755,20 +762,19 @@ static
   * encoding has been done by the extensions' handler, and
   * do 

Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-01 Thread Joe Orton
On Fri, Aug 02, 2013 at 12:33:58PM +, Plüm, Rüdiger, Vodafone Group wrote:
 The typical way to solve this today is to know the keepalive timeout 
 of the backend and set ttl for this worker to a value a few seconds 
 below.

I just looked at a case where the user is hitting this problem and does 
already have the ttl  keepalive-timeout configured like that; and a few 
seconds difference is not necessarily enough.  The problem is that the 
prefetch of the 16K request body is making it a lot worse - the worst 
case is (16K/packet size) * Timeout seconds to complete the prefetch.

That's time when the proxy *thinks* the connection is valid but the 
backend thinks the connection is idle.  And in most reverse-proxy cases 
that prefetch is adding basically no value AFAICT - the backend is a 
known vintage and probably HTTP/1.1.  So... could we make the prefetch 
stuff configurable away?

Regards, Joe


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-01 Thread Yann Ylavic
, Plüm, Rüdiger, Vodafone Group 
ruediger.pl...@vodafone.com wrote:



  -Ursprüngliche Nachricht-
  Von: Joe Orton
  Gesendet: Dienstag, 1. Oktober 2013 14:23
  An: Plüm, Rüdiger, Vodafone Group
  Cc: dev@httpd.apache.org
  Betreff: Re: mod_proxy, oooled backend connections and the keep-alive
  race condition
 
  On Fri, Aug 02, 2013 at 12:33:58PM +, Plüm, Rüdiger, Vodafone Group
  wrote:
   The typical way to solve this today is to know the keepalive timeout
   of the backend and set ttl for this worker to a value a few seconds
   below.
 
  I just looked at a case where the user is hitting this problem and does
  already have the ttl  keepalive-timeout configured like that; and a few
  seconds difference is not necessarily enough.  The problem is that the
  prefetch of the 16K request body is making it a lot worse - the worst
  case is (16K/packet size) * Timeout seconds to complete the prefetch.

 True.

 
  That's time when the proxy *thinks* the connection is valid but the
  backend thinks the connection is idle.  And in most reverse-proxy cases
  that prefetch is adding basically no value AFAICT - the backend is a
  known vintage and probably HTTP/1.1.  So... could we make the prefetch
  stuff configurable away?

 IMHO no issue with this. Let's hear what others say.
 I guess the main point of prefetch was to make better decisions whether to
 use chunked
 encoding when sending to the backend. Or provide a CL to the backend when
 the real client does not.

 Regards

 Rüdiger




httpd-trunk-mod_proxy_http_flushall.patch
Description: Binary data


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-01 Thread Yann Ylavic
On Tue, Oct 1, 2013 at 3:39 PM, Yann Ylavic ylavic@gmail.com wrote:


 It should address this issue, and in the same time allow protocols like MS
 RPC-over-HTTP to work with :
SetEnvIf Request_Method ^RPC_IN_DATA proxy-flushall


See PR40029 for RPC-over-HTTP debate, it was finally RESOLVED INVALID,
which is not obvious...
Sorry if that's off topic though, just to point another side-effect caused
by the prefetch.



 Regards,
 Yann.



Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-01 Thread Jim Jagielski

On Oct 1, 2013, at 8:36 AM, Plüm, Rüdiger, Vodafone Group 
ruediger.pl...@vodafone.com wrote:

 
 
 -Ursprüngliche Nachricht-
 Von: Joe Orton 
 Gesendet: Dienstag, 1. Oktober 2013 14:23
 An: Plüm, Rüdiger, Vodafone Group
 Cc: dev@httpd.apache.org
 Betreff: Re: mod_proxy, oooled backend connections and the keep-alive
 race condition
 
 That's time when the proxy *thinks* the connection is valid but the
 backend thinks the connection is idle.  And in most reverse-proxy cases
 that prefetch is adding basically no value AFAICT - the backend is a
 known vintage and probably HTTP/1.1.  So... could we make the prefetch
 stuff configurable away?
 
 IMHO no issue with this. Let's hear what others say.

+1... fine w/ me

 I guess the main point of prefetch was to make better decisions whether to 
 use chunked
 encoding when sending to the backend. Or provide a CL to the backend when the 
 real client does not.
 



Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-01 Thread Micha Lenk
Hi all,

Am 01.10.2013 14:36, schrieb Plüm, Rüdiger, Vodafone Group:
 That's time when the proxy *thinks* the connection is valid but
 the backend thinks the connection is idle.  And in most
 reverse-proxy cases that prefetch is adding basically no value
 AFAICT - the backend is a known vintage and probably HTTP/1.1.
 So... could we make the prefetch stuff configurable away?
 
 IMHO no issue with this. Let's hear what others say. I guess the main
 point of prefetch was to make better decisions whether to use
 chunked encoding when sending to the backend. Or provide a CL to the
 backend when the real client does not.

As far as I understand the issue, the main point of prefetch was to fix
CVE-2005-2088, a HTTP Request Smuggling attack (see also
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-2088).

This is not an argument against making the prefetch stuff configurable,
but if this ever gets implemented, this CVE should definitely needs to
be mentioned in the documentation so that users are aware of it.

Regards,
Micha


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-10-01 Thread Yann Ylavic
On Tue, Oct 1, 2013 at 4:53 PM, Micha Lenk mi...@lenk.info wrote:

 As far as I understand the issue, the main point of prefetch was to fix
 CVE-2005-2088, a HTTP Request Smuggling attack (see also
 http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-2088).


This is discussed in PR40029 and is not related to HRS, the real fix
regarding HRS was about both CL/TE sent by th client (
https://issues.apache.org/bugzilla/show_bug.cgi?id=40029#c4).

Regards,
 Micha



Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-05 Thread Thomas Eckert
 One could do an 'OPTIONS *' request. But I am not sure if that is any
better than proxy-initial-not-pooled in terms of performance.

I don't see why an OPTIONS request should not encounter problems where a
GET request will. After all, the problem is on the transport layer, not on
the application layer. Am I missing something ?

 Or a filter could just send the first bytes of the request (less than the
request line) and then do a filter flush. If that fails, repeating the
request on a different connection would be ok even for non- idempotent
requests, because we would know that the backend has not received the full
request yet. I don't know how many errors this would catch in practice,
though.

This is pretty much what I stated earlier. So I assume (re)opening a
connection and having the whole process of sending the request transition
to that (re)new(ed) connection is possible for an input filter. I was not
sure about it. Going to look into it once I have time..



On Sat, Aug 3, 2013 at 7:26 PM, Stefan Fritsch s...@sfritsch.de wrote:

 Am Freitag, 2. August 2013, 11:21:56 schrieb Eric Covener:
   I think this does not work for GET requests or request without a
   request body.
  Just re-read spec, you are right -- we are abusing this in a module
  as a sort of extended handshake even w/ no body, but not against
  heterogenous backends.

 One could do an 'OPTIONS *' request. But I am not sure if that is any
 better than proxy-initial-not-pooled in terms of performance.

 Or a filter could just send the first bytes of the request (less than
 the request line) and then do a filter flush. If that fails, repeating
 the request on a different connection would be ok even for non-
 idempotent requests, because we would know that the backend has not
 received the full request yet. I don't know how many errors this would
 catch in practice, though.



Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-05 Thread Eric Covener
On Mon, Aug 5, 2013 at 2:49 AM, Thomas Eckert
thomas.r.w.eck...@gmail.com wrote:
 One could do an 'OPTIONS *' request. But I am not sure if that is any
 better than proxy-initial-not-pooled in terms of performance.

 I don't see why an OPTIONS request should not encounter problems where a GET
 request will. After all, the problem is on the transport layer, not on the
 application layer. Am I missing something ?

Could have problems at either level (e.g. MaxKeepalives)


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-05 Thread Rainer Jung
On 05.08.2013 13:18, Eric Covener wrote:
 On Mon, Aug 5, 2013 at 2:49 AM, Thomas Eckert
 thomas.r.w.eck...@gmail.com wrote:
 One could do an 'OPTIONS *' request. But I am not sure if that is any
 better than proxy-initial-not-pooled in terms of performance.

 I don't see why an OPTIONS request should not encounter problems where a GET
 request will. After all, the problem is on the transport layer, not on the
 application layer. Am I missing something ?
 
 Could have problems at either level (e.g. MaxKeepalives)

I think what people are trying to say: another request in front of each
request might increase the relative frequency (per real request) with
which the problem occurs.

Regards,

Rainer


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-05 Thread Jim Jagielski

On Aug 5, 2013, at 10:13 AM, Rainer Jung rainer.j...@kippdata.de wrote:

 On 05.08.2013 13:18, Eric Covener wrote:
 On Mon, Aug 5, 2013 at 2:49 AM, Thomas Eckert
 thomas.r.w.eck...@gmail.com wrote:
 One could do an 'OPTIONS *' request. But I am not sure if that is any
 better than proxy-initial-not-pooled in terms of performance.
 
 I don't see why an OPTIONS request should not encounter problems where a GET
 request will. After all, the problem is on the transport layer, not on the
 application layer. Am I missing something ?
 
 Could have problems at either level (e.g. MaxKeepalives)
 
 I think what people are trying to say: another request in front of each
 request might increase the relative frequency (per real request) with
 which the problem occurs.
 

+1



Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-04 Thread Jim Jagielski
I've tried looking into that, and I found it more trouble
than it was worth... (I'm sure that the list archives have
posts about the 'http ping' tests). The problem is that the
OPTIONS request could be that request that kicks the backend
from being a keptalive connection to closing it. :/

On Aug 3, 2013, at 1:26 PM, Stefan Fritsch s...@sfritsch.de wrote:

 Am Freitag, 2. August 2013, 11:21:56 schrieb Eric Covener:
 I think this does not work for GET requests or request without a
 request body.
 Just re-read spec, you are right -- we are abusing this in a module
 as a sort of extended handshake even w/ no body, but not against
 heterogenous backends.
 
 One could do an 'OPTIONS *' request. But I am not sure if that is any 
 better than proxy-initial-not-pooled in terms of performance.
 
 Or a filter could just send the first bytes of the request (less than 
 the request line) and then do a filter flush. If that fails, repeating 
 the request on a different connection would be ok even for non-
 idempotent requests, because we would know that the backend has not 
 received the full request yet. I don't know how many errors this would 
 catch in practice, though.
 



Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-03 Thread Stefan Fritsch
Am Freitag, 2. August 2013, 11:21:56 schrieb Eric Covener:
  I think this does not work for GET requests or request without a
  request body.
 Just re-read spec, you are right -- we are abusing this in a module
 as a sort of extended handshake even w/ no body, but not against
 heterogenous backends.

One could do an 'OPTIONS *' request. But I am not sure if that is any 
better than proxy-initial-not-pooled in terms of performance.

Or a filter could just send the first bytes of the request (less than 
the request line) and then do a filter flush. If that fails, repeating 
the request on a different connection would be ok even for non-
idempotent requests, because we would know that the backend has not 
received the full request yet. I don't know how many errors this would 
catch in practice, though.


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-02 Thread Jim Jagielski
+1 for the theory, but I'm not sure if it's feasible or not.

On Aug 2, 2013, at 5:28 AM, Thomas Eckert thomas.r.w.eck...@gmail.com wrote:

 So I've been seeing lots of proxy: error reading status line from remote 
 server by mod_proxy lately. Usually this is caused by the race condition 
 between checking the connection state and the backend closing the connection 
 due to the keep-alive timeout. As Covener pointed out to me in IRC, using 
 mod_proxy_http's env variable proxy-initial-not-pooled does offer a 
 solution to the problem albeit at the cost of performance.
 
 The call to ap_proxy_http_process_response() in mod_proxy_http.c eventually 
 boils down to ap_rgetline_core() which calls ap_get_brigade() on 
 r-input_filters. This looks to me like a simple input filter might do the 
 trick if it only checked for a possibility to read on the socket and reopens 
 the connection upon failure type reset by peer. I took a short look at 
 core_create_proxy_req() in server/core.c to see how connections are set up 
 and I wonder if it's possible to recreate/reuse that logic in an input 
 filter. If so, this input filter would offer a nice alternative if hard 
 coding this behavior into mod_proxy/core is frowned upon. Simply make the 
 filter dependant on an env variable, just like proxy-initial-not-pooled.
 



Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-02 Thread Thomas Eckert
Yes, the theory thing ... I wish I could have added an experimental patch
for such an input filter but I'm afraid that might take a long time for me
to finish. I'll try though I hope someone more knowledgeable will pick this
up.

On Fri, Aug 2, 2013 at 2:28 PM, Jim Jagielski j...@jagunet.com wrote:

 +1 for the theory, but I'm not sure if it's feasible or not.

 On Aug 2, 2013, at 5:28 AM, Thomas Eckert thomas.r.w.eck...@gmail.com
 wrote:

  So I've been seeing lots of proxy: error reading status line from
 remote server by mod_proxy lately. Usually this is caused by the race
 condition between checking the connection state and the backend closing the
 connection due to the keep-alive timeout. As Covener pointed out to me in
 IRC, using mod_proxy_http's env variable proxy-initial-not-pooled does
 offer a solution to the problem albeit at the cost of performance.
 
  The call to ap_proxy_http_process_response() in mod_proxy_http.c
 eventually boils down to ap_rgetline_core() which calls ap_get_brigade() on
 r-input_filters. This looks to me like a simple input filter might do the
 trick if it only checked for a possibility to read on the socket and
 reopens the connection upon failure type reset by peer. I took a short
 look at core_create_proxy_req() in server/core.c to see how connections are
 set up and I wonder if it's possible to recreate/reuse that logic in an
 input filter. If so, this input filter would offer a nice alternative if
 hard coding this behavior into mod_proxy/core is frowned upon. Simply make
 the filter dependant on an env variable, just like proxy-initial-not-pooled.
 




Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-02 Thread Jim Jagielski
True enough, but that's inelegant ;)

On Aug 2, 2013, at 8:33 AM, Plüm, Rüdiger, Vodafone Group 
ruediger.pl...@vodafone.com wrote:

 The typical way to solve this today is to know the keepalive timeout of the 
 backend and set ttl for this worker to a value a few seconds below.
 
 Regards
 
 Rüdiger
 
 -Ursprüngliche Nachricht-
 Von: Jim Jagielski 
 Gesendet: Freitag, 2. August 2013 14:29
 An: dev@httpd.apache.org
 Betreff: Re: mod_proxy, oooled backend connections and the keep-alive
 race condition
 
 +1 for the theory, but I'm not sure if it's feasible or not.
 
 On Aug 2, 2013, at 5:28 AM, Thomas Eckert thomas.r.w.eck...@gmail.com
 wrote:
 
 So I've been seeing lots of proxy: error reading status line from
 remote server by mod_proxy lately. Usually this is caused by the race
 condition between checking the connection state and the backend closing
 the connection due to the keep-alive timeout. As Covener pointed out to
 me in IRC, using mod_proxy_http's env variable proxy-initial-not-
 pooled does offer a solution to the problem albeit at the cost of
 performance.
 
 The call to ap_proxy_http_process_response() in mod_proxy_http.c
 eventually boils down to ap_rgetline_core() which calls ap_get_brigade()
 on r-input_filters. This looks to me like a simple input filter might
 do the trick if it only checked for a possibility to read on the socket
 and reopens the connection upon failure type reset by peer. I took a
 short look at core_create_proxy_req() in server/core.c to see how
 connections are set up and I wonder if it's possible to recreate/reuse
 that logic in an input filter. If so, this input filter would offer a
 nice alternative if hard coding this behavior into mod_proxy/core is
 frowned upon. Simply make the filter dependant on an env variable, just
 like proxy-initial-not-pooled.
 
 



Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-02 Thread Eric Covener
  +1 for the theory, but I'm not sure if it's feasible or not.

Some other ideas:

* Does something like a select/poll/getpeername() ever tell us of an
error when a write() doesn't?
* Could we give people an Expect: 100-continue option on the initial
client request?


Re: mod_proxy, oooled backend connections and the keep-alive race condition

2013-08-02 Thread Eric Covener
 I think this does not work for GET requests or request without a request body.

Just re-read spec, you are right -- we are abusing this in a module as
a sort of extended handshake even w/ no body, but not against
heterogenous backends.