Search This Blog

Showing posts with label iptables. Show all posts
Showing posts with label iptables. Show all posts

centos: save the iptables changes

sudo service iptables save

iptables: delete a rule

 # delete the rule by specifying the whole rule
iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport 4000 -j ACCEPT
 # list the rules with line numbers
iptables -L INPUT --line-numbers

# delete the rule by specifying the line number of the rule (suppose the line number of the rule is 2).
iptables -D INPUT 2

iptables: insert a rule at a specific line number

# list the rules with line numbers
iptables -nL --line-numbers
# insert a rule at line 5
iptables -I INPUT 5 -p tcp -m state --state NEW -m tcp --dport 4000 -j ACCEPT

multicast ip address 224.0.0.251 port 5353

To enable Bonjour/mDNS, you need to allow traffic from multicast ip 224.0.0.251 on port 5353.

Enable simple iptables firewall on Debian 7 Wheezy

  • Install iptables-persistent:
    sudo apt-get install iptables-persistent
  • Edit /etc/iptables/rules.v4 and /etc/iptables/rules.v6
    # /etc/iptables/rules.v4
    *filter :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    :RH-Firewall-1-INPUT - [0:0]
    -A INPUT -j RH-Firewall-1-INPUT
    -A FORWARD -j RH-Firewall-1-INPUT
    -A RH-Firewall-1-INPUT -i lo -j ACCEPT
    -A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
    # ESP protocol
    -A RH-Firewall-1-INPUT -p 50 -j ACCEPT
    # AH protocol
    -A RH-Firewall-1-INPUT -p 51 -j ACCEPT
    # multicast Bonjour/mDNS
    -A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
    # cups printing
    -A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
    -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
    -A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
    -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
    COMMIT 
    
    # /etc/iptables/rules.v6
    *filter :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    :RH-Firewall-1-INPUT - [0:0]
    -A INPUT -j RH-Firewall-1-INPUT
    -A FORWARD -j RH-Firewall-1-INPUT
    -A RH-Firewall-1-INPUT -i lo -j ACCEPT
    -A RH-Firewall-1-INPUT -p icmpv6 -j ACCEPT
    # ESP protocol
    -A RH-Firewall-1-INPUT -p 50 -j ACCEPT
    # AH protocol
    -A RH-Firewall-1-INPUT -p 51 -j ACCEPT
    # multicast Bonjour/mDNS
    -A RH-Firewall-1-INPUT -p udp --dport 5353 -d ff02::fb -j ACCEPT
    # cups printing
    -A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT 
    -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
    -A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A RH-Firewall-1-INPUT -m state --state NEW -p tcp --dport 22 -j ACCEPT
    -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp6-adm-prohibited
    COMMIT 
    

See also

