Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Login redirect from / to /app/template/Login.vm changes from https to http #86

Open
ianhinder opened this issue Mar 10, 2022 · 3 comments

Comments

@ianhinder
Copy link

Describe the bug
Login redirect from / to /app/template/Login.vm changes from https to http.

To Reproduce
Steps to reproduce the behavior:

git clone -b features/dependency-mgmt https://github.com/NrgXnat/xnat-docker-compose xnat-docker-compose-test

cd xnat-docker-compose-test

git apply <<'EOF'
diff --git a/docker-compose.yml b/docker-compose.yml
index b381fc3..9cbb863 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -13,6 +13,7 @@ services:
     ports:
       - "80:80"
       - "8080:8080"
+      - "443:443"
     volumes:
       - /var/run/docker.sock:/var/run/docker.sock:ro
       - ./traefik/config/traefik.yml:/etc/traefik/traefik.yml
@@ -61,7 +62,11 @@ services:
       - "8144:8144"
     labels:
       - "traefik.http.routers.xnat-web.rule=PathPrefix(`/`)"
+      - "traefik.http.routers.xnat-web.entrypoints=web"
       - "traefik.http.services.xnat-web.loadbalancer.server.port=8080"
+      - "traefik.http.routers.xnat-web-secure.rule=Host(`example.com`) && PathPrefix(`/`)"
+      - "traefik.http.routers.xnat-web-secure.entrypoints=websecure"
+      - "traefik.http.routers.xnat-web-secure.tls=true"
     volumes:
       - ./xnat-data/archive:/data/xnat/archive
       - ./xnat-data/build:/data/xnat/build
diff --git a/traefik/config/traefik.yml b/traefik/config/traefik.yml
index 3446a96..9f0f963 100644
--- a/traefik/config/traefik.yml
+++ b/traefik/config/traefik.yml
@@ -17,3 +17,9 @@ log:
 accessLog:
   filePath: "/var/log/access.log"
 
+entryPoints:
+  web:
+    address: ":80"
+
+  websecure:
+    address: ":443"
EOF

sudo ./gradlew composeBuild composeUp

Check http on port 80 works:

