Skip to content
Search

Iptables

lastmod 2026-02-07created 2015-01-15122 edits

iptables is a user-space application program that allows a system administrator to configure the tables provided by the Linux kernel firewall (implemented as different Netfilter modules) and the chains and rules it stores. Different kernel modules and programs are currently used for different protocols; iptables applies to IPv4, ip6tables to IPv6, arptables to ARP, and ebtables to Ethernet frames.

Categories

  • netfilter
  • iptables/ip6tables
  • iptables-apply - a safer way to update iptables remotely
  • iptables-nft-save
  • iptables-save - dump iptables rules - Used to save rules; usually located at /sbin/iptables-save.
  • iptables-nft - iptables using nftables kernel api
  • iptables-restore - Restore IP Tables
  • iptables-translate
  • iptables-nft-restore
  • iptables-restore-translate
  • iptables-xml

About

The Linux kernel provides the IP packet filtering framework Netfilter and the command-line frontends iptables/ip6tables for using it.

IP packet filtering means looking at the header of an IP packet and handling it: pass, discard, forward, and so on. With iptables you can build network environments like the following.

  • Fortify a single host with file filtering
  • Connect the internet and a LAN while hiding the LAN hosts from the internet
  • Give LAN hosts connectivity to the internet and translate the source address
  • Forward packets to a specific host on the LAN
  • Load balancing and load distribution, though the feature is limited

Terms

Masquerade
A feature that lets PCs with internal private IPs connect to the external internet
NAT(Network Address Translation) : network address translation service
SNAT(Source NAT) : Translates an internal private IP to a public IP when going out -> similar to masquerade
DNAT(Destination NAT) : Translates an address requested from outside to the firewall (external IP) into an internal private IP

What is packet filtering

Packet filtering means looking at the header of a passing packet and deciding the fate of the whole packet.

(In iptables, many features under development go beyond the header and inspect the contents of the data. The most representative is the string match feature.)

iptables vs netfilter

It is not iptables that filters packets; the netfilter feature built into the kernel does the actual filtering,

and iptables merely sets up rules in netfilter. In other words, iptables is a rule-set building tool.

Newer versions reportedly integrate several features and use nftables, but in practice iptables still seems to be widely used.

Packet Flow

Packet_flow_in_Netfilter_and_General_Networking_-_Simple.png

Simple version

Packet_flow_in_Netfilter_and_General_Networking.png