shell script: update ufw rules for the hosts with dynamic ip addresses

  • The shell script to check the ip address for the host and update the ufw rules:
    #!/bin/bash
    
    HOSTS_ALLOW=/etc/ufw-dynamic-hosts.allow
    IPS_ALLOW=/var/tmp/ufw-dynamic-ips.allow
    
    add_rule() {
      local proto=$1
      local port=$2
      local ip=$3
      local regex="${port}\/${proto}.*ALLOW.*IN.*${ip}"
      local rule=$(ufw status numbered | grep $regex)
      if [ -z "$rule" ]; then
          ufw allow proto ${proto} from ${ip} to any port ${port}
      else
          echo "rule already exists. nothing to do."
      fi
    }
    
    delete_rule() {
      local proto=$1
      local port=$2
      local ip=$3
      local regex="${port}\/${proto}.*ALLOW.*IN.*${ip}"
      local rule=$(ufw status numbered | grep $regex)
      if [ -n "$rule" ]; then
          ufw delete allow proto ${proto} from ${ip} to any port ${port}
      else
          echo "rule does not exist. nothing to do."
      fi
    }
    
    
    sed '/^[[:space:]]*$/d' ${HOSTS_ALLOW} | sed '/^[[:space:]]*#/d' | while read line
    do
        proto=$(echo ${line} | cut -d: -f1)
        port=$(echo ${line} | cut -d: -f2)
        host=$(echo ${line} | cut -d: -f3)
    
        if [ -f ${IPS_ALLOW} ]; then
          old_ip=$(cat ${IPS_ALLOW} | grep ${host} | cut -d: -f2)
        fi
    
        ip=$(dig +short $host | tail -n 1)
    
        if [ -z ${ip} ]; then
            if [ -n "${old_ip}" ]; then
                delete_rule $proto $port $old_ip
            fi
            echo "Failed to resolve the ip address of ${host}." 1>&2
            exit 1
        fi
    
        if [ -n "${old_ip}" ]; then
            if [ ${ip} != ${old_ip} ]; then
                delete_rule $proto $port $old_ip
            fi
        fi
        add_rule $proto $port $ip
        if [ -f ${IPS_ALLOW} ]; then
          sed -i.bak /^${host}*/d ${IPS_ALLOW}
        fi
        echo "${host}:${ip}" >> ${IPS_ALLOW}
    done
    
  • The sample hosts file: /etc/ufw-dynamic-hosts.allow:
    tcp:22:yourpc.no-ip.org
    
  • The crontab which execute the script every 5 minutes to update the rules:
    # m h  dom mon dow   command
    */5 * * * * /usr/local/sbin/ufw-dynamic-host-update  2>&1 > /dev/null
    

iptables: mac address filtering

iptables supports MAC address rules. For example you can block a MAC address:
/sbin/iptables -A INPUT -m mac --mac-source 00:00:11:22:22:33 -j DROP
or allow a MAC address:
/sbin/iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m mac --mac-source 11:22:33:44:55:66 -s 192.168.1.0/24 -j ACCEPT

However, allowing MAC addresses in iptables is NOT safe since the MAC address can be easily spoofed on all the operating systems. How should we use MAC address filtering safely? Here are some suggestions:
  1. Use MAC address rules to DROP(filter out) packets. DO NOT use MAC address rules to ACCEPT packets
  2. Use MAC address rules for LAN, e.g. a local subnet, which is considered comparably safe. DO NOT use MAC address rules for internet.

SEE ALSO:

simple iptables firewall script

#!/bin/sh
### BEGIN INIT INFO
# Provides:          iptables
# Required-Start:    mountkernfs $local_fs
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Set up iptables rules
### END INIT INFO

#============================================================================#
# Settings                                                                   #
#============================================================================#

# iptables
IPT=/sbin/iptables

# set to 0 to disable logging drop
LOG_DROP=1

# set to 1 to enable logging accept
LOG_ACCEPT=0

# log prefix (do not change if you do not know what you are doing)
LOG_PREFIX="[IPTABLES "

# chain for logging drops
LOG_DROP_CHAIN="LOGDROP"

# chain for logging accepts
LOG_ACCEPT_CHAIN="LOGACCEPT"

# log_drop prefix (do not change if you do not know what you are doing)
LOG_DROP_PREFIX="${LOG_PREFIX}DROP"

# log_accept prefix (do not change if you do not know what you are doing)
LOG_ACCEPT_PREFIX="${LOG_PREFIX}ACCEPT"

#============================================================================#
# Functions                                                                  #
#============================================================================#

reset() {

    # Reset the default policies to accept everything
    $IPT --policy INPUT   ACCEPT
    $IPT --policy OUTPUT  ACCEPT
    $IPT --policy FORWARD ACCEPT

    # Flush/Remove all rules
    $IPT --flush

    # Delete all custom chains
    $IPT --delete-chain

    # Zero counters
    $IPT --zero

    # Reset all built-in tables (nat, mangle and filter)
    for table in filter nat mangle; do
        $IPT -t $table -F
        $IPT -t $table -X
        $IPT -t $table -Z
    done

}

status() {

    echo "============================================================"
    echo "= Filter Rules:                                            ="
    echo "============================================================"
    $IPT -L -v
    echo ""

    echo "============================================================"
    echo "= NAT Rules:                                               ="
    echo "============================================================"
    $IPT -t nat -L -v
    echo ""

    echo "============================================================"
    echo "= Mangle Rules:                                            ="
    echo "============================================================"
    $IPT -t mangle -L -v
    echo ""

}

start() {

    # Reset iptables (remove all rules & chains; reset default policies to accept everything)
    reset

    # Set default policies for all three default chains
    $IPT -P INPUT DROP
    $IPT -P FORWARD DROP
    $IPT -P OUTPUT ACCEPT

    # create LOGDROP chain
    $IPT -N ${LOG_DROP_CHAIN}
    $IPT -A ${LOG_DROP_CHAIN} -m limit --limit 3/m --limit-burst 10 -j LOG --log-level 4 --log-prefix "${LOG_DROP_PREFIX}"
    $IPT -A ${LOG_DROP_CHAIN} -j DROP

    # create LOGACCEPT chain
    $IPT -N ${LOG_ACCEPT_CHAIN}
    $IPT -A ${LOG_ACCEPT_CHAIN} -m limit --limit 3/m --limit-burst 10 -j LOG --log-level 6 --log-prefix "${LOG_ACCEPT_PREFIX}"
    $IPT -A ${LOG_ACCEPT_CHAIN} -j ACCEPT

    # Log or not drops
    DROP_TARGET=${LOG_DROP_CHAIN}
    if [ "${LOG_DROP}" -eq 0 ]; then
        DROP_TARGET=DROP
    fi

    # Log or not accepts
    ACCEPT_TARGET=ACCEPT
    if [ "${LOG_ACCEPT}" -eq 1 ]; then
        ACCEPT_TARGET=${LOG_ACCEPT_CHAIN}
    fi

    # Accept loopback interfaces
    $IPT -A INPUT -i lo -j ACCEPT
    $IPT -A OUTPUT -o lo -j ACCEPT

    # Log & drop packets do not begin with SYN
    $IPT -A INPUT -p tcp ! --syn -m state --state NEW -s 0.0.0.0/0 -j ${DROP_TARGET}

    # Accept inbound TCP packets
    $IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

####### CUSTOM RULES BEGIN

    # Accept ssh connections from subnet 192.168.2.0/24
    $IPT -A INPUT -p tcp --dport 22 -m state --state NEW -s 192.168.2.0/24 -j ${ACCEPT_TARGET}

    # Accept ssh connections from remote ip 172.23.65.1
    $IPT -A INPUT -p tcp --dport 22 -m state --state NEW -s 172.23.65.1/32 -j ${ACCEPT_TARGET}

    # Accept ssh connections from subnet 192.168.1.0/24 and mac address is 11:22:33:44:55:66
    $IPT -A INPUT -p tcp --dport 22 -m state --state NEW -m mac --mac-source 11:22:33:44:55:66 -s 192.168.1.0/24 -j ${ACCEPT_TARGET}

    # Accept http connections from anywhere
    $IPT -A INPUT -p tcp --dport 80 -m state --state NEW -s 0.0.0.0/0 -j ${ACCEPT_TARGET}

####### CUSTOM RULES END

    # Accept inbound ICMP messages
    $IPT -A INPUT -p ICMP --icmp-type 8 -s 0.0.0.0/0 -j ACCEPT

    # Drop all other traffic
    $IPT -A INPUT -j ${DROP_TARGET}
}

#============================================================================#
# Main                                                                       #
#============================================================================#

case "$1" in
  start|restart)
    start
    echo "iptables firewall enabled."
    ;;
  stop)
    reset
    echo "iptables firewall disabled."
    ;;
  status)
    status
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}" >&2
    exit 1
    ;;
esac

exit 0

NOTE:

  • Click here to download the script;
  • You can add your rules between ####### CUSTOM RULES BEGIN and ####### CUSTOM RULES END section by modifying the script.
  • To install the script as startup script on Ubuntu/Debian Linux:
    sudo cp iptables.sh /etc/init.d/
    sudo update-rc.d iptables.sh defaults
    
  • To start the iptables firewall:
    sudo /etc/init.d/iptables.sh start
  • To enable logging on Ubuntu Linux, you also need to do this.

how to reset iptables

  • Reset iptables(IPV4):
      # set default policies to allow everything
      sudo /sbin/iptables --policy INPUT   ACCEPT
      sudo /sbin/iptables --policy OUTPUT  ACCEPT
      sudo /sbin/iptables --policy FORWARD ACCEPT
    
      # flush rules
      sudo /sbin/iptables -F
    
      # delete all user defined chains
      sudo /sbin/iptables -X
    
      # zero counters
      sudo /sbin/iptables -Z
    
      # reset all the tables
      for table in filter nat mangle; do
        sudo /sbin/iptables -t $table -F
        sudo /sbin/iptables -t $table -X
        sudo /sbin/iptables -t $table -Z
      done
    
  • Reset ip6tables(IPV6):
      # set default policies to allow everything
      sudo /sbin/ip6tables --policy INPUT   ACCEPT
      sudo /sbin/ip6tables --policy OUTPUT  ACCEPT
      sudo /sbin/ip6tables --policy FORWARD ACCEPT
    
      # flush rules
      sudo /sbin/ip6tables -F
    
      # delete all user defined chains
      sudo /sbin/ip6tables -X
    
      # zero counters
      sudo /sbin/ip6tables -Z
    
      # reset all the tables
      for table in filter mangle; do
        sudo /sbin/ip6tables -t $table -F
        sudo /sbin/ip6tables -t $table -X
        sudo /sbin/ip6tables -t $table -Z
      done
    

iptables: add new chains to log drop/accept messages

To create the chains to log&drop or log&accept:
# Create LOGDROP chain
/sbin/iptables -N LOGDROP
/sbin/iptables -A LOGDROP -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 4 --log-prefix "[IPTFW DROP] "
/sbin/iptables -A LOGDROP -j DROP

# Create LOGACCEPT chain
/sbin/iptables -N LOGACCEPT
/sbin/iptables -A LOGACCEPT -m limit --limit 5/m --limit-burst 7 -j LOG --log-level 6 --log-prefix "[IPTFW ACCEPT] "
/sbin/iptables -A LOGACCEPT -j ACCEPT

To log & drop, here is an example:
/sbin/iptables -A INPUT -s 111.112.113.114 -j LOGDROP

To log & accept, here is the example:
/sbin/iptables -A INPUT -s 111.112.113.115 -j LOGACCEPT

SEE ALSO:

Enable iptables logging on Ubuntu Linux

The following solution can enable the iptables logging to /var/log/iptables.log:
  1. Make sure you have --log-prefix set in your iptables entries. e.g.
    iptables -A INPUT -j LOG --log-prefix "[IPTABLES "
  2. Create & edit /etc/rsyslog.d/15-iptables.conf file, and add the following lines:
    :msg,contains,"[IPTABLES " /var/log/iptables.log
    & ~
    
  3. Create & edit /etc/logrotate.d/iptables file, and add the following lines:
    /var/log/iptables.log
    {
     rotate 4
     weekly
     missingok
     notifempty
     compress
     delaycompress
     sharedscripts
     postrotate
      reload rsyslog >/dev/null 2>&1 || true
     endscript
    }
    
  4. Restart rsyslogd:
    sudo /etc/init.d/rsyslog restart

NOTE:

In the solution above, [IPTABLES is used as the --log-prefix. You can replace it with anything you like but remember to update /etc/rsyslog.d/15-iptables.conf file.


References: