
✨ يتناول موضوع HAProxy وKeepalived في موازنة التحميل والمجموعة بالإضافة إلى الأمان (منع ثغرة استخدام SSL/تشفير ضعيف (LOGJAM) (CVE-2015-4000)) ومواجهة الأحمال العالية.

HAProxy هو برنامج مفتوح المصدر يوفر خدمة خادم وكيل (proxy) لتطبيقات TCP و HTTP مع قدرة عالية على التوافر (high availability) وموازنة التحميل (load balancing).
Keepalived هو برنامج مفتوح المصدر قادر على توفير خاصية IP failover (تجاوز الفشل) لأكثر من خادمين. يستخدم Keepalived تقنية الاتصال Multicast بين أعضائه.
في بنيتنا، سنستخدم HAProxy لموازنة التحميل، و Keepalived لترحيل عناوين IP أي لجعل بنية HAProxy لدينا مجموعة (Cluster).
في السيناريو لدينا 3 خوادم. سنقوم بتثبيت HAProxy على هذه الخوادم الثلاثة لجعلها موازنة تحميل. ثم سنقوم بتثبيت خدمة Keepalived بحيث عندما يتوقف أحد الخوادم، سيتم تجاوز الفشل (IP failover) إلى خادم آخر دون انقطاع، مما يضمن استمرار عمل خدمة موازنة التحميل.
لهذا سنستخدم 4 عناوين IP (عناوين IP وهمية تمامًا)
الآن، لنقم بتثبيت خدمتي HAProxy و Keepalived على الخوادم الثلاثة كما يلي:
sudo add-apt-repository ppa:vbernat/haproxy-2.7 -y
sudo apt update
sudo apt install haproxy keepalived -y
sudo openssl dhparam -out /etc/haproxy/dhparams.pem 2048
ملاحظة1: يجب أن تحتوي الخوادم على "net.ipv4.ip_nonlocal_bind=1". وإلا، لن يتمكن التكوين المستخدم لـ HAProxy من استضافة نفس عنوان IP في نفس الوقت، مما يؤدي إلى خطأ ربط (bind error) ولن تعمل الخدمة. لذلك، يجب اتباع المسار التالي.
أولاً، قم بتحرير ملف "vi /etc/sysctl.conf" وألصق المعلمة التالية، ثم احفظ واخرج.
net.ipv4.ip_nonlocal_bind=1
ثم قم بتشغيل الأمر التالي.
sysctl -p
ملاحظة2: إذا كنت ستستخدم SSL على المنفذ 443، فيجب أن يكون لديك ملف "haproxy.pem" داخل الدليل "/etc/ssl/private/" والذي يحتوي على حزمة شهادات SSL الخاصة بك (***.crt, .ca, .key).
الآن، دعنا نلقي نظرة على تكوين HAProxy كمثال أدناه. ستستخدم نفس التكوين لكل HAProxy في بنيتك.
لهذا، ستقوم بتحرير ملف "/etc/haproxy/haproxy.cfg". التكوين التالي يدعم الحد الأدنى من HAv2.
vi /etc/haproxy/haproxy.cfg
فيما يلي القيم الافتراضية أيضًا:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# maxconn 100000 #replaceable
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# An alternative list with additional directives can be obtained from
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
#ssl-default-bind-options no-sslv3
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-dh-param-file /etc/haproxy/dhparams.pem
#tune.ssl.default-dh-param 2048
# nbproc 1
# nbthread 8
tune.maxrewrite 16384
tune.bufsize 32768
defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
# maxconn 1000000 #replaceable
timeout connect 3000000
timeout client 6000000
timeout server 6000000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
قسم تكوين Dashboard لـ HAProxy (تمت إضافة تكامل prometheus للمراقبة):
listen stats
bind fatlan.com:8989
mode http
stats enable
stats uri /stats
option http-use-htx
http-request use-service prometheus-exporter if { path /metrics }
#stats hide-version
stats realm HAProxy\ Statistics
stats auth admin:admin
في التكوين أدناه، تم استخدام ACL في كتلتين. في الكتلة الأولى، إذا ظهرت كلمة "rest" في أي مكان داخل الرابط، فسيتم تشغيل كتلة middleware-fatlan-backend. في الثانية، إذا كان الطلب لنطاق مختلف (forum.fatlan.com) فسيتم تشغيل backend fatlan-forum-backend، وإلا فإن جميع الطلبات ستعمل في كتلة fatlan-backend443. باستثناء توجيهات المنافذ الأخرى.
جزء توجيه المنفذ 80 إلى المنفذ 443:
frontend fatlan80
bind fatlan.com:80
mode http
redirect scheme https if !{ ssl_fc }
frontend fatlan443
bind fatlan.com:443 ssl crt /etc/ssl/private/haproxy.pem ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
option httplog
option forwardfor
#http-request set-header X-Client-IP req.hdr_ip([X-Forwarded-For])
#option forwardfor except 127.0.0.0/8
option http-server-close
http-request set-header X-Forwarded-Proto https
# reqadd X-Forwarded-Proto:\ https #old config
mode http
default_backend fatlan-backend443
مثال لتكوين ACL (proxypass) - إذا ظهرت كلمة rest في أي مكان في الرابط، فسيتم التوجيه:
acl middleware-fatlan path_beg /rest
use_backend middleware-fatlan-backend if middleware-fatlan
ACL لتوجيه مضيف مختلف لـ forum:
acl host_fatlanforum hdr(host) -i forum.fatlan.com
use_backend fatlan-forum-backend if host_fatlanforum
الجزء الموجه افتراضيًا لـ 443:
backend fatlan-backend443
mode http
balance roundrobin
stick store-request src
stick-table type ip size 256k expire 30m
option forwardfor
# option httplog
option httpchk HEAD /
server frontend_01 10.10.37.12:8001 check port 8001 inter 3000 rise 2 fall 3
server frontend_02 10.10.37.13:8001 check port 8001 inter 3000 rise 2 fall 3
ACL الواردة - الجزء الموجه لـ rest:
backend middleware-fatlan-backend
mode http
balance roundrobin
stick store-request src
stick-table type ip size 256k expire 30m
option forwardfor
# option httplog
option httpchk OPTIONS /login HTTP/1.0
http-check expect status 200
http-request replace-path (.*)(?:rest\/)(.*) \1\2
# reqrep ^([^\ :]*)\ /rest[/]?(.*) \1\ //\2 #old config
server middleware_01 10.10.37.34:3000 check port 4000 inter 12000 rise 3 fall 3
server middleware_02 10.10.37.35:3000 check port 4000 inter 12000 rise 3 fall 3
ACL الواردة - الجزء الموجه لـ forum:
backend fatlan-forum-backend
mode http
option forwardfor
# option httplog
option httpchk HEAD /
server forum_01 10.10.37.45:8080 check port 8080 inter 3000 rise 2 fall 3
يمكن أيضًا تكوين أمثلة خارجية كما يلي.
مثال على المنفذ 5000:
frontend Panel5000
bind fatlan.com:5000
# option httplog
option forwardfor except 127.0.0.0/8
#option http-server-close
http-request set-header X-Forwarded-Proto https
# reqadd X-Forwarded-Proto:\ https #old config
mode http
default_backend panel-backend5000