C4f1151075b447779af31e99d6cf70e2c6eb47ac
By:
newbie

question regarding ssl setting

May 11, 2017 949 views
Security Server Optimization Ubuntu 16.04

Hello,
i have installed an wildcard ssl from alphassl. and on configuring i used ssl-param from this following post.
https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04

so now i have put all these ssl settings inside snippets/ssl-param.conf

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; always";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

i just added ssl_session_timeout 60m; to the list and change preload to always.

now my question is, are these settings meant to be with with any other certificates other then let's encrypt? im a bit confused are those going to help or degrade ssl negotiation? because on my previous server i used only few of above configs only.

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_session_cache shared:SSL:10m;

also please take a look at the following image, my site initial loading is not that fast i expected. and 6/7 files are now requiring ssl handshake even when they are from the same domain. is this normal??

http://imgur.com/a/89Xyq

@jtittle @hansen

6 Answers

@newbie

Most guides that cover settings for InnoDB make the assumption that you're running MySQL on it's own server as allocating 50-70% of your RAM to the buffer in any other case would most likely be an issue as you'd be severely reducing RAM for other services.

Unless you're experiencing issues, you've ran MySQL Tuner, and it's giving you the same suggestion, I'd keep it set at or around 512M for a 1-2GB instance, but even that may be overkill on a 1GB. I'd even recommend potentially setting it to 256M.

When it comes to MySQL, before changing values, as per recommendations by the sysadmin and developer of MySQL Tuner, you really need to wait 24-48 hours to let MySQL gather details on it's own metrics. If you run MySQL Tuner on a freshly restarted instance of MySQL, it'll tell you the same.

...

In regards to permissions, you shouldn't be using a chmod of 755 on both files and directories. Files should use 644 and directories should be using 755.

By using chmod -R 755 /var/www you're telling the command to recursively set everything from /var/www down to a chmod of 755, regardless of whether it's a file or directory.

Unless you've changed the defaults for files and directories, on Ubuntu, files are normally created with a chmod of 644 and directories with a chmod of 755 by default. So unless you've changed them in some way, shape, or form by running other commands, that step shouldn't really be required.

As far as ownership (chown), that part is correct :).

...

As far as multi-site with NGINX, I used to have a guide that I had written for a client, though I can't seem to find it. I'll have to re-test on my end, though the steps really don't change from one release of PHP or Ubuntu to the next. They may change as WordPress changes the requirements, but beyond WordPress itself, the rest of the steps have no bearing on OS or PHP version (though WordPress does recommend PHP 7.x as of now).

  • @jtittle
    thanks a lot. understood everything.

    i would really appreciate if you search for that guide once again or write a new guide. my production server is already up just waiting for the multi-site setup where i would install my products knowledgebase.

    please please please.......

@newbie

Open up wp-config.php and find:

/* That's all, stop editing! Happy blogging. */

Below it, add:

define( 'WP_ALLOW_MULTISITE', true );

Now login to ./wp-admin and navigate to Tools => Network Setup and choose Sub-Directories.

We'll need to open wp-config.php up once again and below the above define(), we'll add:

define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', false);
define('DOMAIN_CURRENT_SITE', 'yourdomain.com');
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);

So what you end up with is:

/* That's all, stop editing! Happy blogging. */

define( 'WP_ALLOW_MULTISITE', true );

define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', false);
define('DOMAIN_CURRENT_SITE', 'yourdomain.com');
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);

Note: Make sure you change yourdomain.com in the above.

Once you add the above, you'll be asked to log back in to your WordPress Dashboard and you'll see a new option in the admin bar called 'My Sites'. You can add new sites by navigating to:

My Sites => Network Admin => Sites 

For NGINX, you'll want to add the following rewrites to your server block.

if ( !-e $request_filename ) {
    rewrite /wp-admin$ $scheme://$host$uri/ permanent;  
    rewrite ^(/[^/]+)?(/wp-.*) $2 last;                     
    rewrite ^(/[^/]+)?(/.*\.php) $2 last;                   
}

I added the snippet above location /, so what I ended up with is:

if ( !-e $request_filename ) {
    rewrite /wp-admin$ $scheme://$host$uri/ permanent;  
    rewrite ^(/[^/]+)?(/wp-.*) $2 last;                     
    rewrite ^(/[^/]+)?(/.*\.php) $2 last;                   
}

location / {
    try $uri $uri/ /index.php?$args;
}

