Iptables学习笔记
背景
KVM安装了虚拟机通过NAT方式访问外放,但是端口映射一直不成功,可能是iptables哪里配置有问题。
起因
在CentOS学习KVM笔记-网络篇的时候需要映射虚拟机端口,按照网上的iptables介绍的端口映射规则,加了这三条规则,但是没有效果。
1 | iptables -A INPUT -p tcp --dport 10122 -j ACCEPT |
iptables介绍
iptables概念
按照正常的理解上,iptables是个防火墙,跟windows里面的防火墙规则类似。其实iptables不是真正的防火墙,我们可以理解成一个客户端代理工具,用户通过iptables这个代理,将用户的安全设定执行到对应的安全框架中,这个安全框架”才是直正的防火墙,这个框架的名字叫 netfilter。
netfilter才是防火墙真正的安全框架( framework), netfilter位于内核空间。
iptables其实是个命令行工具,位于用户空间,我们用这个工具操作真正的框架。
netfilter/ iptables(下文中简称为 iptables)组成 Linux平台下的包过滤防火墙,与大多数的 Linux软件一样,这个包过滤防火墙是兔费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤、封包重定向和网络地址转换(NAT)等功能。
Netfilter是 Linux操作系统核心层内部的—一个数据包处理模块,它具有如下功能:
网络地址转换( Network Address Translate)
数据包内容修改以及数据包过滤的防火墙功能。所以说,虽然我们使用 service iptables start启动 iptables”服务”,但是其实准确的来说, iptables并没有一个守护进程,所以并不能算是真正意义上的服务,而应该算是内核提供的功能。
iptables原理
我们知道iptables是按照规则来办事的,我们就来说说规则(rules),规则其实就是网络管理员预定义的条件,规则一般的定义为”如果数据包头符合这样的条件,就这样处理这个数据包”。规则存储在内核空间的信息包过滤表中,这些规则分别指定了源地址、目的地址、传输协议(如TCP、UDP、|CMP)和服务类型(如HTP、FP和SMTP)等。
数据包与规则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如放行(accept)、拒绝(reject))和丢弃(drop)等。配置防火墙的主要工作就是添加、修改和删除这些规则。
这样说可能并不容易理解,我们来换个容易理解的角度,从头说起
当客户端访问服务器的web服务时,客户端发送报文到网卡,而tcp/ip协议栈是属于内核的一部分,所以,客户端的信息会通过内核的TCP协议传输到用户空间中的web服务中,而此时,客户端报文的目标终点为web服务所监听的套接字(P:Por)上,当web服务需要响应客户端请求时,web服务发出的响应报文的目标终点则为客户端,这个时候,web服务所监听的P与端囗反而变成了原点,我们说过, netfilter 才是真正的防火墙,它是内核的部分,所以,如果我们想要防火墙能够达到”防火”的目的,则需要在内核中设置关卡,所有进出的报文都要通过这些关卡,经过检查后,符合放行条件的才能放行,符合阻拦条件的则需要被阻止,于是,就出现了input关卡和 output关卡,而这些关卡在 iptables中不被称为关卡”而被称为链”。
其实我们上面描述的场景并不完善,因为客户端发来的报文访问的目标地址可能并不是本机,而是其他服务器,当本机的内核支持 IP FORWARD时,我们可以将报文转发给其他服务器,所以,这个时候,我们就会提到 iptables中的其他”关卡,也就是其他链”,他们就是”路由前”、“转发”、”路由后”,他们的英文名是PREROUTING、FORWARD、POSTROUTING也就是说,当我们启用了防火墙功能时,报文需要经过如下关卡,也就是说,根据实际情况的不同,报文经过链可能不同。如果报文需要转发,那么报文则不会经过Input链发往用户空间,而是直接在内核空间中经过forward链和postrouting链转发出去的。
iptables基础
iptables结构
iptables的结构:iptables -> Tables -> Chains -> Rules. 简单地讲,tables由chains组成,而chains又由rules组成。如下图所示。
iptables表与链
iptables具有Filter,Nat,Mangle,Raw四种内建表:
Filter表
Filter表示iptables的默认表,因此如果你没有自定义表,那么就默认使用filter表,它具有以下三种内建链:
- INPUT
- 处理来自外部的数据。
- OUTPUT
- 处理向外发送的数据。
- FORWARD
- 将数据转发到本机的其他网卡设备上。
Nat表
NAT表有三种内建链:
- PREROUTING
- 处理刚到达本机并在路由转发前的数据包。它会转换数据包中的目标IP地址(destination ip address),通常用于DNAT(destination NAT)。
- POSTROUTING
- 处理即将离开本机的数据包。它会转换数据包中的源IP地址(source ip address),通常用于SNAT(source NAT)。
- OUTPUT
- 处理本机产生的数据包。
Mangle表
Mangle表用于指定如何处理数据包。它能改变TCP头中的QoS位。Mangle表具有5个内建链:
- PREROUTING
- OUTPUT
- FORWARD
- INPUT
- POSTROUTING
Raw表
Raw表用于处理异常、状态跟踪,它具有2个内建链:
- PREROUTING
- OUTPUT
下图展示了iptables的三个内建表:
iptables规则
规则(Rules)注意点
- Rules包括一个条件和一个目标(target)
- 如果满足条件,就执行目标(target)中的规则或者特定值。
- 如果不满足条件,就判断下一条Rules。
目标值(Target Values)
- ACCEPT
- 允许防火墙接收数据包
- DROP
- 防火墙丢弃包
- QUEUE
- 防火墙将数据包移交到用户空间
- RETURN
- 防火墙停止执行当前链中的后续Rules,并返回到调用链(the calling chain)中。
iptables操作
选择iptables表
语法
iptables -t table
-t
- 选择表,有效值:filter,mangle,raw,nat- 不加这个参数默认选择filter,
查看filter表:
注意:如果不指定 -t选项,就只会显示默认的 filter表。因此,以下两种命令形式是一个意思:iptables -t filter --list
或者iptables --list
查看mangle表:
iptables -t mangle --list
查看nat表:
iptables -t nat --list
查看raw表:
iptables -t raw --list
查看iptables规则
- 语法
iptables -nvL chain
-n
- 显示ip-v
- 显示流量信息--line-number
- 显示序号
显示列说明:
- pkts : 对应规则匹配到的报文的个数。
- bytes : 对应匹配到的报文包的大小总和。
- in : 表示数据包由哪个接口(网卡)流入,我们可以设置通过哪块网卡流入的报文需要匹配当前规则。
- target : 规则对应的target,往往表示规则对应的”动作”,即规则匹配成功后需要采取的措施。
- prot : 表示规则对应的协议,是否只针对某些协议应用此规则。
- opt : 表示规则对应的选项。
- out : 表示数据包由哪个接口(网卡)流出,我们可以设置通过哪块网卡流出的报文需要匹配当前规则。
- source : 表示规则对应的源头地址,可以是一个IP,也可以是一个网段。
- destination : 表示规则对应的目标地址。可以是一个IP,也可以是一个网段。
1 | [root@chobon ~]# iptables –list |
以上输出包含下列字段:
- num – 指定链中的规则编号
- target – 前面提到的target的特殊值
- prot – 协议:tcp, udp, icmp等
- source – 数据包的源IP地址
- destination – 数据包的目标IP地址
清空itables规则
- 语法
iptables -F(--flush) chain
chain
- 指定要追加规则的链
在配置iptables之前,你通常需要用iptables –list命令或者iptables-save命令查看有无现存规则,因为有时需要删除现有的iptables规则:iptables -flush
或者iptables -F
这两条命令是等效的。但是并非执行后就万事大吉了。你仍然需要检查规则是不是真的清空了,因为有的linux发行版上这个命令不会清除NAT表中的规则,此时只能手动清除:iptables -t NAT -F
增加iptables规则
可以用 iptables -A
命令追加新规则,其中-A表示Append。因此,新的规则将追加到链尾。
一般而言,最后一条规则用于丢弃(DROP)所有数据包。如果你已经有这样的规则了,并且使用 -A参数添加新规则,那么就是无用功。
追加规则(-A,–append)
- 语法
iptables -A chain firewall-rule
chain
- 指定要追加规则的链firewall-rule
– 具体的规则参数
插入规则(-I,–insert)
- 语法
iptables -I chain [rule-num] firewall-rule
chain
- 指定要追加规则的链[rule-num]
- 可选插入的序号firewall-rule
– 具体的规则参数
删除iptables规则
删除规则有两种方法:
方法一:根据规则的编号去删除规则
方法二:根据具体的匹配条件与动作删除规则
语法
iptables -D chain rule-num
或者firewall-rule
chain
- 指定要删除规则的链rule-num
- 规则的序号firewall-rule
- 具体的规则参数
先查看一下filter表中INPUT链中的规则
1 | [root@chobon ~]# iptables --line -nvL INPUT |
结果出来是带num
序号的,假如我们想删第1条。
1 | [root@chobon ~]# iptables -t filter -D INPUT 1 |
根据具体的匹配条件与动作去删除规则,比如-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
1 | [root@chobon ~]# iptables -t filter -D INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT |
修改iptables规则
修改规则(-R,–replace)
- 语法
iptables -R chain rule-num firewall-rule
chain
- 指定要修改规则的链rule-num
- 规则的序号firewall-rule
- 具体的规则参数
先查看一下filter表中INPUT链中的规则
1 | [root@chobon ~]# iptables --line -nvL INPUT |
如果要将第1条规则的动作修改为REJECT,-s和-d缺省的话会默认0.0.0.0/0
,其他参数不指定的话也会改成默认值。
1 | [root@chobon ~]# iptables -R INPUT 1 -i virbr0 -p udp -m udp --dport 53 -j REJECT |
修改规则链(-P,–policy)
- 语法
iptables -P chain target
chain
- 指定要修改规则的链target
- 指定默认处理动作,DROP和ACCEPT
每张表的每条链中,都有自己的默认策略,我们也可以理解为默认”动作”。
1 | [root@chobon ~]# iptables -P INPUT DROP |
规则基本参数
-p
| 协议(protocol)- 指定规则的协议,如tcp, udp, icmp等,可以使用all来指定所有协议。
- 如果不指定-p参数,则默认是all值。这并不明智,请总是明确指定协议名称。
- 可以使用协议名(如tcp),或者是协议值(比如6代表tcp)来指定协议。映射关系请查看/etc/protocols
- 还可以使用–protocol参数代替-p参数
-s
| 源地址- 指定数据包的源地址
- 参数可以使IP地址、网络地址、主机名
- 例如:-s 192.168.1.101指定IP地址
- 例如:-s 192.168.1.10/24指定网络地址
- 如果不指定-s参数,就代表所有地址
- 还可以使用–src或者–source
-d
| 目的地址(destination)- 指定目的地址
- 参数和-s相同
- 还可以使用–dst或者–destination
-j
| 执行目标(jump to target)- -j代表 “jump to target”
- -j指定了当与规则(Rule)匹配时如何处理数据包
- 可能的值是 ACCEPT, DROP, QUEUE, RETURN, MASQUERADE
- 还可以指定其他链(Chain)作为目标
- 注:MASQUERADE,地址伪装,算是snat中的一种特例,可以实现自动化的snat
-i
| 输入接口(input interface)- -i代表输入接口(input interface)
- -i指定了要处理来自哪个接口的数据包
- 这些数据包即将进入INPUT, FORWARD, PREROUTE链
- 例如:-i eth0指定了要处理经由eth0进入的数据包
- 如果不指定-i参数,那么将处理进入所有接口的数据包
- 如果出现! -i eth0,那么将处理所有经由eth0以外的接口进入的数据包
- 如果出现-i eth+,那么将处理所有经由eth开头的接口进入的数据包
- 还可以使用–in-interface参数
-o
| 输出(out interface)- -o代表 “output interface”
- -o指定了数据包由哪个接口输出
- 这些数据包即将进入FORWARD, OUTPUT, POSTROUTING链
- 如果不指定-o选项,那么系统上的所有接口都可以作为输出接口
- 如果出现! -o eth0,那么将从eth0以外的接口输出
- 如果出现-i eth+,那么将仅从eth开头的接口输出
- 还可以使用–out-interface参数
-m
| 匹配模块(match)- -m表示指定的模块
- 与前面-p选项对应的协议名称相同的模块可以忽略
描述规则的扩展参数
对规则有了一个基本描述之后,有时候我们还希望指定端口、TCP标志、ICMP类型等内容。
–sport
| 源端口(source port)- 针对 -p tcp 或者 -p udp
- 缺省情况下,将匹配所有端口
- 可以指定端口号或者端口名称,例如 “–sport 22” 与 “–sport ssh” 。
- /etc/services文件描述了上述映射关系。
- 从性能上讲,使用端口号更好
- 使用冒号可以匹配端口范围,如 “–sport 22:100”
- 还可以使用 “–source-port”
–-dport
| 目的端口(destination port)- 针对-p tcp 或者 -p udp
- 参数和–sport类似
- 还可以使用 “–destination-port”
-–tcp-flags
| TCP标志- 针对-p tcp
- 可以指定由逗号分隔的多个参数
- 有效值可以是:SYN, ACK, FIN, RST, URG, PSH
- 可以使用ALL或者NONE
-–icmp-type
| ICMP类型- 针对-p icmp
- –icmp-type 0 表示Echo Reply
- –icmp-type 8 表示Echo
--state
| STATE状态- 针对state
- 链接报文状态
- 有五种状态:
- NEW: 连接的第一包
- ESTABLISHED:NEW状态包后面的包状态理解,表示连接已建立
- RELATED:数据进程连接–数据连接<如FTP中的数据连接>
- INVALID:包没有办法被识别,或者空上包没有任何状态,可以主动屏蔽INVALID的报文
- UNTRACKED:未被追踪的报文 ,当报文的状态为Untracked时通常表示无法找到相关的连接
创建自定义链
语法
iptables -t table -N new-chain
new-chain
- 新增自定义链名
在mangle表增加一条名叫NEW_CHAIN的自定义链:
iptables -t mangle -N NEW_CHAIN
引用链
语法
iptables -t table firewall-rule new-chain
firewall-rule
– 具体的规则参数new-chain
- 需要引用的链
在filter表增加一条规则target引用叫NEW_CHAIN的自定义链:
iptables -t filter -I INPUT -p tcp --dport 80 -j NEW_CHAIN
重命名链
语法
iptables -t table -E old-chain new-chain
old-chain
– 需要被重命名的链new-chain
- 重命名后的链
在filter表重命名一条名叫NEW_CHAIN的自定义链为NEW_PREROUTING_CHAIN:
iptables -t filter -E NEW_CHAIN NEW_PREROUTING_CHAIN
删除链
语法
iptables -t table -X chain
chain
– 需要被删除的链
在filter表删除一条名叫NEW_CHAIN的自定义链:
iptables -t filter -X NEW_CHAIN
永久生效
当你删除、添加规则后,这些更改并不能永久生效,这些规则很有可能在系统重启后恢复原样。为了让配置永久生效,根据平台的不同,具体操作也不同。下面进行简单介绍:
Ubuntu
首先,保存现有的规则:iptables-save > /etc/iptables.rules
然后新建一个bash
脚本,并保存到/etc/network/if-pre-up.d/
目录下:1
2
iptables-restore < /etc/iptables.rules这样,每次系统重启后iptables规则都会被自动加载。
!注意:不要尝试在.bashrc或者.profile中执行以上命令,因为用户通常不是root,而且这只能在登录时加载iptables规则。CentOS, RedHat
保存iptables规则
service iptables save
重启iptables服务
service iptables stop
service iptables start
查看当前规则:
cat /etc/sysconfig/iptables
学习总结
刚开始觉得挺复杂,深入后发现没那么难,一切都是按照规则来,有迹可循,只要掌握关键要领就可以按图索骥。
回顾到开头那三条规则,其实是正确的,只是KVM初始得虚拟网卡virbr0有条默认规则做了限制
iptables查看filter表FORWARD链,有条规则里面没有包含NEW,由于ssh请求第一个包是NEW,所以如果不加上,就连不上。
1 | [root@chobon ~]# iptables -nvL FORWARD |
注意:这里后面两条规则REJECT
顺序,如果在前面就得删除或者把ACCEPT
移到前面
1 | [root@chobon ~]# iptables -R FORWARD 2 -o virbr0 -d 192.168.122.0/24 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT |
注意:-m state –state和-m conntrack –ctstate差不多,有些地方说一样的,有些地方说state是被conntrack代替了
现在就可以通过ssh -p 10122 [email protected]
命令来连接虚拟机了。