Haproxy Defense DDOS Configuration

Keywords: socket less Unix PHP

Configuring Haproxy to Prevent DDOS Attacks

As a load balancer, Happroxy often serves as the front-end of the server, providing service entrance to external users. If security-related issues can be handled at the entrance, it will greatly simplify the design of the back-end. In fact, Haproxy is not only an excellent open source load balancer (four and seven layers), but also quite good at security. It cooperates with the core IP/TCP protocol stack, and can resist DOS and DDOS attacks better. It can also prevent malicious behavior of users by limiting the number of connections and request rate of a single IP.

TCP syn flood attacks

By sending a large number of TCP syn packets to the server, malicious users implement TCP syn flood attacks. Fortunately, simple configuration of the kernel network parameters can prevent such attacks.  

# vim/etc/sysctl.conf and sysctl-p

[root@kaka-games-balancers-02 ~]# vim /etc/sysctl.conf

.....................
.....................
.....................

# Protection SYN flood  
net.ipv4.tcp_syncookies = 1  
net.ipv4.conf.all.rp_filter = 1  
net.ipv4.tcp_max_syn_backlog = 1024   


[root@kaka-games-balancers-02 ~]# sysctl -p

 

Slowloris like attacks

A Http request usually includes header, url, methods, etc. The server will respond when it needs to receive the whole Http request. Malicious users send slow Http requests, such as a byte-by-byte header, and the server will always be in a wating state, thus consuming the server's resources. By configuring the timeout http-request parameter, Haproxy disconnects a user when the request time exceeds the set value.  
Parameter: timeout http-request

[root@gadmobe-balances-02 ~]# less /etc/haproxy/haproxy.cfg

global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
        maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

defaults
    mode                    http
    log                     global
    option                  httplog
    log                     127.0.0.1 local3
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s  # Preventing Slowloris like attacks
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

frontend ha_server
        bind 0.0.0.0:80
        mode http
        log global
        option  httpclose
        option  forwardfor
        default_backend rel_server


backend rel_server
        mode http
        option httpchk GET /check_ha.php
        balance roundrobin
        server  web2 10.130.36.96:80 cookie 1 weight 5 check inter 2000 rise 2 fall 3
        server  web3 10.130.74.106:80 cookie 1 weight 5 check inter 2000 rise 2 fall 3
        server  web4 10.130.40.98:80 cookie 1 weight 5 check inter 2000 rise 2 fall 3

 

test

The result of login validation through telnet will automatically be rejected after 10 seconds of login connection.

[root@li857-78 ~]# telnet 159.65.15.11 80
Trying 159.65.15.11...
Connected to 159.65.15.11.
Escape character is '^]'.
HTTP/1.0 408 Request Time-out
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>408 Request Time-out</h1>
Your browser didn't send a complete request in time.
</body></html>
Connection closed by foreign host.

 

Limiting the number of connections per users

Take the website as an example. When ordinary users visit the website or download something from the website, browsers usually set up 5-7 TCP links. When a malicious TCP link is opened, it consumes a lot of resources of the server and affects the access of other users. Therefore, we need to limit the number of links of the same user according to the actual situation.

[root@gadmobe-balances-02 ~]# less /etc/haproxy/haproxy.cfg

global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
        maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

defaults
    mode                    http
    log                     global
    option                  httplog
    log                     127.0.0.1 local3
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s  # Preventing Slowloris like attacks
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

frontend ha_server
        bind 0.0.0.0:80
        mode http
        log global
        option  httpclose
        option  forwardfor
        default_backend rel_server

 # Table definition  
  stick-table type ip size 100k expire 30s store conn_cur
  # 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 
  tcp-request connection reject if { src_conn_cur ge 10 }
  tcp-request connection track-sc1 src

