Iptables (简体中文)
iptables 是一个配置 Linux 内核 防火墙 的命令行工具,是 netfilter 项目的一部分。术语 iptables 也经常代指该内核级防火墙。iptables 可以直接配置,也可以通过许多 前端 和 图形界面 配置。iptables 用于 ipv4,ip6tables 用于 ipv6。
nftables 已经包含在 Linux kernel 3.13 中,以后会取代 iptables 成为主要的 Linux 防火墙工具。
Contents
安装
The stock Arch Linux kernel is compiled with iptables support. You will only need to install the userland utilities, which are provided by the package iptables in the official repositories. (The iproute2 package from the base group depends on iptables, so the iptables package should be installed on your system by default.)
基本概念
iptables is used to inspect, modify, forward, 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 contain 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. Most new users find the complexities of linux IP routing quite daunting, but, in practice, the most common use cases (NAT and/or basic Internet firewall) are considerably less complex.
iptables 可以检测、修改、转发、重定向和丢弃 IPv4 数据包。
The key to understanding how iptables works is this chart. The lowercase word on top is the table and the upper case word below is the chain. Every IP packet that that comes in on any network interface passes through this flow chart from top to bottom. A common source of confusion is that packets entering from, say, an internal interface are handled differently than packets from an Internet-facing interface. All interfaces are handled the same way; it's up to you to define rules that treat them differently. Of course some packets are intended for local processes, hence come in from the top of the chart and stop at <Local Process>, while other packets are generated by local processes; hence start at <Local Process> and proceed downward through the flowchart. A detailed explanation of how this flow chart works can be found here.
In the vast majority of use cases you won't need to use the raw, mangle, or security tables at all. Consequently, the following chart depicts a simplified network packet flow through iptables:
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
表(Tables)
iptables 包含 5 张表(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 actions typically associated with a firewall take place. -
nat
is used for network address translation (e.g. port forwarding). -
mangle
is used for specialized packet alterations (see Mangled packet). -
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. The other tables are aimed at complex configurations involving multiple routers and routing decisions and are in any case beyond the scope of these introductory remarks.
链
Tables consist of chains, which are lists of rules which are followed in order. The default table, filter
, contains three built-in chains: INPUT
, OUTPUT
and FORWARD
which are activated at different points of the packet filtering process, as illustrated in the flow chart. The nat table includes PREROUTING
, POSTROUTING
, and OUTPUT
chains.
See man 8 iptables
for a description of built-in chains in other tables.
By default, none of the chains contain any rules. It is up to you to append rules to the chains that you want to use. Chains do have a default policy, which is generally set to ACCEPT
, but can be reset to DROP
, if you want to be sure that nothing slips through your ruleset. The default policy always applies at the end of a chain only. Hence, the packet has to pass through all existing rules in the chain before the default policy is applied.
User-defined chains can be added to make rulesets more efficient or more easily modifiable. See Simple stateful firewall for an example of how user-defined chains are used.
规则
Packet filtering is based on rules, which are specified by multiple matches (conditions the packet must satisfy so that the rule can be applied), and one 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 destination 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. Built-in targets are ACCEPT
, DROP
, QUEUE
and RETURN
, target extensions are, for example, REJECT
and LOG
. 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 packet passes successfully through this second chain, it will move to the next rule in the original chain. Target extensions can be either terminating (as built-in targets) or non-terminating (as user-defined chains), see man 8 iptables-extensions
for details.
遍历链
A network packet received on any interface traverses the traffic control chains of tables in the order shown in the flow chart. The first routing decision involves deciding if the final destination of the packet is the local machine (in which case the packet traverses through the INPUT
chains) or elsewhere (in which case the packet traverses through the FORWARD
chains). Subsequent routing decisions involve deciding what interface to assign to an outgoing packet. At each chain in the path, every rule in that chain is evaluated in order and whenever a rule matches, the corresponding target/jump action is executed. The 3 most commonly used targets are ACCEPT
, DROP
, and jump to a user-defined chain. While built-in chains can have default policies, user-defined chains can not. If every rule in a chain that you jumped fails to provide a complete match, the packet is dropped back into the calling chain as illustrated here. If at any time a complete match is achieved for a rule with a DROP
target, the packet is dropped and no further processing is done. If a packet is ACCEPT
ed within a chain, it will be ACCEPT
ed in all superset chains also and it will not traverse any of the superset chains any further. However, be aware that the packet will continue to traverse all other chains in other tables in the normal fashion.
模块
有许多模块可以用来扩展 iptables,例如 connlimit, conntrack, limit 和 recent。这些模块增添了功能,可以进行更复杂的过滤。
配置并运行 iptables
iptables 是一个 Systemd 服务,因此可以这样启动:
# systemctl start iptables
但是,除非有 /etc/iptables/iptables.rules
文件,否则服务不会启动,Arch iptables 包不包含默认的 iptables.rules
文件。因此,第一次启动服务时使用以下命令:
# touch /etc/iptables/iptables.rules # systemctl start iptables
或者
# cp /etc/iptables/empty.rules /etc/iptables/iptables.rules # systemctl start iptables
和其他服务一样,如果希望启动时自动加载 iptables,必须启用该服务:
# systemctl enable iptables
从命令行
显示当前规则
使用以下命令查看当前规则和匹配数:
# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0K packets, 0 bytes) pkts bytes target prot opt in out source destination
上面的结果表明还没有配置规则。Nothing is blocked.
To show the line numbers when listing rules, append --line-numbers
to that input. This is useful when deleting and adding individual rules.
重置规则
You can flush and reset iptables to default using these commands:
# iptables -F # iptables -X # iptables -t nat -F # iptables -t nat -X # iptables -t mangle -F # iptables -t mangle -X # iptables -t raw -F # iptables -t raw -X # iptables -t security -F # iptables -t security -X # iptables -P INPUT ACCEPT # iptables -P FORWARD ACCEPT # iptables -P OUTPUT ACCEPT
The -F
command with no arguments flushes all the chains in its current table. Similarly, -X
deletes all empty non-default chains in a table.
Individual chains may be flushed or deleted by following -F
and -X
with a [chain]
argument.
编辑规则
Rules can be added either by appending a rule to a chain or inserting them at a specific position on the chain. We will explore both methods here.
First of all, our computer is not a router (unless, of course, it is a router). We want to change the default policy on the FORWARD
chain from ACCEPT
to DROP
.
# iptables -P FORWARD DROP
The Dropbox LAN sync feature broadcasts packets every 30 seconds to all computers it can see. If we happen to be on a LAN with Dropbox clients and do not use this feature, then we might wish to reject those packets.
# iptables -A INPUT -p tcp --dport 17500 -j REJECT --reject-with icmp-port-unreachable
# iptables -nvL --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:17500 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination
Now, say we change our mind about Dropbox and decide to install it on our computer. We also want to LAN sync, but only with one particular IP on our network. So we should use -R
to replace our old rule. Where 10.0.0.85
is our other IP:
# iptables -R INPUT 1 -p tcp --dport 17500 ! -s 10.0.0.85 -j REJECT --reject-with icmp-port-unreachable
# iptables -nvL --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 REJECT tcp -- * * !10.0.0.85 0.0.0.0/0 tcp dpt:17500 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination
We have now replaced our original rule with one that allows 10.0.0.85
to access port 17500
on our computer. But now we realize that this is not scalable. If our friendly Dropbox user is attempting to access port 17500
on our device, we should allow him immediately, not test him against any firewall rules that might come afterwards!
So we write a new rule to allow our trusted user immediately. Using -I
to insert the new rule before our old one:
# iptables -I INPUT -p tcp --dport 17500 -s 10.0.0.85 -j ACCEPT -m comment --comment "Friendly Dropbox"
# iptables -nvL --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT tcp -- * * 10.0.0.85 0.0.0.0/0 tcp dpt:17500 /* Friendly Dropbox */ 2 0 0 REJECT tcp -- * * !10.0.0.85 0.0.0.0/0 tcp dpt:17500 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination
And replace our second rule with one that rejects everything on port 17500
:
# iptables -R INPUT 2 -p tcp --dport 17500 -j REJECT --reject-with icmp-port-unreachable
Our final rule list now looks like this:
# iptables -nvL --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT tcp -- * * 10.0.0.85 0.0.0.0/0 tcp dpt:17500 /* Friendly Dropbox */ 2 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:17500 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination
配置文件
Iptables rules are, by default in Arch Linux, stored in /etc/iptables/iptables.rules
. They are, however, not loaded automatically, instead you can enable the iptables.service
which reads this file and loads the rules at boot or when started:
# systemctl enable iptables.service # systemctl start iptables.service
ipv6 规则默认保存在/etc/iptables/ip6tables.rules
,ip6tables.service
服务会使用这个规则,可以用类似的方式启动服务。
After adding rules via command-line, the configuration file is not changed automatically — you have to save it manually:
# iptables-save > /etc/iptables/iptables.rules
修改配置文件后,需要重新加载服务:
# systemctl reload iptables
Or you can load it directly through iptables:
# iptables-restore < /etc/iptables/iptables.rules
指南
日志
The LOG
target can be used to log packets that hit a rule. Unlike other targets like ACCEPT
or DROP
, the packet will continue moving through the chain after hitting a LOG
target. This means that in order to enable logging for all dropped packets, you would have to add a duplicate LOG
rule before each DROP rule. Since this reduces efficiency and makes things less simple, a logdrop
chain can be created instead.
LOG 目标可以用来记录匹配某个规则的数据包。和 ACCEPT 或 DROP 规则不同,进入 LOG 目标之后数据包会继续沿着链向下走。所以要记录所有丢弃的数据包,只需要在 DROP 规则前加上相应的 LOG 规则。但是这样会比较复杂,影响效率,所以应该创建一个logdrop
链。
创建 logdrop 链:
# iptables -N logdrop
定义规则:
# iptables -A logdrop -m limit --limit 5/m --limit-burst 10 -j LOG # iptables -A logdrop -j DROP
Explanation for limit
and limit-burst
options is given below.
Now whenever we want to drop a packet and log this event, we just jump to the logdrop
chain, for example:
# iptables -A INPUT -m conntrack --ctstate INVALID -j logdrop
限制日志级别
The above logdrop
chain uses the limit module to prevent the iptables log from growing too large or causing needless hard drive writes. Without limiting an erroneously configured service trying to connect, or an attacker, could fill the drive (or at least the /var
partition) by causing writes to the iptables log.
The limit module is called with -m limit
. You can then use --limit
to set an average rate and --limit-burst
to set an initial burst rate. In the logdrop
example above:
iptables -A logdrop -m limit --limit 5/m --limit-burst 10 -j LOG
appends a rule which will log all packets that pass through it. The first 10 consecutive packets will be logged, and from then on only 5 packets per minute will be logged. The "limit burst" count is reset every time the "limit rate" is not broken, i.e. logging activity returns to normal automatically.
Viewing logged packets
Logged packets are visible as kernel messages in the systemd journal.
To view all packets that were logged since the machine was last booted:
# journalctl -k | grep "IN=.*OUT=.*" | less
syslog-ng
使用 Arch 默认的 syslog-ng 可以控制 iptables 日志的输出文件:
filter f_everything { level(debug..emerg) and not facility(auth, authpriv); };
修改为
filter f_everything { level(debug..emerg) and not facility(auth, authpriv) and not filter(f_iptables); };
iptables 的日志就不会输出到 /var/log/everything.log
。
iptables 也可以不输出到 /var/log/iptables.log
,只需设置syslog-ng.conf
中的 d_iptables 为需要的日志文件。
destination d_iptables { file("/var/log/iptables.log"); };
ulogd
ulogd 是专门用于 netfilter 的日志工具,可以代替默认的 LOG 目标。软件包 ulogd 位于 [community]
源。