ข้ามไปที่เนื้อหา

HAProxy

Setup

Installation

การติดตั้ง HAProxy ลงใน linux server สามารถติดตั้งได้โดยการใช้คำสั่ง apt install

install HAProxy command
sudo apt install haproxy -y

Check version

เนื่องจากความต่างกันของ version จะส่งผลถึง parameter หรือ syntax ในตัวไฟล์ configuration อย่างไรก็ตาม แนะนำให้ตรวจสอบอีกครั้งกับ HAProxy Documentation

check version of HAProxy command
haproxy -v

Configuration

Editing HAProxy configuration file

ไฟล์ configuration จะถูกจัดเก็บอยู่ที่ directory /etc/haproxy/haproxy.cfg สามาถเข้าถึงไฟล์ได้โดยการใช้คำสั่งแก้ไขไฟล์เช่น nano หรือ vi หรือ cat

ไฟล์ haproxy.cfg ตือไฟล์ที่จะเก็บค่าที่เราตั้งค่าให้กับตัว proxy ไปใช้ ดังนั้นการตั้งค่าทั้งหมดจะถูกแก้ไขที่นี่

edit configuration file with nano
sudo nano /etc/haproxy/haproxy.cfg

Tip

เครื่องมือ nano สามารถ save โดยกดปุ่ม Ctrl+X และ Enter


ตัวอย่างไฟล์ haproxy.cfg

การตั้งค่าจะมีด้วยกัน 3 ส่วนหลัก ๆ ได้แก่ ตั้งค่า SSL Certificate, ตั้งค่า frontend และ ตั้งค่า backend

Normal deployment

สำหรับการ deployment แบบปกติไม่ต้องทำ reverse-proxy สามารถใช้ไฟล์ดังนี้

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

    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-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        timeout connect 30000
        timeout client  30000
        timeout server  50000
        timeout tunnel  50000
        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

frontend all
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/PSU240722.pem

    reqadd X-Forwarded-Proto:\ https if { ssl_fc }
    reqadd X-Forwarded-Port:\ 443 if { ssl_fc }
    reqadd X-Forwarded-Proto:\ http if !{ ssl_fc }
    reqadd X-Forwarded-Port:\ 80 if !{ ssl_fc }

    redirect scheme https code 301 if !{ ssl_fc }

    use_backend [backend-name] if { hdr(host) -i [your-domain-name] }

backend [backend-name]
    option redispatch
    option httpclose
    option forwardfor
    balance roundrobin
    server [server-name] [port ที่ deploy service เช่น 0.0.0.0:8080] check-ssl verify none
    http-request set-header X-Forwarded-Port %[dst_port]
    http-request add-header X-Forwarded-Proto https if { ssl_fc }
    http-response set-header X-Frame-Options SAMEORIGIN
    http-response set-header X-XSS-Protection 1
    http-response set-header Content-Security-Policy "img-src 'self' data: code.jquery.com www.gstatic.com wordpress.org ps.w.org s.w.org piwik.psu.ac.th www.google-analytics.com secure.gravatar.com"
    http-response set-header Strict-Transport-Security max-age=31536000
    http-response set-header Referrer-Policy no-referrer-when-downgrade
    http-response set-header Feature-Policy "accelerometer 'none'"

เปลี่ยน reqadd เป็น http-request add-header

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

    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-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 30000
    timeout client  30000
    timeout server  50000
    timeout tunnel  50000
    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

frontend all
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/star.in.pem

    acl is_https ssl_fc
    http-request add-header X-Forwarded-Proto: https if is_https
    http-request add-header X-Forwarded-Port: 443 if is_https
    http-request add-header X-Forwarded-Proto: http if !is_https
    http-request add-header X-Forwarded-Port: 80 if !is_https
    redirect scheme https code 301 if !is_https

    use_backend [backend-name] if { hdr(host) -i [your-domain-name] }

backend [backend-name]
    option redispatch
    option httpclose
    option forwardfor
    balance roundrobin
    server [server-name] [port ที่ deploy service เช่น 0.0.0.0:8080] check-ssl verify none
    http-request set-header X-Forwarded-Port %[dst_port]
    http-request add-header X-Forwarded-Proto https if { ssl_fc }
    http-response set-header X-Frame-Options SAMEORIGIN
    http-response set-header X-XSS-Protection 1
    http-response set-header Content-Security-Policy "img-src 'self' data: code.jquery.com www.gstatic.com wordpress.org ps.w.org >        #http-response set-header X-Content-Type-Options nosniff
    http-response set-header Strict-Transport-Security max-age=31536000
    http-response set-header Referrer-Policy no-referrer-when-downgrade
    http-response set-header Feature-Policy "accelerometer 'none'"

ไฟล์ certificate .pem

