<?xml version="1.0" encoding="utf-8"?>
<!--############################################################################
# An example of strict custom firewall rules for a web server.                 #
################################################################################
# Allowed services:                                                            #
#                                                                              #
#     DNS Client                                                               #
#     DHCP Client                                                              #
#     HTTP Client                                                              #
#     HTTPS Client                                                             #
#     MySQL Client (Loopback Only)                                             #
#     WebSocket Client Proxy (Loopback Only)                                   #
#                                                                              #
#     SSH Server                                                               #
#     HTTP Server                                                              #
#     HTTPS Server                                                             #
#     MySQL Server (Loopback Only)                                             #
#     WebSocket Server (Loopback Only)                                         #
#     WebSocket Server Proxy                                                   #
#                                                "I AM THE LAW!" ~ Judge Dredd #
#############################################################################-->
<direct>

    <!--########################################################################
    # Allow DNS client.                                                        #
    #########################################################################-->
    <rule priority="0" table="filter" ipv="ipv4" chain="OUTPUT">-o eth0 -p udp --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT</rule>
    <rule priority="0" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p udp --sport 53 -m state --state ESTABLISHED     -j ACCEPT</rule>

    <!--########################################################################
    # Allow DHCP client.                                                       #
    #########################################################################-->
    <rule priority="0" table="filter" ipv="ipv4" chain="OUTPUT">-o eth0 -p udp --dport 67 --sport 68 -m state --state NEW,ESTABLISHED -j ACCEPT</rule>
    <rule priority="0" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p udp --dport 68 --sport 67 -m state --state ESTABLISHED     -j ACCEPT</rule>

    <!--########################################################################
    # Martian filtering.                                                       #
    #########################################################################-->
    <rule priority="1" table="filter" ipv="ipv4" chain="OUTPUT">-d 0.0.0.0/8,10.0.0.0/8,100.64.0.0/10,169.254.0.0/16,172.16.0.0/12,192.0.0.0/24,192.0.2.0/24,192.168.0.0/16,198.18.0.0/15,198.51.100.0/24,203.0.113.0/24,224.0.0.0/4,240.0.0.0/4 -j DROP -m comment --comment "martian-filter"</rule>
    <rule priority="1" table="filter" ipv="ipv4" chain="INPUT"> -s 0.0.0.0/8,10.0.0.0/8,100.64.0.0/10,169.254.0.0/16,172.16.0.0/12,192.0.0.0/24,192.0.2.0/24,192.168.0.0/16,198.18.0.0/15,198.51.100.0/24,203.0.113.0/24,224.0.0.0/4,240.0.0.0/4 -j DROP -m comment --comment "martian-filter"</rule>

    <!--########################################################################
    # Allow HTTP client.                                                       #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --sport 80 -m state --state ESTABLISHED     -j ACCEPT</rule>

    <!--########################################################################
    # Allow HTTPS client.                                                      #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --sport 443 -m state --state ESTABLISHED     -j ACCEPT</rule>

    <!--########################################################################
    # Allow MySQL client on loopback.                                          #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --dport 3306 -m state --state NEW,ESTABLISHED -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --sport 3306 -m state --state ESTABLISHED     -j ACCEPT</rule>

    <!--########################################################################
    # Allow WebSocket client proxy on loopback.                                #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --dport 8080 -m state --state NEW,ESTABLISHED -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --sport 8080 -m state --state ESTABLISHED     -j ACCEPT</rule>

    <!--########################################################################
    # Allow WebSocket client on loopback.                                      #
    #                                                                          #
    # Don't forget to run: setsebool -P httpd_can_network_connect 1            #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --dport 8081 -m state --state NEW,ESTABLISHED -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --sport 8081 -m state --state ESTABLISHED     -j ACCEPT</rule>

    <!--########################################################################
    # Allow SSH server with throttles:                                         #
    #   - Drop any new connections if the there were more than ~60 connection  #
    #     attempts made in the past minute.                                    #
    #   - Drop new connections from a specific IP address if there were more   #
    #     than 10 connection attempts made from that address.                  #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 22 -m state --state NEW         -m limit     --limit           60/minute --limit-burst    10 -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 22 -m state --state NEW         -m connlimit --connlimit-above 20        --connlimit-mask 24 -j DROP  </rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 22 -m state --state ESTABLISHED                                                              -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o eth0 -p tcp --sport 22 -m state --state ESTABLISHED                                                              -j ACCEPT</rule>

    <!--########################################################################
    # Allow HTTP server with throttles:                                        #
    #   - Drop any new connections if the there were more than ~60 connection  #
    #     attempts made in the past minute.                                    #
    #   - Drop new connections from a specific IP address if there were more   #
    #     than 10 connection attempts made from that address.                  #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 80 -m state --state NEW         -m limit     --limit           60/minute --limit-burst    10 -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 80 -m state --state NEW         -m connlimit --connlimit-above 20        --connlimit-mask 24 -j DROP  </rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 80 -m state --state ESTABLISHED                                                              -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o eth0 -p tcp --sport 80 -m state --state ESTABLISHED                                                              -j ACCEPT</rule>

    <!--########################################################################
    # Allow HTTPS server with throttles:                                       #
    #   - Drop any new connections if the there were more than ~60 connection  #
    #     attempts made in the past minute.                                    #
    #   - Drop new connections from a specific IP address if there were more   #
    #     than 10 connection attempts made from that address.                  #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 443 -m state --state NEW         -m limit     --limit           60/minute --limit-burst    10 -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 443 -m state --state NEW         -m connlimit --connlimit-above 20        --connlimit-mask 24 -j DROP  </rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 443 -m state --state ESTABLISHED                                                              -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o eth0 -p tcp --sport 443 -m state --state ESTABLISHED                                                              -j ACCEPT</rule>

    <!--########################################################################
    # Allow MySQL server on loopback.                                          #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --dport 3306 -m state --state NEW,ESTABLISHED -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --sport 3306 -m state --state ESTABLISHED     -j ACCEPT</rule>

    <!--########################################################################
    # Allow WebSocket server on loopback.                                      #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --dport 8081 -m state --state NEW,ESTABLISHED -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o lo -s 127.0.0.0/8 -d 127.0.0.0/8 -p tcp --sport 8081 -m state --state ESTABLISHED     -j ACCEPT</rule>

    <!--########################################################################
    # Allow WebSocket server proxy with throttles:                             #
    #   - Drop any new connections if the there were more than ~60 connection  #
    #     attempts made in the past minute.                                    #
    #   - Drop new connections from a specific IP address if there were more   #
    #     than 10 connection attempts made from that address.                  #
    #########################################################################-->
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 8080 -m state --state NEW         -m limit     --limit           60/minute --limit-burst    10 -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 8080 -m state --state NEW         -m connlimit --connlimit-above 20        --connlimit-mask 24 -j DROP  </rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="INPUT"> -i eth0 -p tcp --dport 8080 -m state --state ESTABLISHED                                                              -j ACCEPT</rule>
    <rule priority="2" table="filter" ipv="ipv4" chain="OUTPUT">-o eth0 -p tcp --sport 8080 -m state --state ESTABLISHED                                                              -j ACCEPT</rule>

    <!--########################################################################
    # Log all dropped packets to /var/log/messages.                            #
    #########################################################################-->
    <rule priority="3" table="filter" ipv="ipv4" chain="INPUT"> -m limit --limit 12/minute --limit-burst 2 -j LOG</rule>
    <rule priority="3" table="filter" ipv="ipv4" chain="OUTPUT">-m limit --limit 12/minute --limit-burst 2 -j LOG</rule>

    <!--########################################################################
    # Explicitly drop all packets.                                             #
    #########################################################################-->
    <rule priority="4" table="filter" ipv="ipv4" chain="INPUT"> -j DROP</rule>
    <rule priority="4" table="filter" ipv="ipv4" chain="OUTPUT">-j DROP</rule>
</direct>
