1. Concepts

netfilter is a set of hooks inside the Linux kernel that allows kernel modules to register callback functions with the network stack. A registered callback function is then called back for every packet that traverses the respective hook within the network stack.

iptables is a userspace command line utility for configuring Linux kernel firewall implemented within the Netfilter project. The term iptables is also commonly used to refer to this kernel-level firewall. iptables is used for IPv4, and ip6tables is used for IPv6.

iptables is used to inspect, modify, redirect, and/or drop IPv4 packets. The code for filtering IPv4 packets is already built into the kernel and is organized into a collection of tables, each with a specific purpose. The tables are made up of a set of predefined chains, and the chains rules which are traversed in order. Each rule consists of a predicate of potential matches and a corresponding action (called a target) which is executed if the predicate is true; i.e. the conditions are matched.

iptables is the user utility which allows you to work with these chains/rules.

tables traverse

The key to understanding how iptables works is the chart above. The lowercase word on top is the table and the uppercase word below is the chain. Every IP packet that comes in on any network interface passes through this flow chart from top to bottom.

1.1. Tables

iptables contains five tables:

  • raw is used only for configuring packets so that they are exempt from connection tracking.

  • filter is the default table, and is where all the action typically associated with a firwall take place.

  • nat is used for network address translation (e.g. port forwarding).

  • mangle is used for specialized packet alterations.

  • security is used for Mandatory Access Control networking rules. (e.g. SELinux — see this article for more details).

In most common use cases you will only use two of these: filter and nat.

                               XXXXXXXXXXXXXXXXXX
                             XXX     Network    XXX
                               XXXXXXXXXXXXXXXXXX
                                       +
                                       |
                                       v
 +-------------+              +------------------+
 |table: filter| <---+        | table: nat       |
 |chain: INPUT |     |        | chain: PREROUTING|
 +-----+-------+     |        +--------+---------+
       |             |                 |
       v             |                 v
 [local process]     |           ****************          +--------------+
       |             +---------+ Routing decision +------> |table: filter |
       v                         ****************          |chain: FORWARD|
****************                                           +------+-------+
Routing decision                                                  |
****************                                                  |
       |                                                          |
       v                        ****************                  |
+-------------+       +------>  Routing decision  <---------------+
|table: nat   |       |         ****************
|chain: OUTPUT|       |               +
+-----+-------+       |               |
      |               |               v
      v               |      +-------------------+
+--------------+      |      | table: nat        |
|table: filter | +----+      | chain: POSTROUTING|
|chain: OUTPUT |             +--------+----------+
+--------------+                      |
                                      v
                               XXXXXXXXXXXXXXXXXX
                             XXX    Network     XXX
                               XXXXXXXXXXXXXXXXXX

1.2. Chains

Tables consist of chains, which are lists of rules which are followed in order.

The default table, filter, contains three bultin-chain: INPUT, OUTPUT and FORWARD which are actived at different points of the packet filtering process, as illustrated in the flow chart.

  • INPUT - This chain is used to control the behavior for incoming connections.

    For example, if a user attempts to SSH into your PC/Server, iptables will attempt to match the IP address and port to a rule in the input chain.

  • FORWARD - This chain is used for incoming connections that aren’t actually being delivered locally.

    Think of a router - data is always being sent to it but rarely actually destined for the router itself; the data is just forwarded to its target. Unless you’re doing some kind of routing, NATing, or something else your system that rquires forwarding, you won’t even use this chain.

  • OUTPUT - This chain is used for outgoing connections.

    For example, if you try to ping blog.codefarm.me, iptables will check output chain to see what the rules are regarding ping and blog.codefarm.me before making a decision to allow or deny the connection attempt.

The nat table incudes PREROUTING, POSTROUTING, and OUTPUT chains.

  • PREROUTING - Alters packets before routing. i.e Packet translation happens immediately after the packet comes to the system and before routing.

    This helps to translate the destination ip address of the packets to something that matches the routing on the local server. This is used for DNAT (destination NAT).

  • POSTROUTING - Alters packets after routing. i.e Packet translation happens when the packets are leaving the system.

    This helps to translate the source ip address of the packets to something that might match the routing on the desintation server. This is used for SNAT (source NAT).

  • OUTPUT - NAT for locally generated packets on the firewall.

1.3. Rules

