iptables的一些常见应用场景
iptables有两种类型,一种是nat,一种是filter。
filter表是默认表,负责过滤,决定数据包是允许,拒绝还是丢弃。它包含的链是input,forward和output。
nat表负责地址转换,功能是修改数据包的源或者目的地址和端口。 包含的链是prerouting,postrouting,output
prerouting
数据包刚进入网络接口,在内核进行任何路由决策前,将目的地址进行转化,也就是常说的端口转发
例如: 内网的机器地址是192.168.1.100的8080端口,然后还有一台公网地址为123.123.123.123的服务器。 你希望让所有访问123.123.123.123:80的流量都转发给内网的192.168.1.100:8080. 那么可以在公网服务器上这样设置,假设eth0是它的公网网卡:
# 语法: iptables -t nat -A PREROUTING -i [入站网卡] -p [协议] --dport [外部端口] -j DNAT --to-destination [目标IP:端口]
# 示例: 将从 eth0 进来的 80 端口流量转发到 192.168.1.100 的 8080 端口
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:8080
input
数据包经过prerouting和路由决策后,系统确认这个包的最终目的地址是本机的某个进程(比如ssh服务,web服务,数据库服务等)
input可以用来保护服务器本身,决定是否允许外部访问本机的服务。
比如:
- 只允许10.1.1.5通过22端口访问服务器
- 允许所有人访问web服务,开放80和443端口
- 拒绝所有来自5.6.7.8的连接
# 示例A: 只允许 10.1.1.5 访问 22 端口
iptables -A INPUT -p tcp --dport 22 -s 10.1.1.5 -j ACCEPT
# 示例B: 允许 80 和 443 端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 示例C: 拒绝恶意 IP
iptables -A INPUT -s 5.6.7.8 -j DROP
# 最佳实践: 默认拒绝所有, 再逐个放行 (首先设置默认策略)
iptables -P INPUT DROP
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 允许已建立的连接
iptables -A INPUT -i lo -j ACCEPT
# 允许本地回环
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # 允许 SSH
forward
数据包经过prerouting和路由决策后,系统发现这个包的目的地不是本机,而是需要转发到另一个网络接口。
一般是将linux服务器用作路由器或者网关,并作为网络的防火墙使用的时候经常用到。
场景:
一台linux机器有2块网卡,eth0连接外网,eth1连接内网。 你希望内网机器可以访问互联网,但是互联网的人不能访问内网。
要注意的是input是无效的,因为数据包的目的地不是linux服务器本身。
# 语法: iptables -A FORWARD [匹配条件] -j [动作]
# 示例: 允许内网(eth1)访问外网(eth0)
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
# 示例: 只允许外网(eth0)访问内网(eth1)的已建立连接(即内网发起的连接的返回包)
iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT
# 最佳实践: 默认拒绝所有转发
iptables -P FORWARD DROP
postrouting
数据包即将离开本机网络接口之前,这个是在output或者forward之后。
主要用于源地址转换snat,也就是ip伪装
场景:
内网192.168.1.0/24通过eth1连接到linux的路由器机器。然后内网有一台机器192.168.1.50需要访问互联网。但是这个地址是私有地址,互联网上的机器无法将数据包送回到这个地址。因此当数据包离开linux路由器的eth0公网网卡时候,postrouting会将源地址192.168.1.50替换为linux路由器的公网地址123.123.123.123. 当外部服务器响应时,它发送数据给123.123.123.123,然后linux接受后再将数据包发给192.168.1.50这台内网机器。
# 语法: iptables -t nat -A POSTROUTING -o [出站网卡] -s [源地址段] -j [动作]
# 示例 (IP 伪装, 适用于公网 IP 是动态的, 如ADSL/DHCP):
# 将所有从 eth1 来的包 (源地址为 192.168.1.0/24), 在从 eth0 出去时, 进行 IP 伪装
iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -j MASQUERADE
# 示例 (SNAT, 适用于公网 IP 是固定的):
iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -j SNAT --to-source 123.123.123.123
output
数据包由本机进程产生的,在它被路由到postrouting之前。 主要用于限制服务器自身的出站连接。
比如:
- 禁止这台机器连接外部的25端口
- 只允许访问apt仓库地址
- 只允许连接到某个数据库
# 语法: iptables -A OUTPUT [匹配条件] -j [动作]
# 示例A: 禁止本机发送邮件
iptables -A OUTPUT -p tcp --dport 25 -j DROP
# 示例B: 只允许访问特定 IP
iptables -P OUTPUT DROP # 默认禁止所有
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许返回包
iptables -A OUTPUT -o lo -j ACCEPT # 允许本地回环
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT # 允许 DNS
iptables -A OUTPUT -d 172.217.160.110 -j ACCEPT # 假设这是 apt 仓库 IP
# 示例C: 禁止访问生产数据库
iptables -A OUTPUT -d 198.51.100.10 -j DROP # 生产 DB
简单来说,分为两个场景:
场景1: 数据包从internet到内部网络的过程如下:
公网接口->prerouting(DNAT)->路由->(如果是本地,则input。如果是要转发到其他接口,则用forward)->如果是forward,则下面可以用postrouting进行源地址伪装
场景2: 数据包从内网到internet
本地应用->output->postrouting(源地址转换)->公网接口->internet