文章目录
iptables原理及常用命令
Netfilter 是内核提供的包过滤子系统,它在内核网络中设置了多个钩子(Hooks),数据包在网络栈中流动时会经过这些钩子,从而可以被预设的规则处理,实现对数据包的过滤、修改、重定向以及网络地址转换(NAT)等功能。
而iptables
则是用户空间(Userspace)的一个命令行工具,用于配置、管理内核空间(Kernelspace)中的 Netfilter 防火墙框架。
表链
四表与五链
表(Tables) | 功能 | 内置链(Chains) |
---|---|---|
filter |
包过滤(默认表) | INPUT, FORWARD, OUTPUT |
nat |
网络地址转换(NAT) | PREROUTING, POSTROUTING, OUTPUT |
mangle |
修改报文头(如TTL、TOS) | 所有五个链均可使用 |
raw |
绕过连接跟踪(提升性能) | PREROUTING, OUTPUT |
- 表(Tables):定义规则的功能类别。主要表有:
- filter:负责过滤数据包(允许/拒绝),最常用。
- nat:负责网络地址转换(SNAT, DNAT, MASQUERADE)。
- mangle:用于修改数据包内容(如 TOS, TTL)或给数据包打标记。
- raw:用于连接跟踪(conntrack)前的数据包处理。
- 链(Chains):规则被应用的时机和位置。内置链对应 Netfilter 的钩子:
- INPUT:处理发往本机的数据包。
- OUTPUT:处理由本机发出的数据包。
- FORWARD:处理经过本机路由转发的数据包。
- PREROUTING:数据包进入后,路由决策之前处理(主要用于
nat
,mangle
,raw
表)。 - POSTROUTING:数据包发出前,路由决策之后处理(主要用于
nat
,mangle
表)。
将数据包可以理解成包裹,所谓的路由及规则都是用来分拣及处理包裹的。链则对应不同的分拣阶段的流水线,不同的链(流水线)对应不同的分拣策略,便是表对应的内容功能,表将规则内容分类。通过表和链,使得“分拣中心”能够在不同的阶段对数据包进行各类的分拣操作。
链
链定义了数据包生命周期的五个关键节点,与内核预设的5个关键的钩子点对应(不同时段的数据包处理流水线),使处理器能在正确的时间点执行正确的操作。链是规则生效的时机和位置:
PREROUTING 链 (进港预处理流水线)
- 作用:数据包进入分拣中心,还没来得及看最终地址标签的时候。
- 意义:在这里可以修改数据包的“目的地地址”(DNAT),或者给数据包贴个内部标签(mangle),这会影响后续分拣机(路由系统)的判断。
INPUT 链 (入仓流水线)
- 作用:分拣机判断这个包裹最终目的地就是本分拣中心自己,需要送入内部仓库。
- 意义:这是防火墙的核心!在这里决定是否允许这个数据包裹进入我们的电脑。比如,是否允许别人SSH连接到你。
FORWARD 链 (中转流水线)
- 作用:分拣机判断这个数据包裹只是路过,需要从另一个口发出去(你的电脑充当路由器或网关)。
- 意义:在这里决定是否允许这个数据包裹从本机转发过去。普通电脑默认不开,路由器必须配置此链。
OUTPUT 链 (出仓流水线)
- 作用:本分拣中心自己产生的数据包裹,要发出去。
- 意义:在这里决定是否允许我们自己发出的数据包裹出去。比如,可以禁止某个程序访问网络。
POSTROUTING 链 (出港前流水线)
- 作用:数据包裹已经分拣完毕,马上就要发走了,这是最后的处理机会。
- 意义:在这里可以修改数据包裹的“发货人地址”(SNAT/MASQUERADE),这样对方回包才知道寄回哪里。这是实现共享上网的关键。
表
表是规则的功能分类,将庞大的规则集按功能拆解,让不同的规则各司其职,管理起来更清晰、更高效。可以将不同的表理解为不同的分拣员,负责不同的分拣操作。
filter 表 (安全检查员)
- 作用:它的工作唯一目的就是决定:这个数据包裹是允许通过(ACCEPT)还是扔掉(DROP)?
- 能用的链:主要工作在
INPUT
,FORWARD
,OUTPUT
这三条流水线。 - 意义:这是最常用的表,实现了防火墙最核心的访问控制功能。
nat 表 (收货地址管理员)
- 作用:专门修改数据包裹的源或目标地址。
DNAT
(改目的地址):在PREROUTING
链工作。比如“把发给A地址的数据包,全部改道送到B地址”(端口映射)。SNAT/MASQUERADE
(改源地址):在POSTROUTING
链工作。比如“把所有从内网发出的数据裹,地址都改成网关地址”(共享上网)。
- 能用的链:
PREROUTING
,OUTPUT
,POSTROUTING
。 - 意义:实现网络地址转换,是解决IPv4地址不足和实现内部网络安全的关键。
- 作用:专门修改数据包裹的源或目标地址。
mangle 表 (包裹改装员)
- 作用:专门修改包裹的“元数据”,比如修改TTL(生存时间)、给包裹贴上一个特殊的“标记”(MARK),以便后续的规则或路由策略能识别它。
- 能用的链:所有五条链都可以用。
- 意义:用于高级、特殊的数据包处理,通常普通用户很少用到。
raw 表 (免检特权员)
- 作用:在连接跟踪机制之前,决定是否不对这个包裹进行状态跟踪。
- 能用的链:
PREROUTING
,OUTPUT
。 - 意义:用于处理那些不希望被系统连接跟踪机制干扰的高速或特殊流量,性能优化或处理特殊协议时使用。
链表总结
一个数据包不会经过所有表,不同的表被允许工作的流水线(链)是不同的。下图展示了一个数据包可能流经的完整路径,以及“表”和“链”如何协同工作:
总结与记忆诀窍:
- 先看数据包位于哪个处理阶段?-> 这决定了你用哪个链(
INPUT
/OUTPUT
/FORWARD
…)。 - 要对数据包作什么操作? -> 这决定了你用哪个表。
- 只想允许/拒绝 -> 用
filter
表 (-j ACCEPT/DROP
)。 - 想做地址转换(端口映射、共享上网) -> 用
nat
表 (-j SNAT/DNAT/MASQUERADE
)。 - 想修改包内容或做标记 -> 用
mangle
表。
- 只想允许/拒绝 -> 用
这种分工合作的架构使得 iptables
功能强大而灵活,既能完成简单的包过滤,也能实现复杂的网络地址转换和流量整形。
iptables 常用命令及参数
iptables
命令通用格式:iptables [-t table] <command> [chain] [rule-specification] -j <target>
1. 规则管理命令 (Commands)
命令 | 全称 | 作用 | 示例 |
---|---|---|---|
-A |
--append |
在链的末尾追加一条规则 | iptables -A INPUT -s 192.168.1.1 -j DROP |
-I |
--insert |
在链的指定位置插入一条规则(默认为第1条) | iptables -I INPUT 3 -p tcp --dport 80 -j ACCEPT |
-D |
--delete |
从链中删除一条规则(按编号或按内容) | iptables -D INPUT 2 或 iptables -D INPUT -s 192.168.1.1 -j DROP |
-R |
--replace |
替换链中的一条规则 | iptables -R INPUT 1 -p icmp -j ACCEPT |
-L |
--list |
列出链中的所有规则 | iptables -L INPUT -v -n |
-F |
--flush |
清空链中的所有规则 | iptables -F 或 iptables -F INPUT |
-Z |
--zero |
将链中规则的计数器清零(包和字节数) | iptables -Z |
-N |
--new-chain |
创建一条用户自定义链 | iptables -N MY_CHAIN |
-X |
--delete-chain |
删除一条用户自定义链(必须为空) | iptables -X MY_CHAIN |
-P |
--policy |
设置链的默认策略(只能是ACCEPT/DROP) | iptables -P INPUT DROP |
2. 规则匹配参数 (Rule-Specification - Matches)
参数 | 全称/作用 | 示例 |
---|---|---|
-p, --protocol |
匹配协议(tcp , udp , icmp , all ) |
-p tcp |
-s, --source |
匹配源IP地址或网段 | -s 192.168.1.100 或 -s 192.168.1.0/24 |
-d, --destination |
匹配目标IP地址或网段 | -d 10.0.0.1 |
-i, --in-interface |
匹配数据包进入的网卡(常用于INPUT , FORWARD , PREROUTING ) |
-i eth0 |
-o, --out-interface |
匹配数据包出去的网卡(常用于OUTPUT , FORWARD , POSTROUTING ) |
-o wlan0 |
--sport, --source-port |
匹配源端口(需用 -p tcp 或 -p udp ) |
-p tcp --sport 1024:65535 (1024及以上端口) |
--dport, --destination-port |
匹配目标端口(需用 -p tcp 或 -p udp ) |
-p tcp --dport 22 (SSH端口) |
-m, --match |
加载扩展模块以实现更复杂的匹配 | -m conntrack (状态跟踪) |
-m conntrack --ctstate |
匹配连接状态(最关键的模块) | -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT NEW (新连接), ESTABLISHED (已建立), RELATED (相关连接,如FTP), INVALID (无效) |
-m multiport |
匹配多个不连续端口 | -m multiport --dports 22,80,443 |
-m limit |
限制匹配速率,用于防止DoS攻击 | -m limit --limit 5/sec -j ACCEPT (限制每秒5个包) |
3. 目标动作参数 (Target)
参数 | 全称/作用 | 示例 |
---|---|---|
-j ACCEPT |
--jump ACCEPT |
接受数据包 |
-j DROP |
--jump DROP |
丢弃数据包(无响应) |
-j REJECT |
--jump REJECT |
拒绝数据包(可返回错误信息) |
-j LOG |
--jump LOG |
将数据包信息记录到系统日志(/var/log/syslog ) |
-j SNAT |
--jump SNAT |
源地址转换(用于共享上网) |
-j MASQUERADE |
--jump MASQUERADE |
动态源地址转换(用于拨号等动态IP) |
-j DNAT |
--jump DNAT |
目标地址转换(用于端口映射) |
-j REDIRECT |
--jump REDIRECT |
将包重定向到本机另一个端口(透明代理) |
命令示例
⚠️ 重要警告:在远程配置服务器防火墙时,千万不要直接清空所有规则,否则你可能会立刻断线!最好在本地电脑或虚拟机先练习。
- 查看现有规则
sudo iptables -L
-L
是 List 的意思。这会列出所有规则,但看起来会比较简单。- 想看更详细的信息(比如规则在哪行),可以加参数:
sudo iptables -L -v -n --line-numbers
-v
:显示详细信息-n
:直接显示IP和端口号,而不是去解析成名字(更快更直接)--line-numbers
:显示规则的行号(非常重要,插入和删除规则时要用)
- 设置默认策略(兜底规则)
如果所有规则都对不上,该怎么办?”
# 设置 INPUT 链的默认策略为 DROP(非常严格)
sudo iptables -P INPUT DROP
# 设置 INPUT 链的默认策略为 ACCEPT(非常宽松)
sudo iptables -P INPUT ACCEPT
# 设置 OUTPUT 链的默认策略为 ACCEPT(通常允许本机所有对外请求)
sudo iptables -P OUTPUT ACCEPT
-P
是 Policy 的意思。新手建议先把 INPUT 默认策略设为 ACCEPT,配完规则再改为 DROP,以防把自己锁在外面。
- 允许已建立的连接接收回包(超级重要!)
这是最容易出错的一步!如果你设置了INPUT DROP
,会发现能ping
通外面,但看不到任何返回的数据。因为你拦下了外面的回包!
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT
:在 INPUT 链的末尾追加(Append) 一条规则。-m conntrack
:启用状态检测模块。--ctstate ESTABLISHED,RELATED
:匹配状态为“已建立的连接”或“相关的连接”(比如FTP的数据连接)。-j ACCEPT
:跳转(jump)到 ACCEPT 动作。
这条规则的意思是:凡是回应我本机发起的请求的数据包,都允许进来。必须放在靠前的位置!
- 开放特定端口(允许外部访问特定服务)
例子:允许别人 SSH(端口22)连接到你的电脑
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
-p tcp
:指定协议为 TCP。--dport 22
:指定目标端口(destination port)为 22。
例子:允许别人访问你的网页(端口80)
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
- 允许本机 ping 通别人(允许发出ICMP协议)
sudo iptables -A OUTPUT -p icmp -j ACCEPT
- 禁止某个IP访问
例子:禁止IP为 192.168.1.100 的机器访问你
sudo iptables -A INPUT -s 192.168.1.100 -j DROP
-s 192.168.1.100
:匹配源地址(source)是 192.168.1.100 的数据包。
- 删除某条规则
首先用--line-numbers
查看规则在哪一行:
sudo iptables -L INPUT --line-numbers
假设我们要删除 INPUT 链的第3条规则:
sudo iptables -D INPUT 3
-D
是 Delete 的意思。
- 清空所有规则(重置规则,慎用)
# 清空所有链的所有规则
sudo iptables -F
# 同时将所有链的默认策略重置回 ACCEPT(最宽松的状态)
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
-F
是 Flush 的意思。
配置流程示例
假设我们要配置一台服务器,只允许别人SSH和访问HTTP,其他一律禁止。
首先,设置默认允许,防止掉线。
sudo iptables -P INPUT ACCEPT sudo iptables -F # 清空可能有的旧规则
允许本地内部通信(lo接口)
sudo iptables -A INPUT -i lo -j ACCEPT
允许已建立的连接接收回包(关键!)
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
开放服务端口
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT # HTTP # sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 如果需要HTTPS也可以打开
允许ping(可选)
sudo iptables -A INPUT -p icmp -j ACCEPT
最后,设置INPUT的默认策略为DROP!
sudo iptables -P INPUT DROP
保存规则(否则重启就没了!)
iptables
规则是临时存在的,重启后失效。- Ubuntu 上可以使用
iptables-persistent
包来保存:sudo apt install iptables-persistent sudo netfilter-persistent save # 保存当前规则
- Ubuntu 上可以使用
ip route
常用命令
ip route
命令通用格式:ip route <command> [options] <prefix> [via <gateway>] [dev <device>] [other options]
1. 路由管理命令 (Commands)
命令 | 全称/作用 | 示例 |
---|---|---|
add |
添加一条路由 | ip route add 192.168.2.0/24 via 10.0.0.1 dev eth0 |
del |
删除一条路由 | ip route del 192.168.2.0/24 |
change |
修改一条已有的路由 | ip route change default via 192.168.1.254 dev eth1 |
replace |
替换一条路由,如果不存在则添加 | ip route replace default via 192.168.1.1 |
show |
显示路由表(可加参数过滤) | ip route show 或 ip route show dev eth0 |
flush |
清空路由表(可按条件清空) | ip route flush cache (清空缓存) ip route flush 10.0.0.0/8 (清空特定路由) |
get |
查询到某个地址的路由路径 | ip route get 8.8.8.8 |
2. 核心路由参数 (Options)
参数 | 作用 | 示例 |
---|---|---|
via <address> |
指定下一跳网关的IP地址 | via 192.168.1.1 |
dev <interface> |
指定数据包出去的网络接口 | dev eth0 |
src <address> |
指定从此路由发出数据包的源IP地址 | src 192.168.1.100 |
proto <type> |
路由协议标识(kernel , boot , static , dhcp 等) |
proto static |
scope <scope> |
路由的作用域(global , link , host 等) |
scope link |
metric <value> |
路由优先级(数值越小,优先级越高) | metric 100 |
table <table> |
指定要操作的路由表(默认为main 表) |
table 100 |
3. 特殊路由类型
类型 | 命令示例 | 作用 |
---|---|---|
默认路由 | ip route add default via 192.168.1.1 dev eth0 |
所有未知目的地的流量都发往此网关 |
直连路由 | ip route add 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10 |
通常由系统自动添加,指向本地网络 |
黑洞路由 | ip route add blackhole 10.1.2.0/24 |
发往该网段的数据包将被无声丢弃 |
不可达路由 | ip route add unreachable 172.16.0.0/16 |
发往该网段的数据包将被丢弃,并返回ICMP不可达错误 |
iptables和ip route的联系
iptables和ip route 两者各司其职,紧密配合,共同完成Linux系统的网络数据包处理工作。
ip route
是“地图和导航软件”,负责告诉数据包“下一步该怎么走”。iptables
是“交警和检查站”,负责根据规则“拦截、检查、放行或改装”数据包。
特性 | iptables | ip route |
---|---|---|
核心功能 | 包过滤(Firewalling)、NAT、修改包内容 | 路由(Routing),决定数据包如何转发 |
工作层级 | 主要工作在网络层(L3)和传输层(L4),可扩展至应用层(L7) | 工作在网络层(L3) |
决策依据 | 规则(Rules):基于源/目标IP、端口、协议、连接状态等 | 路由表(Routing Table):基于目标IP地址的网络前缀 |
主要动作 | ACCEPT , DROP , REJECT , SNAT , DNAT |
将数据包发往某个下一跳(nexthop) 或出口设备 |
配置对象 | 数据包(Packet) 本身 | 路径(Path),即数据包的传输路线 |
联系与协作:
- 处理顺序:一个数据包进入系统后,先由
ip route
进行路由判断(决定是发给本机还是转发),然后才由iptables
的相应链(INPUT/FORWARD/OUTPUT)进行过滤或修改。
- PREROUTING (
iptables
nat, mangle) -> 路由决策 (ip route
) -> INPUT/FORWARD (iptables
) -> OUTPUT (iptables
) -> POSTROUTING (iptables
nat, mangle)
- 依赖关系:
iptables
的SNAT/MASQUERADE
动作通常在 POSTROUTING 链完成,依赖于ip route
已经决定好的出口网卡。iptables
的DNAT
动作在 PREROUTING 链完成,会改变数据包的目标IP,从而影响后续ip route
的路由决策。
- 协同工作示例:
- 一台Linux服务器作为网关:
ip route
负责告知内核:如何将数据包从一个网络转发到另一个网络(如ip route add 192.168.2.0/24 via 10.0.0.1
)。iptables
负责:在FORWARD
链中设置规则,允许或禁止特定的转发流量,并在POSTROUTING
链做MASQUERADE
伪装,实现私网访问公网。
实用命令示例对比
iptables
的核心是-A
(规则),-p --dport
(匹配),-j
(动作)。ip route
的核心是add
/del
(操作),via
(网关),dev
(接口)。
iptables 示例组合
保护服务器:只开放SSH, HTTP, HTTPS,并允许Ping。
iptables -P INPUT DROP # 默认拒绝 iptables -A INPUT -i lo -j ACCEPT # 允许本地回环 iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # 允许回包 iptables -A INPUT -p icmp -j ACCEPT # 允许ping iptables -A INPUT -p tcp --dport 22 -j ACCEPT # 允许SSH iptables -A INPUT -p tcp --dport 80 -j ACCEPT # 允许HTTP iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 允许HTTPS
实现端口转发:将公网IP的8080端口转发到内网Web服务器。
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80 iptables -t nat -A POSTROUTING -d 192.168.1.100 -p tcp --dport 80 -j SNAT --to-source 192.168.1.1
ip route 示例组合
添加静态路由:访问不同网络走不同网关。
# 去往 10.10.0.0/16 网络的流量,通过 192.168.1.200 网关走 ip route add 10.10.0.0/16 via 192.168.1.200 dev eth0 # 添加默认网关 ip route add default via 192.168.1.1 dev eth0
策略路由(高级):来自特定源IP的流量走另一条路。
# 1. 创建一条新的路由表(在 /etc/iproute2/rt_tables 中定义,例如编号200,名为my_table) # 2. 为此表添加默认路由 ip route add default via 10.0.0.1 table my_table # 3. 创建规则:如果数据包来自IP 192.168.1.50,就查询my_table表 ip rule add from 192.168.1.50 lookup my_table