ไฟล์ certificate .pem สามารถขอได้จากผู้ดูแลระบบเครือข่าย ไฟล์ certificate จะมี expire date หรือวันหมดอายุ กรุณาตรวจสอบก่อนติดตั้งและเปลี่ยนก่อนจะครบวันหมดอายุ

Meaning of configuration file

บรรทัด ความหมาย สิ่งที่จะต้องทำ
1-13 ส่วนของการประกาศตัวแปร global -
15-30 ค่า default ที่จะถูกใช้ในทุกๆ frontend -
32-43 การกำหนด frontend จะเป็นส่วนที่บอกว่าจะมีการใช้ port ไหนบ้าง, ไฟล์ SSL Certificate สำหรับการใช้งาน https, การกำหนดให้บังคับใช้ https เท่านั้น ถ้ามีการเข้าผ่าน http จะถูก redirect ไปยัง https โดยอัตโนมัติ และการประกาศใช้ backend ถ้ามีการผ่านของเงื่อนไข domain name บรรทัดที่ 34 => แก้ไขที่อยู่ของไฟล์ certificate , บรรทัดที่ 43 => แก้ไขชื่อของ backend และ domain name ภายในการตรวจสอบเงื่อนไข hdr(host) -i {your-domain-name}
45+ การกำหนด backend จะเป็นส่วนที่จะกำหนดว่ามี server หรือ container กี่ตัว ที่อยู่ที่ ip address ไหนบ้าง และจะกำหนดว่าจะส่งค่าอะไรไปให้ service ที่ run อยู่ข้างหลังผ่าน request header และหากมีมากกว่า 1 server จะทำการ load balance แบบ roundrobin บรรทัดที่ 50 => แก้ไข server-name เป็นชื่อ สามารถใช้ชื่ออะไรก็ได้ให้สื่อถึง service นั้นๆ สามารถมีได้มากกว่า 1 server

Reverse-proxy deployment

สำหรับการ deployment แบบ reverse-proxy ให้แก้ไขส่วนของ backend โดยการเพิ่ม 2 บรรทัดดังนี้

haproxy.cfg
...

backend [backend-name]
        option redispatch
        option httpclose
        option forwardfor
        balance roundrobin
        option httpchk HEAD / HTTP/1.1\r\nHost:[your-domain-name]
        server [server-name] [localhost address:port ที่ deploy service เช่น 127.0.0.1:8080]
        http-request set-header X-Forwarded-Port %[dst_port]
        http-request add-header X-Forwarded-Proto https if { ssl_fc }
        http-response set-header X-Frame-Options SAMEORIGIN
        http-response set-header X-XSS-Protection 1
        http-response set-header Content-Security-Policy "img-src 'self' data: code.jquery.com www.gstatic.com wordpress.org ps.w.org >        #http-response set-header X-Content-Type-Options nosniff
        http-response set-header Strict-Transport-Security max-age=31536000
        http-response set-header Referrer-Policy no-referrer-when-downgrade
        http-response set-header Feature-Policy "accelerometer 'none'"

ในบรรทัดที่ 9 ไม่ต้องใส่ check-ssl verify none แล้วเนื่องจากเป็นการใช้งานผ่าน http


Validate and Applying

Validating configuration file

ตรวจสอบความถูกต้องของการตั้งค่า proxy ก่อนจะสั่ง restart เพื่อ apply ค่าไปใช้จริง

validate configuration file command
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

Restart HAProxy to apply configuration

หลังจากแก้ไขเสร็จสิ้น ค่า configuration จะไม่ถูกนำไปใช้ทันทีเนื่องจาก HAProxy ได้มีการ load ไฟล์ไปอ่านตั้งแต่ตอน start service แล้ว ดังนั้นการ apply ค่าชุดใหม่จะต้องใช้คำสั่ง restart service หรือ systemctl restart

restart haproxy service command
sudo systemctl restart haproxy

ณ ขั้นตอนนี้ ไฟล์ configuration ที่ถูกแก้จะถูก compile ถ้ามีส่วนที่ error จะต้องกลับไปแก้ไข โดยสามารถดู logs การ complie ได้จากคำสั่ง

inspect logs of HAProxy command
sudo journalctl -xeu haproxy.service

ข้อควรระวัง

การแก้ไข proxy จะส่งผลต่อการใช้งาน ณ ขณะนั้น ไม่ควรแก้ไขระหว่างมีการใช้งานของผู้ใช้ หาก proxy ไม่สามารถ start ได้ ผู้ใช้ก็จะไม่สามารถเข้าถึง container ภายในได้

Trobleshooting HAProxy

การแก้ไขปัญหาเพิ่มเติมอ่านต่อได้ที่ How To Troubleshoot Common HAProxy Errors


Uninstall HAProxy

HAProxy สามารถลบออกได้โดยการใช้คำสั่ง purge

uninstall HAProxy command
sudo apt purge haproxy -y