Je ne suis pas autorisé à publier dans la section « How-Tos », je vais donc poster ceci ici ![]()
Aperçu
L’objectif est d’ajouter un WAF (pare-feu d’application web) aux ressources existantes tout en maintenant des performances adéquates sur une petite installation. Dans cet exemple, nous utiliserons une seule instance EC2. Comme Discourse est exécuté dans Docker, nous pouvons installer NGINX sur l’hôte et utiliser la fonction de proxy pass pour acheminer le trafic vers notre conteneur Docker. Nous utilisons également RDS pour PostgreSQL.
Configuration de Discourse
Notre première étape consiste à configurer notre fichier app.yml pour une installation personnalisée de Discourse. Dans cet exemple, nous exécuterons les rôles web et redis. Nous n’utiliserons pas les rôles DB ou SSL.
Nous devons également nous assurer de ne pas exposer les ports web du conteneur Docker. La raison en est que nous exposerons notre interface web via le proxy NGINX sur l’hôte.
Exemple de fichier app.yml
## Ceci est le modèle de conteneur Docker Discourse tout-en-un, autonome
##
## Après avoir apporté des modifications à ce fichier, vous DEVEZ reconstruire
## /var/discourse/launcher rebuild app
##
## SOYEZ TRÈS PRUDENT EN ÉDITANT !
## LES FICHIERS YAML SONT EXTRÊMEMENT SENSIBLES AUX ERREURS D'ESPACEMENT OU D'ALIGNEMENT !
## visitez http://www.yamllint.com/ pour valider ce fichier si nécessaire
templates:
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
- "templates/web.socketed.template.yml"
## Décommentez ces deux lignes si vous souhaitez ajouter Lets Encrypt (https)
#- "templates/web.ssl.template.yml"
#- "templates/web.letsencrypt.ssl.template.yml"
## Quels ports TCP/IP ce conteneur doit-il exposer ?
## Si vous souhaitez que Discourse partage un port avec un autre serveur web comme Apache ou nginx,
## consultez https://meta.discourse.org/t/17247 pour plus de détails
expose:
# - "80:80" # http
# - "443:443" # https
params:
db_default_text_search_config: "pg_catalog.english"
## Définir db_shared_buffers à un maximum de 25 % de la mémoire totale.
## sera défini automatiquement par bootstrap en fonction de la RAM détectée, ou vous pouvez le remplacer
db_shared_buffers: "768MB"
## peut améliorer les performances de tri, mais ajoute une utilisation de la mémoire par connexion
#db_work_mem: "40MB"
## Quelle révision Git ce conteneur doit-il utiliser ? (par défaut : tests-passed)
#version: tests-passed
env:
LANG: en_US.UTF-8
# DISCOURSE_DEFAULT_LOCALE: en
## Combien de requêtes web simultanées sont prises en charge ? Dépend de la mémoire et des cœurs CPU.
## sera défini automatiquement par bootstrap en fonction des CPU détectés, ou vous pouvez le remplacer
UNICORN_WORKERS: 2
## TODO : Le nom de domaine auquel cette instance Discourse répondra
## Requis. Discourse ne fonctionnera pas avec une adresse IP brute.
DISCOURSE_HOSTNAME: cloudforums.net
## Décommentez si vous souhaitez que le conteneur soit démarré avec le même
## nom d'hôte (option -h) que spécifié ci-dessus (par défaut « $hostname-$config »)
#DOCKER_USE_HOSTNAME: true
## TODO : Liste d'e-mails séparés par des virgules qui seront administrateurs et développeurs
## lors de l'inscription initiale, par exemple « user1@example.com,user2@example.com »
DISCOURSE_DEVELOPER_EMAILS: 'votreemail@domain.com'
## TODO : Le serveur de messagerie SMTP utilisé pour valider les nouveaux comptes et envoyer des notifications
# L'adresse SMTP, le nom d'utilisateur et le mot de passe sont requis
# ATTENTION : le caractère '#' dans le mot de passe SMTP peut causer des problèmes !
DISCOURSE_SMTP_ADDRESS: VOTRE_SMTP
DISCOURSE_SMTP_PORT: 587
DISCOURSE_SMTP_USER_NAME: VOTRE_NOM_UTILISATEUR_SMTP
DISCOURSE_SMTP_PASSWORD: VOTRE_MOT_DE_PASSE_SMTP
#DISCOURSE_SMTP_ENABLE_START_TLS: true # (optionnel, par défaut true)
## Si vous avez ajouté le modèle Lets Encrypt, décommentez ci-dessous pour obtenir un certificat SSL gratuit
#LETSENCRYPT_ACCOUNT_EMAIL: moi@example.com
DISCOURSE_DB_SOCKET: ''
DISCOURSE_DB_USERNAME: VOTRE_NOM_UTILISATEUR
DISCOURSE_DB_PASSWORD: VOTRE_MOT_DE_PASSE
DISCOURSE_DB_HOST: VOTRE_HOTE
## L'adresse HTTP ou HTTPS du CDN pour cette instance Discourse (configurée pour récupérer)
## voir https://meta.discourse.org/t/14857 pour plus de détails
#DISCOURSE_CDN_URL: https://discourse-cdn.example.com
## Le conteneur Docker est sans état ; toutes les données sont stockées dans /shared
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
- volume:
host: /var/discourse/shared/standalone/log/var-log
guest: /var/log
## Les plugins vont ici
## voir https://meta.discourse.org/t/19157 pour plus de détails
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
## Toute commande personnalisée à exécuter après la construction
run:
- exec: echo "Début des commandes personnalisées"
## Si vous souhaitez définir l'adresse e-mail « De » pour votre première inscription, décommentez et modifiez :
## Après avoir reçu le premier e-mail d'inscription, re-commentez la ligne. Elle ne doit être exécutée qu'une seule fois.
- exec: rails c "SiteSetting.enable_badge_sql = true"
- exec: echo "Fin des commandes personnalisées"
Démarrage de l’installation de Discourse
Cloner le dépôt Discourse
sudo -u root git clone https://github.com/discourse/discourse_docker.git /var/discours
Copier le fichier app.yml personnalisé pour l’installation
Vous pouvez exécuter la commande ci-dessous pour le faire pour vous. Remplacez simplement le test « COLLEZ VOTRE FICHIER APP.YML COMPLET ICI » par votre fichier app.yml complet.
sudo -u root cat > /var/discourse/containers/app.yml <<\EOF
COLLEZ VOTRE FICHIER APP.YML COMPLET ICI
EOF
Exécuter la configuration de Discourse
Démarrez la configuration de Discourse sans invites en utilisant la commande ci-dessous.
sudo -u yes "" | /var/discourse/./discourse-setup
Discourse devrait prendre 10 à 15 minutes pour s’installer.
Installation de NGINX, WAF et GEOIP
Exécutez les mises à jour et installez les prérequis
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
Installez la base de données MindMax pour pouvoir exécuter des règles GEO IP basées sur la localisation. Vous pouvez utiliser cette base de données pour acheminer ou bloquer le trafic en fonction de la localisation. Nos journaux NGINX afficheront désormais le pays de l’utilisateur, même si vous n’activez pas le blocage géographique. I
sudo add-apt-repository -y ppa:maxmind/ppa
apt update -y
apt install -y libmaxminddb0 libmaxminddb-dev mmdb-bin
Télécharger et extraire NGINX et NAXSI WAF
Remarque : Remplacez NGINX par la dernière version
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/
Cloner le module GEO IP2 pour NGINX via Git
apt install -y git
git clone https://github.com/leev/ngx_http_geoip2_module.git /etc/ngx_http_geoip2_module
Compiler NGINX
Nous allons créer un script pour le faire pour nous et l’exécuter ci-dessous.
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
Créer des règles de pare-feu
La configuration par défaut ci-dessous activera le WAF et bloquera les requêtes malveillantes. Si vous souhaitez exécuter le WAF en mode apprentissage, vous pouvez le faire en ajoutant Learning Mode au fichier de règles ci-dessous.
cp ~/nginx-waf/naxsi-master/naxsi_config/naxsi_core.rules /etc/nginx/
cat > /etc/nginx/naxsi.rules <<\EOF
SecRulesEnabled;
DeniedUrl "/RequestDenied";
## Vérifier les règles Naxsi
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
EOF
Créer le fichier de configuration NGINX
Par défaut, dans ce fichier de configuration, le blocage géographique est commenté, mais vous pouvez le décommenter et l’activer si vous le souhaitez.
Remarque : Nous devons exécuter NGINX SANS SSL au départ. Parce que nous avons besoin que certbot voie un domaine actif. Nous obtiendrons SSL à une étape ultérieure et copierons en réalité un nouveau fichier de configuration NGINX pour le remplacer.
Remarque : Remplacez cloudforums.net par votre nom de domaine
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
Créer un script upstart pour NGINX
Nous devons créer un script pour démarrer le service 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
# Inclure les valeurs par défaut de nginx si disponibles
if [ -f /etc/nginx ] ; then
. /etc/nginx
fi
set -e
case "$1" in
start)
echo -n "Démarrage de $DESC: "
start-stop-daemon --start --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Arrêt de $DESC: "
start-stop-daemon --stop --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON
echo "$NAME."
;;
restart|force-reload)
echo -n "Redémarrage de $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 "Rechargement de la configuration $DESC: "
start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Utilisation : $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
EOF
systemctl daemon-reload
Créer le fichier de service NGINX
cat > /lib/systemd/system/nginx.service <<\EOF
[Unit]
Description=Un serveur web haute performance et un serveur proxy inverse
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
Télécharger la base de données Geo IP par pays
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/
Activer et démarrer NGINX
systemctl stop apache2
systemctl daemon-reload
systemctl enable nginx
systemctl start nginx
Ajouter un certificat SSL pour votre domaine
N’oubliez pas de remplacer cloudforums.net par votre domaine.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 votreemail@domain.com
Créer un nouveau fichier NGINX avec des règles SSL
Créez un nouveau fichier NGINX avec votre certificat SSL que vous venez de télécharger.
Remarque : Remplacez cloudforums.net par votre domaine
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';
#***********************************************************
#Décommentez pour activer le blocage géographique. Par défaut, seul les États-Unis est autorisé dans les paramètres ci-dessous
#***********************************************************
#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;
}
}
# Serveur 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
Redémarrer NGINX
systemctl restart nginx
Vous avez maintenant un WAF open source formidable !! ![]()
Publicité sans vergogne
Assurez-vous de nous rejoindre sur cloudforums.net si vous avez apprécié ce guide. Nous serions ravis de vous avoir parmi nous. Nous ne vendons rien et n’avons pas de publicités. Nous cherchons simplement de bons posts IT ![]()