Detailed version

  • INPUT: packets arriving from outside → at a host process
  • OUTPUT: packets created by a host process → sent outside
  • FORWARD: packets that only pass through the host (they don't go through a host process)

The key is who created the packet.

Packet flow example: the actual flow when accessing a Docker container through an SSH tunnel

[로컬 PC] → SSH → [원격 호스트 enp3s0:22]
                         │
                    ① INPUT 체인 (enp3s0 → SSH 데몬)
                         │
                    SSH 데몬 (호스트 프로세스)
                         │
                    ② OUTPUT 체인 (SSH → lo)
                    ③ INPUT 체인 (lo → docker-proxy)
                         │
                    docker-proxy (호스트 프로세스) ← 여기서 끊김!
                         │
                    ④ OUTPUT 체인 (docker-proxy → br-b5897ccd4ced)  ← 이게 문제
                         │
                    [컨테이너 172.18.0.2:18789]

Key point

docker-proxy is a userspace process on the host. Packets don't just pass through it.

lo에서 127.0.0.1:18789 수신
       │
       ▼
docker-proxy가 패킷을 받아서 ← 기존 연결 종료
       │
docker-proxy가 새 패킷을 생성 → 172.18.0.2:18789로 전송  ← 새로운 연결
       │
       ▼
OUTPUT 체인을 통과해야 함 (호스트 프로세스가 생성한 패킷이므로)

Because docker-proxy is a proxy, it:

  1. reads the packet received on lo (handled by INPUT ✅)
  2. creates a new packet and sends it to the container (handled by OUTPUT ❌ DROP!)

② and ③ are loopback, so they are already allowed, but ④ is a new connection going out to br-b5897ccd4ced, so it doesn't match the existing OUTPUT rules and gets DROPped.

Why it isn't lo → docker

Intuitively, it feels like this:

패킷 → lo → INPUT → docker → FORWARD → br-b5897ccd4ced ❌

But that is the FORWARD approach, where the kernel routes the packet directly.

Docker's port mapping doesn't work that way, though. A separate process called docker-proxy cuts the connection in the middle and creates a new one:

[FORWARD 방식 - 이렇게 동작 안 함]
패킷 → lo → 커널 라우팅 → br-xxx → 컨테이너

[실제 동작 - docker-proxy 방식]
패킷 → lo → INPUT → docker-proxy(프로세스) → OUTPUT → br-xxx → 컨테이너

That's why OUTPUT -d 172.16.0.0/12 -j ACCEPT is needed.

Install

Now install the iptables-persistent package. It lets you save rule sets and apply them automatically at boot.

apt-get install -y iptables iptables-persistent

netfilter-persistentis a tool that, includingiptables-persistent, manages the rules of thenetfilterframework. Together withiptables-persistent, it can also manageip6tablesrules. <- needs verification.

Restart the service:

systemctl daemon-reload
systemctl enable iptables.service
systemctl start iptables.service

When asked during installation whether to save the current rules, select <Yes>.

To run the persistent iptables firewall service, you run the netfilter-persistent command. Next, edit the generated rule files.

Before starting, a quick note on IPv4 and IPv6. The iptables command handles only IPv4 traffic. For IPv6 traffic, a separate companion tool called ip6tables is used. The rules are stored in separate tables and chains.

For the netfilter-persistent command,

  • IPv4 rules are written to and read from /etc/iptables/rules.v4, and
  • IPv6 rules are stored in /etc/iptables/rules.v6.

If your services don't use IPv6, it is safer to block access to it entirely, as this guide describes.

Related scripts are also in /usr/share/netfilter-persistent.

  • /usr/share/netfilter-persistent/plugins.d/15-ip4tables start
  • /usr/share/netfilter-persistent/plugins.d/25-ip6tables start

How to add comments

Comments use #, but the comment must start at the first character of the line. You can't put one at the end of a line.

To put one at the end of a line, you have to use the comment module.

... -m comment --comment "주석 입력할 내용"

Defaults

sudo iptables -L

There are no rules and everything is ACCEPT:

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

Slightly relaxed security defaults

FORWARD and OUTPUT are allowed by default. INPUT is restricted.

*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

-I INPUT 1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p udp --sport 123 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22   -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 6443 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited

COMMIT

Rule

규칙 = 매칭 + 타깃

Writing a rule means defining what to extract from the packet header (matching) and how to handle that packet (target). The rule format is as follows.

$ iptables -A <체인> <매칭 옵션> -j <타깃>

Simple Example

$ iptables -A INPUT -s 192.168.2.0/24 -d 192.168.2.1 -p TCP --dport 22 -j ACCEPT
  • -A appends a rule to the INPUT chain.
  • -s specifies the source IP address.
  • -d the destination IP address
  • -p specifies the TCP protocol
  • --dport the destination port
  • -j sets the target to ACCEPT, letting matched packets through.

This specifies access from hosts in the 192.168.2.0/24 network (the source IP address) to 22/TCP on the host with the destination IP address 192.168.2.1.

Table

테이블 = 체인 + 체인

If no table is specified with -t, rules are created in the filter table. The tables are as follows.

Table

Purpose

Available standard chains

filter

Filters target packets

INPUT, OUTPUT, FORWARD

nat

Translates the source or destination address

OUTPUT, PREROUTING, POSTROUTING

mangle

Modifies packet headers, such as TTL

INPUT, OUTPUT, PREROUTING, POSTROUTING

raw

Performs translation without connection tracking

OUTPUT, PREROUTING

  • If you don't need to modify packet headers, the filter and nat tables alone are enough.
  • The filter table uses the INPUT, OUTPUT, and FORWARD chains to filter with ACCEPT/ DROP and so on.
  • The nat table performs NAT (Network Address Translation) to translate the source or destination address.
  • The mangle table adjusts the TTL (Time To Live, a packet lifetime value that decreases with each router it passes) value to keep information such as how many routers a packet passed through on the LAN from leaking to external networks, or uses the TOS target to adjust where packets are routed.

Chain

The purpose of each chain is as follows.

Chain INPUT
Default policy for traffic coming into the server
Every packet destined for the Linux Server passes through the INPUT chain.
Chain FORWARD
Default policy for forwarding on the server
The FORWARD chain is the chain that packets not destined for the current Linux Server pass through.
The FORWARD chain is used for the NAT feature.
Chain OUTPUT
Default policy for traffic going out of the server
Every packet created on the Linux Server and sent outside passes through the OUTPUT chain.
PREROUTING
Translates packets before input.
POSTROUTING
Translates packets after input.

Users can create their own chains.

  • Create a user-defined chain with <coed>-N</code>, then specify it with -A and set the packet matching and target.
  • <coed>-P</coed>, which sets a standard target, can only be used with the built-in chains (INPUT, OUTPUT, FORWARD, PROROUTING, POSTROUTING).
  • When you create your own chain, you must specify DROP or REJECT at the very end.

An example of creating a chain:

$ iptables -N tcp-allow   # tcp-allow 체인 생성

$ iptables -A tcp-allow -p TCP --syn -j ACCEPT
$ iptables -A tcp-allow -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT
$ iptables -A tcp-allow -j DROP   # tcp-allow 체인 종료

$ iptables -A INPUT -p ICMP -j ACCEPT
$ iptables -A INPUT -p TCP -j tcp-allow   # tcp-allow 체인 호출

Target

The parameters you can use as a target are as follows.

  • ACCEPT - allow
  • DROP - discard
  • REJECT - reject (similar to DROP, but sends an ICMP error response. If you want to prevent DDoS, DROP is recommended over REJECT)
  • MASQUERADE - (masquerade) automatically translates the source IP and port number (a feature that lets PCs with internal private IPs connect to the external internet)
  • SNAT - source IP address translation
  • DNAT - destination IP address translation
  • LOG - log output
  • QUEUE - passes the packet to user space
  • RETURN - end of chain

MASQUERADE

MASQUERADE to an internal website.

iptables -t nat -A PREROUTING -m tcp --dport 80 -j DNAT --to 192.168.200.100:80

Automatically translates the source IP and port number (a feature that lets PCs with internal private IPs connect to the external internet)

PREROUTING is the chain used to masquerade incoming packets. DNAT does the opposite of SNAT. Think of it this way: SNAT changes the source, while DNAT is the target that changes the destination.

Options

  • -t [테이블]: Specifies the table to use. The default is filter.
  • -A [체인]:Appends a rule to the specified chain.
  • -D: Deletes a rule from the specified chain
  • -P: Changes the policy of the specified chain
  • -L [체인]: Lists the rules in an iptables table
  • -N [체인]: Creates a user-defined chain with the given name
  • -X: Deletes the specified user-defined chain
  • -I [규칙]: Inserts a rule at the given number
  • -F [체인]: Deletes all rules in the specified chain - WARNING !! If you are connected remotely, you may lose connectivity.
  • -t: Specifies the iptables table
  • -v: Shows the table contents in detail
  • -n: Shows the table contents as numeric values
  • -line-number: Shows rule numbers
  • -m [모듈]: Specifies a match module. (addtype, conntrack, connlimit, iprange, mac, multiport, state)
    • Module-specific options can follow this option.
  • -p [프로토콜]: Specifies one of tcp/udp/icmp/all. The default is all.
  • -d [도착지 주소]: Specifies the destination address
  • -s [출발지 주소]: Specifies the source address
  • --dport [포트]: Specifies the destination port. Used with -p tcp or -p udp.
  • --sport [포트]: Specifies the source port. Used with -p tcp or -p udp.
  • -i [인터페이스]: Specifies the network interface packets come in on.
  • -o [인터페이스]: Specifies the network interface packets go out on.
  • -j [타깃]: See #Target.

Source and destination

The following options:

  • -d [도착지 주소]: Specifies the destination address
  • -s [출발지 주소]: Specifies the source address
  • --dport [포트]: Specifies the destination port. Used with -p tcp or -p udp.
  • --sport [포트]: Specifies the source port. Used with -p tcp or -p udp.

Their meaning changes depending on whether the chain is INPUT or OUTPUT.

For example:

iptables -I INPUT -p tcp -s 0.0.0.0/0 -d 192.168.0.18 --dport 80 -j ACCEPT

In INPUT, src is the client and dest is the server. That is, this is used when the server 192.168.0.18 provides an HTTP service (80) and you want to allow traffic from every IP address coming into this server's port 80. For example, it suits a web server that wants to accept connections from all external clients.

iptables -A OUTPUT -s 192.168.10.10 -d 222.222.222.222 -p tcp --dport 80 -j ACCEPT

In OUTPUT, src is the server and dest is the client. That is, this setting allows traffic going out from the NIC with IP 192.168.10.10 to port 80 of the external server with IP 222.222.222.222. It is useful for allowing HTTP traffic from a specific client program to a specific external server.

Configuration file

  • Check /etc/sysconfig/iptables.

Example

iptables --list or iptables -L
Prints the list of applied iptables rules.
sudo iptables -L -n -v
Prints the list of applied iptables rules, showing numbers like 0.0.0.0/0 instead of words like anywhere, and including details.
iptables -nL
Prints the list of applied iptables rules. (The -n option prints IP addresses and ports as numbers)
service iptables save
Saves after adding rules (saved to /etc/sysconfig/iptables)
iptables -F
Flushes the current iptables rules - WARNING !!!!! You know, right? It could be a one-way trip to Valhalla.
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
-A INPUT - Means append (add) a rule to the INPUT chain. The INPUT chain is used to handle incoming traffic.
-j REJECT - Means reject packets that match this rule. That is, the packet is blocked, but the sender is told that it was rejected.
--reject-with icmp-host-prohibited - Specifies the type of ICMP message sent to the sender when a packet is rejected. Here the "icmp-host-prohibited" message indicates that the host does not allow access.
In short, this command adds a rule to iptables that rejects all incoming network traffic and sends the sender of each packet an ICMP "host prohibited" message. It can be used to strengthen security, for example to block unauthorized traffic while giving a clear response.
Typically, when the INPUT default is ACCEPT, it is added as the last line to reject every packet that wasn't filtered.
sudo service iptables restart
sudo service ip6tables restart
sudo systemctl restart iptables
sudo systemctl restart ip6tables
Restarts the iptables services for IPv4 and IPv6.
iptables -P INPUT ACCEPT
Sets the INPUT default policy to ACCEPT (inbound)
iptables -P OUTPUT ACCEPT
Sets the OUTPUT default policy to ACCEPT (egress; outbound)
iptables -P FORWARD ACCEPT
Sets the FORWARD default policy to ACCEPT
iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP
Ignores (DROP) every ping (ICMP) request (INPUT; inbound) packet coming from local (127.0.0.1).
To remove the rule above, write -D instead of -A.
iptables -D INPUT [필터링 번호]
Removes a rule by its filtering number. (The filtering number can be checked with service iptables stat)
iptables -A INPUT -p tcp --dport 80 -m recent --update --seconds 1 --hitcount 10 --name HTTP -j DROP
If the same IP sends 10 or more SYNs to port 80 within 1 second, drop them. (That is, treat it as an attack on the web service rather than a normal request, and discard the request packets without responding.)
iptables -A INPUT -s 192.168.0.111 -j DROP
Block all ports for connections from source IP 192.168.0.111.
iptables -A INPUT -p icmp -s 127.0.0.1 -j DROP
Adds a policy to the INPUT chain that rejects icmp protocol packets whose source address is 127.0.0.1 (-s 127.0.0.1)
iptables -A INPUT -p tcp --dport 23 -j DROP
Adds a rule to the INPUT chain that rejects tcp protocol packets with destination port 23
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Adds a rule to the INPUT chain that accepts tcp protocol packets with destination port number 80
iptables -A INPUT -p tcp --dport :1023 -j DROP
Adds a rule to the INPUT chain that rejects tcp protocol packets on every destination port number below 1023
iptables -I INPUT -p tcp --dport 21 -j ACCEPT
Open the ftp port (21)
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
Open the http port (80).
iptables -I INPUT -p tcp --dport 443 -j ACCEPT
Open the https port (443).
iptables -R INPUT 2 -p tcp --dport 8880 -j ACCEPT
Replace web server port 80 -> 8880 (when changing the web service port, also change it in /etc/services)
cat access.log | awk '{print $1}' | sort | uniq | xargs iptables -A INPUT -s {} -j DROP
Block all ports for every ip in the access.log file (used to defend against DOS attacks)

16 tips & tricks for sysadmins

Back up your configuration before you start working.
Back up the configuration with the following command. (The backup date is added to the backup.)
/sbin/iptables-save > /root/iptables-works-$(date +%F)
Each time you make a backup copy of the policy, create a link to a file with "latest" in its name.
ln –s /root/iptables-works-(date +%F) /root/iptables-works-latest
Put specific rules (Specific Rules) at the top of the policy and generic rules (Generic rules) at the bottom.
Policies are applied from top to bottom, and once a rule has applied it is not overwritten (Overwrite).
Don't use generic rules like iptables -A INPUT -p tcp --dport 22 -j DROP at the top of the policy rules.
The more criteria you specify in a rule, the less likely you are to lock yourself out. Instead of the very generic rule above, use something like this.
iptables -A INPUT -p tcp --dport 22 –s 10.0.0.0/8 –d 192.168.100.101 -j DROP
Allowlist your IP address at the top of the policy rules.
This is a very effective way to avoid locking yourself out. Others, not so much.
iptables -I INPUT -s<your IP>-j ACCEPT

Set up a workstation firewall policy

Scenario: You want to set up a workstation with a restrictive firewall policy.

Set the default policy to DROP.
# Set a default policy of DROP
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
  • Note that *filter on the first line means apply to the filter table.
  • [0:0] is a counter, meaning no packets have arrived, left, or been forwarded so far. 1
ACCEPT connections in the established (ESTABLISHED) or related (RELATED) state.
-I INPUT 1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-I OUTPUT 1 -m state --state RELATED,ESTABLISHED -j ACCEPT
Note that -I INPUT 1 means insert as the first rule. 2
Allow the minimum services users need to get their work done.
The iptables rules must allow the workstation to get its IP address, netmask, and other important information via DHCP (-p udp --dport 67:68 --sport 67:68).
Rules for remote management:

Full contents:

# Set a default policy of DROP
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]