Packet fitlering is based on rules, which are specified by multiple matches (condition the packet must satisfy so that the rule can be applied), and on target (action taken when the packet matches all conditions).

The typical things a rule might match on are what interface the packet came in on (e.g eth0 or eth1), what type of packet it is (ICMP, TCP, or UDP), or the desitination port of the packet.

Targets are specified using the -j or --jump option. Targets can be either user-defined chains, (i.e. if these conditions are matched, jump to the following user-defined chain and continue processing there), one of the special built-in targets, or a target extension.

  • If the target is a built-in target, the fate of the packet is decided immediately and processing of the packet in current table is stopped.

  • If the target is a user-defined chain and the fate of the packet is not decided by this second chain, it will be filtered against the remaining rules of the original chain.

  • Target extensions can be either terminating (as built-in targets) or non-terminating (as user-defined chains).

1.4. Policy

To see what the policy chains on the default table filter are currently configured to do with unmatched traffic, run the iptables -L command.

$ sudo iptables -L | grep policy
Chain INPUT (policy ACCEPT)
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)

$ sudo iptables -t nat -L | grep policy
Chain PREROUTING (policy ACCEPT)
Chain INPUT (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)
Chain POSTROUTING (policy ACCEPT)

As you can see, we also used the grep command to give use cleaner output. In that screenshot, our chains are currently figured to accpet traffic.

More times than not, you’ll want your system to accept connections by default. Unless you’ve changed the policy chain rules previously, this setting should already be configured. Either way, here’s the command to accept connections by default:

$ sudo iptables -P INPUT ACCEPT
$ sudo iptables -P OUTPUT ACCEPT
$ sudo iptables -P FORWARD ACCEPT

By default to the ACCEPT rule, you can then use iptables to deny specific IP addresses or port numbers, while continuing to accept all other connections.

If you would rather deny all connections manually specify which ones you want to allow to connect, you should change the default policy of yur chains to DROP. Doing this probably only be useful for servers that contain sensitive information and only ever have the same IP addresses connect to them.

$ sudo iptables --policy INPUT DROP
$ sudo iptables --policy OUTPUT DROP
$ sudo iptables --policy FORWARD DROP

2. Usage

IPTABLES(8)                                                       iptables 1.4.21                                                       IPTABLES(8)



NAME
       iptables/ip6tables — administration tool for IPv4/IPv6 packet filtering and NAT

SYNOPSIS
       iptables [-t table] {-A|-C|-D} chain rule-specification

       ip6tables [-t table] {-A|-C|-D} chain rule-specification

       iptables [-t table] -I chain [rulenum] rule-specification

       iptables [-t table] -R chain rulenum rule-specification

       iptables [-t table] -D chain rulenum

       iptables [-t table] -S [chain [rulenum]]

       iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]

       iptables [-t table] -N chain

       iptables [-t table] -X [chain]

       iptables [-t table] -P chain target

       iptables [-t table] -E old-chain-name new-chain-name

       rule-specification = [matches...] [target]

       match = -m matchname [per-match-options]

       target = -j targetname [per-target-options]

