#SysAdmin – Optimizando #Let’s encrypt #Nginx

Bueno ya hace unos meses publique el articulo de #SysAdmin – Asegurar nuestro server web nginx+let’s encrypt+securityheaders bueno después de unas cuantas configuraciones he optimizado mi código el cual comparto con ustedes. Actualmente he logrado la migración del lugares de algunos socios como: frcuba.cu, geocuba.cu, minjus.cu, gacetaoficial.cu, jovenclub.cu, uci.cu Espero que tu seas el proximo

Perfeccionado el Let’s Encrypt

Ubiquemos que tenemos una red donde la única pc que saldría directo a Internet seria el firewall, la misma tiene la función de proxy inverso.

A la hora de sacar el certificado hacemos lo siguiente

Instalación del Let’s Encrypt

apt-get install git
git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
cd /opt/letsencrypt

Creación del certificado
Para la creación del mismo recomiendo no tener ningún servidor web funcionando en ese momento es decir tener libre el 80 y 443.

En este caso crear el certificado como para dominio.cu

/etc/init.d/nginx stop
/opt/letsencrypt/letsencrypt-auto certonly --standalone -d dominio.cu -d mail.dominio.cu -d smtp.dominio.cu -d pop.dominio.cu -d pop3.dominio.cu -d imap.dominio.cu -d www.dominio.cu -d webmail.dominio.cu -d proxy.dominio.cu -d download.dominio.cu -d openvpn.dominio.cu
/etc/init.d/nginx start

si se dan cuenta ahí hago referencia en a los dominios siguientes:

dominio.cu  <-- Dominio principal
www.dominio.cu  <-- Server Web
download.dominio.cu  <-- Web de Programas
mail.dominio.cu webmail.dominio.cu pop.dominio.cu pop3.dominio.cu smtp.dominio.cu imap.dominio.cu <-- Server de Correo
proxy.dominio.cu  <-- Server Proxy
openvpn.dominio.cu  <-- Server Openvpn

Esto es para que a la hora de crear los sitios y esas cosas puedas poner un único certificado en las configuraciones de nginx.

Transmitir el certificado a otro servidor

Creamos la llave ssh
ssh-keygen -t rsa

Creamos la llave ssh para el servidor
ssh-copy-id -i ~/.ssh/id_rsa.pub root@www.dominio.cu

Pasamos el Certificado de Let’s Encrypt
rsync -avi –delete /etc/letsencrypt root@www.dominio.cu:/etc/

Reiniciamos el servicio
ssh root@www.dominio.cu /etc/init.d/nginx restart

Todos estos comandos una vez que ya lo hicimos la primera vez lo podemos automatizar en un script para que cuando valla a renovar el certificado lo haga automáticamente:

touch ~/ssl.sh
nano ~/ssl.sh


#!/bin/bash

#
/etc/init.d/nginx stop
/opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log
#/opt/letsencrypt/letsencrypt-auto certonly --standalone -d dominio.cu -d mail.dominio.cu -d smtp.dominio.cu -d pop.dominio.cu -d pop3.dominio.cu -d imap.dominio.cu -d www.dominio.cu -d webmail.dominio.cu -d proxy.dominio.cu -d download.dominio.cu -d openvpn.dominio.cu
/etc/init.d/nginx start

#Server Web
rsync -avi --delete /etc/letsencrypt root@www.dominio.cu:/etc/
ssh root@www.dominio.cu /etc/init.d/nginx restart

Configuración del Nginx

apt-get install nginx

/etc/nginx/nginx.conf

user www-data;
worker_processes 2;
pid /run/nginx.pid;


events {
        worker_connections 768;
}

