Project

General

Profile

Redmine and SSL once again - force SSL for logged in sessions

Added by Jesco Freund over 14 years ago

Hi everyone,

I am running Redmine with Mongrel behind an Apache reverse proxy. My intention is now to force usage of an SSL-secured connection as soon as a user logs in. In my Apache configuration, I put the following:

<VirtualHost 127.0.0.1:81>
    ServerName projects.my-domain.tld

    RewriteEngine on
    RewriteLog /var/log/proxy/projects/rewrite.log
    RewriteLogLevel 0
    RewriteRule ^/login(.*) https://projects.my-domain.tld/login$1 [L,R=permanent]

    ProxyRequests Off
    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/
    ProxyPassReverseCookieDomain 127.0.0.1:3000 projects.my-domain.tld

    ProxyPreserveHost On
    <Proxy *>
        Order Deny,Allow
        Allow from all
    </Proxy>
</VirtualHost>

<VirtualHost 127.0.0.0:401>
    ServerName projects.my-domain.tld

    SSLEngine on
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
    SSLCertificateFile "/usr/local/etc/ssl/server-cert.pem" 
    SSLCertificateKeyFile "/usr/local/etc/ssl/server-key.pem" 
    SSLCertificateChainFile "/usr/local/etc/ssl/root.pem" 
    <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
    </FilesMatch>

    BrowserMatch ".*MSIE.*" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0

    <IfModule headers_module>
        RequestHeader set X-FORWARDED-PROTO "https" 
    </IfModule>

    ProxyRequests Off
    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/
    ProxyPassReverseCookieDomain 127.0.0.1:3000 projects.my-domain.tld

    ProxyPreserveHost On
    <Proxy *>
        Order Deny,Allow
        Allow from all
    </Proxy>
</VirtualHost>

At a first glance, this works fine. When pressing the login link, one gets redirected to the HTTPS version of the site. When pressing the login button, the /login method itself is called via HTTPS. However, the /login action redirects to an unecrypted site (production.log):

Processing AccountController#login (for 127.0.0.1 at 2010-04-11 13:45:03) [POST]
  Parameters: {"back_url"=>"http%3A%2F%2Fprojects.my-domain.tld%2F", "action"=>"login", "authenticity_token"=>"123abc=",
 "username"=>"testuser", "controller"=>"account", "password"=>"[FILTERED]", "login"=>"Anmelden \302\273"}
