Monday, August 8, 2011

Using Squid Proxy to Fight DDoS

Complicated web applications are often difficult to scale, as a result they become easy DDoS targets. However, making them scale is easy with front-end proxy servers. The added scale gives an application more resiliency to DDoS attacks.

When setup correctly, the proxy “network” becomes the target of any malicious activity and can be placed globally while still keeping the original web application in same location for content.

This is by no means new, it’s been done all over the Internet and in some cases is the base of a bunch of different companies. This is just a simple tutorial that is meant to help people understand how this works.


Proxy servers can also be used with a dynamic caching function which can provide caching which will help increase the speed and functionality of the web site.


Positives:

  • Scales web server farms

  • Increases reach

  • Can accelerate a web site

  • Can provide additional security layers

    Negatives:


  • Adds an additional layer of debugging

  • Slows down long dynamic pages if they are not cacheable

  • Expensive to operate

    To start, I recommend using Squid Proxy version 2.7, it is available at http://www.squid-cache.org/

    After downloading the package, the vanilla build will suffice for most needs. You can use FreeBSD as the operating system and simply make install on the /usr/ports/www/squid package or build the package with a ./configure –prefix=/usr/local ; make install

    Often the prefix is /usr/local but determine what is appropriate for your OS.

    After the build has finished you will need to configure Squid, attached below is a sample configuration file:
    acl all src 0.0.0.0/0.0.0.0
    acl DO_NOT_CACHE urlpath_regex -i cgi-bin \? asp php css js
    acl manager proto cache_object
    acl purge method PURGE
    #
    refresh_pattern .               0       20%     1440
    #
    http_access allow all
    icp_access allow all
    #
    request_header_max_size 10 KB
    #
    cache_dir ufs /vol1/cachedir 512 16 256
    #
    visible_hostname supersite.com
    pid_filename /var/run/squid.pid
    #
    cache_access_log /var/log/httpd/proxy-a_access.log
    #
    cache_mem 64 MB
    maximum_object_size_in_memory 64 MB
    #
    httpd_accel_host virtual
    httpd_accel_uses_host_header on
    #
    #
    connect_timeout 30 seconds
    #
    emulate_httpd_log on
    hierarchy_stoplist cgi-bin ? asp css js php
    http_port XX.YY.ZZ.AA:80
    http_port XX.YY.ZZ.BB:80
    negative_ttl 60 seconds
    no_cache deny NOCACHE
    
    The configuration options are all explained in the default configuration file, the only major items to change are the http_port list, which should be the IP address it should respond on and the cache configuration. Some sites may have special items that should not cache. Often css and js should cache, but for this example they are dynamic.

    The logs will be written to /var/log/httpd/proxy-a_access.log in a combined Apache style format.

    When starting the squid, you will need to create a /cache directory on the server, simply run:

    mkdir /vol1/cachedir
    chown squid /vol1/cachedir
    You will also need to Create swap directories so Squid can run:

    /usr/local/bin/squid –z

    You will also need to teach squid how to communicate back to your “real” or “backend” web farm, often the DNS for www points to the IP address squid is answering requests for, this can be done using the /etc/hosts file:

    XX.YY.AA.BB www.mysitedns.com

    Replace the example above with the real IP address of the web farm and the host entry you want to be used to reach the IP address.

    Once squid is running and answering requests (/usr/local/bin/squid -k reconfigure /usr/local/etc/squid.conf) and the cache is working, it tends to stay stable until the hardware fails or you become under DDoS attack, which may require some additional ACLs within the squid.conf or SYN cookies configurations on the OS itself.

    Scaling squid is also not very difficult, it’s possible to load balance a farm of Squid servers with any standard load balancer, and have the requests still return to the same web farm, which may or may not work with any given user authentication / sessions setup.

    Blocking a given attack in Squid is trivial, however, if there are hundreds of Squid servers to configure at the same time, this may require some special configuration management that could require some development effort.

    Often most attacks have an empty or mal-formed User-Agent, this simple ACL will block 99% of invalid User-Agent attacks:

    acl OK_BROWSER browser a b c d e f g h i j k l m n o p a r s t u v w x y z 1 2 3 4 5 6 7 8 9 0 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    acl DO_NOT_CACHE urlpath_regex -i cgi-bin \? asp php css js
    http_access allow OK_BROWSER
    http_access deny all
    http_access deny manager
    http_access deny purge
    icp_access allow all
    


    You can also create a deny filter by creating an ACL that will deny rather than allow, the above ACL requires the user to have an VARCHAR in their User-Agent, which is pretty wide, so denying a specific item can be done like this:

    acl BAD_BROWSER browser Attack-Bot

    Add the deny line as the first line in the http_access ACL:

    http_access deny BAD_BROWSER

    Blocking a specific URL can look like this configuration line (which is designed to block most malicious requests):

    acl BLOCK_URI urlpath_regex -i \.exe \.\./\.\. \.\.\. \.ida \.idq \.IDA \.cnf \.asp \.dll 333-3333 test999 passwd /etc \` boot \.exe cmd \./\./ filenumber \% \* \; SELECT \\\.\.\\ \/\.\.\/

    Configuration of connection rate limiting looks like:

    acl 8conn maxconn 8

    And blocking a specific source address prefix:

    acl ip_addr1 src 192.168.1.0/24

    Just ensure that the ACL that is created is also configured in the http_access deny/allow list properly. Squid also needs to be told to re-read the configuration file, this is done by sending squid a –k reconfigure flag which will simply reload the rules without impacting traffic.

    To enable reverse proxy of SSL with the Squid cache owning the SSL certificate, you can use a pem cert and the following configuration line:

    https_port IP:443 cert=/usr/local/etc/squid/certs/COMPANY/COMPANY.pem key=/usr/local/etc/squid/certs/COMPANY/COMPANY.key

    http://www.blyon.com/using-squid-proxy-to-fight-ddos/