لا يُسمح لي بالنشر في قسم “كيفية القيام بذلك”، لذا سأقوم بنشر هذا هنا ![]()
نظرة عامة
الهدف هو إضافة جدار حماية لتطبيقات الويب (WAF) إلى الموارد الحالية مع الحفاظ على الأداء في تثبيت صغير. في هذا المثال، سنستخدم مثيل EC2 واحدًا. نظرًا لأن Discourse يعمل داخل حاويات Docker، فإننا نستطيع تثبيت NGINX على المضيف واستخدام توجيه البروكسي (proxy_pass) لتوجيه حركة المرور إلى حاوية Docker الخاصة بنا. كما أننا نستخدم RDS لقاعدة بيانات PostgreSQL.
تكوين Discourse
خطوتنا الأولى هي تكوين ملف app.yml الخاص بنا لتثبيت مخصص لـ Discourse. في هذا المثال، سنقوم بتشغيل أدوار الويب و Redis. لن نستخدم دور قاعدة البيانات (DB) أو أدوار SSL.
كما نريد التأكد من عدم تعريض منافذ الويب داخل حاوية Docker. والسبب في ذلك هو أننا سنقوم بعرض الويب عبر بروكسي NGINX على المضيف.
مثال على ملف app.yml
## هذا هو قالب حاوية Docker لـ Discourse الكل في واحد ومستقل
##
## بعد إجراء تغييرات على هذا الملف، يجب عليك إعادة البناء
## /var/discourse/launcher rebuild app
##
## كن حذرًا جدًا عند التعديل!
## ملفات YAML حساسة للغاية للأخطاء في المسافات البيضاء أو المحاذاة!
## قم بزيارة http://www.yamllint.com/ للتحقق من صحة هذا الملف حسب الحاجة
templates:
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
- "templates/web.socketed.template.yml"
## قم بإلغاء التعليق عن هذين السطرين إذا كنت ترغب في إضافة Lets Encrypt (https)
#- "templates/web.ssl.template.yml"
#- "templates/web.letsencrypt.ssl.template.yml"
## ما هي منافذ TCP/IP التي يجب أن تعرضها هذه الحاوية؟
## إذا كنت ترغب في مشاركة Discourse لمنفذ مع خادم ويب آخر مثل Apache أو nginx،
## راجع https://meta.discourse.org/t/17247 للحصول على التفاصيل
expose:
# - "80:80" # http
# - "443:443" # https
params:
db_default_text_search_config: "pg_catalog.english"
## قم بتعيين db_shared_buffers إلى الحد الأقصى 25% من إجمالي الذاكرة.
## سيتم تعيينها تلقائيًا بواسطة bootstrap بناءً على ذاكرة الوصول العشوائي المكتشفة، أو يمكنك تجاوزها
db_shared_buffers: "768MB"
## يمكن أن يحسن أداء الفرز، لكنه يضيف استخدام الذاكرة لكل اتصال
#db_work_mem: "40MB"
## أي إصدار Git يجب أن تستخدمه هذه الحاوية؟ (الافتراضي: tests-passed)
#version: tests-passed
env:
LANG: en_US.UTF-8
# DISCOURSE_DEFAULT_LOCALE: en
## كم عدد طلبات الويب المتزامنة المدعومة؟ يعتمد على الذاكرة ونوى المعالج.
## سيتم تعيينها تلقائيًا بواسطة bootstrap بناءً على المعالجات المكتشفة، أو يمكنك تجاوزها
UNICORN_WORKERS: 2
## TODO: اسم النطاق الذي ستستجيب له هذه المثيلة من Discourse
## مطلوب. لن يعمل Discourse مع عنوان IP مجرد.
DISCOURSE_HOSTNAME: cloudforums.net
## قم بإلغاء التعليق إذا كنت تريد بدء الحاوية بنفس
## اسم المضيف (خيار -h) المحدد أعلاه (الافتراضي "$hostname-$config")
#DOCKER_USE_HOSTNAME: true
## TODO: قائمة عناوين البريد الإلكتروني المفصولة بفواصل والتي سيتم تعيينها كمسؤول ومطور
## عند التسجيل الأولي، على سبيل المثال 'user1@example.com,user2@example.com'
DISCOURSE_DEVELOPER_EMAILS: 'youremail@domain.com'
## TODO: خادم البريد SMTP المستخدم للتحقق من الحسابات الجديدة وإرسال الإشعارات
## عنوان SMTP واسم المستخدم وكلمة المرور مطلوبة
## تحذير: قد يتسبب حرف '#' في كلمة مرور SMTP في مشاكل!
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 # (اختياري، الافتراضي true)
## إذا أضفت قالب Lets Encrypt، قم بإلغاء التعليق أدناه للحصول على شهادة SSL مجانية
#LETSENCRYPT_ACCOUNT_EMAIL: me@example.com
DISCOURSE_DB_SOCKET: ''
DISCOURSE_DB_USERNAME: YOUR_USERNAME
DISCOURSE_DB_PASSWORD: YOUR_PASSWORD
DISCOURSE_DB_HOST: YOUR_HOST
## عنوان CDN http أو https لهذه المثيلة من Discourse (مُهيأ للسحب)
## راجع https://meta.discourse.org/t/14857 للحصول على التفاصيل
#DISCOURSE_CDN_URL: https://discourse-cdn.example.com
## حاوية Docker غير حالة؛ يتم تخزين جميع البيانات في /shared
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
- volume:
host: /var/discourse/shared/standalone/log/var-log
guest: /var/log
## تذهب الإضافات هنا
## راجع https://meta.discourse.org/t/19157 للحصول على التفاصيل
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
## أي أوامر مخصصة للتشغيل بعد البناء
run:
- exec: echo "Beginning of custom commands"
## إذا كنت ترغب في تعيين عنوان البريد الإلكتروني 'من' لتسجيلك الأول، قم بإلغاء التعليق وتغيير:
## بعد الحصول على بريد التسجيل الأول، قم بإعادة التعليق على السطر. يجب تشغيله مرة واحدة فقط.
- exec: rails c "SiteSetting.enable_badge_sql = true"
- exec: echo "End of custom commands"
بدء تثبيت Discourse
استنساخ مستودع Discourse
sudo -u root git clone https://github.com/discourse/discourse_docker.git /var/discours
نسخ app.yml المخصص للتثبيت
يمكنك تشغيل الأمر أدناه للقيام بذلك نيابةً عنك. فقط استبدل النص “PASTE YOUR FULL APP.YML HERE” بملف app.yml الكامل الخاص بك.
sudo -u root cat > /var/discourse/containers/app.yml <<\EOF
PASTE YOUR FULL APP.YML HERE
EOF
تشغيل إعداد Discourse
ابدأ إعداد Discourse دون مطالبات باستخدام الأمر أدناه.
sudo -u yes "" | /var/discourse/./discourse-setup
يجب أن يستغرق تثبيت Discourse من 10 إلى 15 دقيقة.
تثبيت NGINX و WAF و GEOIP
قم بتشغيل التحديثات وتثبيت المتطلبات المسبقة
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
قم بتثبيت قاعدة بيانات MaxMind DB حتى تتمكن من تشغيل قواعد GEO IP بناءً على الموقع. يمكنك استخدام هذه القاعدة لتوجيه أو حظر حركة المرور بناءً على الموقع. ستظهر سجلات NGINX لدينا الآن بلد المستخدم حتى لو لم تقم بتفعيل الحظر الجغرافي.
sudo add-apt-repository -y ppa:maxmind/ppa
apt update -y
apt install -y libmaxminddb0 libmaxminddb-dev mmdb-bin
تنزيل واستخراج NGINX و NAXSI WAF
ملاحظة: استبدل NGINX بأحدث إصدار
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/
استنساخ وحدة GEO IP2 لـ NGINX عبر Git
apt install -y git
git clone https://github.com/leev/ngx_http_geoip2_module.git /etc/ngx_http_geoip2_module
تجميع NGINX
سنقوم بإنشاء سكريبت للقيام بذلك نيابةً عنا وتشغيله أدناه
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
إنشاء قواعد الجدار الناري
سيؤدي الافتراضي أدناه إلى تفعيل WAF وحظر الطلبات الخبيثة. إذا كنت ترغب في تشغيل WAF في وضع التعلم، يمكنك فعل ذلك عن طريق إضافة Learning Mode إلى ملف القاعدة أدناه.
cp ~/nginx-waf/naxsi-master/naxsi_config/naxsi_core.rules /etc/nginx/
cat > /etc/nginx/naxsi.rules <<\EOF
SecRulesEnabled;
DeniedUrl "/RequestDenied";
## التحقق من قواعد Naxsi
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
EOF
إنشاء ملف تكوين NGINX
بشكل افتراضي في ملف التكوين هذا، يتم التعليق على الحظر الجغرافي، ولكن يمكنك إلغاء التعليق وتفعيله إذا كنت ترغب في ذلك.
ملاحظة: يجب تشغيل NGINX بدون SSL في البداية. لأننا نحتاج إلى أن يرى certbot نطاقًا نشطًا. سنحصل على SSL في خطوة لاحقة وسنقوم فعليًا بنسخ ملف NGINX جديد لاستبدال هذا الملف
ملاحظة: استبدل cloudforums.net باسم نطاقك
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
إنشاء سكريبت upstart لـ NGINX
نحتاج إلى إنشاء سكريبت لخدمة 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
# قم بتضمين قيم nginx الافتراضية إذا كانت متاحة
if [ -f /etc/nginx ] ; then
. /etc/nginx
fi
set -e
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $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 "Reloading $DESC configuration: "
start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
EOF
systemctl daemon-reload
إنشاء ملف خدمة 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
تنزيل قاعدة بيانات Geo IP للدول
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/
تفعيل وبدء تشغيل NGINX
systemctl stop apache2
systemctl daemon-reload
systemctl enable nginx
systemctl start nginx
إضافة شهادة SSL لنطاقك
لا تنس استبدال cloudforums.net بنطاقك.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
إنشاء ملف NGINX جديد بقواعد SSL
قم بإنشاء ملف NGINX جديد بشهادة SSL التي قمت بتنزيلها للتو.
ملاحظة: غيّر cloudforums.net إلى نطاقك
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';
#***********************************************************
#قم بإلغاء التعليق للقيام بالحظر الجغرافي. الافتراضي هو الولايات المتحدة فقط في الإعدادات أدناه
#***********************************************************
#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;
}
}
# HTTPS server
#
#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
إعادة تشغيل NGINX
systemctl restart nginx
الآن لديك جدار حماية مفتوح المصدر رائع!! ![]()
إعلان غير خجول
تأكد من الانضمام إلينا في cloudforums.net إذا استمتعت بهذا الدليل. سنكون سعداء جدًا بوجودك معنا هنا. نحن لا نبيع أي شيء ولا نضع إعلانات. فقط نبحث عن منشورات تقنية جيدة ![]()
