ติดตั้ง haproxy บน ubuntu server 16.04

จาก Wiki Opensource

บันทึกนี้ปรับปรุงล่าสุดเมื่อวันที่ 13-09-2561
ดูแลโดย WIBOON

  • haproxy นำมาใช้ทำเป็น reverse proxy สำหรับ web server
  • haproxy สามารถนำมาใช้ทำ load balance ในระดับ layer 4 และ layer 7 ได้
  • haproxy ทำ load balance layer 4 ต้้งค่า mode tcp
  • haproxy ทำ load balance layer 7 ต้้งค่า mode http
  • haproxy ทำ load balance layer 7 ต้้งค่า mode http และทำ SSL Termination ร่วมด้วย เพื่อให้เป็น https สำหรับ backend server โดยที่ไม่ต้องติดตั้ง SSL เพิ่ม


ขั้นตอน
1. ติดตั้งโปรแกรม haproxy

sudo apt update
sudo apt install haproxy


2. ตั้งค่า

sudo vi /etc/default/haproxy
ENABLED=1


3. restart service

sudo service haproxy restart
sudo service haproxy status


4. ให้ restart service rsyslog เพื่อให้เกิด haproxy.log

sudo service rsyslog restart


5. เก็บสำรองไฟล์ haproxy.cfg ไว้ด้วย

cd /etc/haproxy; sudo cp haproxy.cfg haproxy.cfg.orig


[ตัวอย่างการแก้ไขค่าคอนฟิกใน haproxy.cfg ]
เช่น นำ haproxy ไปใช้กับ wordpress และ apache2 web server
1. แก้ไขไฟล์ haproxy.cfg ด้วยเอดิเตอร์ vi หรือ nano ก็ได้

sudo vi /etc/haproxy/haproxy.cfg

นำท่อนข้างล่างนี้ต่อท้ายไฟล์ haproxy.cfg
เพิ่มต่อท้ายในชุด defaults

        option forwardfor
        option http-server-close

แล้วตามด้วยท่อนนี้ เพื่อใช้ http port 80/tcp

frontend www-http
   bind *:80
   reqadd X-Forwarded-Proto:\ http
   default_backend wordpress-backend

แล้วตามด้วยท่อนนี้ เพื่อใช้ https port 443/tcp (SSL Termination with haproxy)

frontend www-https
   bind *:443 ssl crt /etc/ssl/private/my.pem
   reqadd X-Forwarded-Proto:\ https
   default_backend wordpress-backend

แล้วตามด้วยท่อนนี้

backend wordpress-backend
   balance roundrobin
   redirect scheme https if !{ ssl_fc }
   server wordpress1 10.0.0.52:80 check
   server wordpress2 10.0.0.53:80 check


2. restart service haproxy ด้วยคำสั่ง

sudo service haproxy restart


3. แก้ไข wordpress wp-config.php
เพิ่มท่อนนี้ก่อนบรรทัด /* That's all, stop editing! Happy blogging. */

if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
    $_SERVER['HTTPS'] = 'on';
    $_SERVER['SERVER_PORT'] = 443;
}
/* That's all, stop editing! Happy blogging. */


4. แก้ไข LogFormat ของ apache2 ให้รับ X-Forwarded-For ด้วยเอดิเตอร์ vi หรือ nano ก็ได้

sudo vi /etc/apache2/apache2.conf

แก้ไขดังนี้

#LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined


5. restart service apache2 ด้วยคำสั่ง

sudo service apache2 restart


หมายเหตุ หากเราจะทำ Joomla site ก็ใช้วิธีการเดียวกันกับที่อธิบายไปในการทำ wordpress site แค่ไปเพิ่มบรรทัดในไฟล์ configuration.php แบบนี้

