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

mod_cluster proxy: If jvmRoute contains symbol = session stickiness is broken

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Minor Minor
    • None
    • 7.0.0.ER7
    • Documentation, Undertow
    • None
    • Hide
      According to mod_cluster management protocol, equals {{=}} is a legitimate symbol in jvmRoute. The default configuration of Undertow AJP and HTTP listeners does not allow this symbol to occur in cookies values. The result is that Undertow mod_cluster proxy fails to keep session stickiness, without any warning.

      User can mitigate the aforementioned result by explicitly setting {{allow-equals-in-cookie-value}} to {{true}} for both balancer's HTTP and worker's AJP connectors.
      Show
      According to mod_cluster management protocol, equals {{=}} is a legitimate symbol in jvmRoute. The default configuration of Undertow AJP and HTTP listeners does not allow this symbol to occur in cookies values. The result is that Undertow mod_cluster proxy fails to keep session stickiness, without any warning. User can mitigate the aforementioned result by explicitly setting {{allow-equals-in-cookie-value}} to {{true}} for both balancer's HTTP and worker's AJP connectors.
    • Not Yet Documented

      Problem

      If jvmRoute contains symbol =, the session stickiness breaks. The following example operates with a jvmRoute that contain dots and other symbols, but the issue is reproducible wit as simple jvmRoute as: worker=1. The symbol should be properly parsed and used or rejected as suspicious, alongside with < and such. I incline to the former, i.e. parsing it properly.

      Symptoms

      • session ID remains the same
      • jvmRoute appended to the session ID remains the same – which is especially misleading
      • the servlet is actually executed on random nodes, see undermentioned example

      Example

      Client

      date;curl 192.168.122.172:8080/clusterbench/requestinfo -b cookie.txt -c cookie.txt

      Test

      Follows sequence of client and server log outputs, note header's Cookie=JSESSIONID=... and servlet's JVM route:

      Client event
      Mon Apr  4 05:29:56 EDT 2016
      Headers: {Cookie=JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=..., Accept=*/*, User-Agent=curl/7.29.0, X-Forwarded-Proto=http, X-Forwarded-Host=192.168.122.172, X-Forwarded-For=192.168.122.172, Host=192.168.122.172:8080, Content-Length=0, X-Forwarded-Port=8080, X-Forwarded-Server=192.168.122.172}
      JVM route: .worker.-2=...
      Session ID: YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca
      Session isNew: false
      Session ServletContext: io.undertow.servlet.spec.ServletContextImpl@492e9e9d
      
      Server event
      05:29:56,395 DEBUG [io.undertow.server.handlers.proxy] (default I/O-4) Sending request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      05:29:56,395 DEBUG [io.undertow.server.handlers.proxy] (default I/O-4) Sent request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      05:29:56,396 DEBUG [io.undertow.request] (default I/O-4) suspending writes on io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel@655c8ba8 to prevent listener runaway
      05:29:56,403 DEBUG [io.undertow.server.handlers.proxy] (default I/O-4) Received response io.undertow.client.ClientResponse@1b177dc5 for request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      
      Client event
      Mon Apr  4 05:29:56 EDT 2016
      Headers: {Cookie=JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=..., Accept=*/*, User-Agent=curl/7.29.0, X-Forwarded-Proto=http, X-Forwarded-Host=192.168.122.172, X-Forwarded-For=192.168.122.172, Host=192.168.122.172:8080, Content-Length=0, X-Forwarded-Port=8080, X-Forwarded-Server=192.168.122.172}
      JVM route: .worker.-2=...
      Session ID: YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca
      Session isNew: false
      Session ServletContext: io.undertow.servlet.spec.ServletContextImpl@492e9e9d
      
      Server event
      05:29:56,859 DEBUG [io.undertow.server.handlers.proxy] (default I/O-3) Sending request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      05:29:56,860 DEBUG [io.undertow.server.handlers.proxy] (default I/O-3) Sent request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      05:29:56,860 DEBUG [io.undertow.request] (default I/O-3) suspending writes on io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel@18859d68 to prevent listener runaway
      05:29:56,867 DEBUG [io.undertow.server.handlers.proxy] (default I/O-3) Received response io.undertow.client.ClientResponse@366ef93b for request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      
      05:29:56,891 DEBUG [io.undertow] (default I/O-4) UT005040: Gonna send payload:
      HTTP/1.0 200 OK
      Date: Mon, 4 Apr 2016 05:29:56 -0400
      Sequence: 217
      Digest: b28e7f72ae2c17ba6971bf5eeac50d45
      Server: fbacdea8-4950-4c32-a064-91ff48db17e1
      X-Manager-Address: rhel7GAx86-64:8080
      X-Manager-Url: /
      X-Manager-Protocol: httpd
      X-Manager-Host: rhel7GAx86-64
      
      Client event
      Mon Apr  4 05:29:57 EDT 2016
      Headers: {Cookie=JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=..., Accept=*/*, User-Agent=curl/7.29.0, X-Forwarded-Proto=http, X-Forwarded-Host=192.168.122.172, X-Forwarded-For=192.168.122.172, Host=192.168.122.172:8080, Content-Length=0, X-Forwarded-Port=8080, X-Forwarded-Server=192.168.122.172}
      JVM route: ......worker.-1=...
      Session ID: YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca
      Session isNew: false
      Session ServletContext: io.undertow.servlet.spec.ServletContextImpl@66524317
      
      Server event
      05:29:57,349 DEBUG [io.undertow.server.handlers.proxy] (default I/O-2) Sending request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      05:29:57,349 DEBUG [io.undertow.server.handlers.proxy] (default I/O-2) Sent request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      05:29:57,349 DEBUG [io.undertow.request] (default I/O-2) suspending writes on io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel@7839d343 to prevent listener runaway
      05:29:57,353 DEBUG [io.undertow.server.handlers.proxy] (default I/O-2) Received response io.undertow.client.ClientResponse@73974106 for request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      
      Client event
      Mon Apr  4 05:29:57 EDT 2016
      Headers: {Cookie=JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=..., Accept=*/*, User-Agent=curl/7.29.0, X-Forwarded-Proto=http, X-Forwarded-Host=192.168.122.172, X-Forwarded-For=192.168.122.172, Host=192.168.122.172:8080, Content-Length=0, X-Forwarded-Port=8080, X-Forwarded-Server=192.168.122.172}
      JVM route: .worker.-2=...
      Session ID: YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca
      Session isNew: false
      Session ServletContext: io.undertow.servlet.spec.ServletContextImpl@492e9e9d
      
      Server event
      05:29:57,860 DEBUG [io.undertow.server.handlers.proxy] (default I/O-1) Sending request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      05:29:57,860 DEBUG [io.undertow.server.handlers.proxy] (default I/O-1) Sent request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} to target 192.168.122.172 for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      05:29:57,860 DEBUG [io.undertow.request] (default I/O-1) suspending writes on io.undertow.protocols.ajp.AjpClientRequestClientStreamSinkChannel@16c1c959 to prevent listener runaway
      05:29:57,873 DEBUG [io.undertow.server.handlers.proxy] (default I/O-1) Received response io.undertow.client.ClientResponse@327d939 for request ClientRequest{path='/clusterbench/requestinfo', method=GET, protocol=HTTP/1.1} for exchange HttpServerExchange{ GET /clusterbench/requestinfo request {Accept=[*/*], Cookie=[JSESSIONID=YB7hKkXeSW0iMK-l7ouJ4fwF1w8wxxtn-qaRtSca.......worker.-1=...], User-Agent=[curl/7.29.0], Host=[192.168.122.172:8080]} response {X-Powered-By=[Undertow/1], Server=[JBoss-EAP/7]}}
      

      Expected result

      Both workers are available and sticky sessions are enabled – we expect to keep having responses from single worker with the same session.

      WDYT?

              zrhoads Zach Rhoads (Inactive)
              mbabacek1@redhat.com Karm Karm
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: