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 certificadoPara 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 sshssh-keygen -t rsa
Creamos la llave ssh para el servidorssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
Pasamos el Certificado de Let's Encryptrsync -avi --delete /etc/letsencrypt [email protected]:/etc/
Reiniciamos el serviciossh [email protected] /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 [email protected]:/etc/
ssh [email protected] /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.confEsto 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 2048nano /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 Nginxrm /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/phpmyadminmkdir -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/htmlnano /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







No comments yet