# Accept any related or established connections
-I INPUT  1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-I OUTPUT 1 -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow all traffic on the loopback interface
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT

# Allow outbound DHCP request
-A OUTPUT –o eth0 -p udp --dport 67:68 --sport 67:68 -j ACCEPT

# Allow inbound SSH
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW  -j ACCEPT

# Allow outbound email
-A OUTPUT -o eth0 -p tcp -m tcp --dport 25 -m state --state NEW  -j ACCEPT

# Outbound DNS lookups
-A OUTPUT -o eth0 -p udp -m udp --dport 53 -j ACCEPT

# Outbound PING requests
-A OUTPUT –o eth0 -p icmp -j ACCEPT

# Outbound Network Time Protocol (NTP) requests
-A OUTPUT –o eth0 -p udp --dport 123 --sport 123 -j ACCEPT

# Outbound HTTP
-A OUTPUT -o eth0 -p tcp -m tcp --dport 80 -m state --state NEW -j ACCEPT
-A OUTPUT -o eth0 -p tcp -m tcp --dport 443 -m state --state NEW -j ACCEPT

COMMIT

Check the loopback (lo) and Ethernet (eth0) interfaces in your own environment.

Limit an IP address range

Scenario: The company's CEO thinks employees are spending too much time on Facebook and not getting any work done. The CEO tells the CIO to do something about employees wasting time on Facebook. The CIO tells the CISO to do something about employees wasting time on Facebook. Eventually, you are told that the employees are wasting too much time on Facebook and that you have to do something about it. You decide to block all access to Facebook. First, find Facebook's IP address with the host and whois commands.