You'd then restart NGINX for the changes to take. I just tested this on a demo Droplet and it's working as expected, so hopefully that'll help you to get things running :-).

  • @jtittle
    great. im trying as you instructed right away.

    another thing,
    as per wordpress codex
    https://codex.wordpress.org/Nginx

    please look in to the following section from above link

    1. WordPress Multisite Subdirectory rules (only this part in nginx server block)
    map $uri $blogname{
        ~^(?P<blogpath>/[^/]+/)files/(.*)       $blogpath ;
    }
    
    map $blogname $blogid{
        default -999;
    }
    
    1. Better Performance for Static Files in Multisite (full section)

    i believe experts like you will understand that page without any problem. but would you please explain to me those 2 parts in a bit details to me? and should i need it?

  • @jtittle @hansen
    bro, i run into two issues :(

    first
    it seems its generally not possible to enable multi-site on subdirectory level when u have old or customized wordpress install. see this screenshot
    http://imgur.com/a/GzB8Y

    second
    u see, after i setup my server i installed ssl first then redirect my site from non-www to www version using these line in nginx server block. this same line redirect from http to https as well.

    server {
            listen 80 default_server;
            listen [::]:80 default_server;
            server_name mysite.com www.mysite.com;
            return 301 https://www.$server_name$request_uri;
    }
    

    it was working perfectly until i realized, in my wordpress settings > general

    WordPress Address (URL) is  https://www.mysite.com
    Site Address (URL) is   https://www.mysite.com
    

    but on wordpress multi-site setup its asking me this

    Server Address
    
    We recommend you change your siteurl to mysite.com before enabling the network feature. It will still be possible to visit your site using the www prefix with an address like www.mysite.com but any links will not have the www prefix.
    
    Server Address  The internet address of your network will be www.mysite.com.
    

    so i did changed my WordPress Address (URL) & Site Address (URL) to https://mysite.com to continue, but when i type my site address http://mysite.com its only redirect to https://mysite.com but not with www prefix.

    i can go with wordpress sud-domain that ok, but what should i do about www prefix? i must have it.

@newbie

Most of the SSL configuration you've posted can be placed in your nginx.conf file. You don't need it inside each of your server blocks.

So all of this:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

... can be pasted in to nginx.conf within the http block. The only time I would change that around to use configuration in each block is where I needed something different to be used for each site. Since that's rarely the case, I keep the vast majority of all configuration in nginx.conf.

The only three lines you actually need for each server block using SSL are:

    ssl on;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

... and even then, since you're specifying http2 in the listen directive, you don't really even need the first one, so you could just have:

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

And the rest of what you've posted goes in the main configuration file.

...

That being said, using:

ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";

... imposes a very strict cipher suit. In some cases, some clients may not work (especially older browsers), so you may need to use the following (which is for IE6/WinWP support too):

ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

I run with the first as I prefer to be strict on what ciphers are used, but if you have a large audience that isn't primarily tech oriented, thus they may not always be running the latest, the second may be a better option.

...

In terms of speed, SSL is encrypted communication, so slightly slower may be normal. Even though you may be using HTTP/2, that doesn't make up for a lack of compression or optimization elsewhere.

You'll still want to compress all images (TinyPNG, Compressor.io, or on-server), minify JS/CSS, etc -- and cache where possible.

You'll also want to look in to optimizing MySQL/MariaDB -- they all tie in together and only optimizing one won't benefit you much when the whole stack comes in to play.

Hi @newbie

It's a very limited cipher list. I would recommend having a look at Mozilla's generator:
https://mozilla.github.io/server-side-tls/ssl-config-generator/
Just ignore that the generator recommends that you place most of the ssl-configs in the server-block - they can be located in your snippet include file.

But my guess would be that you're not including the intermediates in ssl_certificate and ssl_trusted_certificate file. Can you give your site a spin at:
https://www.ssllabs.com/ssltest/

By the way, does your listen look like this listen 443 ssl http2; including the http2?

Having the full configuration would be helpful, but let's see what jtittle writes.

@newbie

To give you an idea of what can go in nginx.conf, I just pulled this from one of the servers I have in production right now. This is from the latest mainline release, so you may or may not be able to use this specific configuration.

It's meant to more so show what you can put in the file, and keep out of the server blocks.

pcre_jit on;

timer_resolution 100ms;
user nginx nginx;

worker_priority -10;
worker_processes 2;
worker_rlimit_nofile 260000;

events {
    accept_mutex off;
    accept_mutex_delay 200ms;
    use epoll;
    worker_connections 10000;
}


http {
    aio threads;
    charset utf-8;
    default_type application/octet-stream;
    directio 4m;
    index index.php index.html;

    include /etc/nginx/config/mime.types;

    gzip on;
    gzip_vary on;
    gzip_disable "MSIE [1-6]\.";
    gzip_static on;
    gzip_min_length 1400;
    gzip_buffers 32 8k;
    gzip_http_version 1.0;
    gzip_comp_level 5;
    gzip_proxied any;
    gzip_types text/plain text/css text/xml application/javascript application/x-javascript application/xml application/xml+rss application/ecmascript application/json image/svg+xml;

    client_body_buffer_size 256k;
    client_body_in_file_only off;
    client_body_timeout 10s;
    client_header_buffer_size 64k;
    client_header_timeout 5s;
    client_max_body_size 50m;

    map_hash_bucket_size 128;
    map_hash_max_size 4096;

    open_file_cache max=50000 inactive=60s;
    open_file_cache_errors off;
    open_file_cache_min_uses 2;
    open_file_cache_valid 120s;
    open_log_file_cache max=10000 inactive=30s min_uses=2;

    proxy_temp_path /etc/nginx/cache/proxy;
    proxy_buffers 16 32k;
    proxy_buffer_size 64k;
    proxy_busy_buffers_size 128k;
    proxy_cache_bypass $http_pragma $http_authorization;
    proxy_connect_timeout 59s;
    proxy_hide_header X-Powered-By;
    proxy_http_version 1.1;
    proxy_ignore_headers Cache-Control Expires;
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
    proxy_no_cache $http_pragma $http_authorization;
    proxy_pass_header Set-Cookie;
    proxy_read_timeout 600;
    proxy_redirect off;
    proxy_send_timeout 600;
    proxy_temp_file_write_size 64k;
    proxy_set_header Accept-Encoding '';
    proxy_set_header Cookie $http_cookie;
    proxy_set_header Host $host;
    proxy_set_header Proxy '';
    proxy_set_header Referer $http_referer;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Original-Request $request_uri;

    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_ecdh_curve secp384r1;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_session_cache shared:SSL:50m;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_session_tickets off;
    ssl_session_timeout 5m;

    resolver 208.67.222.222 208.67.220.220 valid=300s;
    resolver_timeout 5s;

    connection_pool_size 512;
    ignore_invalid_headers on;
    keepalive_disable msie6;
    keepalive_requests 500;
    keepalive_timeout 5;
    large_client_header_buffers 8 64k;
    lingering_time 20s;
    lingering_timeout 5s;
    max_ranges 1;
    output_buffers 8 256k;
    postpone_output 1460;
    request_pool_size 32k;
    reset_timedout_connection on;
    sendfile on;
    sendfile_max_chunk 512k;
    send_timeout 10s;
    server_names_hash_bucket_size 128;
    server_names_hash_max_size 2048;
    server_name_in_redirect off;
    server_tokens off;
    tcp_nodelay on;
    tcp_nopush on;
    types_hash_max_size 2048;
    variables_hash_max_size 2048;

    include /etc/nginx/sites/enabled/*.conf;
}

In the above -- SSL, Proxy, Resolver, and Index -- all common things most stick in their server blocks -- all of it can be put in the main configuration file without any issues.

I prefer to keep my server blocks as clean as physically possible. It helps with troubleshooting but it also makes it easier to read as just the basics are there, with a few includes for various other things such as caching, blocking bots or access to specific files/directories, etc.

I know the above works with 1.11.x and up, though it should work on 1.10.x as well.

I normally have Brotli configured as well, though I pulled it from the above as that requires a bit more work to get up and running and repository packages don't provide it.

Keep in mind, I normally compile from source, so there's two things above that you will need to change if you use the above:

include /etc/nginx/config/mime.types;

and

include /etc/nginx/sites/enabled/*.conf;

My source compiles use a more organized directory structure than what the default repositories use, so you'd need to change those lines to match your installation.

@jtittle @hansen
you guy's are awesome. my ssllab report showing A+ now. :)

i need to ask u another question regarding mysql 5.7.
i have separate (1gb) db server thats connected with my webserver though private IP. now is it ok to allot higher space for innodb buffer? i have only an wordpress & my application database where all tables are innodb.
i know everyone says 50-70% should be allocated. but since my whole server is mysql dedicated, should i allocate higher? please post your opinion

is there a problem if i add these inside my.cnf

[mysqld]
innodb_buffer_pool_size = 850M
innodb_log_file_size = 128M
innodb_flush_method = O_DIRECT

also, can u guy's point me to any tutorial on enable multi-site on sub-directory for an existing wordpress install on nginx? i read all post thats related here and over other places but none of one i found concrete and for latest versions of php, ubuntu.
the multi-site setup worked for me last time from this community, gave me issue on fastCGI. so i need some expert guidance from you guy's.

one last thing,
i have 3 server blocks, 2 & 3 is on subdomain

  1. main site which is wordpress
  2. application on codeigniter
  3. affilaite program on php

now what permission should for number 2 & 3 document root?
as per DO tutorial,

sudo chown -R $USER:$USER /var/www/test.com/html
sudo chmod -R 755 /var/www

should i follow above? or make permission like user:www-data

best regards,

Have another answer? Share your knowledge.