Luckylau's Blog

Linux的iptables原理

​ 在Linux系统中,对于防火墙的实现一般分为包过滤防火墙,TCP-Wrapper即程序管控,代理服务器等几种方式。其中,iptables作为一种基于包过滤方式的防火墙工具,在实际中应用非常广泛,是非常重要的一个安全工具。真正实现防火墙功能的是 netfilter,它是一个 linux 内核模块,做实际的包过滤。实际上,除了 iptables 以外,还有很多类似的用户空间工具。

iptables的“链”与“表”

netfilter 使用表(table)和 链(chain)来组织网络包的处理规则(rule)。它默认定义了以下表和链:

表功能 链功能
raw PREROUTING OUTPUT RAW 拥有最高的优先级,它使用PREROUTING和OUTPUT两个链,因此 RAW 可以覆盖所有包。在raw表中支持一个特殊的目标:TRACE,使内核记录下每条匹配该包的对应iptables规则信息。使用raw表内的TRACE target 即可实现对iptables规则的跟踪调试。比如:# iptables -t raw -A OUTPUT -p icmp -j TRACE # ipt ables -t raw -A PREROUTING -p icmp -j TRACE
Filter 包过滤 FORWARD 过滤目的地址和源地址都不是本机的包
INPUT 过滤目的地址是本机的包
OUTPUT 过滤源地址是本机的包
Nat 网络地址转换 PREROUTING 在路由前做地址转换,使得目的地址能够匹配上防火墙的路由表,常用于转换目的地址。
POSTROUTING 在路由后做地址转换。这意味着不需要在路由前修改目的地址。常用于转换源地址。
OUTPUT 对防火墙产生的包做地址转换(很少量地用于 SOHO 环境中)
Mangle TCP 头修改 PREROUTING POSTROUTING OUTPUT INPUT FORWARD 在路由器修改 TCP 包的 QoS(很少量地用在 SOHO 环境中)

先是透过路由判断, 决定了输出的路径后,再透过 filter 的 OUTPUT 链来传送的, mangle 这个表格很少被使用,如果将上图的mangle 拿掉的话,那就容易看的多了:

如果你的防火墙事实上是用来管制 LAN 内的其他主机的话,那么你就必须要再针对 filter 的 FORWARD 这条链,还有 nat 的 PREROUTING, POSTROUTING 以及 OUTPUT 进行额外的规则订定才行。

iptables实现SNAT与DNAT

NAT 服务器的重点就在于上面流程NAT table 的两条重要的链:PREROUTING 与 POSTROUTING。

举例如下:

SNAT封包传送和封包接收

​ 客户端所发出的封包表头中,来源会是 192.168.1.100 ,然后传送到 NAT 这部主机;NAT 这部主机的内部接口 (192.168.1.2) 接收到这个封包后,会主动分析表头数据, 因为表头数据显示目的并非 Linux 本机,所以开始经过路由, 将此封包转到可以连接到 Internet 的 Public IP 处;由于 private IP 与 public IP 不能互通,所以 Linux 主机透过 iptables 的 NAT table 内的 Postrouting 链将封包表头的来源伪装成为 Linux 的 Public IP ,并且将两个不同来源 (192.168.1.100 及 public IP) 的封包对应写入暂存内存当中, 然后将此封包传送出去了;
​ 此时 Internet 上面看到这个封包时,都只会知道这个封包来自那个 Public IP 而不知道其实是来自内部啦。 好了,那么如果 Internet 回传封包呢?又会怎么作?

​ 在 Internet 上面的主机接到这个封包时,会将响应数据传送给那个 Public IP 的主机;当 Linux NAT 服务器收到来自 Internet 的回应封包后,会分析该封包的序号,并比对刚刚记录到内存当中的数据, 由于发现该封包为后端主机之前传送出去的,因此在 NAT Prerouting 链中,会将目标 IP 修改成为后端主机,亦即那部 192.168.1.100,然后发现目标已经不是本机 (public IP), 所以开始透过路由分析封包流向;封包会传送到 192.168.1.2 这个内部接口,然后再传送到最终目标 192.168.1.100 机器上去!

SNAT 主要是应付内部 LAN 连接到 Internet 的使用方式,至于 DNAT 则主要用在内部主机想要架设可以让 Internet 存取的服务器啦!

DNAT封包传送

​ 假设我的内部主机 192.168.1.210 启动了 WWW 服务,这个服务的 port 开启在 port 80 , 那么 Internet 上面的主机 (61.xx.xx.xx) 要如何连接到我的内部服务器呢?当然啦, 还是得要透过 Linux NAT 服务器嘛!所以这部 Internet 上面的机器必须要连接到我们的 NAT 的 public IP 才行。外部主机想要连接到目的端的 WWW 服务,则必须要连接到我们的 NAT 服务器上头;我们的 NAT 服务器已经设定好要分析出 port 80 的封包,所以当 NAT 服务器接到这个封包后, 会将目标 IP 由 public IP 改成 192.168.1.210 ,且将该封包相关信息记录下来,等待内部服务器的响应;上述的封包在经过路由后,来到 private 接口处,然后透过内部的 LAN 传送到 192.168.1.210 上头!

