Uploaded image for project: 'JBoss Enterprise Application Platform'
  1. JBoss Enterprise Application Platform
  2. JBEAP-28295

(7.4.z) UNDERTOW-2033 - secure predicate unreliable with HTTP/2

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • 7.4.20.GA, 7.4.20.CR1
    • None
    • Undertow
    • None
    • False
    • False
    • ?
    • Hide

      Using Http2Server from the Undertow examples, with -Dbind.address=10.224.122.1,
      Using a haproxy configuration listening as HTTP, and forwarding as HTTP2 over SSL:

      global
              maxconn         1000
              ulimit-n        16384
              log             127.0.0.1 local0
              uid             200
              gid             200
              chroot          /var/empty
              daemon
      
      frontend test-proxy
              bind            127.0.0.1:8000
              mode            http
              log             global
              option          httplog
              maxconn         8000
              timeout client  30s
              default_backend test-proxy-srv
      
      backend test-proxy-srv
              mode            http
              timeout connect 5s
              timeout server  5s
              retries         2
      
              server server1 10.224.122.1:8443 ssl alpn h2,http/1.1 maxconn 32 verify none
      

      We run haproxy:

      sudo ./haproxy -f haproxy.cfg -d
      

      We observe:

      # working case
      curl localhost:8000/
      

      We see the correct request in undertow:

      ----------------------------REQUEST---------------------------
                     URI=/
       characterEncoding=null
           contentLength=3
             contentType=[application/x-www-form-urlencoded]
                  header=accept=*/*
                  header=content-length=3
                  header=content-type=application/x-www-form-urlencoded
                  header=user-agent=curl/7.79.1
                  locale=[]
                  method=POST
                protocol=HTTP/2.0
             queryString=
              remoteAddr=/10.224.122.76:42656
              remoteHost=10.224.122.76
                  scheme=https
                    host=null
              serverPort=8443
                isSecure=true
      

      Now with http2:

      # broken case
      curl http://localhost:8000/  --http2-prior-knowledge -v
      < HTTP/2 307 
      < x-undertow-transport: h2
      < location: https://localhost:8363/
      < content-length: 0
      < date: Sat, 19 Feb 2022 16:04:52 GMT
      

      We see the weird request in undertow:

      ----------------------------REQUEST---------------------------
                     URI=/
       characterEncoding=null
           contentLength=3
             contentType=[application/x-www-form-urlencoded]
                  header=accept=*/*
                  header=user-agent=curl/7.79.1
                  header=content-length=3
                  header=content-type=application/x-www-form-urlencoded
                  header=Host=localhost:8000
                  locale=[]
                  method=POST
                protocol=HTTP/2.0
             queryString=
              remoteAddr=/10.224.122.76:42658
              remoteHost=10.224.122.76
                  scheme=http
                    host=localhost:8000
              serverPort=8443
                isSecure=false
      

      isSecure is False as it's deduced from the scheme and host of the query.

      Reproducer:
      assuming you are running the Http2Server from the examples, listening on the default 127.0.0.1:8443 and 127.0.0.1:8080.

      1- This is what you see:

      curl --cacert ./examples/src/main/java/io/undertow/examples/http2/server.pem  https://localhost:8443/
      
      < HTTP/2 200 
      < last-modified: Wed, 08 Jun 2022 07:11:37 GMT
      < cache-control: must-revalidate
      < x-undertow-transport: h2
      < content-type: text/html; charset=UTF-8
      < content-length: 14522
      < date: Wed, 08 Jun 2022 07:11:37 GMT
      
      $ curl http://localhost:8080/ --http2-prior-knowledge -v
      *   Trying 127.0.0.1:8080...
      * TCP_NODELAY set
      * Connected to localhost (127.0.0.1) port 8080 (#0)
      * Using HTTP2, server supports multi-use
      * Connection state changed (HTTP/2 confirmed)
      * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
      * Using Stream ID: 1 (easy handle 0x5574248362f0)
      > GET / HTTP/2
      > Host: localhost:8080
      > user-agent: curl/7.68.0
      > accept: */*
      > 
      * Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)!
      < HTTP/2 307 
      < x-undertow-transport: h2
      < location: https://localhost:8443/
      < content-length: 0
      < date: Wed, 08 Jun 2022 07:12:23 GMT
      < 
      * Connection #0 to host localhost left intact
      

      2- We are now setting up a haproxy to target the insecure port of http2server: write this file

      global
              maxconn         1000
              ulimit-n        16384
              log             127.0.0.1 local0
              daemon
      
      frontend test-proxy
              bind            127.0.0.1:7443 ssl crt ./examples/src/main/java/io/undertow/examples/http2/server.pem
              mode            http
              log             global
              option          httplog
              maxconn         8000
              timeout client  30s
              default_backend test-proxy-srv
      
      backend test-proxy-srv
              mode            http
              timeout connect 5s
              timeout server  5s
              retries         2
      
              server server1 127.0.0.1:8080 proto h2
      

      and run haproxy in this fashion:

      $ haproxy -f haproxy.cfg -d
      [WARNING] 158/100551 (49018) : parsing [haproxy.cfg:8] : 'bind 127.0.0.1:7443' : 
        unable to load default 1024 bits DH parameter for certificate './examples/src/main/java/io/undertow/examples/http2/server.pem'.
        , SSL library will use an automatically generated DH parameter.
      [WARNING] 158/100551 (49018) : Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.
      Available polling systems :
            epoll : pref=300,  test result OK
             poll : pref=200,  test result OK
           select : pref=150,  test result FAILED
      Total: 3 (2 usable), will use epoll.
      
      Available filters :
              [SPOE] spoe
              [COMP] compression
              [CACHE] cache
              [TRACE] trace
      Using epoll() as the polling mechanism.
      

      haproxy connects to the insecure port of Http2Server.

      3- target the haproxy port

      curl --cacert ./examples/src/main/java/io/undertow/examples/http2/server.pem  https://localhost:7443/
      

      Expected result: it should return a redirection to the secure port.

      Actual result: HTTP/1.1 200

      Show
      Using Http2Server from the Undertow examples, with -Dbind.address=10.224.122.1, Using a haproxy configuration listening as HTTP, and forwarding as HTTP2 over SSL: global maxconn 1000 ulimit-n 16384 log 127.0.0.1 local0 uid 200 gid 200 chroot / var /empty daemon frontend test-proxy bind 127.0.0.1:8000 mode http log global option httplog maxconn 8000 timeout client 30s default_backend test-proxy-srv backend test-proxy-srv mode http timeout connect 5s timeout server 5s retries 2 server server1 10.224.122.1:8443 ssl alpn h2,http/1.1 maxconn 32 verify none We run haproxy: sudo ./haproxy -f haproxy.cfg -d We observe: # working case curl localhost:8000/ We see the correct request in undertow: ----------------------------REQUEST--------------------------- URI=/ characterEncoding= null contentLength=3 contentType=[application/x-www-form-urlencoded] header=accept=*/* header=content-length=3 header=content-type=application/x-www-form-urlencoded header=user-agent=curl/7.79.1 locale=[] method=POST protocol=HTTP/2.0 queryString= remoteAddr=/10.224.122.76:42656 remoteHost=10.224.122.76 scheme=https host= null serverPort=8443 isSecure= true Now with http2: # broken case curl http: //localhost:8000/ --http2-prior-knowledge -v < HTTP/2 307 < x-undertow-transport: h2 < location: https: //localhost:8363/ < content-length: 0 < date: Sat, 19 Feb 2022 16:04:52 GMT We see the weird request in undertow: ----------------------------REQUEST--------------------------- URI=/ characterEncoding= null contentLength=3 contentType=[application/x-www-form-urlencoded] header=accept=*/* header=user-agent=curl/7.79.1 header=content-length=3 header=content-type=application/x-www-form-urlencoded header=Host=localhost:8000 locale=[] method=POST protocol=HTTP/2.0 queryString= remoteAddr=/10.224.122.76:42658 remoteHost=10.224.122.76 scheme=http host=localhost:8000 serverPort=8443 isSecure= false isSecure is False as it's deduced from the scheme and host of the query. Reproducer: assuming you are running the Http2Server from the examples, listening on the default 127.0.0.1:8443 and 127.0.0.1:8080. 1- This is what you see: curl --cacert ./examples/src/main/java/io/undertow/examples/http2/server.pem https: //localhost:8443/ < HTTP/2 200 < last-modified: Wed, 08 Jun 2022 07:11:37 GMT < cache-control: must-revalidate < x-undertow-transport: h2 < content-type: text/html; charset=UTF-8 < content-length: 14522 < date: Wed, 08 Jun 2022 07:11:37 GMT $ curl http: //localhost:8080/ --http2-prior-knowledge -v * Trying 127.0.0.1:8080... * TCP_NODELAY set * Connected to localhost (127.0.0.1) port 8080 (#0) * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x5574248362f0) > GET / HTTP/2 > Host: localhost:8080 > user-agent: curl/7.68.0 > accept: */* > * Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)! < HTTP/2 307 < x-undertow-transport: h2 < location: https: //localhost:8443/ < content-length: 0 < date: Wed, 08 Jun 2022 07:12:23 GMT < * Connection #0 to host localhost left intact 2- We are now setting up a haproxy to target the insecure port of http2server: write this file global maxconn 1000 ulimit-n 16384 log 127.0.0.1 local0 daemon frontend test-proxy bind 127.0.0.1:7443 ssl crt ./examples/src/main/java/io/undertow/examples/http2/server.pem mode http log global option httplog maxconn 8000 timeout client 30s default_backend test-proxy-srv backend test-proxy-srv mode http timeout connect 5s timeout server 5s retries 2 server server1 127.0.0.1:8080 proto h2 and run haproxy in this fashion: $ haproxy -f haproxy.cfg -d [WARNING] 158/100551 (49018) : parsing [haproxy.cfg:8] : 'bind 127.0.0.1:7443' : unable to load default 1024 bits DH parameter for certificate './examples/src/main/java/io/undertow/examples/http2/server.pem' . , SSL library will use an automatically generated DH parameter. [WARNING] 158/100551 (49018) : Setting tune.ssl. default -dh-param to 1024 by default , if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear. Available polling systems : epoll : pref=300, test result OK poll : pref=200, test result OK select : pref=150, test result FAILED Total: 3 (2 usable), will use epoll. Available filters : [SPOE] spoe [COMP] compression [CACHE] cache [TRACE] trace Using epoll() as the polling mechanism. haproxy connects to the insecure port of Http2Server. 3- target the haproxy port curl --cacert ./examples/src/main/java/io/undertow/examples/http2/server.pem https: //localhost:7443/ Expected result: it should return a redirection to the secure port. Actual result: HTTP/1.1 200

      Predicates.secure() depends on user input

            rhn-engineering-lgao Lin Gao
            rhn-engineering-lgao Lin Gao
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: