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可以用来保护服务器本身,决定是否允许外部访问本机的服务。

比如:

  1. 只允许10.1.1.5通过22端口访问服务器
  2. 允许所有人访问web服务,开放80和443端口
  3. 拒绝所有来自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之前。 主要用于限制服务器自身的出站连接。

比如:

  1. 禁止这台机器连接外部的25端口
  2. 只允许访问apt仓库地址
  3. 只允许连接到某个数据库
# 语法: 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

| 访问量:
Table of Contents