DESCRIPTION
       Iptables  and ip6tables are used to set up, maintain, and inspect the tables of IPv4 and IPv6 packet filter rules in the Linux kernel.  Sev‐
       eral different tables may be defined.  Each table contains a number of built-in chains and may also contain user-defined chains.

       Each chain is a list of rules which can match a set of packets.  Each rule specifies what to do with a packet that matches.  This is  called
       a `target', which may be a jump to a user-defined chain in the same table.

TARGETS
       A  firewall  rule specifies criteria for a packet and a target.  If the packet does not match, the next rule in the chain is examined; if it
       does match, then the next rule is specified by the value of the target, which can be the name of a user-defined chain, one  of  the  targets
       described in iptables-extensions(8), or one of the special values ACCEPT, DROP or RETURN.

       ACCEPT  means to let the packet through.  DROP means to drop the packet on the floor.  RETURN means stop traversing this chain and resume at
       the next rule in the previous (calling) chain.  If the end of a built-in chain is reached or a rule in a built-in chain with  target  RETURN
       is matched, the target specified by the chain policy determines the fate of the packet.

TABLES
       There are currently five independent tables (which tables are present at any time depends on the kernel configuration options and which mod‐
       ules are present).

       -t, --table table
              This option specifies the packet matching table which the command should operate on.  If the kernel is configured with automatic mod‐
              ule loading, an attempt will be made to load the appropriate module for that table if it is not already there.

              The tables are as follows:

              filter:
                  This is the default table (if no -t option is passed). It contains the built-in chains INPUT (for packets destined to local sock‐
                  ets), FORWARD (for packets being routed through the box), and OUTPUT (for locally-generated packets).

              nat:
                  This table is consulted when a packet that creates a new connection is encountered.  It consists of three  built-ins:  PREROUTING
                  (for  altering  packets as soon as they come in), OUTPUT (for altering locally-generated packets before routing), and POSTROUTING
                  (for altering packets as they are about to go out).  IPv6 NAT support is available since kernel 3.7.

              mangle:
                  This table is used for specialized packet alteration.  Until kernel 2.4.17 it had two built-in chains: PREROUTING  (for  altering
                  incoming  packets before routing) and OUTPUT (for altering locally-generated packets before routing).  Since kernel 2.4.18, three
                  other built-in chains are also supported: INPUT (for packets coming into the box itself), FORWARD  (for  altering  packets  being
                  routed through the box), and POSTROUTING (for altering packets as they are about to go out).

              raw:
                  This  table is used mainly for configuring exemptions from connection tracking in combination with the NOTRACK target.  It regis‐
                  ters at the netfilter hooks with higher priority and is thus called before ip_conntrack, or any other IP tables.  It provides the
                  following  built-in  chains:  PREROUTING  (for packets arriving via any network interface) OUTPUT (for packets generated by local
                  processes)

              security:
                  This table is used for Mandatory Access Control (MAC) networking rules, such as those enabled by the SECMARK and CONNSECMARK tar‐
                  gets.  Mandatory Access Control is implemented by Linux Security Modules such as SELinux.  The security table is called after the
                  filter table, allowing any Discretionary Access Control (DAC) rules in the filter table to take effect before  MAC  rules.   This
                  table provides the following built-in chains: INPUT (for packets coming into the box itself), OUTPUT (for altering locally-gener‐
                  ated packets before routing), and FORWARD (for altering packets being routed through the box).

OPTIONS
       The options that are recognized by iptables and ip6tables can be divided into several different groups.

   COMMANDS
       These options specify the desired action to perform. Only one of them can be specified on the command line unless  otherwise  stated  below.
       For long versions of the command and option names, you need to use only enough letters to ensure that iptables can differentiate it from all
       other options.

       -A, --append chain rule-specification
              Append one or more rules to the end of the selected chain.  When the source  and/or  destination  names  resolve  to  more  than  one
              address, a rule will be added for each possible address combination.

       -C, --check chain rule-specification
              Check  whether  a  rule matching the specification does exist in the selected chain. This command uses the same logic as -D to find a
              matching entry, but does not alter the existing iptables configuration and uses its exit code to indicate success or failure.

       -D, --delete chain rule-specification
       -D, --delete chain rulenum
              Delete one or more rules from the selected chain.  There are two versions of this command: the rule can be specified as a  number  in
              the chain (starting at 1 for the first rule) or a rule to match.

       -I, --insert chain [rulenum] rule-specification
              Insert one or more rules in the selected chain as the given rule number.  So, if the rule number is 1, the rule or rules are inserted
              at the head of the chain.  This is also the default if no rule number is specified.

       -R, --replace chain rulenum rule-specification
              Replace a rule in the selected chain.  If the source and/or destination names resolve to multiple addresses, the command  will  fail.
              Rules are numbered starting at 1.

       -L, --list [chain]
              List  all rules in the selected chain.  If no chain is selected, all chains are listed. Like every other iptables command, it applies
              to the specified table (filter is the default), so NAT rules get listed by
               iptables -t nat -n -L
              Please note that it is often used with the -n option, in order to avoid long reverse DNS lookups.  It is  legal  to  specify  the  -Z
              (zero)  option  as  well, in which case the chain(s) will be atomically listed and zeroed.  The exact output is affected by the other
              arguments given. The exact rules are suppressed until you use
               iptables -L -v

       -S, --list-rules [chain]
              Print all rules in the selected chain.  If no chain is selected, all chains are printed like iptables-save. Like every other iptables
              command, it applies to the specified table (filter is the default).

       -F, --flush [chain]
              Flush the selected chain (all the chains in the table if none is given).  This is equivalent to deleting all the rules one by one.

       -Z, --zero [chain [rulenum]]
              Zero  the  packet and byte counters in all chains, or only the given chain, or only the given rule in a chain. It is legal to specify
              the -L, --list (list) option as well, to see the counters immediately before they are cleared. (See above.)

       -N, --new-chain chain
              Create a new user-defined chain by the given name.  There must be no target of that name already.

       -X, --delete-chain [chain]
              Delete the optional user-defined chain specified.  There must be no references to the chain.   If  there  are,  you  must  delete  or
              replace the referring rules before the chain can be deleted.  The chain must be empty, i.e. not contain any rules.  If no argument is
              given, it will attempt to delete every non-builtin chain in the table.

       -P, --policy chain target
              Set the policy for the chain to the given target.  See the section TARGETS for the legal targets.  Only  built-in  (non-user-defined)
              chains can have policies, and neither built-in nor user-defined chains can be policy targets.

       -E, --rename-chain old-chain new-chain
              Rename the user specified chain to the user supplied name.  This is cosmetic, and has no effect on the structure of the table.

       -h     Help.  Give a (currently very brief) description of the command syntax.

# ...

SEE ALSO
       iptables-apply(8), iptables-save(8), iptables-restore(8), iptables-extensions(8),

       The  packet-filtering-HOWTO  details  iptables usage for packet filtering, the NAT-HOWTO details NAT, the netfilter-extensions-HOWTO details
       the extensions that are not in the standard distribution, and the netfilter-hacking-HOWTO details the netfilter internals.
       See http://www.netfilter.org/.

2.1. iptables [-t table] -L [chain [rulenum]] [options…​]

  • List all rules in the selected chain. If no chain is selected, all chains are listed.

    ~]# iptables -L
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination
    KUBE-SERVICES  all  --  anywhere             anywhere             ctstate NEW /* kubernetes service portals */
    KUBE-EXTERNAL-SERVICES  all  --  anywhere             anywhere             ctstate NEW /* kubernetes externally-visible service portals */
    ...
    
     ~]# iptables -L -n --line-numbers
    Chain INPUT (policy ACCEPT)
    num  target     prot opt source               destination
    1    KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            ctstate NEW /* kubernetes service portals */
    2    KUBE-EXTERNAL-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            ctstate NEW /* kubernetes externally-visible service portals
     */
    ...
    
     ~]# iptables -L INPUT 1 -n
    KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            ctstate NEW /* kubernetes service portals */
  • Like every other iptables command, it applies to the specified table (filter is the default), so NAT rules get listed by:

    ~]# iptables -t nat -L -n
    Chain PREROUTING (policy ACCEPT)
    target     prot opt source               destination
    KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
    CNI-HOSTPORT-DNAT  all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
    ...
  • Please note that it is often used with the -n option, in order to avoid long reverse DNS lookups.

    ~]# iptables -L -n
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination
    KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            ctstate NEW /* kubernetes service portals */
    KUBE-EXTERNAL-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            ctstate NEW /* kubernetes externally-visible service portals */
    ...

2.2. iptables [-t table] -S [chain [rulenum]]

  • Print all rules in the selected chain. If no chain is selected, all chains are printed like iptables-save.

    ~]# iptables -t nat -S
    -P PREROUTING ACCEPT
    -P INPUT ACCEPT
    -P OUTPUT ACCEPT
    -P POSTROUTING ACCEPT
  • Like every other iptables command, it applies to the specified table (filter is the default).

     ~]# iptables -t nat -S OUTPUT
    -P OUTPUT ACCEPT
    -A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
    -A OUTPUT -m comment --comment "portmap/canal-portmap" -j CANAL-DNAT
    -A OUTPUT -m addrtype --dst-type LOCAL -j DOCKER
    -A OUTPUT -m addrtype --dst-type LOCAL -j CNI-HOSTPORT-DNAT

2.3. iptables [-t table] -F [chain [rulenum]] [options…​]

  • Flush the selected chain (all the chains in the table if none is given). This is equivalent to deleting all the rules one by one.

    # Flush your iptables all chains rules at filter table
    ~]# iptables -F
    
    ~]# iptables -F INPUT    # Flush the INPUT chain only
    ~]# iptables -F OUTPUT   # Flush the OUTPUT chain only
    ~]# iptables -F FORWARD  # Flush the FORWARD chain only
    
    # Flush your iptables all chains rules at nat table
    ~]# iptables -t nat -F

2.4. iptables [-t table] {-A|-C|-I|-R|-D} chain …​

iptables [-t table] -A chain rule-specification

iptables [-t table] -C chain rule-specification

iptables [-t table] -I chain [rulenum] rule-specification

iptables [-t table] -R chain rulenum rule-specification

iptables [-t table] -D chain rulenum

Rules can be edited by appending -A a rule to a chain, inserting -I it at a specific position on the chain, replacing -R an existing rule, or delete -D it, and check exists with -C.

2.4.1. Allowing Incomming Traffic on Specific Ports

You could start by blocking traffic, but you might be working over SSH, where you would need to allow SSH before blocking everything else.

To allow incomming traffic on the default SSH port (22), you could tell iptables to allow all TCP traffic on that port to come in.

~]# iptables -C  INPUT -p tcp --dport ssh -j ACCEPT
iptables: Bad rule (does a matching rule exist in that chain?).

~]# iptables -A INPUT -p tcp --dport ssh -j ACCEPT

~]# iptables -C INPUT -p tcp --dport ssh -j ACCEPT

Also, you can also specify the destination port with number.

~]#  iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Referring back to the list above, you can see that this tells iptables:

  1. append this rule to the input chain (-A INPUT) so we look at incomming traffic.

  2. check to see if it is TCP (-p tcp).

  3. if so, check to see if the input goes to the SSH port (--dport ssh).

  4. if so, accept the input (-j ACCEPT.

Lets check the rules: (only the first few lines shown, you will see more)

 ~]# iptables -L INPUT -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22

Now, let’s allow all incomming web traffic

~]# iptables -A INPUT -p tcp --dport http -j ACCEPT
~]# iptables -A INPUT -p tcp --dport https -j ACCEPT

# or

~]# iptables -A INPUT -p tcp -m multiport --dports http,https -j ACCEPT

Checking our rules, we have

 ~]# iptables -L INPUT -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:443
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 80,443

Allow default port range for Kubernetes NodePort servies.

~]# iptables -A INPUT -p tcp --dport 30000:32767 -j ACCEPT -m comment --comment "Allow default port range of kubernetes nodeport services"

~]# iptables -L INPUT -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:443
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            multiport dports 80,443
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpts:30000:32767 /* Allow default port range of kubernetes nodeport services */

We have specifically allowed tcp traffic to the ssh and web ports, but as we have not blocked anything, all traffic can still come in.

2.4.2. Block Incomming Traffic

Once a decision is made to accept a packet, no more rules affect it. As our rules allowing ssh and web traffic come first, as long as our rule to block all traffic comes after them, we can still accept the traffic we want. All we need to do is put the rule to block all traffic at the end.

$ sudo iptables -A INPUT -j DROP
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:https
DROP       all  --  anywhere             anywhere

2.4.3. Allow Incomming Traffic on Specific IP Addresses

  • Here -s 0/0 stand for any incomming source with any IP addresses.

    $ sudo iptables -A INPUT -p tcp -s 0/0 --dport 22 -j ACCEPT
    $ sudo iptables -L
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination
    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
  • -s 192.168.66.128/24 using CIDR values, it stands for IP starting from 192.168.66.1 to 192.168.66.255.

    $ sudo iptables -A INPUT -p tcp -s 192.168.66.128/24 --dport 22 -j ACCEPT
    $ sudo iptables -L
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination
    ACCEPT     tcp  --  192.168.66.0/24      anywhere             tcp dpt:ssh
    $ sudo iptables -A INPUT -p tcp -s 192.168.66.128/32 --dport 22 -j ACCEPT
    $ sudo iptables -L
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination
    ACCEPT     tcp  --  192.168.66.128       anywhere             tcp dpt:ssh
    $ sudo iptables -A INPUT -p tcp -s 192.168.66.128 --dport 22 -j ACCEPT
    $ sudo iptables -L
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination
    ACCEPT     tcp  --  192.168.66.128       anywhere             tcp dpt:ssh

2.4.4. Blocking ICMP

$ sudo iptables -A OUTPUT -p icmp --icmp-type 8 -j DROP
$ sudo iptables -L
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DROP       icmp --  anywhere             anywhere             icmp echo-request
$ ping blog.codefarm.me
PING blog.codefarm.me (104.27.162.235) 56(84) bytes of data.
ping: sendmsg: Operation not permitted

2.4.5. Blocking MongoDB from outside attach

$ sudo iptables -A INPUT -p tcp -s 192.168.66.0/24 --dport 27017 -j ACCEPT
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  192.168.66.0/24      anywhere             tcp dpt:27017

2.4.6. Blocking DDOS

$ sudo iptables -A INPUT -p tcp --dport 80 -m limit --limit 20/minute --limit-burst 100 -j ACCEPT
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http limit: avg 20/min burst 100

2.4.7. Insert a New Rule / Replace an Old Rule

$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http

$ sudo iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http

$ sudo iptables -R INPUT 1 -p tcp --dport 443 -j ACCEPT
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:https
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http

2.4.8. Create User Defined Chain / Target

$ sudo iptables -N CODE_FARM
$ sudo iptables -L | grep 'Chain'
Chain INPUT (policy ACCEPT)
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)
Chain CODE_FARM (0 references)

$ sudo iptables -A INPUT -p tcp --dport 22 -j CODE_FARM
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
CODE_FARM  tcp  --  anywhere             anywhere             tcp dpt:ssh

Chain CODE_FARM (1 references)
target     prot opt source               destination

$ sudo iptables -A CODE_FARM -p tcp -j ACCEPT
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
CODE_FARM  tcp  --  anywhere             anywhere             tcp dpt:ssh

Chain CODE_FARM (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere

$ sudo iptables -P INPUT DROP
$ sudo iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
CODE_FARM  tcp  --  anywhere             anywhere             tcp dpt:ssh

Chain CODE_FARM (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere

2.5. iptables-save & iptables-restore

Changes to iptables are transitory; if the system is rebooted or if the iptables service is restarted, the rules are automatically flushed and reset. To save the rules so that they are loaded when the iptables service is started, use the following command:

$ sudo service iptables save

The rules are stored in the file /etc/sysconfig/iptables and are applied whenever the service is started or the machine is rebooted.

You can also save the current iptables into a file and restore it.

$ sudo iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  192.168.66.0/24      anywhere             tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             multiport dports http,https
DROP       all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
$ sudo iptables-save | tee iptables.rules # save current iptables into iptables.rules and print to standard output
$ sudo Generated by iptables-save v1.6.0 on Fri Jan 18 16:43:19 2019
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [278:30254]
-A INPUT -s 192.168.66.0/24 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
-A INPUT -j DROP
COMMIT
$ sudo Completed on Fri Jan 18 16:43:19 2019
$ sudo iptables -P INPUT ACCEPT # allow any incomming traffic before delete all rules
$ sudo iptables -F # delete all rules
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
$ sudo iptables-restore iptables.rules # restore iptables from iptables.rules
$ sudo iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  192.168.66.0/24      anywhere             tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             multiport dports http,https
DROP       all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

3. References

  1. The netfilter.org project, https://netfilter.org/index.html

  2. iptables - ArchWiki, https://wiki.archlinux.org/index.php/iptables

  3. IPTABLES VS FIREWALLD | Unixmen, https://www.unixmen.com/iptables-vs-firewalld/

  4. The Beginner’s Guide to iptables, the Linux Firewall, https://www.howtogeek.com/177621/the-beginners-guide-to-iptables-the-linux-firewall/

  5. IptablesHowTo - Community Help Wiki, https://help.ubuntu.com/community/IptablesHowTo

  6. HowTos/Network/IPTables - CentOS Wiki, https://wiki.centos.org/HowTos/Network/IPTables

  7. RETURN target, https://www.frozentux.net/iptables-tutorial/chunkyhtml/x4625.html

  8. Linux Firewall Tutorial: IPTables Tables, Chains, Rules Fundamentals, https://www.thegeekstuff.com/2011/01/iptables-fundamentals/

  9. Saving Iptables Firewall Rules Permanently, https://www.thomas-krenn.com/en/wiki/Saving_Iptables_Firewall_Rules_Permanently