3-4-9-HAProxy高级功能与配置之重定向
关于Hproxy请求重定向主要会用到: redirect 和 redir 这两类重定向配置语法。
redirect重定向用法:redirect通常配置在haproxy acl部分redirect一般有两个指令来执行HTTP重定向 :http-requets redirect: 此种方式支持日志变量格式redirect: 此种方式只依赖于静态字符串
这两个指令的语法是相同的 , 即
redirect现在被认为是传统和配置应该移动到http-request redirect形式。 还有一个主要区别是 :http-request redirect使用日志可变格式 , 而redirect语句只依赖于静态字符串。
1 redirect三种重定向方式
位置重定向
redirect location <loc> [code <code>] <option> [{if | unless} <condition>]使用位置重定向 , 例如下面所示指令可以将用户重定向到所提供的精确位置 , 该位置可以是第三方
URL链接 , 也可以是本地web服务的另一个访问路径.http-request redirect location <loc> [code <code>] [<option>] [<condition>] redirect location <loc> [code <code>] [<option>] [<condition>]<loc>: 一个日志格式变量 (或简单的字符串redirect语句)描述了新位置 ;code <code>(可选) :HTTP重定向的状态代码来执行。 此选项下的允许的状态码如下所示<option>(可选): 可以是以下任何或组合的声明set-cookie NAME[=value]:一个Set-Cookie头部被添加到重定向。该cookie被命名为名称 ,可以有一个可选的值。clear-cookie NAME[=]一个特殊的Set-Cookie头被添加到重定向。该Cookie名为名称和最大年龄的cookie参数设置为0, 目的是为了指示浏览器删除cookie。注意: 在于浏览器中 , 这是两个不同的
Cookie:NAME和NAME =以上根据您的流量模式 , 必须将两个语句适应。if | unless: 用于条件判断<condition>(可选) : 用于匹配acl, 一般为acl的名称
前缀重定向
redirect prefix <loc> [code <code>] <option> [{if | unless} <condition>]使用前缀重定向 , 将用户重定向到由
concateneting建立了一个网址<pfx>和完整的原始URI路径:http-request redirect prefix <pfx> [code <code>] [<option>] [<condition>] 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的名称
协议重定向
redirect scheme <sch> [code <code>] <option> [{if | unless} <condition>]使用位置重定向 , 例如下面所示指令可以将用户重定向到所提供的新的
http协议url链接 , 一般用于非安全链接跳转到安全链接 , 比如http跳转到https上http-request redirect scheme <schloc> [code <code>] [<option>] [<condition>] redirect scheme <sch> [code <code>] [<option>] [<condition>]<sch>/<schloc>:url(<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>)中 ,scheme部分code <code>(可选):HTTP重定向的状态代码来执行。 此选项下的允许的状态码如下所示:<option>(可选): 可以是以下任何或组合的声明set-cookie NAME[=value]:一个Set-Cookie头部被添加到重定向。该cookie被命名为名称, 可以有一个可选的值值。clear-cookie NAME[=]一个特殊的Set-Cookie头被添加到重定向。该Cookie名为名称和最大年龄的cookie参数设置为0,目的是为了指示浏览器删除cookie。注意: 在于浏览器中 , 这是两个不同的
Cookie:NAME和NAME =以上根据您的流量模式 , 必须将两个语句适应。
if | unless: 用于条件判断<condition>(可选) : 用于匹配acl, 一般为acl的名称
示例
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 logout2. redir重定向用法
使用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:80的请求做重定向 , 重定向到www.kevin.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.comredir只做跳转 , 如客户端输入:http://ip,将会跳转到指定的页面上 , 此时客户端的页面也会跳转到指定的页面上 ,之后所有的请求都会递交到该站点(前提该站点可以与客户端通讯) , 而不再发往haproxy代理站点 , haproxy也不需要往后端web server提交客户端发过来的请求。
3. errorfile/errorcode 自定义错误页面
对指定的报错进行重定向 , 进行优雅的显示错误页面。
haproxy自定义错误页面有两种方式一种是由
haproxy本机提供错误页面 , 通过errorfile参数来设定。第二种是将错误转到一个指定的
url地址 通过errorcode参数来设定
3.1 基于错误页面文件
语法 :
errorfile <code> <file>。返回文件内容而不是由HAProxy产生的错误。section:default、frontend、listen、backend。<code>:HTTP状态码。目前 ,HAProxy能够生成代码:200,400,401,403,404,405,407,408,410,413,425,429,500,501,502,503,504<file>: 指定了一个包含完整HTTP响应的文件。建议遵循通常的做法 ,在文件名后面加上".http" , 这样人们就不会把响应与HTML错误页面混淆 ; 并使用绝对路径 , 因为在执行任何chroot之前都会读取文件。
errorfile 400 /etc/haproxy/errorfiles/400badreq.http
errorfile 408 /dev/null # work around Chrome pre-connect bug
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http
------------------------------
defaults
#option forwardfor
#no option http-use-htx
#...... #以下三行
errorfile 500 /usr/local/haproxy/html/500.html
errorfile 502 /usr/local/haproxy/html/502.html
errorfile 503 /usr/local/haproxy/html/503.html
3.2 基于http重定向
语法 :
errorloc <code> <url>/errorloc302 <code> <url>。返回一个HTTP重定向到一个URL, 而不是由HAProxy产生的错误。section:default、frontend、listen、backend。<code>:HTTP状态码。目前 ,HAProxy能够生成代码:200,400,401,403,404,405,407,408,410,413,425,429,500,501,502,503,504<uri>: 他是Location头部指定的跳转uri。它可以包含一个相对的URI , 指向同一网站上的错误页面 , 或者一个绝对的URI , 指定另一个网站上的错误页面。应该特别注意相对URI , 以避免重定向循环 , 如果URI本身可能产生相同的错误(如500)
这两个关键词都会返回HTTP 302状态代码 ,它告诉客户端使用相同的HTTP方法来获取指定的URL。在非GET方法(如POST)的情况下 , 这可能是相当有问题的 ,因为发送到客户端的URL可能不允许使用GET以外的方法。为了解决这个问题 , 请使用 "errorloc303 "来发送HTTP 303状态代码 , 向客户端表明该URL必须用GET请求获取。
语法:
errorloc303 <code> <url>: 返回一个HTTP重定向到一个URL , 而不是由HAProxy产生的错误。这两个关键词都会返回HTTP 303状态代码 ,它告诉客户端使用相同的HTTP GET方法来获取指定的URL。这就解决了与 "errorloc"和302代码有关的通常问题。有可能一些在HTTP/1.1之前设计的非常老的浏览器不支持它 , 但到目前为止还没有这样的问题报告。
defaults
#option http-keep-alive
#option forwardfor
#no option http-use-htx
#...... 以下一行
errorloc 503 http://192.168.7.102/error_page/503.html4. 重定向示例
示例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示例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示例3
需求如下
转发所有手机请求
所有通过手机端访问
http.shibo.com域名的话 , 全部转发到http://www.shibo.com这个地址 , 而PC端不受此限制。根据url进行转发 如果手机端请求
http.shibo.com这个域名的url中 , 以docs或者manager这两个关键词开头的话 , 把该请求转发到后端的服务器 , 而PC端不受此限制也就是说手机端访问具体的
url地址的话 , 可以正常访问。如果是直接访问http.shibo.com域名的话 , 直接把该请求转发到http://www.shibo.com这个地址。
配置
[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这个地址。如果有两个域名的话 , 就要进行如下配置
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根据
url进行转发配置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 3acl 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这个后端服务器组。
所有手机端访问的
http.shibo.com, 转到指定的页面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这个页面。
示例4
访问
https://www.shibo.com/guo-hui重定向跳转到https://www.xiaobo.com/an-huifrontend 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