curl -I -v --resolve example.com:80:127.0.0.1 http://example.com
* Added example.com:80:127.0.0.1 to DNS cache
* Hostname example.com was found in DNS cache
*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to example.com (127.0.0.1) port 80 (#0)
> HEAD / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
HTTP/1.1 302 Found
< Content-Security-Policy: frame-ancestors 'self'
Content-Security-Policy: frame-ancestors 'self'
< Date: Thu, 10 Mar 2022 10:03:07 GMT
Date: Thu, 10 Mar 2022 10:03:07 GMT
< Location: http://example.com/app/template/Login.vm
Location: http://example.com/app/template/Login.vm
< Set-Cookie: JSESSIONID=BF3513D322BDFA96EDBA88BD7C4418E5; Path=/; HttpOnly
Set-Cookie: JSESSIONID=BF3513D322BDFA96EDBA88BD7C4418E5; Path=/; HttpOnly
< Set-Cookie: SESSION_EXPIRATION_TIME="1646906587007,900000"; Version=1; Path=/
Set-Cookie: SESSION_EXPIRATION_TIME="1646906587007,900000"; Version=1; Path=/
< X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
X-Frame-Options: SAMEORIGIN
< X-Xss-Protection: 1; mode=block
X-Xss-Protection: 1; mode=block

< 
* Connection #0 to host example.com left intact

Note the Location line, which gives a correct redirection.

Now check https on port 443:

curl I -v --insecure --resolve example.com:443:127.0.0.1 https://example.com

* Added example.com:443:127.0.0.1 to DNS cache
* Hostname example.com was found in DNS cache
*   Trying 127.0.0.1:443...
* TCP_NODELAY set
* Connected to example.com (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=TRAEFIK DEFAULT CERT
*  start date: Mar 10 09:56:29 2022 GMT
*  expire date: Mar 10 09:56:29 2023 GMT
*  issuer: CN=TRAEFIK DEFAULT CERT
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* 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 0x55c96d7a0880)
> GET / HTTP/2
> Host: example.com
> user-agent: curl/7.68.0
> accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 302 
< content-security-policy: frame-ancestors 'self'
< date: Thu, 10 Mar 2022 10:04:56 GMT
< location: http://example.com/app/template/Login.vm
< set-cookie: JSESSIONID=82EBA7F926B6648064A5BCB4B92215EF; Path=/; HttpOnly
< set-cookie: SESSION_EXPIRATION_TIME="1646906696481,900000"; Version=1; Path=/
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
< content-length: 0
< 
* Connection #0 to host example.com left intact

Note the location: line, which has redirected to http from https. When used in a browser, you can replace the http after redirection with an https, and the rest of XNAT works fine over https, until you get another redirection, at which point it uses http and you need to change it manually to https. Note that it is redirecting to the correct host and path; it's just the scheme (https vs http) that is wrong.

This is all independent of the site URL configured in XNAT; even if you set that to the correct https URL, it breaks in the same way.

Expected behavior
I expect https requests to be redirected to https, not to http.

Screenshots
n/a

Docker server environment (please complete the following information):

  • Host OS: Ubuntu 20.04
  • Docker version: Docker version 20.10.12, build e91ed57
  • docker-compose version: docker-compose version 1.25.0, build unknown
  • Anything else?

Configuration:

  • Branch of XNAT docker-compose project: features/dependency-mgmt
  • Commit hash or tag: 13295cd
  • Environment settings: defaults
  • Configuration:defaults

Additional context

This is a cut down example which makes use of the internal self-signed traefik certificate, and I use --insecure in curl to handle this. I have set up traefik's LetsEncrypt support in this docker-compose file successfully, and everything works apart from this redirect. Once the redirect works, I can add my config to #1 for other people to use.

I don't know if this is caused by XNAT itself, or if the traefik reverse proxying is not working, or if traefik needs to be configured differently to work with XNAT. But it would be great to get this working, as it provides a very simple way to set up https access to XNAT with docker-compose.

@ianhinder ianhinder changed the title [BUG] Short description of issue Login redirect from / to /app/template/Login.vm changes from https to http Mar 10, 2022
@prantikk
Copy link

Hi Ian, Did you find a resolution to this redirect issue?

@jmzumg
Copy link

jmzumg commented Jan 25, 2023

Hey, I was experiencing the same problem (using nginx rather than traefik, but I think it still applies)

I solved it by making the following changes:

  • In my nginx site config, I set the X-Forwarded-Proto header like this: proxy_set_header X-Forwarded-Proto $scheme;
    (I am not sure how to configure this header in traefik, but it should be possible)

  • In my tomcat server.xml, I modified the Host section like this:

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<!-- blah blah blah -->
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>
</Host>

This solved the issue for me.

References:

@ianhinder
Copy link
Author

Apologies; I was able to fix it a while back. Here was my solution:

commit 20b167cb0ada9d22574e4d5bceade485c2eb3481
Author: Ian Hinder <XXX>
Date:   Tue Mar 15 22:57:02 2022 +0000

    Add proxy header configuration to tomcat server.xml during image build
    
    This allows xnat to work correctly behind traefik with TLS

diff --git a/xnat/Dockerfile b/xnat/Dockerfile
index 8021783..b7b2704 100644
--- a/xnat/Dockerfile
+++ b/xnat/Dockerfile
@@ -31,7 +31,7 @@ ADD wait-for-postgres.sh /usr/local/bin/wait-for-postgres.sh
 ADD ${XNAT_PATH} /webapps
 
 RUN apt-get update && \
-    apt-get --yes install postgresql-client wget && \
+    apt-get --yes install postgresql-client wget patch && \
     apt-get --yes --auto-remove upgrade && \
     rm -rf ${CATALINA_HOME}/webapps/* && \
     mkdir -p \
@@ -50,6 +50,10 @@ RUN apt-get update && \
     rm /usr/local/bin/make-xnat-config.sh && \
     apt-get clean
 
+ADD RemoteIpValve.patch /tmp/RemoteIpValve.patch
+RUN patch /usr/local/tomcat/conf/server.xml /tmp/RemoteIpValve.patch
+RUN rm -f /tmp/RemoteIpValve.patch
+
 EXPOSE 8000
 EXPOSE 8080
 
diff --git a/xnat/RemoteIpValve.patch b/xnat/RemoteIpValve.patch
new file mode 100644
index 0000000..ffdd278
--- /dev/null
+++ b/xnat/RemoteIpValve.patch
@@ -0,0 +1,16 @@
+--- server.xml 2022-02-21 21:01:10.000000000 +0000
++++ server.xml 2022-03-15 22:41:45.228952764 +0000
+@@ -137,6 +137,13 @@
+       <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
+       -->
+ 
++      <!-- Ensure that original protocol and port information is
++           available when behind a reverse proxy -->
++      <Valve className="org.apache.catalina.valves.RemoteIpValve"
++             protocolHeader="x-forwarded-proto"
++             portHeader="x-forwarded-port"
++           />
++
+       <!-- Use the LockOutRealm to prevent attempts to guess user passwords
+            via a brute-force attack -->
+       <Realm className="org.apache.catalina.realm.LockOutRealm">

So similar to @jmzumg's solution, though not quite the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants