Skip to content

Instantly share code, notes, and snippets.

@oskaralmlov
Last active September 23, 2021 17:13
Show Gist options
  • Save oskaralmlov/af9931d303617afc0031dbe7471e6881 to your computer and use it in GitHub Desktop.
Save oskaralmlov/af9931d303617afc0031dbe7471e6881 to your computer and use it in GitHub Desktop.

IPTABLES

Overview

iptables contains 5 tables which in turn contain a number of built-in chains and may also contain user defined chains. Each chain is a list of rules that can match a set of packets. Each rule specifies what to do with a packet that matches. The action to take on matched packets are known as a 'target' and are specified via the --jump flag. The target can either be a chain, a target from an iptables-extension or one of the special built-in targets:

  • ACCEPT: Let the packet through
  • DROP: Throw away this packet and stop processing subsequent rules
  • RETURN: Stop processing the packet in this chain and jump back to the previous chain

Packet flow

The way that a packet 'flows' through iptables can be complicated. See the below flowchart if you want to understand the details. Processing Flowchart

Tables and their default built-in chains

filter: The default table

  • INPUT: Packets destined for local sockets
  • OUTPUT: Packets generated locally on the host
  • FORWARD: Packets being routed through the localhost

nat: Consulted when a packet that creates a new connection is encountered

  • INPUT: Altering packets destined for local sockets
  • OUTPUT: Altering packets generated locally before routing
  • PREROUTING: Altering packets as soon as they arrive at the host
  • POSTROUTING: Altering packets as they are about to leave the host

mangle: Used for special packet alterations (resetting TTL for example)

  • OUTPUT: Altering packets generated locally before routing
  • PREROUTING: Altering packets as soon as they arrive at the host

raw: Mainly used for configuring excemptions from connection tracking

  • OUTPUT Packets generated by local processes
  • PREROUTING Packets arriving via any network interface

security: Mandatory Access Control (MAC) networking roles. SELinux stuff.

  • INPUT: Packets coming into the localhost
  • OUTPUT: Altering locally generated packets before routing
  • FORWARD: Packets being routed through the localhost

Which table should I use?

I want to do..

  • source/destination NAT: NAT
  • basic firewall filtering (allow/drop): INPUT
  • excempt traffic from connection tracking: RAW
  • specific alterations to packet headers: MANGLE
  • MAC networking rules (not to be confused with L2 MAC addresses): SECURITY

Which chain should I use?

I want to..

  • perform source translation (SNAT): POSTROUTING [NAT]
  • perform destination translation (DNAT): PREROUTING [NAT]
  • allow or drop traffic destined TO the localhost: INPUT [FILTER]
  • allow or drop traffic originating FROM the localhost: OUTPUT [FILTER]
  • allow or drop traffic being routed THROUGH the localhost: FORWARD [FILTER]

FAQ

Q: Do rules in the OUTPUT chain in the filter table affect packets being SNAT by the localhost?
A: No. The OUTPUT chain in the filter table is only consulted when packets are generated locally by the localhost.

Q: Isn't it more performant to drop traffic in the PREROUTING chain in the raw table?
A: Yes, it's about 280% more performant (according to this article). But it makes organizing the firewall policy much harder by spreading rules between the tables. Look into configuring connection tracking excemptions before configuring drop rules here.

Q: When should I put drop rules in the PREROUTING chain in the raw table?
A: When performance is absolutely key, such as dropping traffic to prevent DDOS.

Q: Can I set the default policy for a user-defined chain?
A: No, default policy can only be set on built-in chains.

Q: What happens if a packet reaches the end of a chain without having matched any rules?
A: The packet will continue to traverse down the parent chain.

Examples

Set the default policy for a built-in chain

iptables -P INPUT DROP

Allowing any source connecting to the localhost via ssh:

iptables --append INPUT --protocol tcp --dport 22 --jump ACCEPT

Drop any source connecting to the localhost via ssh:

iptables --append INPUT --protocol tcp --dport 22 --jump DROP

Allowing clients in to 10.0.0.0/24 network to be routed out eth0

iptables --append FORWARD --source 10.0.0.0/24 --out-interface eth0 --jump ACCEPT

Source NAT client from the 10.0.0.0/24 network routed out eth0

iptables --table nat --append POSTROUTING --source 10.0.0.0/24 --out-interface eth0 --jump MASQUERADE

Source NAT client from the 10.0.0.0/24 network behind 1.2.3.4

iptables --table nat --append POSTROUTING --source 10.0.0.0/24 --to-source 1.2.3.4 --jump SNAT

Allow established return traffic to SNATed clients

iptables --append INPUT --match conntrack --cstate RELATED,ESTABLISED --jump ACCEPT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment