linux 内核通过 netfilter 模块实现网络访问控制功能,在用户层我们可以通过iptables程序对netfilter进行控制管理。
使用 iptables
命令创建一条规则,一般规则包含以下几个部门:
iptables 【表】【链】【匹配属性】【动作】
iptables -t filter【表】 -A INPUT【链】 -s 192.168.1.1【匹配属性】 -j DROP【动作】
raw:高级功能,如:网址过滤。
mangle:数据包修改(QOS),用于实现服务质量。
nat:地址转换,用于网关路由器。
filter:包过滤,用于防火墙规则。
INPUT链:处理输入数据包。
OUTPUT链:处理输出数据包。
PORWARD链:处理转发数据包。
PREROUTING链:用于目标地址转换(DNAT)。
POSTOUTING链:用于源地址转换(SNAT)。
-s 192.168.1.1
)-d 10.0.0.0/8
)-i eth0
、-o eth1
)-s '!' 192.168.1.0/24
所有不来自192.168.1.0/24的ip)-p tcp --dport 23
、 -p udp --sport 53
、 -p icmp
)ACCEPT:接收数据包。
DROP:丢弃数据包。
REDIRECT:重定向、映射、透明代理。
SNAT:源地址转换。
DNAT:目标地址转换。
MASQUERADE:IP伪装(NAT),用于ADSL。
LOG:日志记录。
-t<表>:指定要操纵的表;
-A:向规则链中添加条目;
-D:从规则链中删除条目;
-I:向规则链中插入条目;
-R:替换规则链中的条目;
-L:显示规则链中已有的条目;
-F:清楚规则链中已有的条目;
-Z:清空规则链中的数据包计算器和字节计数器;
-N:创建新的用户自定义规则链;
-P:定义规则链中的默认目标;
-h:显示帮助信息;
-p:指定要匹配的数据包协议类型;
-s:指定要匹配的数据包源ip地址;
-j<目标>:指定要跳转的目标;
-i<网络接口>:指定数据包进入本机的网络接口;
-o<网络接口>:指定数据包要离开本机所使用的网络接口。
iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作
列出现有iptables规则
iptables -L
(iptables规则中默认表名是filter,iptables -L
相当于只是iptables -t filter -L
,想列nat表中规则,则应iptables -t nat -L
。其他命令也是一样的,如不指定表名,默认表名是filter)
插入一个规则
iptables -I INPUT 3 -p tcp --dport 22 -j ACCEPT
(插入到第三个)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
删除一个规则
iptables -D INPUT 3
(删掉第三个)
iptables -D INPUT -p tcp --dport 22 -j ACCEPT
删除所有规则
iptables -F
iptables -A INPUT -s 192.168.1.100 -j DROP
(丢弃来自ip为192.168.1.100的流量)
iptables -A INPUT -p tcp --dport 80 -j DROP
(丢弃访问本机网页服务80端口的流量)
iptables -A INPUT -s 123.45.0.0/16 -p tcp --dport 22 -j DROP
(丢弃来自ip 123.45.0.1至123.45.255.254 的ssh连接)
iptables -A INPUT -s 123.45.0.0/16 -p tcp --dport 22 -j DROP
(丢弃来自ip 123.45.0.1至123.45.255.254 的ssh连接)
如:
iptables -A FORWARD -s 192.168.1.0/24 -d 10.1.1.0/24 -j DROP
(禁止192.168.0.1192.168.0.254到10.1.1.110.1.1.254的流量)
iptables中实现NAT功能的是NAT表
通过NAT进行跳转:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-dest 192.168.1.10
通过NAT对出向数据进行跳转:
iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-dest 192.168.1.100
通过NAT对数据流进行伪装:(一般意思上的NAT,将内部地址全部伪装成一个外部公网ip地址)
iptables -t nat -A POSTROUTING -o ech0 -j MASQUERADE
通过NAT隐藏源IP地址:
iptables -t nat -A POSTROUTING -j SNAT --to-source 1.2.3.4
通过iptables命令添加的规则不会永久保存,只存在内存,重启失效。如果需要永久保存规则,则需要将规则保存在 /etc/sysconfig/iptables
配置文件中
通过以下命令将iptables规则写入配置文件
service iptables save
或者 iptables-save > /etc/sysconfig/iptables
保存现有的规则到指定文件,主要是配合iptables-restore命令,iptables-restore命令用来还原iptables-save命令所备份的iptables配置。
iptables-save > iptables.bak
iptables-restor < iptables.bak
参照: http://man.linuxde.net/iptables
底层的原理往下阅读
在内核协议栈中,有5个跟netfilter有关的钩子,数据包经过每个钩子时,都会检查上面是否注册有函数,如果有的话,就会调用相应的函数处理该数据包。流程:
|
| Incoming
↓
+-------------------+
| NF_IP_PRE_ROUTING |
+-------------------+
|
|
↓
+------------------+
| | +----------------+
| routing decision |-------->| NF_IP_LOCAL_IN |
| | +----------------+
+------------------+ |
| |
| ↓
| +-----------------+
| | local processes |
| +-----------------+
| |
| |
↓ ↓
+---------------+ +-----------------+
| NF_IP_FORWARD | | NF_IP_LOCAL_OUT |
+---------------+ +-----------------+
| |
| |
↓ |
+------------------+ |
| | |
| routing decision |<----------------+
| |
+------------------+
|
|
↓
+--------------------+
| NF_IP_POST_ROUTING |
+--------------------+
|
| Outgoing
↓
从上面的流程中,可看出,不考虑特殊情况的话,一个数据包只会经过下面三个路径中的一个:
iptables用表(table)来分类管理它的规则(rule),根据rule的作用分成了好几个表,比如用来过滤数据包的rule就会放到filter表中,用于处理地址转换的rule就会放到nat表中,其中rule就是应用在netfilter钩子上的函数,用来修改数据包的内容或过滤数据包。目前iptables支持的表有下面这些:
从名字就可以看出,这个表里面的rule主要用来过滤数据,用来控制让哪些数据可以通过,哪些数据不能通过,它是最常用的表。
里面的rule都是用来处理网络地址转换的,控制要不要进行地址转换,以及怎样修改源地址或目的地址,从而影响数据包的路由,达到连通的目的,这是家用路由器必备的功能。
里面的rule主要用来修改IP数据包头,比如修改TTL值,同时也用于给数据包添加一些标记,从而便于后续其它模块对数据包进行处理(这里的添加标记是指往内核skb结构中添加标记,而不是往真正的IP数据包上加东西)。
在netfilter里面有一个叫做connection tracking的功能(后面会介绍到),主要用来追踪所有的连接,而raw表里的rule的功能是给数据包打标记,从而控制哪些数据包不被connection tracking所追踪。
里面的rule跟SELinux有关,主要是在数据包上设置一些SELinux的标记,便于跟SELinux相关的模块来处理该数据包。
上面我们根据不同功能将rule放到了不同的表里面之后,这些rule会注册到哪些钩子上呢?于是iptables将表中的rule继续分类,让rule属于不同的链(chain),由chain来决定什么时候触发chain上的这些rule。
iptables里面有5个内置的chains,分别对应5个钩子:
netfilter的钩子(hooks) | iptables的链(chains) |
---|---|
NF_IP_PRE_ROUTING | PREROUTING |
NF_IP_LOCAL_IN | INPUT |
NF_IP_FORWARD | FORWARD |
NF_IP_LOCAL_OUT | OUTPUT |
NF_IP_POST_ROUTING | POSTROUTING |
每个表里面都可以包含多个chains,但并不是每个表都能包含所有的chains,因为某些表在某些chain上没有意义或者有些多余。多个表里面可以包含同样的chain,会涉及到优先级的问题。
netfilter的钩子(hooks) | iptables的链(chains) | Filter | NAT | Mangle | Raw | Security |
---|---|---|---|---|---|---|
NF_IP_PRE_ROUTING | PREROUTING | √ | √ | √ | ||
NF_IP_LOCAL_IN | INPUT | √ | √ | √ | √ | |
NF_IP_FORWARD | FORWARD | √ | √ | √ | ||
NF_IP_LOCAL_OUT | OUTPUT | √ | √ | √ | √ | √ |
NF_IP_POST_ROUTING | POSTROUTING | √ | √ |
|
| Incoming ++---------------------++
↓ || raw ||
+-------------------+ || connection tracking ||
| NF_IP_PRE_ROUTING |= = = = = =|| mangle ||
+-------------------+ || nat (DNAT) ||
| ++---------------------++
|
↓ ++------------++
+------------------+ || mangle ||
| | +----------------+ || filter ||
| routing decision |-------->| NF_IP_LOCAL_IN |= = = = = =|| security ||
| | +----------------+ || nat (SNAT) ||
+------------------+ | ++------------++
| |
| ↓
| +-----------------+
| | local processes |
| +-----------------+
| |
| | ++---------------------++
++------------++ ↓ ↓ || raw ||
|| mangle || +---------------+ +-----------------+ || connection tracking ||
|| filter ||= = = = = =| NF_IP_FORWARD | | NF_IP_LOCAL_OUT |= = = = = =|| mangle ||
|| security || +---------------+ +-----------------+ || nat (DNAT) ||
++------------++ | | || filter ||
| | || security ||
↓ | ++---------------------++
+------------------+ |
| | |
| routing decision |<----------------+
| |
+------------------+
|
|
↓
+--------------------+ ++------------++
| NF_IP_POST_ROUTING |= = = = = =|| mangle ||
+--------------------+ || nat (SNAT) ||
| ++------------++
| Outgoing
↓
rule存放在特定表的特定chain上,每条rule包含下面两部分信息:
Matching就是如何匹配一个数据包,匹配条件很多,比如协议类型、源/目的IP、源/目的端口、in/out接口、包头里面的数据以及连接状态等,这些条件可以任意组合从而实现复杂情况下的匹配。
详情请参考Iptables matches https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#MATCHES
Targets就是找到匹配的数据包之后怎么办,常见的有下面几种:
DROP:直接将数据包丢弃,不再进行后续的处理
RETURN: 跳出当前chain,该chain里后续的rule不再执行
QUEUE: 将数据包放入用户空间的队列,供用户空间的程序处理
ACCEPT: 同意数据包通过,继续执行后续的rule
跳转到其它用户自定义的chain继续执行
当然iptables包含的targets很多很多,但并不是每个表都支持所有的targets,
rule所支持的target由它所在的表和chain以及所开启的扩展功能来决定,
具体每个表支持的targets请参考Iptables targets and jumps https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#TARGETS
原文:https://segmentfault.com/a/1190000009043962