前面已經詳細介紹了Haproxy基礎知識 , 今天這里再贅述下Haproxy的重定向跳轉的設置. haproxy利用acl來實現haproxy動靜分離,然而在許多運維應用環境中,可能需要將訪問的站點請求跳轉到指定的站點上,比如客戶單端訪問kevin.a.com需要將請求轉發到bobo.b.com或將http請求重定向到https請求,再比如當客戶端訪問出錯時,需要將錯誤code代碼提示請求到指定的錯誤頁面,諸如此類需求實現,這種情況下就需要利用haproxy的重定向功能來達到此目的。
Haproxy是一款提供高可用性、負載均衡以及基於TCP(第四層)和HTTP(第七層)應用的代理軟件,支持虛擬主機,它是免費、快速並且可靠的一種解決方案。 Haproxy特別適用於那些負載特大的web站點,這些站點通常又需要會話保持或七層處理。Haproxy運行在時下的硬件上,完全可以支持數以萬計的 並發連接。並且它的運行模式使得它可以很簡單安全的整合進您當前的架構中, 同時可以保護你的web服務器不被暴露到網絡上。
Haproxy實現了一種事件驅動、單一進程模型,此模型支持非常大的並發連接數。多進程或多線程模型受內存限制 、系統調度器限制以及無處不在的鎖限制,很少能處理數千並發連接。事件驅動模型因為在有更好的資源和時間管理的用戶端(User-Space) 實現所有這些任務,所以沒有這些問題。此模型的弊端是,在多核系統上,這些程序通常擴展性較差。這就是為什么他們必須進行優化以 使每個CPU時間片(Cycle)做更多的工作。
Haproxy支持連接拒絕 : 因為維護一個連接的打開的開銷是很低的,有時我們很需要限制攻擊蠕蟲(attack bots),也就是說限制它們的連接打開從而限制它們的危害。 這個已經為一個陷於小型DDoS攻擊的網站開發了而且已經拯救了很多站點,這個優點也是其它負載均衡器沒有的。
一. Haproxy實現request請求重定向
關於Hproxy 請求重定向主要會用到: redirect 和 redir 這兩類重定向配置語法。
1) redirect重定向用法: (redirect通常配置在haproxy acl部分)
redirect一般有兩個指令來執行HTTP重定向:
http-requets redirect #此種方式支持日志變量格式
redirect #此種方式只依賴於靜態字符串
這兩個指令的語法是相同的,即redirect現在被認為是傳統和配置應該移動到http-request redirect形式。
還有一個主要區別是:http-request redirect使用日志可變格式, 而redirect語句只依賴於靜態字符串。
2) redirect三種重定向方式
a) 位置重定向
使用語法如下:
redirect location <loc> [code <code>] <option> [{if | unless} <condition>]
使用位置重定向,例如下面所示指令可以將用戶重定向到所提供的精確位置, 該位置可以是第三方URL鏈接,也可以是本地web服務的另一個訪問路徑.
1. http-request redirect location <loc> [code <code>] [<option>] [<condition>]
2. redirect location <loc> [code <code>] [<option>] [<condition>]
相關指令參數如下:
* <loc> :一個日志格式變量 (或簡單的字符串redirect語句)描述了新位置;
* code <code>(可選):HTTP重定向的狀態代碼來執行。 此選項下的允許的狀態碼如下所示:

* <option>(可選): 可以是以下任何或組合的聲明:
1. set-cookie NAME[=value] :一個Set-Cookie頭部被添加到重定向。該cookie被命名為名稱,可以有一個可選的值值。
2. clear-cookie NAME[=]一個特殊的Set-Cookie頭被添加到重定向。該Cookie名為名稱和最大年齡的cookie參數設置為0,目的是為了指示瀏覽器刪除cookie。
注意: 在於瀏覽器中,這是兩個不同的Cookie:NAME和NAME = 以上根據您的流量模式,必須將兩個語句適應。
* if | unless : 用於條件判斷
*<condition> (可選):用於匹配acl,一般為acl的名稱
b) 前綴重定向
使用語法如下:
redirect prefix <loc> [code <code>] <option> [{if | unless} <condition>]
使用前綴重定向,將用戶重定向到由concateneting建立了一個網址<pfx>和完整的原始URI路徑:
1. http-request redirect prefix <pfx> [code <code>] [<option>] [<condition>]
2. redirect prefix <pfx> [code <code>] [<option>] [<condition>]
相關指令參數如下:
* <pfx>: 一個日志格式變量 (或簡單的字符串redirect語句)描述了新的位置前綴。
* code <code>(可選):HTTP重定向的狀態代碼來執行。 此選項下的允許的狀態碼如下所示:

* <option>(可選): 可以是以下任何或組合的聲明:
drop-query :在執行串聯時從原來的URL刪除查詢字符串
append-slash :配合使用drop-query ,在該URL的末尾添加一個“/”字符
set-cookie NAME[=value] :一個Set-Cookie頭部被添加到重定向。該cookie被命名為名稱,可以有一個可選的值值。
clear-cookie NAME[=] :一個特殊的Set-Cookie頭被添加到重定向。該Cookie名為名稱和最大年齡的cookie參數設置為0,目的是為了指示瀏覽器刪除cookie。
* if | unless :用於條件判斷
* <condition> (可選):用於匹配acl,一般為acl的名稱
c) 協議(計划)重定向(比如將http重定向到https)
使用語法如下:
redirect scheme <sch> [code <code>] <option> [{if | unless} <condition>]
使用位置重定向,例如下面所示指令可以將用戶重定向到所提供的新的http協議url鏈接, 一般用於非安全鏈接跳轉到安全鏈接,比如http跳轉到https上
1. http-request redirect scheme <schloc> [code <code>] [<option>] [<condition>]
2. redirect scheme <sch> [code <code>] [<option>] [<condition>]
相關指令參數如下:
* <loc> :一個日志格式變量 (或簡單的字符串redirect語句)描述了新位置;
* code <code>(可選):HTTP重定向的狀態代碼來執行。 此選項下的允許的狀態碼如下所示:

* <option>(可選): 可以是以下任何或組合的聲明:
1. set-cookie NAME[=value] :一個Set-Cookie頭部被添加到重定向。該cookie被命名為名稱,可以有一個可選的值值。
2. clear-cookie NAME[=]一個特殊的Set-Cookie頭被添加到重定向。該Cookie名為名稱和最大年齡的cookie參數設置為0,目的是為了指示瀏覽器刪除cookie。
注意: 在於瀏覽器中,這是兩個不同的Cookie:NAME和NAME = 以上根據你的流量模式,必須將兩個語句適應。
* if | unless :用於條件判斷
* <condition> (可選):用於匹配acl,一般為acl的名稱
一個簡單的實例:
acl http ssl_fc,not http-request redirect scheme https if http
下面是redirect 綜合應用的一個小示例:
acl clear dst_port 80 acl secure dst_port 8080 acl login_page url_beg /login acl logout url_beg /logout acl uid_given url_reg /login?userid=[^&]+ acl cookie_set hdr_sub(cookie) SEEN=1 redirect prefix https://kevin.com set-cookie SEEN=1 if !cookie_set redirect prefix https://kevin.com if login_page !secure redirect prefix http://kevin.com drop-query if login_page !uid_given redirect location http://kevin.com/ if !login_page secure redirect location / clear-cookie USERID= if logout
總結: redirect三種重定向可以混合使用,比較常用的有redirect prefix 和 redirect location這兩種方式,從某種理解上可以交差使用;
3) redir重定向用法:(redir通常配置在haproxy backend部分)
使用redir 會將發往backend的站點服務請求均以302狀態響應發給需要重定向的server服務或站點,此時haproxy不需要向后端web server提交請求;需要注意的是,在prefix后面不能使用/,且不能使用相對地址,以避免造成循環,例如:
frontend main *:80
default_backend app
backend app
balance roundrobin
server node1 127.0.0.1:81 check weight 3 redir http://www.kevin.com
上面配置含義:所有發往localhost:81的請求做重定向,重定向到www.kevin.com因此可以實現單台服務器的重定向
又例如,如果我們要講訪問的站點重定向到grace.com
frontend main *:80
default_backend app
backend app
balance roundrobin
server node1 127.0.0.1:81 check weight 3 redir http://www.grace.com
注意:redir只做跳轉,如客戶端輸入:http://ip ,將會跳轉到指定的頁面上,此時客戶端的頁面的頁面也會跳轉到指定的頁面上,之后所有的請求都會遞交到該站點(前提該站點可以與客戶端通訊),而不再發往haproxy代理站點,haproxy也不需要往后端web server提交客戶端發過來的請求。
二. haproxy實現error重定向
格式為: errorfile 錯誤代碼code 錯誤代碼響應提示頁路徑
* errorfile 即根據客戶端頁面錯誤code狀態將指定的錯誤狀態頁面提示給客戶端,比如友情提示頁面,一般如下:
errorfile 403 /etc/haproxy/errorfiles/403.http errorfile 500 /etc/haproxy/errorfiles/500.http errorfile 502 /etc/haproxy/errorfiles/502.http errorfile 503 /etc/haproxy/errorfiles/503.http errorfile 504 /etc/haproxy/errorfiles/504.http
例如:如果想訪問403頁面重定向到其他頁面的話 (errorloc),則參考以下配置:
frontend web_server
bind *:80
default_backend webserver
acl badguy src 172.16.50.10
block if badguy
errorloc 403 http://grace.com/ #定義錯誤頁面重定向
errorfile 表示在用戶請求不存在的頁面時,返回一個頁面給客戶端而非有haproxy生成的錯誤代碼,可用於所有段中;
格式: errorfile <code> <file>
errorloc 表示請求錯誤時,返回一個HTTP重定向至某URL的信息,可以用於所有端中;
格式: errorloc <code> <url>
總結: 錯誤重定向可以更加友好地提示客戶端錯誤狀態,比如做定制頁面化跳轉,以及網站維護升級等等,當出現錯誤時,可以及時跳轉到預定好錯誤提示頁面上。
三. haproxy定義規則
1) haproxy常用的acl匹配條件
-i:不區分<value>中模式字符的大小寫;
-f:從指定的文件中加載模式;
path_beg:用於測試請求的URL是否以<string>指定的模式開頭
例:匹配url以/static、/images、/javascript /stylesheets開頭
acl url_static path_beg -i /static /images /javascript /stylesheets
path_end:用於測試請求的URL是否以<string>指定的模式結尾
例:匹配url以jpg、gif、png、css、js結尾
acl url_static path_end -i .jpg .gif .png .css .js
hdr_beg:用於測試請求報文的指定首部的開頭部分是否符合<string>指定的模式
例:匹配請求的主機以img、video、download或ftp開頭
acl host_static hdr_beg(host) -i img. video. download. ftp.
即匹配訪問的域名是img.bobo.com,video.bobo.com,download.bobo.com,ftp.bobo.com
url_beg:匹配的是整個url
例:匹配url為http://www.bobo.com.com
acl is_bobo.com url_beg http://www.bobo.com.com
use_backend bobo.com if is_bobo.com
dst_port:判斷請求的端口
hdr_sub:判斷客戶的user-agent
例:判斷客戶端的user-agent是否為手機
acl shouji hdr_sub(user-agent) -i android iphone
2) haproxy定義分發規則
根據請求的主機頭,實現不同項目的請求,分發到不同的backend hdr_beg(host):判斷主機頭 例如: acl is_www hdr_beg(host) -i www.bobo.com.com acl is_wap hdr_beg(host) -i wap.bobo.com.com acl is_erp hdr_beg(host) -i erp.bobo.com.com acl is_interface hdr_beg(host) -i interface.bobo.com.com use_backend tomcat_erp_v2 if is_erp use_backend tomcat_interface_v2 if is_interface use_backend tomcat_web_v2 if is_www use_backend tomcat_mobile_v2 if is_wap 通過定義以上規則即可實現訪問不同的域名分發到不同的backend
3) haproxy定義重定向規則
prefix:表示重定向url location:表示重定向訪問路徑,即url不變,url后邊跟的路徑發生改變 例如: redirect prefix http://weihu.bobo.com.com/PC if is_www redirect prefix http://weihu.bobo.com.com/H5 if is_wap 說明: 當訪問is_www時,重定向到weihu.bobo.com.com/PC 當訪問is_wap時,重定向到weihu.bobo.com.com/H5
4) haproxy定義放行規則
僅放行通過驗證的IP地址或者IP范圍段; 例如: 如果訪問的是is_www,但來源IP不是指定的IP時,用http-request deny進行拒絕; acl is_www hdr_beg(host) -i www.bobo.com.com acl is_dns src 172.16.60.0/24 218.65.212.0/24 http-request deny if is_www !is_dns(滿足條件的直接進行拒絕) 也可以寫為: acl is_www hdr_beg(host) -i www.bobo.com.com acl is_dns src 172.16.60.0/24 218.65.212.0/24 user_backend www if is_www is_dns(兩個條件同時滿足才使用后端的www) 說明: 源地址有多個時,用空格進行隔開
5) haproxy定義手機只能訪問手機端,電腦端只能訪問電腦端規則
例如: 當手機訪問www.bobo.com時轉發到wap.bobo.com 當電腦訪問wap.bobo.com時轉發到www.bobo.com 配置如下: acl is_shouji hdr_sub(user-agent) -i android iphone acl is_diannao hdr_beg(host) www redirect prefix http://wap.bobo.com if shouji redirect prefix http://www.bobo.com if is_diannao !is_shouji
Haproxy 重定向跳轉 - 示例 1
1) 首先每個域名解析到自己的ip www.kevin.com 172.16.51.100 www.grace.com 172.16.51.200 www.bobo.com 172.16.51.210 2) 域名重定向 acl name_redirectA hdr_beg(host) -i www.kevin.com redirect prefix http://www.bobo.com/A if name_redirectA acl name_redirectB hdr_beg(host) -i www.grace.com redirect prefix http://www.bobo.com/B if name_redirectB 3) 跳轉規則 acl name_A hdr_beg(host) -i www.kevin.com acl name_B hdr_beg(host) -i www.grace.com acl name_C hdr_beg(host) -i www.bobo.com acl api_reqA path_beg -i /A/api acl api_reqB path_beg -i /B/api use_backend appserver_8081 if name_A or name_B #匹配"或"的規則 use_backend appserver_8082_A if name_C api_reqA #匹配"和"的規則 use_backend appserver_8082_B if name_C api_reqB backend appserver_8081 balance source server web1 172.16.51.171:8081 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3 server web2 172.16.51.174:8081 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3 backend appserver_8082_A server web1 172.16.51.180:80 weight 3 check inter 2000 rise 2 fall 3 backend appserver_8082_B server web1 172.16.51.180:80 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
Haproxy 重定向跳轉 - 示例 2
redirect location <to> [code <code>] <option> [{if | unless} <condition>]
redirect prefix <to> [code <code>] <option> [{if | unless} <condition>] 重定向,相當於rewrite
示例配置如下:
acl shibo hdr_reg(host) -i ^(shibo.kevin.com|forum.kevin.com) #使用正則匹配
acl shibo_path path_beg -i /shibo #url 目錄
acl youxi path_beg -i /youxi
acl static path_end -i .html .css .js #url 結尾文件
acl php path_end -i .php
acl jsp path_end -i .jsp .do
use_backend shibo_pool if shibo or shibo_path #注意"或"的匹配用"or"
use_backend youxi_pool if youxi
use_backend static_pool if static
use_backend php_pool if php
use_backend jsp_pool if jsp
default_backend www.kevin.com
#當滿足host_bb.cn的策略,跳轉(重定向)到http://www.bb.cn
acl host_bb.cn hdr_beg(host) -i (bb.cn|beijing.com)
redirect prefix http://www.bb.cn if host_bb.cn
#有個問題: haproxy能否在接到一個請求時選擇一個后端服務器,然后301重定向url 。
#主要原因是他有5個1G的出口,這樣就能充分利用其帶寬。
#測試了一下是可以的
frontend free
bind *:80
default_backend lvs2
backend lvs2
mode http
option forwardfor header ORIG_CLIENT_IP
server free174 172.16.51.16:8081 redir http://free71-174-grace.com:8081 weight 10 rise 3 fall 5 check inter 2000
server free173 172.16.51.15:8081 redir http://free71-173-grace.com:8081 weight 10 rise 3 fall 5 check inter 2000
#當輸入負載均衡機器的域名后,url會直接變成http://free71-17(3|4)-grace.com:8081.
acl monitor hdr_beg(host) -i monitor.kevin.com #定義ACL名稱(monitor),對應的請求的主機頭是monitor.kevin.com
acl shibo hdr_reg(host) -i ^(shibo.kevin.com|forum.kevin.com) #使用正則匹配
acl host_bb.cn hdr_beg(host) -i bb.cn
acl host_hui.cn hdr_beg(host) -i beijing.com
redirect prefix http://www.bb.cn if host_bb.cn
redirect prefix http://www.bb.cn if host_hui.cn
frontend localhost
bind *:80
bind *:443 ssl crt /etc/ssl/bb.web/bb.web.pem
redirect scheme https if !{ ssl_fc }
mode http
default_backend nodes
# 上面配置中, 添加了redirect導向,如果連接不是通過SSL連接的,它將http重定向到https
acl host_bb.cn hdr_beg(host) -i bb.cn
acl host_jiu.cn hdr_beg(host) -i beijing.com
acl www_jiu.cn hdr_beg(host) -i www.beijing.com
acl host_hui.cn hdr_beg(host) -i pp.com
acl www_hui.cn hdr_beg(host) -i www.pp.com
redirect prefix http://www.bb.cn if host_bb.cn
redirect prefix http://www.bb.cn if host_jiu.cn
redirect prefix http://www.bb.cn if www_jiu.cn
redirect prefix http://www.bb.cn if host_hui.cn
redirect prefix http://www.bb.cn if www_hui.cn
訪問bb.cn,beijing.com,www.beijing.com,pp.com,www.pp.cpm 都跳轉到http://www.bb.cn
Haproxy 重定向跳轉 - 示例 3 (手機規則匹配)
一. 線上業務的實際需求
現在根據業務的實際需要,有以下幾種不同的需求。如下:
a) 轉發所有手機請求
所有通過手機端訪問http.shibo.com域名的話,全部轉發到http://www.shibo.com這個地址,而PC端不受此限制。
b) 根據url進行轉發
如果手機端請求http.shibo.com這個域名的url中,以docs或者manager這兩個關鍵詞開頭的話,把該請求轉發到后端的服務器,而PC端不受此限制。
也就是說手機端訪問具體的url地址的話,可以正常訪問。如果是直接訪問http.shibo.com域名的話,直接把該請求轉發到http://www.shibo.com這個地址。
============================================================
二. haproxy配置
下面根據不同的業務需求進行配置haproxy,如下。
a) 轉發所有手機請求配置
要把所有的手機端請求轉到www.shibo.com這個地址,需要我們首先把訪問的終端匹配出來,haproxy可以通過hdr_sub(user-agent)這個參數把手機端匹配出來。
手機端匹配出來后,我們就可以定義相應的規則,把手機端的請求轉發到www.shibo.com這個地址了。haproxy.cf配置文件如下:
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
uid 188
gid 188
daemon
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.1
option redispatch
retries 3
option redispatch
maxconn 2000
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
listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /stats
stats auth admin:admin
stats hide-version
frontend weblb
bind *:80
acl is_http hdr_beg(host) http.shibo.com
acl ua hdr_sub(user-agent) -i android iphone
redirect prefix http://www.shibo.com if ua
use_backend httpserver if is_http
backend httpserver
balance source
server web1 127.0.0.1:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
溫馨提示:
在以上配置文件中,有以下兩行需要注意:
acl ua hdr_sub(user-agent) -i android iphone
redirect prefix http://www.shibo.com if ua
這兩行:
第一行是第一個ua規則,該規則是判斷是否是手機端。
注意:在此手機端,我們只匹配了安卓手機和iphone。
第二行是跳轉規則,如果匹配是手機端的話,那么直接跳轉到http://www.shibo.com這個地址。
如果是PC端的話,默認跳轉到httpserver這個后端服務器組。
以上配置是一台服務器對外只提供一個域名訪問的請求,如果有兩個域名的話,就要進行如下配置:
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
uid 188
gid 188
daemon
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.1
option redispatch
retries 3
option redispatch
maxconn 2000
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
listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /stats
stats auth admin:admin
stats hide-version
frontend weblb
bind *:80
acl is_http hdr_beg(host) http.shibo.com
acl is_haproxy hdr_beg(host) haproxy.shibo.com
acl ua hdr_sub(user-agent) -i android iphone
redirect prefix http://www.shibo.com if ua !is_haproxy
use_backend haproxyserver if ua is_haproxy
use_backend haproxyserver if is_haproxy
use_backend httpserver if is_http
backend httpserver
balance source
server web1 127.0.0.1:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
backend haproxyserver
balance source
server web1 127.0.0.1:7070 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
b) 測試轉發所有手機請求
在手機瀏覽器中輸入http.shibo.com會自動跳轉到http://www.shibo.com這個地址。
c) 根據url進行轉發配置
根據手機端請求的url進行轉發的話,首先也是需要匹配出手機端,然后定義url路徑規則。最后結合手機端和url路徑規則,進行跳轉。
haproxy具體配置文件,如下:
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
uid 188
gid 188
daemon
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.1
option redispatch
retries 3
option redispatch
maxconn 2000
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
listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /stats
stats auth admin:admin
stats hide-version
frontend weblb
bind *:80
acl is_http hdr_beg(host) http.shibo.com
acl is_docs url_beg /docs /manager
acl ua hdr_sub(user-agent) -i android iphone
redirect prefix http://www.shibo.com if ua !is_docs
use_backend httpserver if ua is_docs
use_backend httpserver if is_http
backend httpserver
balance source
server web1 127.0.0.1:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
溫馨提示:
在上述配置文件中,需要以下幾行解釋下:
acl is_docs url_beg /docs /manager
定義一個is_docs規則。如果url以/docs或者/manager開頭的,則全部屬於該規則。
acl ua hdr_sub(user-agent) -i android iphone
redirect prefix http://www.shibo.com if ua !is_docs
這兩行首先是匹配出手機端,然后如果是手機端訪問,並且訪問的不是is_docs規則的話,則直接跳轉到http://www.shibo.com這個地址。
use_backend httpserver if ua is_docs
這條命令是,如果是手機端訪問,並且訪問的是is_docs規則的話,則直接跳轉到httpserver這個后端服務器組。
如果是PC端的話,默認跳轉到httpserver這個后端服務器組。
d) 測試根據url進行轉發
手機端訪問http://http.shibo.com/docs/這個連接的話,是可以直接訪問的。
============================================================
三. 其他haproxy相關配置
上面說明了有關手機的相關配置,在實際的生產環境中,有時候還會碰到一些奇奇怪怪的要求。
比如要求所有手機端訪問的http.shibo.com,轉到指定的頁面。haproxy主要配置文件如下:
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
frontend weblb
bind *:80
acl is_http hdr_beg(host) http.shibo.com
acl ua hdr_sub(user-agent) -i android iphone
redirect prefix http://www.shibo.com/?p=10624 if ua
use_backend httpserver if is_http
backend httpserver
balance source
server web1 127.0.0.1:8080 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
以上配置是所有手機端訪問的,都跳轉到http://www.shibo.com/?p=10624這個頁面。
haproxy重定向跳轉 - 示例4 (修改路徑, 即重寫URL)
1) 訪問https://www.shibo.com/guo-hui 重定向跳轉到 https://www.xiaobo.com/an-hui
frontend https
option http-server-close
reqadd X-Forwarded-Proto:\ https
acl shi_bo hdr(host) -i www.shibo.com
acl guo_hui path_beg /guo-hui
acl an_hui path_beg /an-hui
reqirep ^([^\ ]*\ /)guo-hui(.*) \1an-hui\2 if shi_bo guo_hui #注意中間的空格, 以及\1 和 \2;
redirect prefix https://www.xiaobo.com code 301 if shi_bo an_hui
2) 訪問http://front-end/app-2/do-that 重定向跳轉到 http://back-end/app-2-another-path/do-that
frontend http
acl do-that path_end -i /app-2/do-that
use_backend server1 if do-that
backend server1
reqirep ^([^\ :]*)\ /app-2/(.*) \1\ /app-2-another-path/\2
server server 172.16.60.51
3) 訪問原請求為 http://www.kevin.com/OLD/ab...
重定向到 http://www.kevin.com/NEW/ab...
在nginx里可以通過rewrite來實現跳轉配置, 配置內容如下:
server {
listen 80;
server_name www.kevin.com;
location / {
rewrite ^/OLD(.*) /NEW$1 permanent;
proxy_pass http://backend_www_kevin_com;
}
}
在haproxy里重定向跳轉的配置如下:
frontend web80
bind *:80
acl domain_www_kevin_com hdr_beg(host) -i www.kevin.com kevin.com
acl url_old url_beg -i /old
reqirep ^([^\ ]*)\ /old(.*) \1\ /new\2 if domain_www_kevin_com url_old
use_backend kevin_com if domain_www_kevin_com
最后總結:
通過以上haproxy和nginx的重寫配置, 可以看出二者配置的不同在於:
- http://www.kevin.com/old,后端真實服務器收到的請求被重寫為 /new/ ,並且瀏覽器收到 HTTP/1.1 302 Location: /new/ ,
地址欄改為 http://www.kevin.com/new/
- http://www.kevin.com/old/,或者 http://www.kevin.com/old/ab... 后端真實服務器收到的請求被重寫為 /new/ ,
瀏覽器並沒有收到 302 , 地址欄依舊為 http://www.kevin.com/old/
4) haproxy URL 重新 , 如下兩個規范配置
reqirep ^([^\ ]*)\ /books/(.*) \1\ /books.php?title=\2
reqirep ^([^\ ]*)\ /(.*) \1\ /wdn/\2
# 注意中間的空格, 以及\1 和 \2
5) reqirep可以修改http的頭; 如果haproxy 配置里要替換主機頭, 則:
在backend 選項下面加入:
reqirep ^Host:\ (.*) Host:\ 標識
haproxy重定向跳轉 - 示例5 (錯誤/黑白名單/動靜分離/讀寫(上傳和下載)分離的重定向 )
1) haproxy 錯誤重定向(403), 即黑名單設置
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
acl blacklist src 172.16.51.250
http-request deny if blacklist
如上配置后, 當來源ip是172.16.51.250時, 就直接返回一個403錯誤頁面!!
=============================================================
當haproxy配置里限制一個來源ip訪問時, 直接給用戶返回403錯誤頁面, 會顯得不太友好, 所以haproxy重定向應運而生.
如下配置, 當來源ip是172.16.51.250時, 直接重定向跳轉到172.16.51.10的8000端口的錯誤頁面
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
acl badhost src 172.16.51.250
block if badhost
errorloc 403 http://172.16.51.10:8000
在172.16.51.10機器上部署nginx, 端口為8000, 然后在nginx根目錄的index.html里設置錯誤頁面信息,
錯誤頁面信息可以自己隨便定義, 比如"抱歉, 頁面臨時出錯, 運維工程師正在搶修中, 請耐心等待~"
2) haproxy 黑名單重定向
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
acl badhost src 172.16.51.250
redirect location http://172.16.51.10:8000 if badhost
在172.16.51.10機器上部署nginx, 端口為8000, 然后在nginx根目錄的index.html里設置錯誤頁面信息,
錯誤頁面信息可以自己隨便定義, 比如"抱歉, 這是一個禁止訪問的來源ip地址!請嘗試從其他機器訪問."
3) haproxy 網頁重定向
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
acl shibo.com hdr_beg(host) -i shibo.com
redirect code 301 location http://www.shibo.com if shibo.com
溫馨提示:
如果不寫301,只寫code默認是302,臨時重定向 (不推薦), 加上301則表示永久重定向
4) haproxy 訪問IP自動跳轉到域名
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
acl 172.16.51.10 hdr(host) -i 172.16.51.10
redirect code 301 location http://www.shibo.com if 172.16.51.10
5) haproxy 讀寫分離 配置 (即上傳和下載分離)
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
acl read method GET
acl read method HEAD
acl write method PUT
acl write method POST
use_backend dynamic if write
default_backend static
backend static #"上傳"讀取操作的負載代理.
balance roundrobin
server web1 172.16.51.30:80 check
backend dynamic #"下載"寫入操作的負載代理
balance roundrobin
server web2 172.16.51.40:80 check
6) haproxy 動靜分離 配置
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
frontend public
bind *:80 name clear
#bind 172.16.51.10:443 ssl crt /etc/haproxy/haproxy.pem
#use_backend static if { hdr_beg(host) -i img }
#use_backend static if { path_beg /img /css }
use_backend static2 if { path_end -i .php }
default_backend static1
# The static backend backend for 'Host: img', /img and /css.
backend static1
balance roundrobin
server statsrv1 172.16.51.20:80 check inter 1000
backend static2
balance roundrobin
server statsrv2 172.16.51.30:80 check inter 1000
7) haproxy的白名單設置
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
frontend tcp-8080-front
bind *:8080
mode tcp
default_backend tcp-8080-back
tcp-8080-back
mode tcp
balance leastconn
tcp-request content accept if { src -f /usr/local/haproxy/white_ip_list }
tcp-request content reject
server tcp-8080 10.1.27.20:8080
配置中/usr/local/haproxy/white_ip_list文件即為白名單文件, 在文件里配置允許的白名單地址: 一行一個IP或者IP段。
haproxy 重定向跳轉 - 示例6
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
acl admin_req path_beg -i /admin
use_backend admin_80 if admin_req
backend admin_80
mode http
balance roundrobin
server apphost01_8083 172.16.50.133:80 check inter 2000 fall 3
接着去172.16.50.133服務器上看下tomcat配置
[root@tomcat-133 ~]# vim /usr/local/tomcat/conf/server.xml
.............
<Context docBase="/data02/kevin-web" path="/" reloadable="false"/>
[root@tomcat-133 ~]# cd /data02/kevin-web
[root@tomcat-133 kevin-web]# ls
admin adminwechat index.html jquery.2.1.4.min.js META-INF WEB-INF kevin-web-0.0.1-SNAPSHOT.war
[root@tomcat-133 kevin-web]# ls
bobo.html
最后, 可驗證:
訪問http://www.kevin.com/admin/bobo.html 實際上返回的是172.16.50.133服務器的/data02/kevin-web/admin/bobo.html頁面內容
haproxy 重定向跳轉 - 示例7 (haproxy 代理 https)
haproxy代理https有兩種方式:
1)haproxy服務器本身提供ssl證書,后面的web服務器走正常的http
2)haproxy服務器本身只提供代理,后面的web服務器走https(配置ssl證書)
=====================================================
第一種方式:haproxy服務器本身提供ssl證書
注意: 需要編譯haproxy的時候支持ssl
編譯參數:
[root@localhost ~]# make TARGET=linux26 USE_OPENSSL=1 ADDLIB=-lz
[root@localhost ~]# ldd haproxy | grep ssl
libssl.so.10 => /usr/lib64/libssl.so.10 (0x00007fb0485e5000)
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
frontend https_frontend
bind *:443 ssl crt /etc/ssl/certs/servername.pem
mode http
option httpclose
option forwardfor
reqadd X-Forwarded-Proto:\ https
default_backend web_server
backend web_server
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
server s1 172.16.50.150:80 check cookie s1
server s2 172.16.50.151:80 check cookie s2
溫馨提示: 這里的pem 文件是下面兩個文件合並而成
[root@localhost ~]# cat servername.crt servername.key |tee servername.pem
=====================================================
第二種方式:haproxy服務器本身只提供代理,沒有ssl證書 (一般我們常用的就是這種方式)
這種方式,haproxy不需要重新編譯支持ssl,簡單方便,只需要后面的web服務器配置好ssl即可。
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
.............
.............
frontend https_frontend
bind *:443
mode tcp
default_backend web_server
backend web_server
mode tcp
balance roundrobin
stick-table type ip size 200k expire 30m
stick on src
server s1 172.16.50.150:443
server s2 172.16.50.151:443
溫馨提示: 這種模式下mode 必須是tcp模式!!!!!!!!
haproxy重定向跳轉 - 示例8 (http, https的有關重定向, 案例分析)
需要提前說明下:
下面配置操作全部是在haproxy1.5.4版本下進行配置和通過測試的!
haproxy1.3版本以下haproxy配置參數可能不能使用,所以需要注意haproxy的版本號
以下的haproxy配置可以在線上生產環境直接使用的!
一、業務要求
根據系統業務的實際需要,有以下幾種不同的需求:
1.1) http跳轉https
把所有請求http://http.kevin.com的地址全部跳轉為https://http.kevin.com這個地址。
1.2) http與https並存
服務器同時開放http://http.kevin.com和https://http.kevin.com的訪問形式。
1.3) 同台服務器不同域名之間的https與http
同一台服務器對http.kevin.com域名訪問的全部跳轉為https://http.kevin.com,而對haproxy.kevin.com訪問走http協議,
也就是跳轉到http://haproxy.kevin.com這個地址。
1.4) 同台服務器多域名均使用https
同一台服務器對http.kevin.com和haproxy.kevin.com訪問走http是協議。
二、配置haproxy, 實現以上業務需求
2.1) http跳轉https的haproxy配置文件內容
說實話haproxy的https配置要比nginx配置簡單的多了,只需要加入幾行代碼即可實現https的功能。
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
uid 188
gid 188
daemon
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.1
option redispatch
retries 3
option redispatch
maxconn 2000
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
listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /stats
stats auth admin:admin
stats hide-version
frontend weblb
bind *:80
acl is_http hdr_beg(host) http.kevin.com
redirect scheme https if !{ ssl_fc }
bind *:443 ssl crt /etc/haproxy/kevin.com.pem
use_backend httpserver if is_http
backend httpserver
balance source
server web1 127.0.0.1:7070 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
溫馨提示:
在以上配置文件中,只要需要注意下面四個選項的配置:
tune.ssl.default-dh-param 2048 #因為我們的SSL密鑰使用的是2048bit加密,所以在此進行聲明。
acl is_http hdr_beg(host) http.kevin.com
redirect scheme https if !{ ssl_fc }
bind *:443 ssl crt /etc/haproxy/kevin.com.pem
# 這三行表示把所有訪問http.kevin.com這個域名的請求,全部轉發到https://http.kevin.com這個連接。
測試:
發現在瀏覽器中,無論輸入的是http.kevin.com, 還是http://http.kevin.com, 亦或是https://http.kevin.com,都會自動跳轉到https://http.kevin.com。
這樣就達到了,把所有的http請求跳轉到https的目的。
2.2) http與https並存配置
haproxy要實現http和https並存的話,配置也很簡單,只需要把haproxy分別監控不同的端口就行,配置文件如下:
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
user haproxy
group haproxy
daemon
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /stats
stats auth admin:admin
stats hide-version
frontend weblb
bind *:80
acl is_http hdr_beg(host) http.kevin.com
use_backend httpserver if is_http
backend httpserver
balance source
server web1 127.0.0.1:7070 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
frontend weblb443
bind *:443 ssl crt /etc/haproxy/kevin.com.pem
acl is_443 hdr_beg(host) http.kevin.com
use_backend httpserver443 if is_443
backend httpserver443
balance source
server web1 127.0.0.1:7070 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
溫馨提示:
在以上配置文件中,定義了兩個前端,一個前端用於監聽80端口,也就是http協議。另外一個前端監聽443端口,也就是https協議。
此時haproxy會根據客戶端請求的協議進行分發,如果發現客戶端請求的是http協議,則把該請求分發到監聽80端口的前端。
如果發現客戶端請求的是https協議,則把該請求分發到監聽443端口的前端。如此就達到了haproxy讓http和https並存的要求。
測試:
通過測試會發現,在瀏覽器中如果輸入的是http://http.kevin.com或者是http.kevin.com都會直接跳轉到http://http.kevin.com,
而輸入的是https://http.kevin.com,則只會跳轉到https://http.kevin.com。
如此就到達了,我們業務的要求實現http和https並存。
2.3) 同台服務器不同域名之間的https與http配置
同台服務器不同域名之間的http和https配置比較復雜,第一需要監聽兩個端口,第二還要根據不同的域名進行分發。
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
uid 188
gid 188
daemon
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.1
option redispatch
retries 3
option redispatch
maxconn 2000
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
listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /stats
stats auth admin:admin
stats hide-version
frontend weblb
bind *:80
acl is_haproxy hdr_beg(host) haproxy.kevin.com
acl is_http hdr_beg(host) http.kevin.com
redirect prefix https://http.kevin.com if is_http
use_backend haproxyserver if is_haproxy
backend haproxyserver
balance source
server web1 127.0.0.1:9090 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
frontend weblb443
bind *:443 ssl crt /etc/haproxy/kevin.com.pem
acl is_443 hdr_beg(host) http.kevin.com
use_backend httpserver443 if is_443
backend httpserver443
balance source
server web1 127.0.0.1:7070 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
溫馨提示:
同台服務器不同域名之間的https與http配置,上面配置了兩個前端一個用於監聽80端口,並且根據不同的域名進行跳轉。
在80端口的規則中,如果客戶端請求的是http.kevin.com,這個域名的話,則haproxy會把該請求直接跳轉到https://http.kevin.com。
如果是haproxy.kevin.com,這個域名的話,則分發到后端的服務器。
另外一個前端用於監聽443端口,用於分發客戶端https://http.kevin.com的請求。
測試:
可以發現在瀏覽器中輸入haproxy.kevin.com會跳轉到http://haproxy.kevin.com這個地址,
而如果輸入的是http.kevin.com或者是http://http.kevin.com,亦或是https://http.kevin.com的話,都會跳轉到https://http.kevin.com。
如此就達到了上面的業務要求,同台服務器上訪問haproxy.kevin.com直接跳轉到80端口,如果訪問的是http.kevin.com域名的話則跳轉
到https://http.kevin.com這個地址。
2.4) 同台服務器多域名均使用https配置
要使同台服務器的兩個設置多個域名都使用https協議的話,配置很簡單。只需要在haproxy中啟用各自的https配置即可。
[root@localhost ~]# vim /usr/local/haproxy/conf/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
uid 108
gid 116
daemon
tune.ssl.default-dh-param 2048
defaults
log global
mode http
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.1
option redispatch
retries 3
option redispatch
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
listen admin_stats
bind 0.0.0.0:1080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /stats
stats auth admin:admin
stats hide-version
frontend web80
bind *:80
acl is_http hdr_beg(host) http.kevin.com
redirect scheme https if !{ ssl_fc }
bind *:443 ssl crt /etc/haproxy/kevin.com.pem
acl is_haproxy hdr_beg(host) haproxy.kevin.com
redirect scheme https if !{ ssl_fc }
bind *:443 ssl crt /etc/haproxy/kevin.com.pem
use_backend httpserver if is_http
use_backend haproxyserver if is_haproxy
backend httpserver
balance source
server web1 127.0.0.1:6060 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
backend haproxyserver
balance source
server web1 127.0.0.1:9090 maxconn 1024 weight 3 check inter 2000 rise 2 fall 3
測試:
在瀏覽中無論是輸入http.kevin.com、http://http.kevin.com,還是haproxy.kevin.com、http://haproxy.kevin.com,都會跳轉到相應的https地址。
這也達到了業務的要求