$ host -t a www.facebook.com
www.facebook.com is an alias for star.c10r.facebook.com.
star.c10r.facebook.com has address 31.13.65.17

$ whois 31.13.65.17 | grep inetnum
inetnum:        31.13.64.0 - 31.13.127.255

Then convert that range to CIDR notation with the CIDR to IPv4 conversion page. You get 31.13.64.0/18 . To prevent outgoing access to www.facebook.com, enter the following.

iptables -A OUTPUT -p tcp -i eth0 –o eth1 –d 31.13.64.0/18 -j DROP

Regulate by time

Scenario: The company employees' backlash over being denied access to Facebook has made the CEO relent a little (he and his administrative assistant remind him that she keeps HIS Facebook page up to date). The CEO decides to allow access to Facebook.com only during lunchtime (12 PM to 1 PM). Assuming the default policy is DROP, use iptables' time features to open access.

iptables –A OUTPUT -p tcp -m multiport --dport http,https -i eth0 -o eth1 -m time --timestart 12:00 --timestart 12:00 –timestop 13:00 –d 
31.13.64.0/18  -j ACCEPT

This command sets a policy that allows (-j ACCEPT) http and https (-m multiport --dport http,https) to Facebook.com (–d 31.13.64.0/18) between noon (--timestart 12:00) and 1 PM (--timestop 13:00).

