TLS: Cipher Specific hardening for a Posit server

Follow

When hardening your Posit servers, there are a number of options available:


Posit Workbench: https://docs.posit.co/ide/server-pro/access_and_security/access_and_security.html

Posit Connect: https://docs.posit.co/connect/admin/security/#strong-https

Posit Package Manager: https://docs.posit.co/rspm/admin/security

 

To this end, our most common support request is for stronger HTTPS protocols. Each product has an  allowance for broad-stroke TLS version configuration:


In Workbench:  

# /etc/rstudio/rserver.conf
ssl-protocols=TLSv1.2 TLSv1.3

https://docs.posit.co/ide/server-pro/access_and_security/secure_sockets.html#ssl-protocols


In Connect:

# /etc/rstudio/rstudio-connect.gcfg

[HTTPS] Listen = 443 MinimumTLS = 1.2

https://docs.posit.co/connect/admin/security/#strong-https


In Package Manager:

# /etc/rstudio-pm/rstudio-pm.gcfg

[HTTPS]
Listen = 443
MinimumTLS = 1.2  

https://docs.posit.co/rspm/admin/security/#strong-https

 

With Connect and Package Manager, we are often asked for fine-grained, per-cipher, exclusion options - here is what this type of request might look like:


"We need to disable TLSv1.1 and we need to disable DES, 3DES, IDEA, and RC2 ciphers, on our HTTPS/SSL enabled RStudio Package Manager instance."


Unfortunately, due to decisions outside of our control(1) we no longer offer the HTTPS.ExcludedCiphers configuration option, and our advice is putting the server behind a reverse proxy and utilising that proxy's cipher suite modules.


This document will go through the setting up of both nginx and apache2 proxies, and how to then configure each of Connect and Package Manager accordingly.


Using nginx as a reverse proxy


Connect

Using what we know from the simple Connect and proxy set up, we will add the necessary lines to the appropriate nginx configuration file.


First, set up the nginx configuration per the appropriate documentation:
https://docs.posit.co/connect/admin/proxy/#simple-configuration


Then, using the ssl_ciphers syntax
http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers

 

and using the openssl library's format described here:
https://www.openssl.org/docs/man1.1.1/man1/ciphers.html


For the above request "we need to disable DES, 3DES, IDEA, and RC2 ciphers", this is what we want to see:

 

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''    close;
    }
    server {
        listen 80;
        client_max_body_size 0; # Disables checking of client request body size
        ssl_prefer_server_ciphers on;
        ssl_ciphers -DES:-3DES:-IDEA:-RC2;

        location / {
            proxy_set_header X-RSC-Request $scheme://$http_host$request_uri;
            proxy_pass http://localhost:3939;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_http_version 1.1;
            proxy_buffering off; # Required for XHR-streaming
        }
    }
}


Note that we have added the directive ssl_prefer_server_ciphers as well - this is because a server will naturally default to the client's cipher choice.


Package Manager


For Package Manager, it will be the same two lines, added to the appropriate nginx configuration:
https://docs.posit.co/rspm/admin/proxy/#nginx-configuration

 

  http {
    map $http_upgrade $connection_upgrade {
      default upgrade;
      ''  close;
  }
    server {
      listen 80;
      ssl_prefer_server_ciphers on;
      ssl_ciphers -DES:-3DES:-IDEA:-RC2;
      location / {
        proxy_set_header X-RSPM-Request
        $scheme://$host:$server_port$request_uri;
        proxy_pass <http://localhost:4242>;
    }
  }
}


Using Apache as a reverse proxy

Connect

Using what we know from the simple Connect and proxy set up, we will add the necessary lines to the appropriate apache configuration file.


First, set up the apache configuration per the appropriate documentation:
https://docs.posit.co/connect/admin/proxy/#simple-configuration_1


Then, using the SSLCipherSuite syntax
https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html#onlystrong


and using the openssl library's format described here:
https://www.openssl.org/docs/man1.1.1/man1/ciphers.html

For the above request "we need to disable DES, 3DES, IDEA, and RC2 ciphers", this is what we want to see:

 

  LoadModule ssl_module modules/mod_ssl.so
  Listen 80
  
  <VirtualHost *:80>
  SSLCipherSuite -DES:-3DES:-IDEA:-RC2
  
RewriteEngine on # store variable values with dummy rewrite rules RewriteRule . - [E=req_scheme:%{REQUEST_SCHEME}] RewriteRule . - [E=http_host:%{HTTP_HOST}] RewriteRule . - [E=req_uri:%{REQUEST_URI}] # set header with variables RequestHeader set X-RSC-Request "%{req_scheme}e://%{http_host}e%{req_uri}e" # unprefixed websocket proxying RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteCond %{HTTP:Connection} upgrade [NC] RewriteRule ^/(.*) "ws://localhost:3939/$1" [P,L] <Location /> ProxyPass http://localhost:3939/ connectiontimeout=5 </Location> </VirtualHost>

 

Package Manager


For Package Manager, it will be the same two lines, added to the appropriate apache configuration:

https://docs.posit.co/rspm/admin/proxy/#apache-configuration

 

  LoadModule ssl_module modules/mod_ssl.so
  Listen 3737

  <VirtualHost *:3737>
    SSLCipherSuite -DES:-3DES:-IDEA:-RC2
    RewriteEngine on
    RequestHeader set X-RSPM-Request "%{REQUEST_SCHEME}s://%{HTTP_HOST}s%{REQUEST_URI}s"
    ProxyPass / <http://172.17.0.1:4242/>
    ProxyPassReverse / <http://172.17.0.1:4242/>
  </VirtualHost>

 

These are relatively simple changes to implement - if you have a need to cipher specific hardening, this is the process Posit will recommend.

 

Workbench

Workbench doesn't need a separate reverse proxy in front to implement per-cipher hardening - there is a proxy already built in. You can customise the default proxy by editing the file /etc/rstudio/nginx.server.conf to look like this:

# /etc/rstudio/nginx.server.conf

ssl_prefer_server_ciphers on;
ssl_ciphers -DES:-3DES:-IDEA:-RC2;

 

Update

Note that newer versions of openssl and TLS might require a different syntax - shown here for nginx:

ssl_protocols TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384;
ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384;
ssl_prefer_server_ciphers off;

 

1: See this discussion in the Go language about removing per-cipher exclusions:

https://github.com/golang/go/issues/29349

 

 

 

Comments