>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:
relayd.conf:
log state changes
log connection

table <test> { 4.5.6.7 }

http protocol test_http {
   match request header set "X-Forwarded-For" value "$REMOTE_ADDR"
   match request url log
}

relay test {
   listen on 1.2.3.4 port 80
   protocol test_http
   forward to <test> port 80
}

test program:
#!/usr/bin/env ruby

require 'net/http/persistent'

uri = URI.parse('http://someserver')
http = Net::HTTP::Persistent.new
req = Net::HTTP::Options.new(uri.path)
req.body = "asdjhakdjahsdkjsad" if ARGV[1]
http.request(uri, req) if ARGV[0]
req = Net::HTTP::Get.new(uri.path)
http.request(uri, req)
http.request(uri, req)

Just 2 GET queries.
$ ./emptyoptions.rb
relayd log: relay test, session 9 (1 active), 0, 1.2.3.4 -> 5.6.7.8:80, done, 
[User-Agent: Ruby] [someserver/] GET; [User-Agent: Ruby] 
[someserver/] GET;

OPTIONS with some body as the first query.
$ ./emptyoptions.rb 1 1
relayd log: relay test, session 10 (1 active), 0, 1.2.3.4 -> 5.6.7.8:80, done, 
[User-Agent: Ruby] [someserver/] OPTIONS; [User-Agent: Ruby] 
[someserver/] GET; [User-Agent: Ruby] [someserver/] GET;

OPTIONS without body as the first query.
$ ./emptyoptions.rb 1
relayd log: relay test, session 11 (1 active), 0, 1.2.3.4 -> 5.6.7.8:80, done, 
[User-Agent: Ruby] [someserver/] OPTIONS;;;

         <code/input/activities to reproduce the problem (multiple lines)>
 >Fix:
         I'm working on a fix but so far I haven't found one which doesn't 
break some regress test. Avoiding following code path in 
relay_http.c solves the problem.
                         /* Single-pass HTTP body */
                         if (cre->toread < 0) {
                                 cre->toread = TOREAD_UNLIMITED;
                                 bev->readcb = relay_read;
                         }

Reply via email to