Please do not run this if you don’t understand it. I don’t take any responsibility for losing access to your servers because of a too tight firewall rules.

iptables with bash

#!/bin/bash
### BEGIN INIT INFO
# Provides: Simple Firewall for iptables
# Required-Start: $local_fs $remote_fs $network
# Required-Stop: $local_fs $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start/stop/restart/status iptables-firewall
### END INIT INFO

# Modified by: https://cojo.eu
# Initial Author: Marian Amza.
#    $ sudo nano /etc/init.d/fw
#    $ sudo chmod +x /etc/init.d/fw
#    $ sudo update-rc.d fw defaults
#    $ sudo /etc/init.d/fw start
#####

# Custom Variables
IPT="iptables"
PORT_SSH="4422"

# Class for MASQUERADE
MASQ="10.10.10.0/24"

# User have the sudo rights?
fw_check() {
    if [ "$(id -u)" != "0" ]; then
        echo "You need to be root for using this script."
        exit 1
    fi
    return 0
}

# Remove all rules from iptables
fw_clear() {
    echo "Removing rules from iptables..."
    tables="filter nat mangle"
    for tables in ${table}
    do
        ${IPT} -F -t ${table}
        ${IPT} -X -t ${table}
        # Reset iptables counters
        ${IPT} -Z -t ${table}
    done

    # Policy ACCEPT to all packets
    echo "All packets have policy ACCEPT..."
    ${IPT} --policy INPUT ACCEPT
    ${IPT} --policy OUTPUT ACCEPT
    ${IPT} --policy FORWARD ACCEPT

    return 0
}

# Start Firewall
fw_start() {
    fw_clear

    # Policy default DROP all packets. Paranoid Mode - Whitelist.
    ${IPT} --policy INPUT DROP
    ${IPT} --policy OUTPUT DROP
    ${IPT} --policy FORWARD DROP

    # Kernel
        # Drop ICMP echo-request messages sent to broadcast or multicast addresses
            echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
        # Don't accept ICMP redirect messages
            echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
        # Don't send ICMP redirect messages
            echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
        # Drop source routed packets
            echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
        # Enable TCP SYN cookie protection from SYN floods
            echo 1 > /proc/sys/net/ipv4/tcp_syncookies
        # Enable source address spoofing protection
            echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
        # Log packets with impossible source addresses (spoofing)
            echo 1 > /proc/sys/net/ipv4/conf/all/log_martians
        # Enable IP Forward
            echo 1 > /proc/sys/net/ipv4/ip_forward

    # General permissions
        # Allow traffic to 127.0.0.1 (localhost)
            ${IPT} -I INPUT -d 127.0.0.0/8 -j ACCEPT
            ${IPT} -I OUTPUT -s 127.0.0.0/8 -j ACCEPT
        # Allow established traffic
            ${IPT} -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
            ${IPT} -I OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
            ${IPT} -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

    # Services
        # Accept all OUTPUT (reverse shell?)
            ${IPT} -I OUTPUT -p all -j ACCEPT
        # SSH
            ${IPT} -I INPUT -p tcp --dport ${PORT_SSH} -j ACCEPT

    # OpenVZ
        # Masquerade
            for NET in ${MASQ}
            do
                ${IPT} -t nat -A POSTROUTING -s ${NET} -o vmbr0 -j MASQUERADE
            done
            ${IPT} -A FORWARD -i vmbr0 -o vmbr1 -m state --state RELATED,ESTABLISHED -j ACCEPT
            ${IPT} -A FORWARD -i vmbr1 -o vmbr0 -j ACCEPT

    # DROP invalid or malformation packets
        # Check TCP Flags
        # Flags are: SYN ACK FIN RST URG PSH : ALL NONE
            # NULL Packets || No TCP Flags
                ${IPT} -I INPUT -p tcp --tcp-flags ALL NONE -j DROP
            # Stop Xmas Tree type scanning
                ${IPT} -I INPUT -p tcp --tcp-flags ALL ALL -j DROP
                ${IPT} -I INPUT -p tcp --tcp-flags ALL URG,ACK,PSH,RST,SYN,FIN -j DROP
            # NMAP Xmas Scan
                ${IPT} -I INPUT -p tcp --tcp-flags ALL URG,PSH,FIN -j DROP
            # NMAP ID
                ${IPT} -I INPUT -p tcp --tcp-flags ALL URG,PSH,SYN,FIN -j DROP
            # NMAP FIN/URG/PSH
                ${IPT} -I INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
            # SYN-FIN Scan
                ${IPT} -I INPUT -p tcp --tcp-flags ALL SYN,FIN -j DROP
            # FIN Scan
                ${IPT} -I INPUT -p tcp --tcp-flags ALL FIN -j DROP
            # pscan
                ${IPT} -I INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
            # SYN/RST
                ${IPT} -I INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
            # SYN/FIN || pscan 2
                ${IPT} -I INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
            # FIN/RST || pscan 2
                ${IPT} -I INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
            # FIN without ACK
                ${IPT} -I INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
            # PSH without ACK
                ${IPT} -I INPUT -p tcp --tcp-flags ACK,PSH PSH -j DROP
            # URG without ACK
                ${IPT} -I INPUT -p tcp --tcp-flags ACK,URG URG -j DROP

        # Fragments Packets
            ${IPT} -I INPUT -p tcp -f -j DROP
        # Bad Packets
            ${IPT} -I INPUT -p tcp -m state --state INVALID -j DROP
            ${IPT} -I FORWARD -p tcp -m state --state INVALID -j DROP
            ${IPT} -I OUTPUT -p tcp -m state --state INVALID -j DROP
        # Check SYN Packets
            ${IPT} -I INPUT -p tcp ! --syn -m state --state NEW -j DROP

    echo "Firewall Started!"
    return 0
}

