报文修改:
option forwardfor 
在由haproxy发往后端主机的请求报文中添加 "X-Forwarded-For" 首部-其值
为前端客户端的地址,用于向后端主机发送真是的客户端IP[except <network>]-请求报文请来自此处指定的网络时不予以添加此
首部--如haproxy所在网络
默认配置:
option forwardfor except 127.0.0.0/8
需要更改后端服务器日志配置:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{X-Forwarded-For}i" combined
效果展示:
192.168.23.36 - - [04/Nov/2018:10:27:10 +0800] "GET / HTTP/1.1" 200 9 "-" "curl/7.29.0" 172.20.23.20
192.168.23.36 - - [04/Nov/2018:10:27:11 +0800] "GET / HTTP/1.1" 200 9 "-" "curl/7.29.0" 172.20.23.20[header <name>]:使用自定义的首部名称,而非"X-Forwarded-For"
具体使用:
option forwardfor except 127.0.0.0/8 header xxx
使用后需要更改后端服务器端日志格式!
具体使用:
option forwardfor except 127.0.0.0/8 header HostClient[if-none] 如果没有首部才添加首部 如果有使用默认值
在请求报文尾部添加指定首部:
reqadd <string> [{if|unless} <cond>]
具体应用:
reqadd testheader:\ test
结果展示:
192.168.23.36 - - [04/Nov/2018:11:28:49 +0800] "HEAD / HTTP/1.1" 200 - "-" "curl/7.29.0" test在响应报文尾部添加指定首部:
rspadd <string> [{if|unless} <cond>]
示例:
rsqadd X-Via:\ HAPorxy
\ -----转移空白字符
请求报文中删除匹配正则表达式的首部:
reqdel <search> [{if|unless} <cond>]
reqidel <search> [{if|unless} <cond>] --不区分大小写从响应报文中删除匹配正则表达式的首部:
rspdel <search> [{if|unless} <cond>]
rspidel <search> [{if|unless} <cond>] --不区分大小写示例:rspidel server.*
删除响应报文的server:
frontend web
bind 172.20.23.36:80 
default_backend httpd
rspidel server.*
backend httpd
balance roundrobin 
server srv1 192.168.23.41:80 check 
server srv2 192.168.23.40:80 check 
server sorryserver 127.0.0.1:8080 check backup添加报文头部--响应首部:
frontend web
bind 172.20.23.36:80 
default_backend httpd
rspidel server.* --删除server响应首部
rspadd Server:\ nginx --添加自定义首部
backend httpd
balance roundrobin 
reqadd testheader:\ test
server srv1 192.168.23.41:80 check 
server srv2 192.168.23.40:80 check 
server sorryserver 127.0.0.1:8080 check backup总结:
1 对于前端使用响应相关命令
2 对于后端使用请求相关命令错误页面配置:
errorfile <code> <file>自定义错误页面
<code>:HTTP status code
支持200|400|403|408|500|502|503|504
<file>:错误页面文件路径
具体使用:
frontend web
bind 172.20.23.36:80 
default_backend httpd
errorfile 503 /etc/haproxy/errorfile/503.htmlerrorloc <code> <url>
相当于errorloc 302 <code> <url>--利用302重定向至URL
具体案例:
errorloc 503 http://172.20.23.36/test/503.html压缩功能:为指定的MIME类型启用压缩传输功能:
compression algo <algorithm>..:启用http协议的压缩机制,指明压缩
算法gzip|deflatecompression type <mine type>...:指明压缩的MIMI类型
7层健康性检查:frontend web
bind 172.20.23.36:80 
default_backend httpd
backend httpd
balance roundrobin 
option httpchk GET /test.html
http-check expect status 200
server srv1 192.168.23.41:80 check 
server srv2 192.168.23.40:80 check 
server sorryserver 127.0.0.1:8080 check backup
简单使用:
option httpchk [请求方法] [uri]
具体使用:
option httpchk GET /test.html
ACL:Haproxy--------ACL
访问控制列表[ACL]的使用提供了一个灵活的解决方案来执行容器交换
并且通常基于从请求中提取的内容,响应或任何环境状态决策acl <aclname> <criterion> [flags] [operator] [value]
<aclname>--ACL名称 可以使用字母数字 - _ , 区分字符代销写
<criterion> --比较的标准和条件<value>的类型:
• boolean 
• integer or integer range --整数范围
• IP address /netmask --IP/掩码
• sting --字符串
• regular expression --正则表达式
• hex block --十六进制
<flags>
-i 不区分大小写
-m 使用指定的paatterm匹配方法
-n 不做DNS解析
-u 强制每个ACL必须唯一ID 
-- 强制flag结束 当字符串和某个flag相似时使用[operator]:
匹配整数值:eq ge gt le lt
匹配字符串:• exact match (-m str):字符串必须完全匹配模式
• substring match (-m sub):在提取的字符串中查找模式
如果其中任何一个被发现,ACL将匹配• prefix match (-m beg):在提取的字符串首部中查找模式,如果其中任何一个
被发现,ACL将匹配• suffix match (-m end):将模式与提取字符串的尾部进行比较,如果其中任何
一个匹配,则ACL进行匹配• subdir match (-m dir):查看提取出来的用斜线分隔("/")的字串,如果其中
任何一个匹配,则ACL进行匹配• domain match (-m dom):查找提取的用点(".")分隔字符串,如果其中
任何一个匹配,则ACL进行匹配ACL中的逻辑关系:
• 与:隐式(默认)使用
• 或:使用"or"或"||"表示
• 否定:使用"!"表示
简单示例:
if invalid_src invalid_port --与关系
if invalid_src || invalid_port --或关系
if !invalid_src invalid_port --非关系
不满足第一个但是满足第二个<criterion> --条件
dst --目标IP
dst_port --目标端口
src --源IP
src_port --源端口
简单用法:
acl invalid_src src 172.20.23.20base:string
<scheme>://<user>:<password>@[<host>:<port>/<path>;<params>]?<query>#<frag>path:string 
<scheme>://<user>:<password>@<host>:<port>[/<path>;<params>]?<query>#<frag>path_beg /images/ --以/images/开头
path_end .jpg --以jpg结尾
path_reg ^/images.*.jpeg$ --正则表达式
path_sub image --包括了image字串检查每一个/xx/
path_dir jpegs --包括jpegs文件夹
path_dom linux --使用linux域 xxx.[linux].com
对比案例:
/images/jpegs/20181104/log.jpg
具体使用:
拒绝某IP用户访问:配合errorfile
frontend web
bind 172.20.23.36:80 
default_backend httpd
acl false_IP src 172.20.23.20
block if false_IP
errorfile 403 /etc/haproxy/errorfile/403.html
backend httpd
balance roundrobin 
server srv1 192.168.23.41:80 check 
server srv2 192.168.23.40:80 check 
server sorryserver 127.0.0.1:8080 check backup具体使用2:
拒绝所有test为前缀的访问
frontend web
bind 172.20.23.36:80 
default_backend httpd
acl false_page path_beg /test
block if false_page
errorfile 403 /etc/haproxy/errorfile/403.html
backend httpd
balance roundrobin 
server srv1 192.168.23.41:80 check 
server srv2 192.168.23.40:80 check 
server sorryserver 127.0.0.1:8080 check backup实现动静分离:
use_backend [backname] if 
具体提使用:
frontend web
bind 172.20.23.36:80 
default_backend httpd
acl false_page path_beg /test 
block if false_page
acl php_page path_end .php
use_backend vip if php_page --当访问php后缀的就网vip组中的主机调度
errorfile 403 /etc/haproxy/errorfile/403.html
backend httpd
balance roundrobin 
server srv1 192.168.23.41:80 check 
server srv2 192.168.23.40:80 check 
server sorryserver 127.0.0.1:8080 check backup
backend vip
balance roundrobin
server vip1 192.168.23.42:80 check 
server vip2 192.168.23.43:80 checkurl:string
提取请求中的URL,一个典型的应用时具有预取能力的缓存
以及需要从数据库聚合多个信息并将它们保存在缓存中的网页门户入口
推荐使用pathreq.hdr([<name>[,<occ>]]):string
提取在一个HTTP请求报文的首部
hdr([<name>[,<occ>]]): exact string match
hdr_beg([<name>[,<occ>]]): prefix match
hdr_dir([<name>[,<occ>]]): subdir match
hdr_dom([<name>[,<occ>]]): domain match
hdr_end([<name>[,<occ>]]): suffix match
hdr_len([<name>[,<occ>]]): length match
hdr_reg([<name>[,<occ>]]): regex match
hdr_sub([<name>[,<occ>]]): substring match
示例:
acl bad_agent hdr_sub(User-Agent) -i curl wget
block if bad_agent
拒绝使用curl和wget访问!
测试:
wget -O -- 172.20.23.20实现访问不同主机名称调度到不同的后端主机:
frontend web
bind 172.20.23.36:80 
default_backend httpd
acl false_page path_beg /test 
block if false_page
acl php_page path_end .php
use_backend vip if php_page
errorfile 403 /etc/haproxy/errorfile/403.html
acl bad_agent hdr_sub(Host) -i www.a.com
use_backend vip if bad_agent
backend httpd
balance roundrobin 
server srv1 192.168.23.41:80 check 
server srv2 192.168.23.40:80 check 
server sorryserver 127.0.0.1:8080 check backup
backend vip
balance roundrobin
server vip1 192.168.23.42:80 check 
server vip2 192.168.23.43:80 checkstatus : integer
返回在响应报文中的状态码系统预定义ACL
TRUE --总是匹配
FALSE --总是不匹配
HTTP --匹配http协议
HTTP_1.0 --匹配1.0协议
HTTP_1.1 --匹配1.1协议
HTTP_CONTENT --匹配已经存在的内容长度
HTTP_URL_ABS --匹配URL绝对路径
HTTP_URL_SLASH --匹配URL相对路径
HTTP_URL_STAR --匹配URL等于"*" 
LOACLHOST --匹配从localhost来的连接
METH——CONNECT --匹配HTTP CONNECT方法
METH_GET --匹配使用get为请求方法的
METH-HEAD --匹配使用head为请求方法的其它配置项:
当被acl匹配到时就切换到指定backend
use_backend [backendname] if [aclname]
阻止7层请求如果acl匹配成功
block if [aclname]http-request {allow|deny|add-header} 
acl niceguy src 172.20.23.1
acl bedguy src 172.20.23.2
具体使用:白名单
http-request allow niceguy
http-request deny bedguy根据第四层条件对传入连接执行操作:
tcp-request connection {accept|reject} [{if|unless} <condition>]示例:
listen ssh
bind :22222
balance roundrobin
mode tcp
acl false_ip src 172.20.23.20
tcp-request connection reject if false_ip
server ssh1 192.168.23.40:22 check
server ssh2 192.168.23.41:22 check


https://blog.51cto.com/13878078/2375045