backend rel_server
        mode http
        option httpchk GET /check_ha.php
        balance roundrobin
        server  web2 10.130.36.96:80 cookie 1 weight 5 check inter 2000 rise 2 fall 3
        server  web3 10.130.74.106:80 cookie 1 weight 5 check inter 2000 rise 2 fall 3
        server  web4 10.130.40.98:80 cookie 1 weight 5 check inter 2000 rise 2 fall 3

 

  • Type defines the key type of the table, which can be one of ip,ipv6,integer,string,binary
    "type ip" is used to store IPv4 type ip addresses, each entry takes up about 50 bytes of memory space, the main purpose is to store the client source IP.
    "type ipv6" is used to store IPv6 type IP addresses. Each entry takes up about 60 bytes of memory space. Its main purpose is to store client source IP.
    "type integer" for storing 32-bit integers
    "type string [len]" is used to store strings. If len is set, many characters will be truncated. If len is not specified, the default length is 32 characters.
    "type binary [len]" is used to store binary blocks. If len is set, the maximum length of storage is specified. If the data is less than len, 0 is used to fill in. The default length is 32 bytes.
  • size defines the maximum number of entries that the table can store.
  • Store] is used to store additional information that can be used by ACL. to control various standards related to client activities. Various data types can be separated by commas and written behind the store. Except that "server_id" is automatically enabled and detected by the system, other data types must be explicitly stated. If an ACL refers to an undeclared data type, the ACL returns the mismatch directly.
  • - conn_cur: The current connection number, a positive 32-bit integer, increases when a new connection matches the specified entry, and decreases when the connection ends. From this value, we can know the exact number of connections at any point in an entry.
  • - conn_rate(): Connection frequency, the frequency at which a connection is established within a specified time range (in milliseconds).
  • Related parameters of http://blog.sina.com.cn/s/blog_704836f40102w243.html---"can be referred to in this article.

Download httpd

yum install httpd -y
Using apache ab test tool for validation, and the server has maintained 10 links.  

[root@li857-78 ~]# ab -n 50000000 -c 10 http://159.65.15.11:80/


Open the 11th link with telnet and the server rejects it.

[root@li857-78 ~]# telnet 159.65.15.11 80
Trying 159.65.15.1...
Connected to 159.65.15.11.
Escape character is '^]'.
Connection closed by foreign host.

 

Limiting the connection rate per user

Limiting the number of concurrent links of a single user means that everything is going to be fine. If a user sends a request for establishing and closing links to the server in a short time, it will also consume server resources and affect the performance of the server. Therefore, it is necessary to control the access rate/frequency of a single user establishing a connection.

Usually, considering that users usually create 5-7 TCP links through browsers, we can think that ordinary users should not create more than 20 links in 3 seconds.

global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
        maxconn     4000
    user        haproxy
    group       haproxy
    daemon

    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats

defaults
    mode                    http
    log                     global
    option                  httplog
    log                     127.0.0.1 local3
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    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

frontend ha_server
        bind 0.0.0.0:80
        mode http
        log global
        option  httpclose
        option  forwardfor
        default_backend rel_server

 # Table definition  
  stick-table type ip size 100k expire 30s store conn_cur,conn_rate(3s) # Limit the number of connections in 3 seconds to 20
  # 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 } || { src_conn_rate ge 20 }
  tcp-request connection track-sc1 src

backend rel_server
        mode http
        option httpchk GET /check_ha.php
        balance roundrobin
        server  web2 10.130.36.96:80 cookie 1 weight 5 check inter 2000 rise 2 fall 3
        server  web3 10.130.74.106:80 cookie 1 weight 5 check inter 2000 rise 2 fall 3
        server  web4 10.130.40.98:80 cookie 1 weight 5 check inter 2000 rise 2 fall 3

Note: If some users access the website through NAT in the same private segment, such configuration is unreasonable, it is better to add the public address at NAT to the whitelist.lst file.
ab -n 20 -c 1 -r http://127.0.0.1:8080/
Then open the 21st link with telnet, and the server rejects the request

Posted by spoons84 on Fri, 17 May 2019 00:41:04 -0700