http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        server_tokens off;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        gzip on;
        gzip_http_version 1.1;
        gzip_vary on;
        gzip_comp_level 6;
        gzip_proxied any;
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
        gzip_buffers 16 8k;
        gzip_disable "MSIE [1-6].(?!.*SV1)";
        gzip_static on;
        ignore_invalid_headers on;
        keepalive_requests 100;
        keepalive_disable none;
        max_ranges 1;
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/ban_tor_net.conf;
        include /etc/nginx/sites-enabled/*;
}

/etc/nginx/ban_tor_net.conf
Esto es un listado que sacamos de https://www.dan.me.uk/torlist/ para banear en el Nginx las IP Tor aunque se aconseja que se DROP a través de iptables tambien

deny 100.0.240.30;
deny 100.11.109.99;
deny 100.34.15.226;
deny 100.36.111.217;
deny 100.36.136.10;
deny 100.38.159.190;
deny 101.100.140.94;
deny 101.100.144.174;
deny 101.164.68.36;
deny 101.167.33.247;
deny 101.55.125.10;
deny 101.98.11.146;
deny 103.10.197.50;

Bueno ahora pasamos a configurar los Virtual Hosts, en este primer momento lo hace como Proxy Inverso, pero primero crearemos archivos y configuraciones que usaremos en todos nuestros sitios:

Baneamos todas las expresiones de Exploits en Nginx
nano /etc/nginx/ban_exploits.conf

## Block SQL injections
    set $block_sql_injections 0;
    if ($query_string ~ "union.*select.*\(") {
        set $block_sql_injections 1;
    }
    if ($query_string ~ "union.*all.*select.*") {
        set $block_sql_injections 1;
    }
    if ($query_string ~ "concat.*\(") {
        set $block_sql_injections 1;
    }
    if ($block_sql_injections = 1) {
        return 403;
    }

    ## Block file injections
    set $block_file_injections 0;
    if ($query_string ~ "[a-zA-Z0-9_]=http://") {
        set $block_file_injections 1;
    }
    if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") {
        set $block_file_injections 1;
    }
    if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") {
        set $block_file_injections 1;
    }
    if ($block_file_injections = 1) {
        return 403;
    }
   ## Block common exploits
    set $block_common_exploits 0;
    if ($query_string ~ "(|%3E)") {
        set $block_common_exploits 1;
    }
    if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") {
        set $block_common_exploits 1;
    }
    if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") {
        set $block_common_exploits 1;
    }
    if ($query_string ~ "proc/self/environ") {
        set $block_common_exploits 1;
    }
    if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") {
        set $block_common_exploits 1;
    }
    if ($query_string ~ "base64_(en|de)code\(.*\)") {
        set $block_common_exploits 1;
    }
    if ($block_common_exploits = 1) {
        return 403;
    }

  ## Block spam
    set $block_spam 0;
    if ($query_string ~ "\b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)\b") {
        set $block_spam 1;
    }
    if ($query_string ~ "\b(erections|hoodia|huronriveracres|impotence|levitra|libido)\b") {
        set $block_spam 1;
    }
    if ($query_string ~ "\b(ambien|blue\spill|cialis|cocaine|ejaculation|erectile)\b") {
        set $block_spam 1;
    }
    if ($query_string ~ "\b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)\b") {
        set $block_spam 1;
    }
    if ($block_spam = 1) {
        return 403;
    }

    ## Block user agents
    set $block_user_agents 0;

    # Don't disable wget if you need it to run cron jobs!
    #if ($http_user_agent ~ "Wget") {
    #    set $block_user_agents 1;
    #}

    # Disable Akeeba Remote Control 2.5 and earlier
    if ($http_user_agent ~ "Indy Library") {
        set $block_user_agents 1;
    }
  # Common bandwidth hoggers and hacking tools.
    if ($http_user_agent ~ "libwww-perl") {
        set $block_user_agents 1;
    }
    if ($http_user_agent ~ "GetRight") {
        set $block_user_agents 1;
    }
    if ($http_user_agent ~ "GetWeb!") {
        set $block_user_agents 1;
    }
    if ($http_user_agent ~ "Go!Zilla") {
        set $block_user_agents 1;
    }
    if ($http_user_agent ~ "Download Demon") {
        set $block_user_agents 1;
    }
    if ($http_user_agent ~ "Go-Ahead-Got-It") {
        set $block_user_agents 1;
    }
    if ($http_user_agent ~ "TurnitinBot") {
        set $block_user_agents 1;
    }
    if ($http_user_agent ~ "GrabNet") {
        set $block_user_agents 1;
    }

    if ($block_user_agents = 1) {
        return 403;
    }

Creamos el favicon que sera para todas nuestras webs en caso que no la tenga y lo ponemos en /var/www
nano /etc/nginx/favicon.conf

location ~ /favicon.ico {
        access_log off;
        log_not_found off;
        alias /var/www/favicon.ico;
}

Personalizamos las pagina de error del nginx
nano /etc/nginx/error.conf

if ($request_method !~ ^(GET|HEAD|POST)$ ) {

                 return 444;

}
error_page 502 /50x.html;
location = /50x.html {

      root  /var/www/;

}
error_page 403 /403.html;
        location = /403.html {
           root /var/www;
       }

Creamos la configuración para todos los Dominios que tendran let’s encrypt
Generate Strong Diffie-Hellman Group

sudo openssl dhparam -out /etc/ssl/certs/dominio.pem 2048

nano /etc/nginx/ssl.conf

resolver 8.8.8.8 valid=300s;
 resolver_timeout 5s;
 ssl_certificate           /etc/letsencrypt/live/dominio.cu/fullchain.pem;
 ssl_certificate_key       /etc/letsencrypt/live/dominio.cu/privkey.pem;
 ssl_trusted_certificate   /etc/letsencrypt/live/dominio.cu/chain.pem;
        ssl on;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_dhparam /etc/ssl/certs/dominio.pem;
        ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
        ssl_session_timeout 1440m;
        ssl_session_cache builtin:1000 shared:SSL:10m;
        spdy_headers_comp 0;
        add_header Strict-Transport-Security "max-age=15768000;";
        add_header X-Xss-Protection "1; mode=block";
        add_header X-Frame-Options "SAMEORIGIN";
#        add_header X-Content-Type-Options "nosniff";
#        add_header X-Permitted-Cross-Domain-Policies "master-only";
        add_header Cache-Control "public";
        add_header Public-Key-Pins 'pin-sha256="94h51gJiEKZVEwaG4r2YHLAOQGepNRzE/PYytHrBr/A="; pin-sha256="YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg="; max-age=2592000';

 location ~ /.well-known {
                allow all;
 }

Eliminamos el VirtualHost por defecto del Nginx
rm /etc/nginx/sites-enabled/default

Ahora para una mejor gestion sugiero crear una conf por cada host virtual que vallas a usar
nano /etc/nginx/sites-enabled/maildominio

server {
 listen 80;
 server_name mail.dominio.cu;
 return 301 https://$host$request_uri;
 include /etc/nginx/ban_exploits.conf;
 include /etc/nginx/favicon.conf;
 include /etc/nginx/error.conf;
}

server {
listen 443 ssl;
 server_name mail.dominio.cu;
 include /etc/nginx/ssl.conf;
 include /etc/nginx/error.conf;
 include /etc/nginx/ban_exploits.conf;
 include /etc/nginx/favicon.conf;
 access_log            /var/log/nginx/mail-access.log;
 error_log            /var/log/nginx/mail-error.log;

location / {
  proxy_set_header        Host $host;
  proxy_set_header        X-Real-IP $remote_addr;
  proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header        X-Forwarded-Proto $scheme;
  proxy_pass          https://192.168.0.2;
  proxy_read_timeout  90;
  proxy_redirect      https://192.168.0.2 https://mail.dominio.cu;
}
location ~ /(\.|wp-config.php|readme.html|license.txt|schema.txt|password.txt|passwords.txt|phpmyadmin|admin|download|iredadmin|traza|colas)
{
        deny all;
}

}

En el caso que quieras habilitar el sitio por http y https seria de la siguiente forma

server {
 listen 80;
 server_name mail.dominio.cu;
 include /etc/nginx/ban_exploits.conf;
 include /etc/nginx/favicon.conf;
 include /etc/nginx/error.conf;

location / {
  proxy_set_header        Host $host;
  proxy_set_header        X-Real-IP $remote_addr;
  proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header        X-Forwarded-Proto $scheme;
  proxy_pass          https://192.168.0.2;
  proxy_read_timeout  90;
  proxy_redirect      https://192.168.0.2 https://mail.dominio.cu;
}
}

server {
listen 443 ssl;
 server_name mail.dominio.cu;
 include /etc/nginx/ssl.conf;
 include /etc/nginx/error.conf;
 include /etc/nginx/ban_exploits.conf;
 include /etc/nginx/favicon.conf;
 access_log            /var/log/nginx/mail-access.log;
 error_log            /var/log/nginx/mail-error.log;

location / {
  proxy_set_header        Host $host;
  proxy_set_header        X-Real-IP $remote_addr;
  proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header        X-Forwarded-Proto $scheme;
  proxy_pass          https://192.168.0.2;
  proxy_read_timeout  90;
  proxy_redirect      https://192.168.0.2 https://mail.dominio.cu;
}
location ~ /(\.|wp-config.php|readme.html|license.txt|schema.txt|password.txt|passwords.txt|phpmyadmin|admin|download|iredadmin|traza|colas)
{
        deny all;
}

}

Ya de esta forma debe funcionarte perfectamente el Nginx Proxy Inverso

Configurando el Nginx Web Server

En /etc/nginx/nginx.conf ponemos la misma conf del nginx proxy inverso acá las cosas donde van a variar es en los virtualhost y a la hora de darle soporte al php.

apt-get install nginx php5-fpm mysql-server-5.6 phpmyadmin

nano /etc/nginx/php.conf

location ~ \.php$ {
        try_files $uri /index.php;
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
}

Creamos la plantila para el phpmyadmin
ln -s /usr/share/phpmyadmin/ /var/www/phpmyadmin
mkdir -p /etc/nginx/templates/
nano /etc/nginx/templates/phpmyadmin.tmpl

set $pma_doc_root /var/www;
set $pma_socket unix:/var/run/php5-fpm.sock;

location /phpmyadmin {
   root $pma_doc_root;
    index index.php index.html index.htm;

    location ~ ^/phpmyadmin/(.+\.php)$ {
        try_files $uri =404;
        root $pma_doc_root;

        fastcgi_pass $pma_socket;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        include /etc/nginx/fastcgi_params;

        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 4k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        fastcgi_intercept_errors on;
        }
    location ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
    root $pma_doc_root;
    }
}

location /phpMyAdmin {
    rewrite ^/* /phpmyadmin last;
}

Si deseamos darle soporte a un sitio para acceder al phpmyadmin solamente tenemos que poner en http o https del virtualhost lo siguiente
include /etc/nginx/templates/phpmyadmin.tmpl;

Creamos el virtual host para www.dominio.cu con soporte para PHP
mkdir -p /var/www/www.dominio.cu/html
nano /etc/nginx/sites-enabled/www

server {
 listen 80;
 server_name www.dominio.cu;
 return 301 https://$host$request_uri;
include /etc/nginx/ban_exploits.conf;
include /etc/nginx/favicon.conf;
}

server {
listen 443 ssl;
server_name www.dominio.cu;
include /etc/nginx/ssl.conf;
include /etc/nginx/php.conf;
include /etc/nginx/ban_exploits.conf;
include /etc/nginx/favicon.conf;
index index.php index.html index.htm;
root /var/www/www.dominio.cu/html;
    index index.php index.html index.htm;

location / {
        try_files $uri $uri/ /index.php?$args ;
}
    access_log  /var/log/nginx/www.dominio.cu-access.log;
    error_log   /var/log/nginx/www.dominio.cu-error.log;
}

Creamos el virtual host para download.dominio.cu con soporte para Indexar
nano /etc/nginx/sites-enabled/download

server {
 listen 80;
 server_name download.dominio.cu;
 return 301 https://$host$request_uri;
include /etc/nginx/ban_exploits.conf;
include /etc/nginx/favicon.conf;
}
server {
listen 443 ssl;
server_name download.dominio.cu;
include /etc/nginx/ssl.conf;
include /etc/nginx/ban_exploits.conf;
include /etc/nginx/favicon.conf;
autoindex on;
root /var/www/download.dominio.cu/html;

location / {
}
    access_log  /var/log/nginx/download.dominio.cu-access.log;
    error_log   /var/log/nginx/download.dominio.cu-error.log;
}

Bueno ya con esto tienes un servidor en Nginx con Let’s Encrypt con todo lo que se debe, cualquier duda o algo me pueden escribir a armandof (at) armandof.com

Share and Enjoy

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

3 pensamientos sobre “#SysAdmin – Optimizando #Let’s encrypt #Nginx

  1. Una duda, teniendo internet(usando proxies) y un dominio de 3 o 4 nivel se podria usar para desplegarlo en una lan? o es obligado para poder usarlo tener IPs de cara a internet?
    Saludos

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*