作为 load balancer, Happroxy 常常作为服务器的前端,向外界用户提供服务的入口,如果能在入口处处理安全相关问题,将极大简化后端的设计。事实上,Haproxy 不仅仅是一款开源出色的 load balancer(四层和七层),而且在安全上也相当出色。它配合内核 IP/TCP 协议栈,能够较好的抵抗 DOS, DDOS ***,还能通过限制单个 IP 的连接数和请求速率等,防止用户的恶意行为。

 Haproxy配置参数多的一塌糊涂,因而功能丰富,灵活多样,本文抛砖引玉,更多的安全功能请详见官网手册。


TCP syn flood attacks

通过向服务器发送大量的 TCP syn 分组,恶意用户实现了了 TCP syn flood ***,幸运的是,简单的配置内核网络参数即可防止这种***。 

/etc/sysctl.conf


[plain] view plain copy 在CODE上查看代码片派生到我的代码片

  1. # Protection SYN flood  

  2. net.ipv4.tcp_syncookies = 1  

  3. net.ipv4.conf.all.rp_filter = 1  

  4. net.ipv4.tcp_max_syn_backlog = 1024   

  5. sysctl -p  


Slowloris like attacks

 

  一个 Http 请求通常包括头部、url、methods 等,服务器需要接收整个 Http 请求后会做出响应。恶意用户发送缓慢的 Http 请求,比如一个字节一个字节的发送头部,服务器将一直处于 wating 状态,从而耗费服务器的资源。Haproxy 通过配置 timeout http-request 参数,当一个用户的请求时间超过设定值时,Haproxy 断开与该用户的连接。


[plain] view plain copy 在CODE上查看代码片派生到我的代码片

  1. defaults  

  2.   option http-server-close  

  3.   mode http  

  4.   <span style="color:#ff0000;">timeout http-request 5s</span>  # 防止 Slowloris like attacks  

  5.   timeout connect 5s  

  6.   timeout server 10s  

  7.   timeout client 30s  

  8.   

  9. listen stats  

  10.   bind 0.0.0.0:8880  

  11.   stats enable  

  12.   stats hide-version  

  13.   stats uri     /  

  14.   stats realm   HAProxy\ Statistics  

  15.   stats auth    admin:admin  

  16.   

  17. frontend ft_web  

  18.   bind 0.0.0.0:8080  

  19.   default_backend bk_web  

  20.   

  21. backend bk_web  

  22.   balance roundrobin  

  23.   cookie MYSRV insert indirect nocache  

  24.   server srv1 192.168.1.2:80 check cookie srv1 maxconn 100  

  25.   server srv2 192.168.1.3:80 check cookie srv2 maxconn 100  


通过 telnet 登录验证结果

[plain] view plain copy 在CODE上查看代码片派生到我的代码片

  1. telnet 127.0.0.1 8080  

  2. Trying 127.0.0.1...  

  3. Connected to 127.0.0.1.  

  4. Escape character is '^]'.  

  5. HTTP/1.0 408 Request Time-out  

  6. Cache-Control: no-cache  

  7. Connection: close  

  8. Content-Type: text/html  

  9. <h1>408 Request Time-out</h1>  

  10. Your browser didn't send a complete request in time.  

  11. Connection closed by foreign host.  


Limiting the number of connections per users

 

  以网站为例,普通用户访问网站,或者从网站下载东西时,浏览器一般会建立 5-7 个 TCP 链接。当一个恶意打开了大量 TCP 链接时,耗费服务器大量资源,影响其它用户的访问,因此我们需要根据实际情况,限制同一个用户的链接数。


[plain] view plain copy 在CODE上查看代码片派生到我的代码片

  1. defaults  

  2.   option http-server-close  

  3.   mode http  

  4.   timeout http-request 5s  

  5.   timeout connect 5s  

  6.   timeout server 10s  

  7.   timeout client 30s  

  8.   

  9. listen stats  

  10.   bind 0.0.0.0:8880  

  11.   stats enable  

  12.   stats hide-version  

  13.   stats uri     /  

  14.   stats realm   HAProxy\ Statistics  

  15.   stats auth    admin:admin  

  16.   

  17. frontend ft_web  

  18.   bind 0.0.0.0:8080  

  19.   

  20. <span style="color:#ff0000;">  # Table definition    

  21.   stick-table type ip size 100k expire 30s store conn_cur  

  22.   

  23.   # Allow clean known IPs to bypass the filter  

  24.   tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst }  

  25.   # Shut the new connection as long as the client has already 10 opened   

  26.   tcp-request connection reject if { src_conn_cur ge 10 }  

  27.   tcp-request connection track-sc1 src</span>  

  28.   

  29.   default_backend bk_web  

  30.   

  31. backend bk_web  

  32.   balance roundrobin  

  33.   cookie MYSRV insert indirect nocache  

  34.   server srv1 192.168.1.2:80 check cookie srv1 maxconn 100  

  35.   server srv2 192.168.1.3:80 check cookie srv2 maxconn 100  


注:若某些用户在同一个私有网段通过 NAT 访问网站,这样的配置存在不合理之处,最好把 NAT 处的公网地址添加到 whitelist.lst 文件中。

利用 apache 测试工具做验证,和服务器一直保持建立 10 个链接。

ab -n 50000000 -c 10 http://127.0.0.1:8080/用 telnet 打开第 11 个链接,服务器拒绝该链接。[plain] view plain copy telnet 127.0.0.1 8080  Trying 127.0.0.1...  Connected to 127.0.0.1.  Escape character is '^]'.  Connection closed by foreign host.


Limiting the connection rate per user

  仅仅限制单个用户的并发链接数并意味着万事大吉,如果用户在短时间内向服务器不断的发送建立和关闭链接请求,也会耗费服务器资源,影响服务器端的性能,因此需要控制单个用户的访问速率。

  通常情况下,考虑到用户通过浏览器一般会建立 5-7 条 TCP 链接,我们可以认为普通用户在 3 秒内不应该建立超过 20 条链接。

[plain] view plain copy defaults    option http-server-close    mode http    timeout http-request 5s    timeout connect 5s    timeout server 10s    timeout client 30s    listen stats    bind 0.0.0.0:8880    stats enable    stats hide-version    stats uri     /    stats realm   HAProxy\ Statistics    stats auth    admin:admin    frontend ft_web    bind 0.0.0.0:8080      # Table definition      stick-table type ip size 100k expire 30s store conn_cur,<span style="color:#ff0000;">conn_rate(3s)</span>      # Allow clean known IPs to bypass the filter    tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst }    # Shut the new connection as long as the client has already 10 opened or rate more than 20    tcp-request connection reject if { src_conn_cur ge 10 } <span style="color:#ff0000;">|| { src_conn_rate ge 20}</span>      tcp-request connection track-sc1 src      default_backend bk_web    backend bk_web    balance roundrobin    cookie MYSRV insert indirect nocache    server srv1 192.168.1.2:80 check cookie srv1 maxconn 100    server srv2 192.168.1.3:80 check cookie srv2 maxconn 100  注:若某些用户在同一个私有网段通过 NAT 访问网站,这样的配置存在不合理之处,最好把 NAT 处的公网地址添加到 whitelist.lst 文件中。测试,采用 ab 打开 20 个链接。(本次测试把 限制单个用户并发数功能 去掉)
ab -n 20 -c 1 -r http://127.0.0.1:8080/再用 telnet 打开第 21 个链接,服务器拒绝该请求。
[plain] view plain copy telnet 127.0.0.1 8080  Trying 127.0.0.1...  Connected to 127.0.0.1.  Escape character is '^]'.  Connection closed by foreign host.