優點 缺點 HAProxy安裝方式可以是yum安裝或源碼安裝。yum安裝的版本都是當前合適系統的穩定版本,個人喜歡使用yum安裝。 haproxy配置文件可分為全局配置(globalsettings)和 代理配置(proxies),而代理段配置包含defaults、frontend、backend、 ...
一、簡介
HAProxy是由C語言編寫基於事件驅動模型的一款高效穩定、功能強大的負載均衡軟體,其性能可媲美商業負載均衡軟體,不過在最新的版本中HAProxy已經分為社區版本和企業版,社區版完全免費,企業版有豐富的額外功能。
優缺點:
優點- 支持虛擬主機的,通過frontend指令來實現
- 能彌補Nginx的一些缺點比如Session的保持,Cookie的引導等工作
- 支持後端伺服器健康檢查,自動實現故障轉移;
- 它跟LVS一樣,本身僅僅就只是一款負載均衡軟體,單純從效率上來講HAProxy更會比Nginx有更出色的負載均衡速度,在併發處理上也是優於Nginx;
- 同時支持四層和七層代理模式;
- 能對請求的url和header中的信息做匹配,更細粒度的七層負載均衡;
- 自帶監控管理web頁面;
- 能從進出兩個方向修改http頭信息;
- 同樣支持多種負載均衡演算法;
缺點
- 重載配置的功能需要重啟進程,雖然也是 soft restart,但沒有 Nginx 的 reaload 更為平滑和友好。
- 不支持 HTTP cache 功能(不知道最新版是否支持)。
二、安裝配置
HAProxy安裝方式可以是yum安裝或源碼安裝。yum安裝的版本都是當前合適系統的穩定版本,個人喜歡使用yum安裝。
安裝
yum install haproxy -y #centos7預設安裝版本是1.5 #主程式:/usr/sbin/haproxy #配置文件:/etc/haproxy/haproxy.cfg #啟動服務:systemctl start haproxy #停止服務:systemctl stop haproxy #開機啟動:systemctl enable haproxy
配置文件結構
haproxy配置文件可分為全局配置(globalsettings)和 代理配置(proxies),而代理段配置包含defaults、frontend、backend、listen。global settings:#全局參數配置,主要用於定義haproxy進程管理安全及性能相關的參數 defaults <name>:#預設配置參數,下麵的段繼承該配置,名稱是可選的,這配置預設配置參數可由下一個"defaults"所重新設定 frontend <name>:#前端配置,定義一系列監聽的套接字,這些套接字可接受客戶端請求並與之建立連接,可以監聽多個埠。 backend <name>:#後端配置,定義後臺伺服器,前端代理伺服器將會把客戶端的請求調度至這些伺服器,類似nginx中的upstream listen <name>:#定義一組前端和後端的完整代理,可理解為frontend+backend,通常用於tcp流量代理
#ps:name名稱必須由大寫和小寫字母,數字,'-','_','.'組成
配置參數可支持的時間單位
- us : 微秒. 1 microsecond = 1/1000000 s - ms : 毫秒. 1 millisecond = 1/1000 s - s : 秒 1s = 1000ms - m : 分 1m = 60s = 60000ms - h : 小時 1h = 60m = 3600s = 3600000ms - d : 天 1d = 24h = 1440m = 86400s = 86400000ms
一個超級簡單的WEB配置示例如下:
global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 frontend webserver *:80 #監聽80,也可以使用bind定義,類似於nginx中的server default_backend web #指明代理的後端伺服器為web backend web #定義web包含的伺服器詳細以及使用的演算法,類似nginx中的upstream balance roundrobin server web1 10.1.210.52:80 check server web2 10.1.210.53:80 check
說明:在以上配置中frontend段定義了前臺代理配置,代理的後端伺服器由default_backend指定,web則是代理的真實後端伺服器名稱,而web的定義由backend 欄位負責。
全局配置參數( globalsettings)
chroot: #修改haproxy的工作目錄至指定的目錄,併在放棄許可權之前執行chroot()操作,可以提升haproxy的安全級別,不過需要註意的是確保指定的目錄為空目錄且任何用戶均不能有寫許可權; daemon: #讓haproxy以守護進程的方式工作於後臺,其等同於"-D"選項的功能,當然,也可以在命令行中以"-db"選項將其禁用; gid: #以指定的GID運行haproxy,建議使用專用於運行haproxy的GID,以避免因許可權帶來的風險; group: #同gid,不過這裡為指定的組名; uid: #已指定的UID身份運行haproxy進程; user: #同uid,但這裡使用的為用戶名; log: #定義全局的syslog伺服器,最多可以定義兩個; nbproc: #指定啟動的haproxy進程個數,只能用於守護進程模式的haproxy;預設為止啟動一個進程,鑒於調試困難等多方面的原因,一般只在但進程僅能打開少數文件描述符的場中才使用多進程模式; pidfile: #pid文件的存放位置; ulimit-n: #設定每個進程所能夠打開的最大文件描述符,預設情況下其會自動進行計算,因此不建議修改此選項; node: #定義當前節點的名稱,用於HA場景中多haproxy進程共用同一個IP地址時; description: #當前實例的描述信息; maxconn: #設定每個haproxy進程所接受的最大併發連接數,其等同於命令行選項"-n","ulimit-n"自動計算的結果正式參照從參數設定的; maxpipes: #haproxy使用pipe完成基於內核的tcp報文重組,此選項用於設定每進程所允許使用的最大pipe個數,每個pipe會打開兩個文件描述符,因此,"ulimit -n"自動計算的結果會根據需要調大此值,預設為maxcoon/4; noepoll: #在linux系統上禁用epoll機制; nokqueue: #在BSE系統上禁用kqueue機制; nopoll: #禁用poll機制; nosepoll: #在linux系統上禁用啟髮式epoll機制; nosplice: #禁止在linux套接字上使用tcp重組,這會導致更多的recv/send調用,不過,在linux2.6.25-28系列的內核上,tcp重組功能有bug存在; spread-checks<0..50,in percent>: #在haprorxy後端有著眾多伺服器的場景中,在緊缺是時間間隔後統一對中伺服器進行健康狀況檢查可能會帶來意外問題,此選項用於將檢查的時間間隔長度上增加或減少一定的隨機時長,為當前檢查檢測時間的%; maxconnrate:#設置每個進程每秒種所能建立的最大連接數量,速率,一個連接里可以有多個會話,也可以沒有會話 maxsessrate:#設置每個進程每秒種所能建立的最大會話數量 maxsslconn:#每進程支持SSL 的最大連接數量 tune.bufsize: #設定buffer的大小,同樣的記憶體條件下,較小的值可以讓haproxy有能力接受更多的併發連接,較大的值了可以讓某些應用程式使用較大的cookie信息,強烈建議使用預設值; tune.chksize: #設定檢查緩衝區的大小,單位為位元組,更大的值有助於在較大的頁面中完成基於字元串或模式的文本查找,但也會占用更多的系統資源,不建議修改; tune.maxaccept: #設定haproxy進程內核調度運行時一次性可以接受的連接的個數,較大的值可以帶來較大的吞吐量。 tune.maxpollevents: #設定一次系統調用可以處理的事件最大數,預設值取決於OS,其至小於200時可介於帶寬,但會略微增大網路延遲,但大於200時會降低延遲,但會稍稍增加網路帶寬的占用; tune.maxrewrite: #設定在首部重寫或追加而預留的緩存空間,建議使用1024左右的大小,在需要更大的空間時,haproxy會自動增加其值; tune.rcvbuf.client: #設定內核套接字中客戶端接收緩存區的大小,單位為位元組,強烈推薦使用預設值; tune.rcvbuf.server: #設定內核套接字中伺服器接收緩存區的大小,單位為位元組,強烈推薦使用預設值; tune.sndbuf.client: #設定內核套接字中客戶端發送緩存區的大小,單位為位元組,強烈推薦使用預設值; tune.sndbuf.server: #設定內核套接字中伺服器端發送緩存區的大小,單位為位元組,強烈推薦使用預設值; debug: #調試模式,輸出啟動信息到標準輸出; quiet: #安裝模式,啟動時無輸出;
defaults預設的配置
defaults mode http #預設負載均衡模式為http log global #日誌定義 option httplog #啟用日誌記錄HTTP請求,預設haproxy日誌記錄是不記錄HTTP請求 option dontlognull #設置日誌中不記錄空連接。 option httpclose # 每次請求完畢後主動關閉http通道 option forwardfor except 127.0.0.0/8 #插入x-forward標記,反向代理時候可以通過該欄位獲取客戶端真實IP retries 3 # 定義連接後端伺服器的失敗重連次數 timeout http-request 10s:#在客戶端建立連接但不請求數據時,關閉客戶端連接 timeout queue 1m : #伺服器的maxconn時,連接在隊列中保持掛起狀態而設置的超時時間,想客戶端返回503錯誤 timeout connect 10s: #定義haproxy將客戶端請求轉發至後端伺服器所等待的超時時長 timeout client 1m:#客戶端非活動狀態的超時時長 timeout server 1m:#客戶端與伺服器端建立連接後,等待伺服器端的超時時長 timeout http-keep-alive 10s: #定義保持連接的超時時長 timeout check 10s: #健康狀態監測時的超時時間,過短會誤判,過長資源消耗 maxconn 3000: #每個server最大的連接數
超時參數
timeout http request :#在客戶端建立連接但不請求數據時,關閉客戶端連接 timeout queue :#等待最大時長 timeout connect: #定義haproxy將客戶端請求轉發至後端伺服器所等待的超時時長 timeout client:#客戶端非活動狀態的超時時長 timeout server:#客戶端與伺服器端建立連接後,等待伺服器端的超時時長, timeout http-keep-alive :#定義保持連接的超時時長 timeout check:#健康狀態監測時的超時時間,過短會誤判,過長資源消耗
三、常用配置參數
bind
bind [<address>]:<port_range> [,...] [param*] #此指令僅能用於frontend和listen區段,用於定義一個或幾個監聽的套接字
- <address>:可選選項,其可以為主機名、IPv4地址、IPv6地址或*;
- <port_range>:可以是一個特定的TCP埠,也可是一個埠範圍(如5005-5010);
- <param>: 其他格式代理比如sock、ipv6等
示例:
listen http_proxy bind :80,:443 bind 10.0.0.1:10080,10.0.0.1:10443 bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy listen http_https_proxy bind :80 bind :443 ssl crt /etc/haproxy/site.pem listen http_https_proxy_explicit bind ipv6@:80 bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem bind unix@ssl-frontend.sock user root mode 600 accept-proxy listen external_bind_app1 bind fd@${FD_APP1}
balance
balance <algorithm> [ <arguments> ] balance url_param <param> [check_post] #定義負載均衡演算法,可用於defaults、listen和backend段。algorithm有如下幾種演算法:
- roundrobin(預設):根據權重進行輪詢,在伺服器的處理時間保持均勻分佈時,這是最平衡、最公平的演算法。此演算法是動態的,權重可以在haproxy運行時調整後端伺服器的權重並生效,每個後端中最多支持4095個後端伺服器;
- static-rr:基於權重進行輪詢,與roundrobin類似,但是為靜態方法,在haproxy運行時調整其伺服器權重不會生效;
- leastconn:最少連接數,新的連接請求被派發至具有最少連接數目的後端伺服器;在有著較長時間會話的場景中推薦使用此演算法,如LDAP、SQL等,其並不太適用於較短會話的應用層協議,如HTTP;此演算法是動態的,可以在運行時調整其權重;
- source:將請求的源地址進行hash運算,使得同一個客戶端IP的請求始終被派發至某特定的伺服器;但當伺服器權重總數發生變化時,如某伺服器宕機或添加了新的伺服器,許多客戶端的請求可能會被派發至與此前請求不同的伺服器;類似於nginx的ip_hash,可用於負載均衡無cookie功能的基於TCP的協議。預設為靜態;
- uri:對URI(get傳遞參數不計入url)進行hash運算,並除以伺服器的總權重來計算派發至某匹配伺服器;這可以使得對同一個URI的請求總是被派發至某特定的伺服器,除非伺服器的權重總數發生了變化;此演算法常用於代理緩存以提高緩存的命中率;但此演算法僅應用於提供http服務的後端伺服器;預設為靜態演算法;缺點是後端server宕機會造成嚴重抖動,可以通過hash-type設置hash演算法為一致性哈希解決。
- url_param:對用戶請求的uri的<params>部分中的參數的值作hash計算,並由伺服器總權重相除以後派發至某挑出的伺服器;通常用於追蹤用戶,以確保來自同一個用戶的請求始終發往同一個後臺伺服器;
- hdr(name):根據請求報文中指定的header(如use_agent, referer, hostname)進行調度;把指定的header的值做hash計算,預設為靜態;
- rdp-cookie :表示根據據cookie(name)來鎖定並哈希每一次TCP請求,相同的用戶或者相同的會話都會到達後端同一臺伺服器,如果找不到cookie,會使用roundrobin演算法代替;
mode
mode { tcp|http|health } #指定代理模式
- tcp:實例運行於純TCP模式,在客戶端和伺服器端之間將建立一個全雙工的連接,且不會對7層報文做任何類型的檢查;通常用於SSL、SSH、SMTP等應用;
- http:實例運行於HTTP模式,客戶端請求在轉發至後端伺服器之前將被深度分析,所有不與RFC格式相容的請求都會被拒絕;此為預設模式;
- health:實例工作於health模式,其對入站請求僅響應“OK”信息並關閉連接,且不會記錄任何日誌信息;此模式將用於響應外部組件的健康狀態檢查請求;目前來講,此模式已經廢棄,因為tcp或http模式中的monitor關鍵字可完成類似功能;
hash-type
hash-type <method> <function> <modifier> #用於將hash碼映射至後端伺服器的方法;可用方法有map-based和consistent,一般情況推薦使用預設的map-based方法。
- map-based:hash表是一個包含了所有線上伺服器的靜態數組。其hash值將會非常平滑,會將權重考慮在列,但其為靜態方法,對線上伺服器的權重進行調整將不會生效,這意味著其不支持慢速啟動。此外,挑選伺服器是根據其在數組中的位置進行的,因此,當一臺伺服器宕機或添加了一臺新的伺服器時,大多數連接將會被重新派發至一個與此前不同的伺服器上,對於緩存伺服器的工作場景來說,此方法不甚適用。
- consistent:“一致性哈希演算法”,hash表是一個由各伺服器填充而成的樹狀結構,將伺服器散列在hash環上;基於hash鍵在hash樹中查找相應的伺服器時,最近的伺服器將被選中。此方法是動態的,支持在運行時修改伺服器權重,因此相容慢速啟動的特性。添加一個新的伺服器時,僅會對一小部分請求產生影響,因此,尤其適用於後端伺服器為cache的場景。不過,此演算法不甚平滑,派發至各伺服器的請求未必能達到理想的均衡效果,因此,可能需要不時的調整伺服器的權重以獲得更好的均衡性。
log
log global log <address> <facility> [<level> [<minlevel>]] #用於日誌配置,可以用於所有的配置段,每個段中最多可以指定兩個log參數,如果使用了“log global”且”global”段已經定了兩個log參數時,多餘了log參數將被忽略
- global:當前實例的日誌系統參數同”global”段中的定義時,將使用此格式;每個實例僅能定義一次“log global”語句,且其沒有任何額外參數;
- <address>:定義日誌發往的位置,其格式之一可以為<IPv4_address:PORT>,其中的port為UDP協議埠,預設為514;格式之二為Unix套接字文件路徑,但需要留心chroot應用及用戶的讀寫許可權;
- <facility>:可以為syslog系統的標準facility之一;
- <level>:定義日誌級別,即輸出信息過濾器,預設為所有信息;指定級別時,所有等於或高於此級別的日誌信息將會被髮送;
示例:
[root@app51 ~]# vi /etc/haproxy/haproxy.cfg log 127.0.0.1 local2 [root@app51 ~]# systemctl restart haproxy [root@app51 ~]# vi /etc/rsyslog.conf ###haproxy $ModLoad imudp $UDPServerRun 514 local2.* /var/log/haproxy.log [root@app51 ~]# systemctl restart rsyslog
capture request header&capture response header
capture request header <name> len <length> capture response header <name> len <length> #用於捕獲並記錄最近一次出現的指定請求首部或響應首部。請求首部是從客戶端發起的請求首部,響應首部是從後端server響應併在haproxy準備發送給客戶端前捕獲的。 #捕獲的首部值使用大括弧{}括起來後會添加進日誌中。如果需要捕獲多個首部值,它們將以指定的秩序出現在日誌文件中,並以豎線"|"作為分隔符。不存在的首部記錄為空字元串.定義在frontend和listen段
- <name>:要捕獲的首部的名稱,此名稱不區分字元大小寫,但建議與它們出現在首部中的格式相同,比如大寫首字母。需要註意的是,記錄在日誌中的是首部對應的值,而非首部名稱。
- <length>:指定記錄首部值時所記錄的精確長度,超出的部分將會被忽略。
示例:
capture response header Content-length len 9 capture response header Location len 15 capture request header Host len 15 capture request header X-Forwarded-For len 15 capture request header Referer len 15
use_backend& default_backend
use_backend <backend> [{if | unless} <condition>] #用於定義滿足條件的backend,條件判斷是可選的,並且condition是基於acl的條件。 default_backend <backend> #用於指定預設的backend,在沒有匹配的”use_backend”規則時為實例指定使用的預設後端。
示例:
use_backend dynamic if url_dyn use_backend static if url_css url_img extension_img default_backend dynamic
server
server <name> <address>[:port] [param*] #為後端聲明一個server,因此,不能用於defaults和frontend區段。
- <name>:為此伺服器指定的內部名稱,其將出現在日誌及警告信息中;如果設定了”http-send-server-name”,它還將被添加至發往此伺服器的請求首部中;
- <address>:此伺服器的的IPv4地址,也支持使用可解析的主機名,只不過在啟動時需要解析主機名至相應的IPv4地址;
- [:port]:指定將連接請求所發往的此伺服器時的目標埠,其為可選項;未設定時,將使用客戶端請求時的同一相埠;
- [param*]:為此伺服器設定的一系參數;其可用的參數非常多,具體請參考官方文檔中的說明,下麵僅說明幾個常用的參數;
- backup:設定為備用伺服器,僅在負載均衡場景中的其它server均不可用於啟用此server;
- check:啟動對此server執行健康狀態檢查,其可以藉助於額外的其它參數完成更精細的設定,如:inter <delay>:設定健康狀態檢查的時間間隔,單位為毫秒,預設為2000;也可以使用fastinter和downinter來根據伺服器端狀態優化此時間延遲;
- rise <count>:設定健康狀態檢查中,某離線的server從離線狀態轉換至正常狀態需要成功檢查的次數;
- fall <count>:確認server從正常狀態轉換為不可用狀態需要檢查的次數;
- cookie <value>:為指定server設定cookie值,此處指定的值將在請求入站時被檢查,第一次為此值挑選的server將在後續的請求中被選中,其目的在於實現持久連接的功能;
- maxconn <maxconn>:指定此伺服器接受的最大併發連接數;如果發往此伺服器的連接數目高於此處指定的值,其將被放置於請求隊列,以等待其它連接被釋放;haproxy 有n個進程,每個支持m個連接,後端有x個伺服器,每個最大支持y個連接,則 n*m <= x*y,如果後端伺服器支持排隊,則n*m <= x*(y+z),z為每個伺服器的排隊隊列
- maxqueue <maxqueue>:設定請求隊列的最大長度;
- observe <mode>:通過觀察伺服器的通信狀況來判定其健康狀態,預設為禁用,其支持的類型有“layer4”和“layer7”,“layer7”僅能用於http代理場景;
- redir <prefix>:啟用重定向功能,將發往此伺服器的GET和HEAD請求均以302狀態碼響應;需要註意的是,在prefix後面不能使用/,且不能使用相對地址,以免造成迴圈重定向;
- weight <weight>:權重,預設為1,最大值為256,0表示不參與負載均衡(不被調度);
示例:
server first 10.1.1.1:1080 cookie first check inter 1000 server second 10.1.1.2:1080 cookie second check inter 1000 server transp ipv4@ server backup ${SRV_BACKUP}:1080 backup server www1_dc1 ${LAN_DC1}.101:80 server www1_dc2 ${LAN_DC2}.101:80
option httpchk
option httpchk option httpchk <uri> option httpchk <method> <uri> option httpchk <method> <uri> <version> #此指令表示基於http協議來做健康狀況檢查,只有返回狀態碼為2xx或3xx的才認為是健康的,其餘所有狀態碼都認為不健康。不設置該選項時,預設採用tcp做健康檢查,只要能建立tcp就表示健康
- <uri>:檢查的uri路徑,預設為"/"。接受帶有查詢參數的uri
- <method>:http檢查時使用的method,常用的http方法是GET、POST、HEAD、DELETE、OPTIONS、PUT,預設為"OPTIONS"方法,也建議採用此方法,因為該請求方法對伺服器造成的資源損耗最小。
- <version>:檢查的http協議版本,預設為http/1.0,但現在很多都採用HTTP/1.1,因此此處檢查版本需要修改為HTTP/1.1,但對於該版本的HTTP協議來說,還強制要求指定Host,中間使用\r\n隔離。
示例:
option httpchk GET /index.html
option forwardfor
option forwardfor [ except <network> ] [ header <name> ] [ if-none ] #允許在發往伺服器的請求首部中插入“X-Forwarded-For”首部。
- <network>:可選參數,當指定時,源地址為匹配至此網路中的請求都禁用此功能。
- <name>:可選參數,可使用一個自定義的首部,如X-Client來替代X-Forwarded-For。有些獨特的web伺服器的確需要用於一個獨特的首部。
- if-none:僅在此首部不存在時才將其添加至請求報文問道中。
frontend www mode http option forwardfor except 127.0.0.1
option httplog
option httplog [ clf ] #啟用記錄HTTP請求、會話狀態和計時器的功能,認情況下,日誌輸入格式非常簡陋,因為其僅包括源地址、目標地址和實例名稱 #而“option httplog”參數將會使得日誌格式變得豐富許多,其通常包括但不限於HTTP請求、連接計時器、會話狀態、連接數、捕獲的首部及cookie、“frontend”、“backend”及伺服器名稱,當然也包括源地址和埠號等。
- clf:使用CLF格式來代替HAProxy預設的HTTP格式,通常在使用僅支持CLF格式的特定日誌分析器時才需要使用此格式
errorfile
errorfile <code> <file> #錯誤頁面配置,常用錯誤如404、403、400、500等
- <code>:指定對HTTP的哪些狀態碼返回指定的頁面;這裡可用的狀態碼有400、403、408、500、502、503和504;
- <file>:指定用於響應的頁面文件;
示例:
errorfile 400 /etc/haproxy/errorfiles/400badreq.http errorfile 408 /dev/null # workaround Chrome pre-connect bug errorfile 403 /etc/haproxy/errorfiles/403forbid.http errorfile 503 /etc/haproxy/errorfiles/503sorry.http
errorloc&errorloc302
errorloc <code> <url> errorloc302 <code> <url> #請求錯誤時,返回一個HTTP重定向至某URL的信息;可用於所有配置段中。
- <code>:指定對HTTP的哪些狀態碼返回指定的頁面;這裡可用的狀態碼有200、400、403、408、500、502、503和504;
- <url>:Location首部中指定的頁面位置的具體路徑,可以是在當前伺服器上的頁面的相對路徑,也可以使用絕對路徑;需要註意的是,如果URI自身錯誤時產生某特定狀態碼信息的話,有可能會導致迴圈定向;
修改頭部信息相關
reqadd <string> [{if | unless} <cond>] #在HTTP請求的末尾添加標頭 rspadd <string> [{if | unless} <cond>] #在HTTP響應的末尾添加標頭 reqdel <search> [{if | unless} <cond>] #刪除與HTTP請求中的正則表達式匹配的所有頭信息 rspdel <search> [{if | unless} <cond>] #刪除與HTTP響應中的正則表達式匹配的所有頭信息 reqidel <search> [{if | unless} <cond>] #忽略大小寫刪除同reqdel rspidel <search> [{if | unless} <cond>] #忽略大小寫刪除同rspidel
示例:
#Add "X-Proto: SSL" to requests coming via port 81 acl is-ssl dst_port 81 reqadd X-Proto:\ SSL if is-ssl # remove X-Forwarded-For header and SERVER cookie reqidel ^X-Forwarded-For:.* reqidel ^Cookie:.*SERVER=
附上:官方1.5使用手冊
四、 ACL
ACL(Access Control List),即訪問控制列表,HAProxy的ACL提供了一種靈活的解決方案來執行內容切換,並且通常基於從請求,響應或任何環境狀態中提取的內容來做出決策。控制列表原則很簡單:
- 從數據流,表,環境中提取數據樣本
- 對提取的樣本可選地應用格式轉換
- 對一個樣本應用一個或多個模式匹配
- 當模式匹配樣本時才執行動作
需要提醒的是,獲取的樣本數據不光可以使用在acl中,也可以使用別處,例如記錄log中。
定義ACL語法:
acl <aclname> <criterion> [flags] [operator] [<value>] ...<aclname>: ACL名稱,必須由大寫和小寫字母,數字,' - '(短劃線),'_'(下劃線),'.' 組成。ACL名稱區分大小寫 <criterion>:獲取樣本方法的名稱,可以分為tcp和http類型,常用獲取樣本方法名稱如下:
###基於tcp的criterion##### dst : #目標ip dst_port : #目標埠 src : #源ip src_port : #源埠 ###基於http的criterion##### ###url_path相關 #ps: path從第一個"/"開始,不包含host,不包含參數 path : #精確匹配 path_beg : #首碼匹配 path_dir : #子串匹配 path_dom : #子功能變數名稱匹配 path_end : #路徑尾碼匹配 path_len : #路徑長度匹配 path_reg : #路徑的正則表達式模式匹配 path_sub : #路徑的子字串匹配 ###url相關 #ps:url包含了包含host和path以及參數 url : #精確匹配 url_beg : #首碼匹配 url_dir : #子串匹配 url_dom : #子功能變數名稱匹配 url_end : #尾碼匹配 url_len : #長度匹配 url_reg : #正則表達式匹配 url_sub : #子字串匹配 ###http頭信息相關 hdr([<name>[,<occ>]]) : #精確匹配 hdr_beg([<name>[,<occ>]]) : #首碼匹配 hdr_dir([<name>[,<occ>]]) : #子串匹配 hdr_dom([<name>[,<occ>]]) : #子功能變數名稱匹配 hdr_end([<name>[,<occ>]]) : #尾碼匹配 hdr_len([<name>[,<occ>]]) : #長度匹配 hdr_reg([<name>[,<occ>]]) : #正則表達式匹配 hdr_sub([<name>[,<occ>]]) : #子字串匹配 ###http請求方法 method [string] :#匹配http請求方法,string為http方法
[flags]:標誌,用於對<criterion>進行局部調整,一下為可使用的列表:
-i : #忽略大小寫 -f filename : #從文件中載入模式 -m method : #指定模式匹配方法 -n : #禁止DNS解析 -M : #-f 載入的文件作為映射文件使用 -u : #強制ACL的名稱唯一 -- : #強制結束flag結束,避免了字元串中含有的- 引起混淆 其中flag中的 -m 選項可使用的模式匹配方法如下,需要說明的是有些方法已被預設指定無需聲明,例如int,ip: "found" : #只是用來探測數據流中是否存在指定數據,不進行任何比較 "bool" : #檢查結果返回布爾值。匹配沒有模式,可以匹配布爾值或整數,不匹配0和false,其他值可以匹配 "int" : #匹配整數類型數據;可以處理整數和布爾值類型樣本,0代表false,1代表true "ip" : #匹配IPv4,IPv6地址類型數據。該模式僅被IP地址相容,不需要特別指定 "bin" : #匹配二進位數據 "len" : #匹配樣本的長度的整數值 "str" : #精確匹配,根據字元串匹配文本 "sub" : #子串匹配,匹配文本是否包含子串 "reg" : #正則匹配,根據正則表達式列表匹配文本 "beg" : #首碼匹配,檢查文本是否以指定字元串開頭 "end" : #尾碼匹配,檢查文本是否以指定字元串結尾 "dir" : #子目錄匹配,檢查部分文本中以" / "作為分隔符的內容是否含有指定字元串 "dom" : #域匹配。檢查部分文本中以" . "作為分隔符的內容是否含有指定字元串
[operator]:操作符,通常分字元串和整數,如下
###匹配整數值: eq #等於 ge #大於等於 gt #大於 le #小於 lt #小於等於 ###匹配字元串: exact match #精確匹配 substring match #子串匹配 prefix match #首碼匹配 suffix match #尾碼匹配 subdir match #子路徑匹配 domain match #子功能變數名稱匹配[operator]
[<value>]:值,操作符右邊的值,通常為以下幾種類型:
boolean #布爾型 integer or integer range #整數或整數範圍 IP address / network #IP或網路地址 string #字元串 hex block #16進位的塊匹配value類型
在使用多個ACL作為條件可使用邏輯運算符:
- and #預設操作符,可省略
- || #或者使用
- ! #取反
ACL之4層訪問控制
四層訪問控制一般只能針對IP以及埠來進行,其指定是 tcp-request。
語法:
tcp-request connection <action> [{if | unless} <condition>]
- < condition >: 即為ACL定義的訪問控制列表
- < action > :常用值有 "accept", “reject”,代表著允許或者拒絕
示例:
#阻斷來自非10.1.210.52訪問80埠的請求 frontend webserver acl myhost src 10.1.210.52 acl myport dst_port 80 tcp-request connection reject if !myhost myport bind 0.0.0.0:80 default_backend app
ACL之七層訪問控制
七層上的訪問控制方法有多種,列如可以利用http的報文、頭信息、URL、PATH等相關信息進行訪問控制,訪問控制的指令也有多個,常用指令如下:
#阻斷符合ACL的訪問請求 block { if | unless } <condition> #允許或拒絕http請求的控制指令 http-request { allow | deny} [ { if | unless } <condition> ] #根據條件來調用指定後端 use_backend <backend> [{if | unless} <condition>]在以上控制指令中,block語法可以使用http-request deny代替。 示例一:根據條件制定後端伺服器
#請求資源為圖片,則調用圖片伺服器後端 acl picture path_end -i .jpg .png .gif use_backend server_img if picture
示例二:阻斷請求
#根據http頭信息中的User-Agent阻斷火狐瀏覽器訪問 frontend webserver bind 0.0.0.0:80 acl bad_curl hdr_sub(User-Agent) -i .*firefox.* #hdr_sub根據頭信息中的字元串匹配 block if bad_curl default_backend app
示例三:允許或拒絕http請求
#拒絕POST HEAD 方式之外的HTTP請求 acl valid_method method POST HEAD http-request deny if ! valid_method
其他控制指令
除了以上控制指令還有比如內部狀態控制指令,如會話速率:
# 與後端建立會話速率,每秒鐘建立的新會話 be_sess_rate([<backend>]) : integer #與前端代理會話建立速率,每秒鐘建立的新會話 fe_sess_rate([frontend]) <integer>
示例一:
# 某後端被請求速率大於100,則重定向至錯誤頁,可以用於阻止一些攻擊行為 mode http acl being_scanned be_sess_rate gt 100 redirect location /denied.html if being_scanned
示例二:
#限定入站郵件速率不能大於50封/秒,所有在此指定範圍之外的請求都將被延時50毫秒 frontend mail bind :25 mode tcp maxconn 500 acl too_fast fe_sess_rate ge 50 tcp-request inspect-delay 50ms tcp-request content accept if ! too_fast tcp-request content accept if WAIT_END
五、狀態監控
HAProxy優點之一就是自帶狀態監控頁面,開啟監控頁面需要配置stats enable。
開啟stats
listen admin bind *:5656 # 定義監聽埠 stats enable # 啟用狀態統計報告 stats auth admin:admin # 設置統計頁面用戶名和密碼設置 stats uri /admin # 定義統計頁面的URL,預設為/haproxy?stats stats hide-version # 隱藏統計頁面上HAProxy的版本信息 stats refresh 30s # 統計頁面自動刷新時間 stats admin if TRUE #如果認證通過就做管理功能,可以管理後端的伺服器 stats realm “LOGIN” #登陸頁面提示信息
訪問:http://ip:5656/admin登陸後即可看到管理頁面。
六、常用配置示例
https配置
frontend web *:80 bind *:443 ssl crt /etc/haproxy/haproxy.crt #haproxy.crt包含key和pem秘鑰對 reqadd X-Forwarded-Proto:\ https #頭信息中添加https協議 redirect scheme https if !{ ssl_fc } #將80埠跳轉到443 default_backend webserver backend webserver balance roundrobin server app1 10.1.210.52:80 check server app2 10.1.210.53:80 check
mysql代理(雙主)
listen mysql_36 0.0.0.0:3306 mode tcp option tcplog balance leastconn option tcpka option mysql-