Regulate by time - take two

Scenario: During planned downtime for system maintenance, you need to deny all TCP and UDP traffic between 2 AM and 3 AM so that maintenance work isn't disrupted by incoming traffic.

Two iptables rules are needed.

iptables -A INPUT -p tcp -m time --timestart 02:00 --timestop 03:00 -j DROP 
iptables -A INPUT -p udp -m time --timestart 02:00 --timestop 03:00 -j DROP

TCP and UDP traffic (-p tcpand -p udp) are denied (-j DROP) between the hours of 2AM (--timestart 02:00) and 3AM (--timestop 03:00) on input (-A INPUT).

Limit connections with iptables

Scenario: Your internet-connected web server is under attack from bad actors around the world attempting a DoS (denial of service). To mitigate these attacks, limit the number of connections a single IP address can have to the web server.

iptables –A INPUT –p tcp –syn -m multiport -–dport http,https –m connlimit -–connlimit-above 20 –j REJECT -–reject-with-tcp-reset

Let's look at what this rule does. If a host makes more than 20 (-–connlimit-above 20) new connections (–p tcp –syn) to the web server (-–dport http,https) within one minute, the new connection is rejected (–j REJECT) and the connecting host is told the connection is refused (--reject-with-tcp-reset).

When the default policy (Policy) is ACCEPT

