There are a large number of filters you may apply to your server's network rules via the iptables command. Some of these are found in extensions to iptables.
The following topics are explained in this article:
- iptables command line structure and syntax
- List of commands and their purpose
- Interacting with chains vs. tables
- Parameters
- Extensions: Match Extensions, Target Extensions
- Actions and Targets
Every Linux distribution comes with a pre-determined bounty of network packet controls, many of which are found under the context of iptables. This article contains explains a limited set of commands and filters found in the most frequently used iptables extensions. If you're hunkering for more information, I recommend checking out the Ubuntu iptables-extensions Man Page and the official netfilter website. The Unix iptables Man Page - maintained by the Unix & Linux Forums - is also an excellent resource for iptables that includes a lot of helpful details on the command set.
Command Line Syntax
The iptables command line syntax is:
iptables {table} [COMMAND] [CHAIN] {parameter} {extension} [ACTION] {target}
Important syntax notes for iptables commands:
- May be applied to packets or connections
- COMMAND, CHAIN, and ACTION are required values
- Commands
- Always UPPERcase
- Only one command instruction per line
- Define actions to be performed on a packet matching a specified, corresponding rule
- Tables
- Use -t prefix, such as iptables -t INPUT
- If no table name is specified, the FILTER table is presumed
Let’s look at an example and break it down.
iptables -A INPUT -i eth1 --src-range 8.8.8.0/24 -j ACCEPT
In the example above, we have a command with these values:
iptables {COMMAND} {CHAIN} {PARAMETER} {EXTENSION} {ACTION}
Breaking it down....
Argument | Value |
---|---|
COMMAND | -A |
CHAIN | INPUT |
PARAMETER | -i eth1 --src-range 8.8.8.0/24 |
EXTENSION | -j |
ACTION | ACCEPT |
Where are the TABLE and TARGET? The chain must be specified, but the table is optional. When a table is not specified, by default the rule is inserted into the FILTER table. No target is specified in the example above because there is no target. So, in the case of this example, the rule may be roughly interpreted as:
"Append to the end of the INPUT chain, accept the packet if all of the following conditions are true:
the Interface is eth1 AND the Source IP Address is between 8.8.8.0 and 8.8.8.255"
Reading each segment in the line:
- -A is the command
- INPUT is the chain being acted upon
- -i indicates the next value will be the interface (in this case eth1)
- --src-range narrows the filter to a specific range of IP addresses (in this case 8.8.8.0/24 or 8.8.8.0-8.8.8.255)
The ACCEPT action tells netfilter to accept the packet and stop processing the packet in the current chain. Matching a rule with an ACCEPT target means the processing of this packet is finished for this chain. The packet will then proceed through the remainder of the network packet filtering process. If there are other chains after this one, they will still need to accept the packet in order for it to continue moving on.
iptables Commands and Chains
Aside from applying iptables commands to IP packets, you may also create rules that control the chains themselves. This is particularly useful when you have created custom chains.
Here's a list of the important commands that affect chains:
iptables Commands | Description |
---|---|
-A {chain} {rule} | Append (append rule to the end of the selected chain) |
-D {chain} {rule} | Delete rule in specified chain using rule specification |
-D {chain} {rule #} | Delete rule x in specified chain where x is rule number |
-E {old-name} {new-name} | Exchange (replace) old chain name with new chain name |
-F {chain} | Flush selected chain or table (delete all rules); all chains flushed if none specified |
-I {chain} {priority} | Insert new rule into a chain; 1 [default] = insert in front of any other existing rules |
-L {chain} | List all rules in specified chain |
-N {chain name} | Create a new chain |
-P {chain} {target} | Policy (must be ACCEPT or DROP) |
-S {chain} | List rule specifications in specified chain |
-X {chain} | Delete custom chain (by name) |
Next, let's group them. This will make it easier to figure out which command you need for whatever you're trying to accomplish.
Actions Upon Chains
Chain Actions | Description |
---|---|
-F {chain} | Flush selected chain or table (delete all rules); all chains flushed if none specified |
-N {chain} {name} | Create a new chain |
-P {chain} {target} | Policy (must be ACCEPT or DROP) |
-X {chain} {name} | Delete custom chain |
Actions Upon Rules
Rule Actions | Description |
---|---|
-A {chain} {rule} | Append (append rule to the end of the selected chain) |
-D {chain} {rule} | Delete rule in specified chain using rule specification |
-D {chain} {rule #} | Delete rule x in specified chain where x is rule number |
-I {chain} {priority} | Insert new rule into a chain; 1 [default] = insert in front of any other existing rules |
Parameters
Parameters are optional filters that further narrow the scope of commands. For example, the -p or -protocol parameter defines a protocol that restricts the action of the command line to:
- a specific chain; and
- a specific parameter within the chain
So, in an example with ... INPUT -p tcp... for instance, the action and target would apply only to the INPUT chain and within that chain, only to TCP/IP traffic. Parameters are always expressed in lower case.
Parameter | Description |
---|---|
-d addr/mask | Destination address; may be network name or IP, hostname, external IP |
-i interface name | Name of interface In (receiving packet); only INPUT, FORWARD, PREROUTING |
-m | Match; tries to match conditions in order (all criteria must be met) |
-o interface name | Interface out (sending packets); only FORWARD, OUTPUT, POSTROUTING chains |
-p | Protocol of a packet (TCP, UDP, ICMP, or ALL) |
-s addr /mask | Source address; internal or external network name/IP, hostname |
iptables Extensions
One of the most powerful tools in iptables are extensions.
iptables is built as a semi-modular framework. Some tasks are handed off to the Linux kernel, and some are handed off to modules, which are external filters initiated by the iptables process called extensions. The most common use of extensions pertains to parameter filters. There are dozens of parameter filters. Due to the manner in which iptables man pages tend to order extension explanations, digesting their syntax can be quite confusing.
Extensions are modules called by the iptables process. Comprised of classes or groups of functions, extensions provide additional processing on behalf of iptables. One way to think of parameters and extensions is of parameters as coarse filters, and extensions as fine filters with more granular control over packets and connections.
For example, -protocol (shortcut for -p) is an iptables parameter. It restricts a rule to a particular network protocol (e.g. -p tcp or -protocol udp). The -protocol It's also possible to extend that capability and create a more granular filter, such as a rule combining a networking protocol (e.g. TCP) with a defined source or destination port range. While the former concept is a capability built-in to iptables, the latter requires the use of iptables extensions.
Extensions are grouped into various modules. The modules are not called in the command line. Rather, they contain groups or sets of extensions, and those extensions are the parameters called in iptables rules. It gets confusing when attempting to comprehend whether you need to use the extension name itself and/or a particular extension name sub-set. From an implementation perspective, it boils down to understanding which parameters to use to accomplish your goals. We'll focus primarily on two extension sub-sets: Match and Target extensions. These are the most commonly used iptables extensions, regardless of the purpose of the local device.
Some comments below refer to a media server because they are derived from my guide on building a custom media server.
They are loaded via the -m parameter.Extension Syntax
The syntax format of all iptables extensions is:
-{parameter} --{extension} {option} {argument}
For example, with match extensions the relevant portion of the iptables command line looks like this:
iptables ... -match --{extension} {option} {argument}
Or the shorthand version:
iptables ... -m --{extension} {option} {argument}
Following the -m parameter, match uses options and arguments to filter traffic. Multiple match options and argument variants are permitted on the same line. For instance, matching a connection state and a protocol at the same time.
Bear in mind multiple match extensions may be grouped together on the same line. Needs will vary, but these extensions - grouped by function - are the most commonly utilized. If you can't find a function to suit your needs here, you may wish to read the official man page for Ubuntu. For non-Ubuntu operating systems, check the iptables man page for Linux, or for either simply request the man page via your terminal:
man iptables
Match Extensions
Match extensions identify packets that match a specified criteria. This document focuses on the most frequently used match extension modules, which are:
Let's take a look at the relevant match extensions and what characteristics they match. As previously mentioned, the match extensions are grouped into modules. Within each module is a set of extensions and/or options. The relevant match extension modules are:
Match Module | Description |
---|---|
connmark | netfilter marked fields associated with a connection |
conntrack | Connection tracking |
iprange | Range of IP addresses |
mac | Source MAC ID |
mark | netfilter marked fields associated with a packet |
multiport | Set of source or destination ports |
owner | Outgoing packets based on userid or groupid |
These modules are explained below.
Match extensions are written in lowercase
connmark
Part of the ConnTrack module (CONNection MARKing), this has to be the worst-named extension. Why do I say that? Because there are two (2) ConnMark extensions. One is a match extension, which is connmark. The other is a target extension, which is CONNMARK. Confused yet?
connmark matches connections marked with the netfilter mark field (see MARK target extension). Use it to check for the presence of a specific mark value associated with a connection.
Syntax: -m connmark --mark {value}
Example:
iptables {table} {COMMAND} {CHAIN} {parameter} -m connmark --mark 10 {ACTION} {target}
conntrack
conntrack allows access to the connection tracking state for the current packet/connection. It can be used to match connections based on state, protocol, source/destination originating IP addresses, TTL (Time To Live), reply source/destination IP addresses, and flow direction (originating or reply). Most of those features are not explained here as they are managed with other commands. The most important function of conntrack is its ability to branch based on connection state.
You may query the state of the connection using the extension --ctstate.
Syntax: -m conntrack --ctstate {statelist}
--ctstate is unique compared with the other match extensions. It branches based on a connection's state. The statelist includes the following valid states. You may use more than one as the argument:
Connection State | Description |
---|---|
NEW | Packet is part of a known 2-way connection |
ESTABLISHED | Connection tracking |
RELATED | Packet is starting new connection, but associated with an existing connection |
INVALID | The packet has no known associated connection |
UNTRACKED | Packet is exempt from tracking per NOTRACK command in RAW table |
SNAT | Virtual state. Matches if source IP address has been altered |
DNAT | Virtual state. Matches if destination IP address has been altered |
Example syntax:
iptables ... -m conntrack --ctstate RELATED {ACTION} {target}
There is a netfilter process called conntrack, which is responsible for tracking and maintaining the current state of network connections. The conntrack module within netfilter and the conntrack match extension within iptables are independent of one another. However, their identical names can and do create confusion. The key difference is the iptables conntrack reference is a match extension and read-only.
iprange
iprange allows you to create a match rule based on a specified IPv4 address or range of addresses. You must specify if the address(es) to be matched are source or destination addresses. The format is:
-m iprange --src-range from{-to}
-m iprange --dst-range from{-to}
mac
A Media Access Control or MAC address is a unique identifier assigned to a network interface controller. MAC addresses are tied to a specific device, rather than a specific IP address.
In iptables the mac match extension requires a 2-part argument, as shown here, where {XX:XX:XX:XX:XX:XX} is the host device MAC ID:
-m mac --mac-source XX:XX:XX:XX:XX:XX
-m calls the match extension. mac indicates the mac match extension is being called. --mac-source is an argument prefix and indicates the actual MAC ID will follow. The target MAC ID is then specified after the prefix.
Syntax: -m mac --mac-source XX:XX:XX:XX:XX:XX
If you forget to include the -m mac prefix in the command, it won't work.
mark
Matches packets with a previously associated mark value. A mark may be assigned via any of three methods:
- The current connection was previously marked with the CONNMARK target extension
- The current packet was previously marked via the MARK target extension
- Via a rule set in ip rule that sets a corresponding fwmark (FireWall mark)
The syntax of the mark match extension is: -m mark --mark {value}
multiport
muliport allows matching based on source, destination, or both direction of traffic flow (source/destination) with a single port, group of ports, or range of ports. The maximum number of ports specified as a command line argument is 15.
A range (e.g. x-y) counts as two (2) ports out of the maximum of 15
Syntax: -m multiport {--source-ports | --destination-ports | --ports {port,port,port:port}
Like all match extensions, multiport may be combined on the same line with other match extensions. For example, you could match the TCP extension with the multiport extension. Here is an example that matches a condition where the protocol is TCP and the port the packet is coming either to or from is either 80 (HTTP) or 443 (HTTPS):
iptables ... -p tcp -m multiport --ports 80,443 {ACTION} {target}
There is one exception in syntax that should be noted. Multiport may not be combined with standalone --source-port or --destination-port matches when the multiport command corresponds with the same action as --source-port or --destination-port. If you do combine them in the same command, the first related action will be executed and subsequent actions affecting the same module will be ignored.
owner
The owner module matches packets with the local owner (of the packet) that corresponds to the match criteria. An "owner" is a user on the local host device, and may be a single UsernameID, single UserGroupID, a range of UserIDs, or a range of GroupIDs. Ranges may only be specified if numeric arguments are used (i.e. userid or groupid).
Owner is applicable only in the mangle table of the OUTPUT and POSTROUTING chains.
If attempts are made to apply it in any other chains or tables it will be ignored.
Possible applications are:
--uid-owner {username}
--uid-owner {userid | userid-userid}
--gid-owner {groupname}
--gid-owner {groupid | groupid-groupid}
Examples in context with -m switch:
-m owner --uid-owner username
-m owner --uid-owner userid1
-m owner --uid-owner userid1-userid2
-m owner --gid-owner groupname
-m owner --gid-owner groupid
-m owner --gid-owner groupid1-groupid2
state (deprecated)
Although the state match exists, it was deprecated in iptables version 1.4.16, and its use should be avoided.1 The state match is now aliased to the conntrack module (-m conntrack), meaning ConnTrack functions are what is called by state, and therefore ConnTrack's functions are the ones you should be using. While currently functional for backward compatibility, the state match extension should be avoided and conntrack should be used instead.
Since you may continue to see this match parameter represented in documentation, you should be aware of its (now deprecated) syntax:
iptables ... -m state --state
The statelist utilized by state is the same as ConnTrack's.
--source-port
Source Port allows matching based on a single, group, or range of source ports. The maximum number of ports specified as a command line argument is 15. A range (e.g. x-y) counts as two (2) ports out of the maximum of 15. The source port match extension may be expressed as --source-port or --sport.
As --source-port specifies port numbers only, it must be used in conjunction with a protocol.
iptables ... -p {protocol} --source-port {port,port,port:port}
Or
iptables ... -p {protocol} --sport {port,port,port:port}
Here is an example that matches source ports 52, 53, 80, and 443:
iptables ... -p tcp --source-ports 52-53,80,443 {ACTION} {target}
Note: --destination-port and --source-port are protocol specific. The protocol must be specified on the command line, and must precede the -port command. The protocol must be one of TCP, UDP, or ICMP.
Target Extensions
Target extensions affect the final disposition or destination of a packet or a connection. This could mean halting a particular packet or connection, tagging it, or redirecting its destination. A target extension need not necessarily end a packet’s or a connection’s processing tree, though some do.
Target extensions are invoked via the jump action (-j | -jump).
There are three (3) target types built-in to the core iptables code:
- ACCEPT
- DROP
- REJECT
A target module is one that performs an action against the current packet or connection. The following additional target modules are added by the target extension module:
Target Module | Description |
---|---|
CONNMARK | Matches packets based on a mark value |
CONNSECMARK | Assign a security mark to a connection |
CT | Disables tracking for current packet when used with --notrack option |
DNAT | Alters destination address of incoming packets |
MARK | Assigns a mark value to a packet |
MASQUERADE | Conceal internal IP address when sending packets outside the LAN |
NOTRACK | Do not track the state of the current packet |
REJECT | Drop packet and return error |
SECMARK | Assign a security mark to a packet |
SNAT | Change source IP address to specified value |
--destination-port | Protocol specific matching by destination port number(s) [ TCP | UDP | ICMP ] |
--source-port | Protocol specific matching by source port number(s) [ TCP | UDP | ICMP ] |
Target extension modules are written in UPPERCASE
CONNMARK
Set the netfilter mark associated with a connection. The mark must be an integer (32-bits).
Syntax:
Connection Mark | Description | |
---|---|---|
--restore-mark | Copy the connection mark to the packet mark | |
--save-mark | Copy the packet mark to the connection mark |
Example:
iptables -A POSTROUTING -t mangle -j CONNMARK --restore-mark
CONNMARK target commands may be used in any chain and in any table. However, it is recommended to use them only in the mangle table (Andreasson, 2006; p. 215). Unpredictable results may occur if used in other tables.
Note the important distinction between CONNMARK (connection) and MARK (packet).
CONNSECMARK
Assigns a security mark to a connection.
SELinux is beyond the scope of this document. However, due to legacy code in iptables, a small number of functions in SELinux have comparable functions in iptables that may be accessed even when SELinux is not present. This section briefly describes one of those functions, for the sake of completeness.
This is an oddball. Ideally, it belongs only in the security table of the INPUT, FORWARD, and OUTPUT chains. However, in the event you're working with a host not running a SELinux security module, there is a legacy entry point of sorts. This extension can be utilized via the mangle table of the PREROUTING chain.
Syntax:
Connection Mark | Description | |
---|---|---|
--restore | If no SECMARK exists on the packet, copy the connection security context mark to the packet | |
--save | If security context mark exists on packet AND no security context mark exists on connection, then copy packet security mark to connection |
Example:
iptables -A POSTROUTING -t mangle -p tcp -dport 80 -j CONNSECMARK --restore
CT
CT is an acronym for Connection Target. Exclusive to the RAW table, the CT target extension allows one to set parameters for a packet OR its associated connection. I only mention CT in this document as an alternative to removing connection tracking in the RAW table. CT basically creates and applies a connection tracking template to an incoming packet, which is then overlaid onto the conntrack module in netfilter. This is why it's only relevant in the RAW table.
Syntax:
--notrack | Disable connection tracking for the packet |
CT has other capabilities, but they are quite advanced and well beyond the scope of this document
DNAT (Destination Network Address Translation)
DNAT is acronym for Destination Network Address Translation. DNAT is the opposite of SNAT. It determines where a packet should go on the local server. Applied only during the PREROUTING chain, when the packet has just entered the server. This ensures future traffic over the same connection has the DNAT change applied to it.
DNAT rewrites the destination address of the packet.
DNAT translates an incoming public IP address into a specific private (LAN side) IP address. A typical use case would be when you always want traffic directed to a certain public IP address to be routed to a certain internal server.
Port Forwarding uses DNAT in combination with port filtering. DNAT may also be used to force protocol filtering, which while very similar to port forwarding, causes incoming network traffic to be redirected based on protocol (e.g. UDP). This results in a wider scope of packet redirection.
Port forwards may include a range of port numbers.
A neat trick is DNAT may be used to change destination port numbers without affecting the IP address.
Example:
iptables -t nat -A PREROUTING -p tcp -o eth0 -j DNAT --to-destination :80
What it says:
"Funnel all incoming TCP/IP traffic on interface eth0 to port 80, without changing the destination IP address."
Dynamic DNAT
There is a variation of DNAT sometimes referred to as Dynamic DNAT or Dynamic Mode DNAT. Dynamic DNAT is simply a list of range-bound DNAT addresses, any of which may be assigned to the current connection. iptables will select the least frequently used address (a form of load-balancing).
An example of Dynamic DNAT:
iptables -t nat -A PREROUTING -j DNAT --to-destination 192.168.0.21-192.168.0.25
MARK
A numeric field (32-bit integer) used to mark (flag) a packet by associating a value with it. The MARK command is used by iptables to set a packet mark. It is the same thing as fwmark (FireWall Mark) in ip rules.
Packet marks may be read by both iptables and ip rules (per fwmark), regardless of which one set the mark.
The MARK command can only be used in the Mangle table. It is normally applied in the PREROUTING chain, but may be applied in the INPUT or OUTPUT chains as well.
In order to be used in conjunction with a corresponding fwmark rule (ip rules),
the MARK command must be in the PREROUTING chain (Mangle table).
The syntax is: --set-mark
Example:
... -j mark --set-mark 32
Note the important distinctions between CONNMARK (connection), MARK (packet), and fwmark (ip rules).
MASQUERADE
MASQUERADE is an alternative to SNAT. It is applicable to outbound connections and works almost exactly like SNAT, except it cannot force a public IP address. Instead, it passes the public IP address of the router, thus masquerading or disguising the internal IP address of the originating server. MASQUERADE requires Connection Tracking to be in use on the current connection (e.g. it won't work if state has been de-activated via a command in the RAW table).
MASQUERADE may only be used with one of the following protocols: TCP, UDP, DCCP, or SCTP.
MASQUERADE may only be applied in the nat table of the POSTROUTING chain.
The following options may be applied:
--to-ports | Specifies a range of source ports to use | |
--random | Randomizes source port mapping |
NOTRACK
Disables connection tracking for all packets matching the rule. Equivalent to using CT --notrack. As with CT, this function can only be used in the RAW table. It may be applied in the PREROUTING or OUTPUT chains.
REJECT
This is effectively the same as executing a DROP command (via "jump to," i.e. -j DROP). The difference is the REJECT command will return an error packet to the server on the other end of the connection, informing it the packet was rejected.
SECMARK
Assigns a security mark to the current packet.
SELinux is beyond the scope of this document. However, due to legacy code in iptables, a small number of functions in SELinux have comparable functions in iptables that may be accessed even when SELinux is not present. This section briefly describes one of those functions, for the sake of completeness.
This is an oddball. Ideally, it belongs in the security table of the INPUT, FORWARD, and OUTPUT chains. However, in the event you're working with a host not running a SELinux security module, there is a legacy entry point (backdoor) of sorts; namely, it can be utilized via the mangle table of the PREROUTING chain.
Syntax:
-A {chain} -t {table} {parameters} -j SECMARK {security context}
Example:
iptables -A POSTROUTING -t mangle -p tcp -dport 80 -j SECMARK --selctx httpcontext
SNAT (Source Network Address Translation)
SNAT is acronym for Source Network Address Translation. SNAT is the opposite of DNAT. Applied only during the POSTROUTING chain, just before the packet leaves the server. This ensures future traffic over the same connection has the SNAT change applied to it.
SNAT rewrites the source IPv4 address of the packet and is used in conjunction with the -o parameter (e.g. -o eth0) to modify an outgoing packet on the given interface.
For example:
iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to-source :80
What it says:
"Funnel all outgoing TCP/IP traffic on interface eth0 to port 80, without changing the source IP address."
Dynamic SNAT
There is a variation of SNAT sometimes referred to as Dynamic SNAT or Dynamic Mode SNAT. Dynamic SNAT is simply a list of range-bound SNAT addresses, any of which may be assigned to the current connection. iptables will select the least frequently used address (a form of load-balancing).
An example of Dynamic SNAT:
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 192.168.0.1-192.168.0.10
Actions and Targets
An action is a parameter applied at the end of a line, just before the target. The most common actions are -goto and -jump, which are similar but are distinctly different in their behavior.
Goto
The -goto or -g action instructs iptables to 'go to' a custom chain name specified after the -g. When iptables finds a matching rule containing a -goto command, it stops processing the current chain and jumps or goes to the specified target custom chain name.
iptables ... -g my_custom_chain_name
Or
iptables ... -goto my_custom_chain_name
Jump
The -jump or -j action instructs iptables to 'jump' to the target identified after the -j. When iptables finds a matching rule containing a -jump command, it stops processing the current chain and performs the specified target action.
The target is the last item in an iptables command line. The most common are the built-in targets mentioned in the previous section: ACCEPT, DROP, and REJECT. Target indicates the target process or what the desired behavior is if all conditions of the line are met.
ACCEPT ends the processing of the current packet within the current chain. From there it goes on to the next chain in the order previously discussed. If the packet is currently in the POSTROUTING chain, when it reaches an ACCEPT target, all mangling of the packet ends and it is sent out of the server.
-j ACCEPT
The difference between DROP and REJECT is DROP simply drops the connection, while REJECT drops the connection and returns a message to the requesting process, advising it the packet was rejected.
-j REJECT
DROP provides no notification.
-j DROP
Endnotes
1 See Edwards & Engelhardt (2013) in Bibliography.