<?php
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')  $_SERVER['HTTPS']='on';
class JConfig {
/* default datas */


[ตัวอย่างการตั้งค่าด้วย acl ของ haproxy.cfg]
สมมติว่าเว็บไซต์เรามีชื่อเริ่มต้นว่า myweb เช่น myweb.mydomain และ tblog1.mydomain เป็นต้น เราเขียนได้ 2 แบบ ดังนี้
แบบที่ 1 ใช้ acl ระบุว่าชื่อขึ้นต้นด้วย myweb

frontend www-http
   bind *:80
   mode http
   acl host_myweb hdr_beg(host) -i myweb
   use_backend myweb-backend if host_myweb
   default_backend wordpress-backend

backend myweb-backend
   mode http
   balance roundrobin
   option forwardfor
   http-request set-header X-Forwarded-Port %[dst_port]
   http-request add-header X-Forwarded-Proto https if { ssl_fc }
   option httpchk HEAD / HTTP/1.1\r\nHost:\ localhost
   server myweb 10.0.0.51:80 check

backend wordpress-backend
   mode http
   balance roundrobin
   option forwardfor
   http-request set-header X-Forwarded-Port %[dst_port]
   http-request add-header X-Forwarded-Proto https if { ssl_fc }
   option httpchk HEAD / HTTP/1.1\r\nHost:\ localhost
   server wordpress1 10.0.0.52:80 check
   server wordpress2 10.0.0.53:80 check


แบบที่ 2 ใช้ acl ระบุว่าชื่อขึ้นต้นด้วย tblog1 และ tblog2

frontend www-http
   bind *:80
   mode http
   acl host_tblog1 hdr_beg(host) -i tblog1
   use_backend tblog1-backend if host_tblog1
   acl host_tblog2 hdr_beg(host) -i tblog2
   use_backend tblog2-backend if host_tblog2
   default_backend server-backend

backend tblog1-backend
   mode http
   balance roundrobin
   option forwardfor
   http-request set-header X-Forwarded-Port %[dst_port]
   http-request add-header X-Forwarded-Proto https if { ssl_fc }
   option httpchk HEAD / HTTP/1.1\r\nHost:\ localhost
   server wordpress1 10.0.0.52:80 check
   server wordpress2 10.0.0.53:80 check

backend tblog2-backend
   mode http
   balance roundrobin
   option forwardfor
   http-request set-header X-Forwarded-Port %[dst_port]
   http-request add-header X-Forwarded-Proto https if { ssl_fc }
   option httpchk HEAD / HTTP/1.1\r\nHost:\ localhost
   server wordpress1 10.0.0.52:80 check
   server wordpress2 10.0.0.53:80 check

backend server-backend
   mode http
   balance roundrobin
   option forwardfor
   http-request set-header X-Forwarded-Port %[dst_port]
   http-request add-header X-Forwarded-Proto https if { ssl_fc }
   option httpchk HEAD / HTTP/1.1\r\nHost:\ localhost
   server myweb 10.0.0.51:80 check


เพิ่มเติม HTTP Headers เกี่ยวกับ security ให้ใส่ก่อนบรรทัด server myweb 10.0.0.51:80 check

   http-response set-header Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'"
   http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
   http-response set-header X-Frame-Options "SAMEORIGIN"
   http-response set-header X-XSS-Protection "1; mode=block"
   http-response set-header X-Content-Type-Options "nosniff"
   http-response set-header Expect-CT "max-age=3600"
   http-response set-header Referrer-Policy "no-referrer-when-downgrade"
   http-response set-header Feature-Policy "accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'"

อ่านเพิ่มเติม

  1. ติดตั้ง ssl-cert บน ubuntu 16.04 server
  2. https://www.digitalocean.com/community/tutorial_series/load-balancing-wordpress-with-haproxy
  3. https://feliciano.tech/blog/running-wordpress-behind-an-sslhttps-terminating-proxy/
  4. https://serverfault.com/questions/331079/haproxy-and-forwarding-client-ip-address-to-servers
  5. https://gist.github.com/ajaegers/7eda2eadffbc1bbcf12f