On Sun, May 12, 2019 at 09:03:20PM +0000, Rivo Nurges wrote:
> >Synopsis:      one side of the http relay gets changed to tcp relay if first 
> >query of the persistent connection is empty OPTIONS
>  >Category:      system
>  >Environment:
>          System      : OpenBSD 6.5
>          Details     : OpenBSD 6.5-current (GENERIC.MP) #11: Mon May  6 
> 17:40:38 MDT 2019
>                           
> [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> 
>          Architecture: OpenBSD.amd64
>          Machine     : amd64
>  >Description:
>       When first query of persistent http connection is OPTIONS without body 
> one direction of the session gets changed to tcp relay. The session 
> still works but eg appending request headers stops happening.
> 
>  >How-To-Repeat:

Thanks for the report!  I was able to reproduce it.

In the general case, relayd should add a Connection: close header to
prevent a persistent connection after switching to TOREAD_UNLIMITED.
It will cause the server to close the connection after handling the
request (or, at least, kindly asking it to do so) and subsequent
requests will open a new connection.

The attached diff fixes the test case for me.

Ideally, methods like OPTIONS with optional body would have a
case-by-case handling to work in a persistent way, but this can be
done later.  We'd have to identify such methods and switch to
TOREAD_HTTP_HEADER instead of TOREAD_UNLIMITED, but only if we're sure
that it will not include a body without Content-Length.  [...] closing
the connection after one request is a safer fix for now.

OK?

Reyk

Index: usr.sbin/relayd/relay_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay_http.c,v
retrieving revision 1.75
diff -u -p -u -p -r1.75 relay_http.c
--- usr.sbin/relayd/relay_http.c        13 May 2019 09:54:07 -0000      1.75
+++ usr.sbin/relayd/relay_http.c        13 May 2019 10:17:44 -0000
@@ -522,6 +522,15 @@ relay_read_http(struct bufferevent *bev,
                        bev->readcb = relay_read_httpchunks;
                }
 
+               /*
+                * Ask the server to close the connection after this request
+                * since we don't read any further request headers.
+                */
+               if (cre->toread == TOREAD_UNLIMITED)
+                       if (kv_add(&desc->http_headers, "Connection",
+                           "close", 0) == NULL)
+                               goto fail;
+
                if (cre->dir == RELAY_DIR_REQUEST) {
                        if (relay_writerequest_http(cre->dst, cre) == -1)
                            goto fail;

Reply via email to