​ 192.186.1.210 会响应数据给 61.xx.xx.xx ,这个回应当然会传送到 192.168.1.2 上头去;经过路由判断后,来到 NAT Postrouting 的链,然后透过刚刚的记录,将来源 IP 由 192.168.1.210 改为 public IP 后,就可以传送出去了!

iptables常用命令

注释:

  1. 如果想查看特别的表时使用-t指定,如果查看单独的链需要在操作后面指定.
  2. 如果是查看规则定义,使用-S. -S-L查看规则时更加清晰.
  3. 如果查看匹配状况使用-nvL.配合watch使用.
  4. --line-number用于查看规则号.

iptables [-t tables][-L] [-nv]

选项与参数:

-t :后面接 table ,例如 nat 或 filter ,若省略此项目,则使用默认的 filter

-L :列出目前的 table 的规则

-n :不进行 IP 与 HOSTNAME 的反查,显示讯息的速度会快很多!

-v :列出更多的信息,包括通过该规则的封包总位数、相关的网络接口等

iptables-save [-t table] (列出完整的防火墙规则)

选项与参数:

-t :可以仅针对某些表格来输出,例如仅针对 nat 或 filter 等等

​ 这个命令主要是把内存态的规则保存到文件,然后下次启动的时候用iptables-restore来载入规则. 但是这个命令常常用来查看防火墙规则。比iptables用得都多, 主要是输出结果的格式比较紧凑直观.而且能方便的能看到所有表的规则.

iptables [-t tables][-FXZ]

选项与参数:
-F :清除所有的已订定的规则;
-X :杀掉所有使用者 “自定义” 的 chain (应该说的是 tables )啰;
-Z :将所有的 chain 的计数与流量统计都归零

iptables命令举例

清空当前的所有规则和计数

1
2
3
iptables -F #清空所有的防火墙规则
iptables -X #删除用户自定义的空链
iptables -Z #清空计数

配置允许ssh端口连接

1
2
iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT
#22为你的ssh端口, -s 192.168.1.0/24表示允许这个网段的机器来连接,其它网段的ip地址是登陆不了你的机器的。 -j ACCEPT表示接受这样的请求

允许本地回环地址可以正常使用

1
2
3
iptables -A INPUT -i lo -j ACCEPT
#本地圆环地址就是那个127.0.0.1,是本机上使用的,它进与出都设置为允许
iptables -A OUTPUT -o lo -j ACCEPT

设置默认的规则

1
2
3
iptables -P INPUT DROP #配置默认的不让进
iptables -P FORWARD DROP #默认的不允许转发
iptables -P OUTPUT ACCEPT #默认的可以出去

一些例子

1
2
3
4
5
6
7
8
9
iptables -A INPUT -s 10.10.10.10 -j DROP #丢弃从 10.10.10.10 主机来的所有包
iptables -A INPUT -s 10.10.10.0/24 -j DROP #丢弃从 10.10.10.0/24 网段进来所有包
iptables -A INPUT -p tcp --dport ssh -s 10.10.10.10 -j DROP # 如果协议是 tcp,目标端口是 ssh 端口,源IP 为 10.10.10.10,那么丢弃它
iptables -A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT #接受从 virbr0 进来的所有目标端口 53 的 udp 包
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT #接受 RELEASED 和 ESTABLISHED 状态的连接。Linux 3.7 以后,--state 被替换成了 --conntrack
iptables -A FORWARD -d 192.168.122.0/24 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT #转发时接受这些包
iptables -A FORWARD -p icmp -j ACCEPT #转发时接受所有 ICMP 路由包。
iptables -A INPUT -i lo -j ACCEPT #使用 -i 过滤从 lo 设备进来的包
iptables -A INPUT -i eth0 -j ACCEPT #使用 -i 过滤从网卡 eth0 进来的包。不指定网卡的话表示所有网卡。

iptables的常见问题

1.你听说过Linux下面的iptables和Firewalld么?知不知道它们是什么,是用来干什么的?

​ iptables通常被用作类UNIX系统中的防火墙,更准确的说,可以称为iptables/netfilter。管理员通过终端/GUI工具与iptables打交道,来添加和定义防火墙规则到预定义的表中。Netfilter是内核中的一个模块,它执行包过滤的任务。

​ Firewalld是RHEL/CentOS 7中最新的过滤规则的实现。它已经取代了iptables接口,并与netfilter相连接。

2.请在iptables中添加一条规则,接受所有从一个信任的IP地址(例如,192.168.0.7)过来的包。

​ iptables -A INPUT -s 192.168.0.7 -j ACCEPT

3.假如有一台电脑的本地IP地址是192.168.0.6。你需要封锁在21、22、23和80号端口上的连接,你会怎么做?

​ iptables -A INPUT -s 192.168.0.6 -p tcp -m multiport –dport 22,23,80,8080 -j DROP

参考:

http://fishcried.com/2016-02-19/iptables/

http://cn.linux.vbird.org/linux_server/0250simple_firewall_3.php

https://linux.cn/article-5948-1.html#3_10137

Luckylau wechat
如果对您有价值,看官可以打赏的!