# Stop Firewall
fw_stop() {
    fw_clear
    echo "Firewall Stopped!"
    return 0
}

# Status Firewall
fw_status() {
    tables="filter nat mangle"
    for tables in ${table}
    do
        echo "$table table: "
        ${IPT} -t $table -L -v
    done
    return 0
}

# MAIN
case "${1}" in
    start)
        fw_check
        fw_start
        ;;
    stop)
        fw_check
        fw_stop
        ;;
    restart)
        fw_check
        fw_stop
        fw_start
        ;;
    status)
        fw_check
        fw_status
        ;;
    version)
        echo "Version: 1.0"
        ;;
    *)
        echo "Use: ${0} {start|stop|restart|status}"
        exit 1
        ;;
esac

exit 0

Port Knocking

This is useful if you don’t want to have any ports open on your servers.

# Add new chain for KNOCKING
iptables -N KNOCKING
iptables -N GATE1
iptables -N GATE2
iptables -N GATE3
iptables -N PASSED

# Remaining traffic will go to KNOCKING
iptables -A INPUT -j KNOCKING

# Gate 1
iptables -A GATE1 -p tcp --dport 1111 -m recent --name AUTH1 --set -j DROP
iptables -A GATE1 -j DROP
iptables -A GATE2 -m recent --name AUTH1 --remove
iptables -A GATE2 -p tcp --dport 2222 -m recent --name AUTH2 --set -j DROP
iptables -A GATE2 -j GATE1
iptables -A GATE2 -j GATE1
iptables -A GATE3 -m recent --name AUTH2 --remove
iptables -A GATE3 -p tcp --dport 3333 -m recent --name AUTH3 --set -j DROP
iptables -A GATE3 -j GATE1
iptables -A PASSED -m recent --name AUTH3 --remove
iptables -A PASSED -p tcp --dport 22 -j ACCEPT
iptables -A PASSED -j GATE1

# Only 30 seconds to connect to SSH
iptables -A KNOCKING -m recent --rcheck --seconds 30 --name AUTH3 -j PASSED

# 10 seconds to hit all gates
sudo iptables -A KNOCKING -m recent --rcheck --seconds 10 --name AUTH2 -j GATE3
sudo iptables -A KNOCKING -m recent --rcheck --seconds 10 --name AUTH1 -j GATE2
sudo iptables -A KNOCKING -j GATE1
# www.digitalocean.com/community/tutorials/how-to-configure-port-knocking-using-only-iptables-on-an-ubuntu-vps

DDoS Testing

You can do this with BoNeSi.