Non mi è consentito pubblicare nella sezione How-To, quindi pubblicherò qui ![]()
Panoramica
L’obiettivo è aggiungere un WAF alle risorse esistenti mantenendo le prestazioni su un’installazione di piccole dimensioni. In questo esempio, utilizzeremo una singola istanza EC2. Poiché Discourse viene eseguito in Docker, siamo in grado di installare NGINX sull’host e utilizzare proxy_pass per instradare il traffico nel nostro contenitore Docker. Stiamo inoltre utilizzando RDS per PostgreSQL.
Configurazione di Discourse
Il nostro primo passo è configurare il file app.yml per un’installazione personalizzata di Discourse. In questo esempio, eseguiremo i ruoli web e redis. Non utilizzeremo il ruolo DB né i ruoli SSL.
Inoltre, vogliamo assicurarci di non esporre le porte web nel contenitore Docker. Il motivo è che esporremo il web tramite il proxy NGINX sull’host.
Esempio di file app.yml
## questo è il template del contenitore Docker Discourse all-in-one, standalone
##
## Dopo aver apportato modifiche a questo file, DEVI ricostruire
## /var/discourse/launcher rebuild app
##
## FAI *MOLTA* ATTENZIONE DURANTE LA MODIFICA!
## I FILE YAML SONO SUPER SUPER SENSIBILI A ERRORI NEGLI SPAZI O NELL'ALLINEAMENTO!
## visita http://www.yamllint.com/ per convalidare questo file se necessario
templates:
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
- "templates/web.socketed.template.yml"
## Scommenta queste due righe se desideri aggiungere Lets Encrypt (https)
#- "templates/web.ssl.template.yml"
#- "templates/web.letsencrypt.ssl.template.yml"
## quali porte TCP/IP deve esporre questo contenitore?
## Se desideri che Discourse condivida una porta con un altro server web come Apache o nginx,
## consulta https://meta.discourse.org/t/17247 per i dettagli
expose:
# - "80:80" # http
# - "443:443" # https
params:
db_default_text_search_config: "pg_catalog.english"
## Imposta db_shared_buffers al massimo al 25% della memoria totale.
## verrà impostato automaticamente da bootstrap in base alla RAM rilevata, oppure puoi sovrascriverlo
db_shared_buffers: "768MB"
## può migliorare le prestazioni di ordinamento, ma aumenta l'utilizzo della memoria per connessione
#db_work_mem: "40MB"
## Quale revisione Git deve utilizzare questo contenitore? (default: tests-passed)
#version: tests-passed
env:
LANG: en_US.UTF-8
# DISCOURSE_DEFAULT_LOCALE: en
## Quanti richieste web simultanee sono supportate? Dipende dalla memoria e dai core della CPU.
## verrà impostato automaticamente da bootstrap in base alle CPU rilevate, oppure puoi sovrascriverlo
UNICORN_WORKERS: 2
## TODO: Il nome di dominio a cui risponderà questa istanza di Discourse
## Obbligatorio. Discourse non funzionerà con un semplice indirizzo IP.
DISCOURSE_HOSTNAME: cloudforums.net
## Scommenta se desideri che il contenitore venga avviato con lo stesso
## hostname (opzione -h) specificato sopra (default "$hostname-$config")
#DOCKER_USE_HOSTNAME: true
## TODO: Elenco di email separate da virgola che diventeranno amministratori e sviluppatori
## all'iscrizione iniziale, ad esempio 'user1@example.com,user2@example.com'
DISCOURSE_DEVELOPER_EMAILS: 'youremail@domain.com'
## TODO: Il server SMTP utilizzato per validare nuovi account e inviare notifiche
## INDIRIZZO SMTP, nome utente e password sono obbligatori
## ATTENZIONE: il carattere '#' nella password SMTP può causare problemi!
DISCOURSE_SMTP_ADDRESS: YOUR_SMTP
DISCOURSE_SMTP_PORT: 587
DISCOURSE_SMTP_USER_NAME: YOUR_SMTP_USERNAME
DISCOURSE_SMTP_PASSWORD: YOUR_SMTP_PASSWORD
#DISCOURSE_SMTP_ENABLE_START_TLS: true # (opzionale, default true)
## Se hai aggiunto il template Lets Encrypt, scommenta qui sotto per ottenere un certificato SSL gratuito
#LETSENCRYPT_ACCOUNT_EMAIL: me@example.com
DISCOURSE_DB_SOCKET: ''
DISCOURSE_DB_USERNAME: YOUR_USERNAME
DISCOURSE_DB_PASSWORD: YOUR_PASSWORD
DISCOURSE_DB_HOST: YOUR_HOST
## L'indirizzo CDN http o https per questa istanza di Discourse (configurato per il recupero)
## consulta https://meta.discourse.org/t/14857 per i dettagli
#DISCOURSE_CDN_URL: https://discourse-cdn.example.com
## Il contenitore Docker è senza stato; tutti i dati sono archiviati in /shared
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
- volume:
host: /var/discourse/shared/standalone/log/var-log
guest: /var/log
## I plugin vanno qui
## consulta https://meta.discourse.org/t/19157 per i dettagli
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
## Qualsiasi comando personalizzato da eseguire dopo la compilazione
run:
- exec: echo "Inizio dei comandi personalizzati"
## Se desideri impostare l'indirizzo email 'From' per la tua prima registrazione, scommenta e modifica:
## Dopo aver ricevuto la prima email di iscrizione, rimetti in commento la riga. Deve essere eseguita solo una volta.
- exec: rails c "SiteSetting.enable_badge_sql = true"
- exec: echo "Fine dei comandi personalizzati"
Inizia l’installazione di Discourse
Clona il repository Discourse
sudo -u root git clone https://github.com/discourse/discourse_docker.git /var/discours
Copia il file app.yml personalizzato per l’installazione
Puoi eseguire il comando seguente per farlo per te. Sostituisci semplicemente il testo “PASTE YOUR FULL APP.YML HERE” con il tuo intero file app.yml.
sudo -u root cat > /var/discourse/containers/app.yml <<\EOF
PASTE YOUR FULL APP.YML HERE
EOF
Esegui la configurazione di Discourse
Avvia la configurazione di Discourse senza prompt utilizzando il comando seguente.
sudo -u yes "" | /var/discourse/./discourse-setup
Discourse dovrebbe impiegare 10-15 minuti per l’installazione.
Installazione di NGINX, WAF e GEOIP
Esegui gli aggiornamenti e installa i prerequisiti
apt update -y
apt upgrade -y
apt -y install libpcre3-dev libssl-dev unzip build-essential daemon libxml2-dev libxslt1-dev libgd-dev libgeoip-dev zlib1g-dev libpcre3
Installa il database MindMax in modo da poter eseguire regole GEO IP in base alla posizione. Puoi utilizzare questo database per instradare o bloccare il traffico in base alla posizione. I nostri log NGINX mostreranno ora il paese dell’utente anche se non attivi il blocco geografico.
sudo add-apt-repository -y ppa:maxmind/ppa
apt update -y
apt install -y libmaxminddb0 libmaxminddb-dev mmdb-bin
Scarica ed estrai NGINX e NAXSI WAF
Nota: Sostituisci NGINX con l’ultima versione
mkdir ~/nginx-waf
wget https://nginx.org/download/nginx-1.16.1.tar.gz -O ~/nginx-waf/nginx.tar.gz
tar xzf ~/nginx-waf/nginx.tar.gz -C ~/nginx-waf
wget https://github.com/nbs-system/naxsi/archive/master.zip -O ~/nginx-waf/waf.zip
unzip ~/nginx-waf/waf.zip -d ~/nginx-waf/
Clona Git il modulo GEO IP2 per NGINX
apt install -y git
git clone https://github.com/leev/ngx_http_geoip2_module.git /etc/ngx_http_geoip2_module
Compila NGINX
Costruiremo uno script per farlo per noi e lo eseguiremo qui sotto
cat > ~/nginx-waf/nginx-1.16.1/install.sh <<\EOF
cd ~/nginx-waf/nginx-1.16.1/
./configure --conf-path=/etc/nginx/nginx.conf --add-module=../naxsi-master/naxsi_src/ --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --user=www-data --group=www-data --with-http_ssl_module --without-mail_pop3_module --without-mail_smtp_module --without-mail_imap_module --without-http_uwsgi_module --add-dynamic-module=/etc/ngx_http_geoip2_module --without-http_scgi_module --prefix=/usr
make
make install
EOF
sh ~/nginx-waf/nginx-1.16.1/install.sh
Crea le regole del firewall
Di seguito, l’impostazione predefinita attiverà il WAF e bloccherà le richieste dannose. Se desideri eseguire il WAF in modalità di apprendimento, puoi farlo aggiungendo Learning Mode al file di regole qui sotto.
cp ~/nginx-waf/naxsi-master/naxsi_config/naxsi_core.rules /etc/nginx/
cat > /etc/nginx/naxsi.rules <<\EOF
SecRulesEnabled;
DeniedUrl "/RequestDenied";
## Controlla le regole Naxsi
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
EOF
Crea il file di configurazione NGINX
Di default in questo file di configurazione, il blocco geografico è commentato, ma puoi scommentarlo e attivarlo se lo desideri.
Nota: Dobbiamo eseguire NGINX SENZA SSL all’inizio. Perché abbiamo bisogno che certbot veda un dominio attivo. Otterremo SSL in un passaggio successivo e in realtà copieremo un nuovo file di configurazione NGINX per sostituire questo
Nota: Sostituisci cloudforums.net con il tuo nome di dominio
cat > /etc/nginx/nginx.conf <<\EOF
#user nobody;
worker_processes 1;
load_module modules/ngx_http_geoip2_module.so;
events {
worker_connections 1024;
}
http {
include mime.types;
include /etc/nginx/naxsi_core.rules;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
geoip2 /etc/geo_ip/GeoLite2-Country.mmdb {
$geoip2_data_country_code source=$remote_addr country iso_code;
$geoip2_data_country_name source=$remote_addr country names en;
}
log_format main_geo '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$geoip2_data_country_code $geoip2_data_country_name';
access_log /var/log/nginx/access.log main_geo;
default_type application/octet-stream;
error_log /var/log/nginx/error.log;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name cloudforums.net;
root /;
location /.well-known/acme-challenge/ {
root /var/www;
}
location / {
return 301 https://$host$request_uri;
include /etc/nginx/naxsi.rules;
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
EOF
Crea lo script upstart per NGINX
Dobbiamo creare uno script per avviare il servizio NGINX.
cat > /etc/init.d/nginx <<\EOF
#! /bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/nginx
NAME=nginx
DESC=nginx
test -x $DAEMON || exit 0
# Includi i valori predefiniti di nginx se disponibili
if [ -f /etc/nginx ] ; then
. /etc/nginx
fi
set -e
case "$1" in
start)
echo -n "Avvio $DESC: "
start-stop-daemon --start --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Arresto $DESC: "
start-stop-daemon --stop --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON
echo "$NAME."
;;
restart|force-reload)
echo -n "Riavvio $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/var/run/nginx.pid --exec $DAEMON
sleep 1 start-stop-daemon --start --quiet --pidfile \
/var/run/nginx.pid --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
reload)
echo -n "Ricaricamento configurazione $DESC: "
start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Utilizzo: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
EOF
systemctl daemon-reload
Crea il file di servizio NGINX
cat > /lib/systemd/system/nginx.service <<\EOF
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
Scarica il database Geo IP Country
mkdir /etc/geo_ip
wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz
gzip -d GeoLite2-Country.mmdb.gz
mv GeoLite2-Country.mmdb /etc/geo_ip/
Abilita e avvia NGINX
systemctl stop apache2
systemctl daemon-reload
systemctl enable nginx
systemctl start nginx
Aggiungi il certificato SSL per il tuo dominio
Non dimenticare di sostituire cloudforums.net con il tuo dominio.com.
mkdir /var/www
apt-get -y update
apt-get -y install letsencrypt
yes "n" | letsencrypt certonly --webroot --agree-tos -w /var/www -d cloudforums.net -m youremail@domain.com
Crea un nuovo file NGINX con le regole SSL
Crea un nuovo file NGINX con il certificato SSL appena scaricato.
Nota: cambia cloudforums.net con il tuo dominio
cat > /etc/nginx/nginx.conf <<\EOF
#user nobody;
worker_processes 1;
load_module modules/ngx_http_geoip2_module.so;
events {
worker_connections 1024;
}
http {
include mime.types;
include /etc/nginx/naxsi_core.rules;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
geoip2 /etc/geo_ip/GeoLite2-Country.mmdb {
$geoip2_data_country_code source=$remote_addr country iso_code;
$geoip2_data_country_name source=$remote_addr country names en;
}
log_format main_geo '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$geoip2_data_country_code $geoip2_data_country_name';
#***********************************************************
#Scommenta per fare il blocco geografico. Di default è impostato solo sugli USA nelle impostazioni sottostanti
#***********************************************************
#map $geoip2_data_country_code $allowed_country {
# default no;
# US yes;
# }
access_log /var/log/nginx/access.log main_geo;
default_type application/octet-stream;
error_log /var/log/nginx/error.log;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name cloudforums.net;
root /;
location /.well-known/acme-challenge/ {
root /var/www;
}
location / {
return 301 https://$server_name$request_uri;
include /etc/nginx/naxsi.rules;
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 443 ssl; listen [::]:443 ssl;
server_name cloudforums.net;
ssl on;
ssl_certificate /etc/letsencrypt/live/cloudforums.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cloudforums.net/privkey.pem;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=63072000;";
ssl_stapling on;
ssl_stapling_verify on;
client_max_body_size 0;
location / {
proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
}
}
# Server HTTPS
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
EOF
Riavvia NGINX
systemctl restart nginx
Ora hai un fantastico WAF open source!! ![]()
Pubblicità senza vergogna
Assicurati di unirti a noi su cloudforums.net se ti è piaciuta questa guida. Saremmo davvero felici di averti qui. Non vendiamo nulla né abbiamo pubblicità. Cerchiamo solo buoni post IT ![]()
