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 your 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.8.9                          IPTABLES(8)

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

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

       ip6tables [-t table] {-A|-C|-D|-V} 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.  Several 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 speci‐
       fies 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 modules 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 module 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 sockets), 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 four built-ins: PREROUTING (for  altering
                  packets as soon as they come in), INPUT (for altering packets destined
                  for local sockets), OUTPUT (for altering locally-generated packets be‐
                  fore 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  it‐
                  self),  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 registers at the
                  netfilter hooks with higher priority and is thus called before ip_con‐
                  ntrack,  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  targets.
                  Mandatory Access Control is implemented by Linux Security Modules such
                  as SELinux.  The security table is called after the filter table,  al‐
                  lowing  any Discretionary Access Control (DAC) rules in the filter ta‐
                  ble to take effect before MAC rules.  This table provides the  follow‐
                  ing  built-in  chains: INPUT (for packets coming into the box itself),
                  OUTPUT (for altering locally-generated 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
              or iptables-save(8).

       -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  tar‐
              get of that name already.

       -X, --delete-chain [chain]
              Delete the 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 delete all empty chains in the table.  Empty
              builtin chains can only be deleted with iptables-nft.

       -P, --policy chain target
              Set the policy for the built-in (non-user-defined) chain to the given tar‐
              get.  The policy target must be either ACCEPT or DROP.

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

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

   PARAMETERS
       The  following  parameters  make  up  a  rule  specification (as used in the add,
       delete, insert, replace and append commands).

       -4, --ipv4
              This option has no effect in iptables and iptables-restore.  If a rule us‐
              ing  the  -4 option is inserted with (and only with) ip6tables-restore, it
              will be silently ignored. Any other uses will throw an error. This  option
              allows  IPv4  and IPv6 rules in a single rule file for use with both ipta‐
              bles-restore and ip6tables-restore.

       -6, --ipv6
              If a rule using the -6 option is inserted with (and only  with)  iptables-
              restore,  it will be silently ignored. Any other uses will throw an error.
              This option allows IPv4 and IPv6 rules in a single rule file for use  with
              both iptables-restore and ip6tables-restore.  This option has no effect in
              ip6tables and ip6tables-restore.

       [!] -p, --protocol protocol
              The protocol of the rule or of the packet to check.  The specified  proto‐
              col can be one of tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh or the
              special keyword "all", or it can be a numeric value, representing  one  of
              these  protocols  or a different one.  A protocol name from /etc/protocols
              is also allowed.  A "!" argument before the  protocol  inverts  the  test.
              The  number zero is equivalent to all. "all" will match with all protocols
              and is taken as default when this option is omitted.  Note that, in ip6ta‐
              bles,  IPv6  extension  headers  except  esp  are  not  allowed.   esp and
              ipv6-nonext can be used with Kernel version 2.6.11 or later.   The  number
              zero  is  equivalent to all, which means that you cannot test the protocol
              field for the value 0 directly. To match on a HBH header, even if it  were
              the last, you cannot use -p 0, but always need -m hbh.

       [!] -s, --source address[/mask][,...]
              Source  specification. Address can be either a network name, a hostname, a
              network IP address (with /mask), or a plain IP address. Hostnames will  be
              resolved  once  only,  before the rule is submitted to the kernel.  Please
              note that specifying any name to be resolved with a remote query  such  as
              DNS  is  a  really  bad idea.  The mask can be either an ipv4 network mask
              (for iptables) or a plain number, specifying the number of 1's at the left
              side  of  the network mask.  Thus, an iptables mask of 24 is equivalent to
              255.255.255.0.  A "!" argument before the  address  specification  inverts
              the  sense  of  the  address.  The flag --src is an alias for this option.
              Multiple addresses can be specified, but  this  will  expand  to  multiple
              rules  (when  adding  with -A), or will cause multiple rules to be deleted
              (with -D).

       [!] -d, --destination address[/mask][,...]
              Destination specification.  See the description of the  -s  (source)  flag
              for  a detailed description of the syntax.  The flag --dst is an alias for
              this option.

       -m, --match match
              Specifies a match to use, that is, an extension module that  tests  for  a
              specific  property. The set of matches make up the condition under which a
              target is invoked. Matches are evaluated first to last as specified on the
              command  line  and  work  in  short-circuit fashion, i.e. if one extension
              yields false, evaluation will stop.

       -j, --jump target
              This specifies the target of the rule; i.e., what  to  do  if  the  packet
              matches  it.   The  target can be a user-defined chain (other than the one
              this rule is in), one of the special builtin targets which decide the fate
              of  the  packet  immediately,  or an extension (see EXTENSIONS below).  If
              this option is omitted in a rule (and -g is not used), then  matching  the
              rule  will  have  no  effect on the packet's fate, but the counters on the
              rule will be incremented.

       -g, --goto chain
              This specifies that the processing should continue  in  a  user  specified
              chain.  Unlike  the  --jump  option return will not continue processing in
              this chain but instead in the chain that called us via --jump.

       [!] -i, --in-interface name
              Name of an interface via which a packet was received (only for packets en‐
              tering  the  INPUT, FORWARD and PREROUTING chains).  When the "!" argument
              is used before the interface name, the sense is inverted.  If  the  inter‐
              face  name  ends  in a "+", then any interface which begins with this name
              will match.  If this option is omitted, any interface name will match.

       [!] -o, --out-interface name
              Name of an interface via which a packet is going to be sent  (for  packets
              entering  the FORWARD, OUTPUT and POSTROUTING chains).  When the "!" argu‐
              ment is used before the interface name, the sense is inverted.  If the in‐
              terface name ends in a "+", then any interface which begins with this name
              will match.  If this option is omitted, any interface name will match.

       [!] -f, --fragment
              This means that the rule only refers to second and further IPv4  fragments
              of fragmented packets.  Since there is no way to tell the source or desti‐
              nation ports of such a packet (or ICMP type), such a packet will not match
              any  rules  which  specify  them.  When the "!" argument precedes the "-f"
              flag, the rule will only match head fragments,  or  unfragmented  packets.
              This option is IPv4 specific, it is not available in ip6tables.

       -c, --set-counters packets bytes
              This  enables the administrator to initialize the packet and byte counters
              of a rule (during INSERT, APPEND, REPLACE operations).

   OTHER OPTIONS
       The following additional options can be specified:

       -v, --verbose
              Verbose output.  This option makes the list  command  show  the  interface
              name,  the  rule options (if any), and the TOS masks.  The packet and byte
              counters are also listed, with the  suffix  'K',  'M'  or  'G'  for  1000,
              1,000,000  and 1,000,000,000 multipliers respectively (but see the -x flag
              to change this).  For appending, insertion, deletion and replacement, this
              causes  detailed information on the rule or rules to be printed. -v may be
              specified multiple times to possibly emit more detailed debug  statements:
              Specified  twice,  iptables-legacy will dump table info and entries in li‐
              biptc, iptables-nft dumps rules in netlink (VM code) presentation.  Speci‐
              fied three times, iptables-nft will also dump any netlink messages sent to
              kernel.

       -V, --version
              Show program version and the kernel API used.

       -w, --wait [seconds]
              Wait for the xtables lock.  To prevent multiple instances of  the  program
              from  running concurrently, an attempt will be made to obtain an exclusive
              lock at launch.  By default, the program will exit if the lock  cannot  be
              obtained.  This option will make the program wait (indefinitely or for op‐
              tional seconds) until the exclusive lock can be obtained.

       -n, --numeric
              Numeric output.  IP addresses and port numbers will be printed in  numeric
              format.   By  default, the program will try to display them as host names,
              network names, or services (whenever applicable).

       -x, --exact
              Expand numbers.  Display the exact value of the packet and byte  counters,
              instead  of only the rounded number in K's (multiples of 1000) M's (multi‐
              ples of 1000K) or G's (multiples of 1000M).  This option is only  relevant
              for the -L command.

       --line-numbers
              When listing rules, add line numbers to the beginning of each rule, corre‐
              sponding to that rule's position in the chain.

       --modprobe=command
              When adding or inserting rules into a chain, use command to load any  nec‐
              essary modules (targets, match extensions, etc).

LOCK FILE
       iptables uses the /run/xtables.lock file to take an exclusive lock at launch.

       The  XTABLES_LOCKFILE  environment  variable  can be used to override the default
       setting.

MATCH AND TARGET EXTENSIONS
       iptables can use extended packet matching and target modules.  A list of these is
       available in the iptables-extensions(8) manpage.

DIAGNOSTICS
       Various  error  messages  are  printed to standard error.  The exit code is 0 for
       correct functioning.  Errors which appear to be caused by invalid or abused  com‐
       mand line parameters cause an exit code of 2, and other errors cause an exit code
       of 1.

BUGS
       Bugs?   What's  this?  ;-)  Well,  you   might   want   to   have   a   look   at
       http://bugzilla.netfilter.org/  iptables will exit immediately with an error code
       of 111 if it finds that it was called as a setuid-to-root program.  iptables can‐
       not  be  used  safely  in  this  manner  because  it  trusts the shared libraries
       (matches, targets) loaded at run time, the search path can be set using  environ‐
       ment variables.

COMPATIBILITY WITH IPCHAINS
       This  iptables is very similar to ipchains by Rusty Russell.  The main difference
       is that the chains INPUT and OUTPUT are only traversed for  packets  coming  into
       the  local  host  and  originating from the local host respectively.  Hence every
       packet only passes through one of the  three  chains  (except  loopback  traffic,
       which involves both INPUT and OUTPUT chains); previously a forwarded packet would
       pass through all three.

       The other main difference is that -i refers to the input interface; -o refers  to
       the  output  interface,  and  both are available for packets entering the FORWARD
       chain.

       The various forms of NAT have been separated out; iptables is a pure packet  fil‐
       ter when using the default `filter' table, with optional extension modules.  This
       should simplify much of the previous confusion over the combination  of  IP  mas‐
       querading  and  packet  filtering  seen previously.  So the following options are
       handled differently:
        -j MASQ
        -M -S
        -M -L
       There are several other changes in iptables.

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/.

AUTHORS
       Rusty Russell originally wrote iptables, in early consultation with Michael Neul‐
       ing.

       Marc Boucher made Rusty abandon ipnatctl by lobbying for a generic packet  selec‐
       tion  framework  in  iptables,  then wrote the mangle table, the owner match, the
       mark stuff, and ran around doing cool stuff everywhere.

       James Morris wrote the TOS target, and tos match.

       Jozsef Kadlecsik wrote the REJECT target.

       Harald Welte wrote the ULOG and NFQUEUE target, the new libiptc, as well  as  the
       TTL, DSCP, ECN matches and targets.

       The  Netfilter  Core  Team is: Jozsef Kadlecsik, Pablo Neira Ayuso, Eric Leblond,
       Florian Westphal and  Arturo Borrero Gonzalez.  Emeritus Core Team  members  are:
       Marc  Boucher, Martin Josefsson, Yasuyuki Kozakai, James Morris, Harald Welte and
       Rusty Russell.

       Man page originally written by Herve Eychenne <rv@wallfire.org>.

VERSION
       This manual page applies to iptables/ip6tables 1.8.9.

iptables 1.8.9                                                               IPTABLES(8)

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.

    $ sudo 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 */
    ...
    
    $ sudo 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
     */
    ...
    
    $ sudo 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:

    $ sudo 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.

    $ sudo 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.

    $ sudo 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).

    $ sudo 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
    $ sudo iptables -F
    # Flush your iptables the specfic chain rules at filter table
    $ sudo iptables -F INPUT    # Flush the INPUT chain only
    $ sudo iptables -F OUTPUT   # Flush the OUTPUT chain only
    $ sudo iptables -F FORWARD  # Flush the FORWARD chain only
    # Flush your iptables all chains rules at `nat` table
    $ sudo 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.

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

$ sudo iptables -A INPUT -p tcp --dport ssh -j ACCEPT

$ sudo iptables -C INPUT -p tcp --dport ssh -j ACCEPT

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

$ sudo  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)

 $ sudo 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

$ sudo iptables -A INPUT -p tcp --dport http -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport https -j ACCEPT

Or

$ sudo iptables -A INPUT -p tcp -m multiport --dports http,https -j ACCEPT

Checking our rules, we have

 $ sudo 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.

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

$ sudo 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
# save current iptables into iptables.rules and print to standard output
sudo iptables-save | tee iptables.rules
$ 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
# restore iptables from iptables.rules
sudo iptables-restore 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