Redirected to http://projects.my-domain.tld/
Completed in 37ms (DB: 33) | 302 Found [https://projects.my-universe.com/login]

I found several tickets dealing with this issue, and everywhere the X_FORWARDED_PROTO header was mentionned. So I set Mongrel to debug mode to get a glance of what's going on. Hell, the X_FORWAREDED_PROTO header is properly set to https:

Sun Apr 11 13:45:03 +0200 2010 REQUEST /login
--- !map:Mongrel::HttpParams
SERVER_NAME: projects.my-universe.com
HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_HOST: projects.my-universe.com
CONTENT_LENGTH: "184" 
HTTP_X_FORWARDED_HOST: projects.my-universe.com
HTTP_USER_AGENT: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100402 Namoroka/3.6.3
REQUEST_PATH: /login
SERVER_PROTOCOL: HTTP/1.1
CONTENT_TYPE: application/x-www-form-urlencoded
HTTP_ACCEPT_LANGUAGE: de-de,de;q=0.8,en-us;q=0.6,en;q=0.4,fr;q=0.2
REMOTE_ADDR: 127.0.10.10
PATH_INFO: /login
SERVER_SOFTWARE: Mongrel 1.1.5
HTTP_CONTENT_LENGTH: "184" 
HTTP_CONTENT_TYPE: application/x-www-form-urlencoded
SCRIPT_NAME: /
HTTP_REFERER: https://projects.my-domain.tld/login
HTTP_COOKIE: _redmine_session=bbb
HTTP_VERSION: HTTP/1.1
HTTP_X_FORWARDED_SERVER: projects.my-domain.tld
HTTP_X_FORWARDED_PROTO: https
REQUEST_URI: /login
SERVER_PORT: "80" 
HTTP_X_FORWARDED_FOR: 12.34.56.79
HTTP_ACCEPT_CHARSET: ISO-8859-1,utf-8;q=0.7,*;q=0.7
REQUEST_METHOD: POST
GATEWAY_INTERFACE: CGI/1.2
HTTP_CONNECTION: Keep-Alive
HTTP_ACCEPT_ENCODING: gzip,deflate

Sun Apr 11 13:45:04 +0200 2010 REQUEST /
--- !map:Mongrel::HttpParams
SERVER_NAME: projects.my-domain.tld
HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_HOST: projects.my-domain.tld
HTTP_X_FORWARDED_HOST: projects.my-domain.tld
HTTP_USER_AGENT: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100402 Namoroka/3.6.3
REQUEST_PATH: /
SERVER_PROTOCOL: HTTP/1.1
HTTP_IF_NONE_MATCH: "\"50fe8f1b7b7fcfc5af81a0f99e802c7e\"" 
HTTP_ACCEPT_LANGUAGE: de-de,de;q=0.8,en-us;q=0.6,en;q=0.4,fr;q=0.2
REMOTE_ADDR: 127.0.10.10
PATH_INFO: /
SERVER_SOFTWARE: Mongrel 1.1.5
SCRIPT_NAME: /
HTTP_COOKIE: _redmine_session=bbb
HTTP_VERSION: HTTP/1.1
HTTP_X_FORWARDED_SERVER: projects.my-domain.tld
REQUEST_URI: /
SERVER_PORT: "80" 
HTTP_X_FORWARDED_FOR: 12.34.56.78
HTTP_ACCEPT_CHARSET: ISO-8859-1,utf-8;q=0.7,*;q=0.7
REQUEST_METHOD: GET
GATEWAY_INTERFACE: CGI/1.2
HTTP_CONNECTION: Keep-Alive
HTTP_ACCEPT_ENCODING: gzip,deflate

Actually, I am more than only a bit confused now. Obviously, the X_FORWAREDED_PROTO header is correctly passed to Mongrel, and yet, the redirect after the login leads to a HTTP URI. The only hint for strange behaviour I could discover is the SERVER_PORT: "80" in the Mongrel debug log - I do not use port 80, neither for http nor for https...

Just to give you the complete information; I installed Redmine and Mongrel from the FreeBSD ports. That's what script/about tells:

About your application's environment
Ruby version              1.8.7 (amd64-freebsd8)
RubyGems version          1.3.5
Rack version              1.0
Rails version             2.3.5
Active Record version     2.3.5
Active Resource version   2.3.5
Action Mailer version     2.3.5
Active Support version    2.3.5
Edge Rails revision       unknown
Application root          /local/usr-local/www/redmine
Environment               production
Database adapter          mysql
Database schema version   20100221100219

Does anybody see the flaw? I am now really at a loss...

Regards,
Jesco


Replies (3)

RE: Redmine and SSL once again - force SSL for logged in sessions - Added by Tim Horemans about 14 years ago

Jesco,

A bit late maybe but i suffered from kind of the same problem today.
The problem lies in the Location header returned from Mongrel, mod_proxy seems to change the host/port in the header but not the http:// part.
Solution:
Enable mod_headers in your httpd.conf:

LoadModule headers_module modules/mod_headers.so

Add the following line between your <Virtualhost> tags:

Header edit Location "^http\:(.*)$" "https:$1"

This solved the problem for me !

Regards,
Tim

RE: Redmine and SSL once again - force SSL for logged in sessions - Added by Jesco Freund about 14 years ago

Hi Tim,

thank you, this did the trick for me.

Regards,
Jesco

RE: Redmine and SSL once again - force SSL for logged in sessions - Added by Felix Schäfer almost 14 years ago

Jesco Freund wrote:

At a first glance, this works fine. When pressing the login link, one gets redirected to the HTTPS version of the site. When pressing the login button, the /login method itself is called via HTTPS. However, the /login action redirects to an unecrypted site (production.log):

The login action will always bump you back to where you came from, i.e. if you came from an unencrypted page to login, it will send you back to the unencrypted page, no matter if login was called over an encrypted connection or not.

Your best bet to secure redmine with SSL is to have it SSL-only no matter what.

    (1-3/3)