This is what the default rules saved on Oracle Cloud looked like.

Reject at the end of the chain.

*filter
:INPUT ACCEPT [0:0]
...
-A INPUT -j REJECT --reject-with icmp-host-prohibited

For reference, -A INPUT -j REJECT --reject-with icmp-host-prohibited means "reject all traffic with an ICMP host-prohibited message."

Oracle Cloud Default Settings

This is what the default rules in the /etc/iptables/rules.v4 file saved on Oracle Cloud looked like.

# CLOUD_IMG: This file was created/modified by the Cloud Image build process
# iptables configuration for Oracle Cloud Infrastructure

# See the Oracle-Provided Images section in the Oracle Cloud Infrastructure
# documentation for security impact of modifying or removing these rule

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [463:49013]
:InstanceServices - [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p udp --sport 123 -j ACCEPT
# ----------------------------------------------------------------------------------------------------------------------------------
# 내가 추가한 사용자 정의 체인
-A INPUT -p tcp -m state --state NEW -m tcp --dport   22 -j ACCEPT -m comment --comment "SSH"
-A INPUT -p udp -m state --state NEW -m udp --dport   53 -j ACCEPT -m comment --comment "DNS (Nebula Lighthouse)"
-A INPUT -p tcp -m state --state NEW -m udp --dport  443 -j ACCEPT -m comment --comment "HTTPS (Caddy)"
-A INPUT -p udp -m state --state NEW -m udp --dport 4242 -j ACCEPT -m comment --comment "Nebula Lighthouse"
# ----------------------------------------------------------------------------------------------------------------------------------
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
-A OUTPUT -d 169.254.0.0/16 -j InstanceServices
-A InstanceServices -d 169.254.0.2/32 -p tcp -m owner --uid-owner 0 -m tcp --dport 3260 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.2.0/24 -p tcp -m owner --uid-owner 0 -m tcp --dport 3260 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.4.0/24 -p tcp -m owner --uid-owner 0 -m tcp --dport 3260 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.5.0/24 -p tcp -m owner --uid-owner 0 -m tcp --dport 3260 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.0.2/32 -p tcp -m tcp --dport 80 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.169.254/32 -p udp -m udp --dport 53 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.169.254/32 -p tcp -m tcp --dport 53 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.0.3/32 -p tcp -m owner --uid-owner 0 -m tcp --dport 80 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.0.4/32 -p tcp -m tcp --dport 80 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.169.254/32 -p tcp -m tcp --dport 80 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.169.254/32 -p udp -m udp --dport 67 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.169.254/32 -p udp -m udp --dport 69 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.169.254/32 -p udp --dport 123 -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j ACCEPT
-A InstanceServices -d 169.254.0.0/16 -p tcp -m tcp -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j REJECT --reject-with tcp-reset
-A InstanceServices -d 169.254.0.0/16 -p udp -m udp -m comment --comment "See the Oracle-Provided Images section in the Oracle Cloud Infrastructure documentation for security impact of modifying or removing this rule" -j REJECT --reject-with icmp-port-unreachable
COMMIT

Block all ipv6 connections

If you don't actively use it or aren't sure, just turn it all off.

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*raw
:PREROUTING DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*nat
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT

*security
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*mangle
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT

Monitoring iptables rules

Scenario: iptables works on a "first match wins" basis as packets traverse the rules in a chain, so frequently matched rules should be at the top of the policy and less frequently matched rules at the bottom. How can you tell which rules are traversed the most or the least, so they can be ordered closer to the top or the bottom?

Check how many times each rule has been hit.

Use the following command.

sudo iptables -nvL --line-numbers
  • -n - Print numbers instead of well-known names (e.g. anywhere == 0.0.0.0/0)
  • -v - Print packet and byte counters
  • -L - List all rules in the chain
  • --line-numbers - Show a line number at the start of each rule

The output looks something like this.

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
  991  128K ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
   69  5654 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp spt:123
    5   280 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
   12   720 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 775 packets, 1077K bytes)
 pkts bytes target     prot opt in     out     source               destination
  126  8837 InstanceServices  all  --  *      *       0.0.0.0/0            169.254.0.0/16

