Best Practice for Securing 52°North Web Services


Using HTTPS as the schema for our services should be considered as the default nowadays. We have documented some best practices on how to set up a Tomcat and place a Proxy server (nginx or apache2) in front of it. The Tomcat is only available on localhost and the Proxy server takes care of all HTTPS related tasks.

This guide focusses on Debian installations. For Windows-based systems, a similar approach might work, but most likely different configurations, SSL Certificate setups and installation guides need to be followed. So, better go for Linux wink

Requirements

  • SSL Certificate
  • Proxy web server, e.g. nginx or apache2
  • java servlet container, e.g. tomcat

Workflow

The following workflow describes how to set-up a secure web server proxy and link it with tomcat. It looks like the following:
  1. Set-Up proxy web server
    1. Configure SSL and proxy module
    2. Optional: Add redirect all or context only to ssl for http (port 80) requests
  2. Set-Up servlet container
    1. Limit to localhost
  3. Set-Up SSL cert
  4. Validate set-up

  1. Set-Up proxy web server
    1. Configure SSL and proxy module
      1. nginx
        • an nginx binary with these modules is required
        • if sudo nginx -V | grep "ngx_http_proxy_module" | grep "http_ssl_module" generates output, the modules are available
        • if not, get an nginx build with these modules
      2. apache2
        • Check the list of active modules for mod_ssl and mod_proxy_http via sudo apache2ctl -M | egrep "ssl|proxy"
        • If you see just Syntax OK: run the following command to enable the required modules: sudo a2enmod ssl ; sudo a2enmod proxy_http. If you need to rewrite the HTML output, activate proxy_http, too.
    2. Configure proxy context for web app and manager. This provides the possibility to add additional security layers like IP filter on proxy level for each webapp differently. In addition, the server landingpage can be served by the web server and not the servlet container.
      • nginx:
        1. Prepare ssl_param:
          user@host:~$ cd /etc/ssl/certs; sudo openssl dhparam -out dhparam.pem 4096; cd -
        2. To enable these site configs, you need to link them into /etc/nginx/sites-enabled/ and force-reload your nginx instance.
          SSL configuration in /etc/nginx/sites-available/:
          upstream tomcat {
                  server 127.0.0.1:8080 fail_timeout=0;
          }
          
          server {
                  listen                          443;
                  server_name                     www.example.com;
                  ssl                             on;
                  ssl_session_timeout             5m;
                  ssl_session_cache               shared:SSL:50m;
                  ssl_dhparam                     /etc/ssl/certs/dhparam.pem;
                  ssl_protocols                   TLSv1 TLSv1.1 TLSv1.2;
                  ssl_ciphers                     'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
                  ssl_prefer_server_ciphers       on; 
                  ssl_certificate                 /etc/ssl/certs/nexos.demo.52north.org.crt;
                  ssl_certificate_key             /etc/ssl/private/nexos.demo.52north.org.key;
          
                  index                           index.html index.htm;
          
                  location = /50x.html { root   /usr/share/nginx/html; }
                  location = /robots.txt  { access_log off; log_not_found off; }
                  location = /favicon.ico { access_log off; log_not_found off; }
                  location ~ /\. { return 404; }
          
          
          
                  location /nginx_status {
                          stub_status on; 
                          access_log   off;
                          allow 127.0.0.1;
                          deny all;
                  }   
          
                  location /manager {
                          client_max_body_size  128m;
                          proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
                          proxy_set_header      Host $http_host;
          # this is the important setting for SSL:
                          proxy_set_header      X-Forwarded-Proto https;
                          proxy_redirect        off;
                          proxy_connect_timeout 240;
                          proxy_send_timeout    240;
                          proxy_read_timeout    240;
                          proxy_pass            http://tomcat;
                          allow                 your.allowed.v4.ip;
                          deny                  all;
                  }   
          
          #        location /52n-supervisor {
          #                proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
          #                proxy_set_header      Host $http_host;
          # this is the important setting for SSL:
          #                proxy_set_header      X-Forwarded-Proto https;
          #                proxy_redirect        off;
          #                proxy_connect_timeout 240;
          #                proxy_send_timeout    240;
          #                proxy_read_timeout    240;
          #                proxy_pass            http://tomcat;
          #                allow                 your.allowed.v4.ip;
          #                deny                  all;
          #        }   
          
                  location / { 
                          proxy_set_header      X-Forwarded-For $proxy_add_x_forwarded_for;
                          proxy_set_header      Host $http_host;
          # this is the important setting for SSL:
                          proxy_set_header      X-Forwarded-Proto https;
                          proxy_redirect        off;
                          proxy_connect_timeout 240;
                          proxy_send_timeout    240;
                          proxy_read_timeout    240;
                          proxy_pass            http://tomcat;
                  }   
           
          }
          Sync with mozilla ssl configuration recommendations to ensure best security set-up.
      • apache2: To enable these site configs, you need to link them into /etc/nginx/sites-enabled/ and force-reload your nginx instance.
        This is the SSL site configuration in /etc/apache2/sites-enabled/:
        <IfModule mod_ssl.c>
        <VirtualHost *:443>
                ServerAdmin webmaster@example.com
                ServerName www.example.com
                ServerAlias example.com
                #
                #       DOCUMENT ROOT
                #
                DocumentRoot /srv/example.com/htdocs/
                <Directory /srv/example.com/htdocs/>
                        Options Indexes MultiViews
                        AllowOverride all
                        Order allow,deny
                        allow from all
                </Directory>
        
                <Location "/manager">
                        Order deny,allow
                        deny from all
                        allow from your.allowed.v4.ip
                </Location>
        
                #
                ServerSignature Off 
                #
                #
                ErrorLog /var/log/apache2/ssl_error.log
                #
                LogLevel warn
                CustomLog /var/log/apache2/ssl_access.log combined
                CustomLog /var/log/apache2/ssl_access_log_time.log common-time
                #
        
                SSLEngine on
                SSLCertificateFile      /etc/ssl/certs/example.com.crt
                SSLCertificateKeyFile   /etc/ssl/private/example.com.pem
                SSLCertificateChainFile /etc/ssl/certs/ca_chain.crt
                SSLCACertificateFile    /etc/ssl/certs/ca_root.crt
                # intermediate configuration, tweak to your needs
                SSLProtocol             all -SSLv2 -SSLv3
                SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
                SSLHonorCipherOrder     on  
            
        </VirtualHost>
        </IfModule>
        Sync with mozilla ssl configuration recommendations to ensure best security set-up.
        In contrast to nginx, apache2 requires the proxy configuration to be placed in /etc/apache2/mods-enabled/proxy.conf:
        <IfModule mod_proxy.c>
        ProxyAddHeaders On
        RequestHeader set X-Forwarded-Proto "https"
        ProxyPass /manager http://127.0.0.1:8080/manager
        ProxyPassReverse /manager https://www.example.com/manager
        
        ProxyPreserveHost On
        
        </IfModule>
    3. Optional: Add redirect all or context only to ssl for http (port 80) requests
      • nginx: Redirect http to https site in /etc/nginx/sites-available/:
         server {
            listen 80; 
            
                if ($remote_addr != 127.0.0.1) {
                  return 301 https://$host$request_uri;
                }   
                if ($request_uri != /nginx_status) {
                  return 301 https://$host$request_uri;
                }   
            
                server_name www.example.com;
            
                location /nginx_status {
                        stub_status on; 
                        access_log   off;
                        allow 127.0.0.1;
                        deny all;
            }   
         
          }
        This example contains the optional redirect all to HTTPS config with /nginx_status context for local monitoring systems.
      • apache2: This configuration pushes all requests to SSL in /etc/apache2/sites-enabled/:
        NameVirtualHost *:80
        <VirtualHost *:80>
           ServerName www.example.com   Redirect permanent / https://www.example.com/ 
        </VirtualHost>
  2. Set-Up servlet container (e.g. apache tomcat 8)
    1. Limit to localhost in /etc/tomcat8/server.xml:
      <?xml version='1.0' encoding='utf-8'?>
      <Server port="8005" shutdown="SHUTDOWN">
        <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
        <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
        <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
        <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
        <GlobalNamingResources>
          <Resource name="UserDatabase" auth="Container"
                    type="org.apache.catalina.UserDatabase"
                    description="User database that can be updated and saved"
                    factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                    pathname="conf/tomcat-users.xml" />
        </GlobalNamingResources>
        <Service name="Catalina">
          <Connector port="8080" protocol="HTTP/1.1"
                     connectionTimeout="20000"
                     URIEncoding="UTF-8"
                     redirectPort="8443"
                     <!-- <=== The next line limits to localhost -->
                     address="127.0.0.1" /> 
          <Engine name="Catalina" defaultHost="localhost">
            <Realm className="org.apache.catalina.realm.LockOutRealm">
              <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                     resourceName="UserDatabase"/>
            </Realm>
            <Host name="localhost"  appBase="webapps"
                  unpackWARs="true" autoDeploy="true">
              <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                     prefix="localhost_access_log" suffix=".txt"
                     pattern="%h %l %u %t &quot;%r&quot; %s %b" />
            </Host>
          </Engine>
        </Service>
      </Server>
  3. Set-Up SSL cert (e.g. Debian based linuxes)
    Abstract steps are the following:
    1. Optional: create certificate signing request (CSR) on the server.
    2. Request certificate from your authority (CA) with or without CSR.
    3. Install CA root and optional chain certificates on your server.
    4. Install your certificate on your server.
    5. Install en-/decrypted private key for your certificate on your server.
    6. Configure your webserver (see steps above).
    7. Reload/-start your server and perform the next step. Detailed steps are available from e.g. http://tcsoftware.net/blog/2012/02/installing-class-1-startssl-certificate-on-debian/
  4. Validate set-up e.g. https://ssllabs.com/ssltest/analyze.html?d=your.newly.secured.host.example.com

Issues

External References

Topic revision: r2 - 26 Apr 2016 10:45:56, EikeJuerrens
This site is powered by FoswikiCopyright &© by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki? Send feedback