• Haproxy 重定向跳转设置


    前面已经详细介绍了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-hui2 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 /new2  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地址。
    这也达到了业务的要求
  • 相关阅读:
    Linux设置高分辨率后无法进入X系统
    C++中struct和class的总结
    Jenkins 使用slave管理进行持续集成测试说明
    从BUG工具redmine上获取数据后借助python模块pycha 画出BUG分析类报表,利用xlsxwriter
    生成jmeter可用文件和必要参数化的csv
    从BUG工具redmine上获取数据后借助python模块pycha 画出BUG分析类报表
    遍历jenkins build后的文件夹,找出最新“build NO.”复制到制定目录进行操作
    计算http接口签名,并驱动其参数进行测试
    举一反三,取buglist中的url
    测试sq3数据库,读取数据库把内容输出到csv文件,附上输出到excel方法
  • 原文地址:https://www.cnblogs.com/kevingrace/p/10182538.html
Copyright © 2020-2023  润新知