Chain InstanceServices (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            169.254.0.2          owner UID match 0 tcp dpt:3260 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            169.254.2.0/24       owner UID match 0 tcp dpt:3260 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            169.254.4.0/24       owner UID match 0 tcp dpt:3260 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            169.254.5.0/24       owner UID match 0 tcp dpt:3260 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            169.254.0.2          tcp dpt:80 
    5   406 ACCEPT     udp  --  *      *       0.0.0.0/0            169.254.169.254      udp dpt:53 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            169.254.169.254      tcp dpt:53 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            169.254.0.3          owner UID match 0 tcp dpt:80 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            169.254.0.4          tcp dpt:80 
  120  8355 ACCEPT     tcp  --  *      *       0.0.0.0/0            169.254.169.254      tcp dpt:80 
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            169.254.169.254      udp dpt:67 
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            169.254.169.254      udp dpt:69 
    1    76 ACCEPT     udp  --  *      *       0.0.0.0/0            169.254.169.254      udp dpt:123 
    0     0 REJECT     tcp  --  *      *       0.0.0.0/0            169.254.0.0/16       tcp
    0     0 REJECT     udp  --  *      *       0.0.0.0/0            169.254.0.0/16       udp

Using the packet and byte counts, you can order the most frequently traversed rules to the top and the least frequently traversed rules to the bottom.

For monitoring, it can be used together with the watch command.

sudo watch -n 0.1 'iptables -nvL --line-numbers'

Use it in combination with the netstat command.

Remove unnecessary rules

Which rules don't match at all? They would be good candidates for removal from the policy. You can check with the following command.

iptables -nvL | grep -v "0     0"

Note: there are five spaces between the 0 and the 0.

Monitor what's going on

You want to monitor what's happening in iptables in real time, like top. Use this command to monitor iptables activity dynamically and show only the rules that are actively being traversed.

$ watch -n 0.1  'sudo iptables -nvL'

Reporting on iptables

Scenario: Your manager thinks this iptables firewall is great, but a daily activity report would be even better. Sometimes writing a report is more important than doing the work.

Use the packet filter/firewall/IDS log analyzer FWLogwatch to generate reports based on the iptables firewall logs. FWLogwatch supports many log formats and offers many analysis options. It generates daily and monthly summaries of log files, which frees up considerable time for security administrators, gives better control over network security, and reduces unnoticed attacks.

Here is sample output from FWLogwatch.

Fwlogwatch_-_sample.png

State Module

A module that performs connection tracking.

  • Right after the -m state option, you can add --state [인수].
  • The argument specifies the state of the packets to detect.
  • To specify multiple states, separate them with commas (,) as in the example above.

The packet states are as follows.

  • NEW: A packet requesting a new connection, e.g., an HTTP request
  • ESTABLISHED: A packet that enters the connected state after a connection request (SYN) was followed by a response (SYN/ACK), or after a response (SYN/ACK) was followed by an (ACK) (a packet that is part of an existing connection)
  • RELATED: A packet related to a packet in the connected state. The FTP data port (20/tcp) uses this.
    • A packet that belongs to an existing connection but requests a new connection. For example, in passive FTP with connection port 20, the transfer port can be any unused port above 1024.
  • INVALID: A packet other than NEW, ESTABLISHED, or RELATED. Most of these packets can be DROPped.

State Module Example

$ iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT

This rule ACCEPTs ESTABLISHED (connected state) or RELATED (packets related to a packet in the connected state) packets sent from eth0 to eth1.

Chain

체인 = 규칙 + 규칙 + ...

A chain is a set of rules. The order in which rules are defined also matters. Because packets are matched in rule order, important packets sometimes get missed.

List of chains:

  • INPUT - packets coming into the host
  • OUTPUT - packets created on the local host
  • FORWARD - packets passing through the host
  • PREROUTING - translates incoming packets
  • POSTROUTING - translates outgoing packets

Chain Example

$ iptables -P INPUT DROP
$ iptables -A INPUT -p TCP -d 192.168.2.1 -dport 22 -s 192.168.2.0/24 -j ACCEPT
$ iptables -A INPUT -p TCP -d 192.168.2.1 -dport 80 -s 192.168.2.0/24 -j ACCEPT
$ iptables -A INPUT -p UDP -d 192.168.2.1 -dport 53 -s 192.168.2.0/24 -j ACCEPT
  • A set of rules in the INPUT chain that accepts 22/TCP, 80/TCP, and 53/UDP and DROPs the rest.
  • The standard way to use a chain is to first set the policy to DROP or similar, then specify the packets to let through.
  • Several rules build up the chain called INPUT, and users can also define chains freely.

Custom chains

Logging

If you set the target to LOG or ULOG, you can write packet logs to syslog or ulog.

  • Packet logs are written to the kernel log by default.
  • To change the log facility, use --log-level.
  • You can also set a prefix when logging.
  • If you set a string with --log-prefix, you can tell which rule a logged packet matched.
  • When the target is LOG/ULOG, the packet passes that rule and moves on to the next rule.
  • So after a LOG/ULOG target, add another rule with a DROP or REJECT target.
$ iptables -N LOGGING # LOGGING 체인 생성
$ iptables -A INPUT -j LOGGING
$ iptables -A INPUT -p ICMP -d 192.168.2.121 -j ACCEPT
$ iptables -A LOGGING -j LOG # 상기 규칙 이외의 패킷을 로그 기록
$ iptables -A LOGGING -j DROP # LOGGING 체인 종료

Config file paths

  • /etc/sysconfig/iptables
  • /etc/iptables/rules.v4
  • /etc/iptables/rules.v6

Logging dropped packets

Log dropped packets (optional, can be noisy)

iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-dropped: " --log-level 4

Adding SYN flood protection

# SYN flood protection / SYN 플러드 방어
iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT

# Port scan detection / 포트 스캔 탐지
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

Allowing specific IPs/ranges (for management)

# Trusted management network / 관리용 신뢰 네트워크
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT

# Specific trusted IP (full access) / 특정 관리 IP 전체 허용
iptables -A INPUT -s 203.0.113.10 -j ACCEPT

How to reapply modified rules

To reapply the iptables rules after editing the /etc/iptables/rules.v4 file:

Apply immediately without rebooting

# iptables-persistent 패키지 사용
sudo iptables-restore < /etc/iptables/rules.v4

# 또는 netfilter-persistent 서비스 재시작
sudo netfilter-persistent reload

Restart the service

sudo systemctl restart netfilter-persistent

Traffic control

Blocking packets containing a specific string

iptables -I INPUT -p tcp --dport 9090 -m string --string "name" --algo bm -j DROP
Block by a string contained in the Request URL
Configures blocking of packets coming into port 9090 that contain "name"
iptables -I INPUT -p tcp --sport 9090 -m string --string "pong" --algo bm -j DROP
Block by a string contained in the Response Body
Configures blocking of packets coming from port 9090 that contain "pong"

Blocking packets coming into a specific port in the DOCKER-USER chain

iptables -I DOCKER-USER -p tcp --dport 8888 -j DROP
Block packets coming into destination port 8888 in the DOCKER-USER chain
According to the Docker docs, when a packet matches a rule registered in the DOCKER chain, the DOCKER chain's rule takes precedence, so this time we try adding the rule to the DOCKER-USER chain.

Docker traffic control

# Accept Docker FORWARD
-A FORWARD -i docker0 -j ACCEPT
-A FORWARD -o docker0 -j ACCEPT

# Allow Docker OUTPUT (docker-proxy -> container)
-A OUTPUT -d 172.16.0.0/12 -j ACCEPT

Building a virtual network

iptables in Kubernetes

Troubleshooting

Roles order

The final result depends on the order in which the configuration file is applied.

Rules get duplicated when the service restarts

Flush the iptables rules, then restart.

WARNING

Be careful: the moment you fire off iptables -F on a remotely connected server, you could be sent off to Valhalla

iptables -F
sudo systemctl restart iptables

See also

Favorite site

in Ubuntu

Tutorials

Online Tools

Best Practice

References

author Zer0 sitemap