研究了warden和OpenStack的网络相关的内容,发现底层都是使用的iptables,对这个不是很熟悉,专门拿出时间学习了一下。参考文档:https://www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html
iptables 表
iptable 链只是一组规则的组合,iptables 有三个默认的链:FORWARD 链过滤所有不是本地产生的并且目的地不是本地(所谓本地就是防火墙了)的包,而 INPUT恰恰针对那些目的地是本地的包。OUTPUT 是用来过滤所有本地生成的包的。 iptables可以增加,减少链.
一个表内包含链
mangle 表
这个表主要用来mangle包,你可以使用mangle匹配来改变包的TOS等特性。
强烈建议不要在这个表里做任何过滤,不管是DANT,SNAT或者Masquerade。
以下是mangle表中仅有的几种操作:
-
TOS
-
TTL
-
MARK
TOS操作用来设置或改变数据包的服务类型域。这常用来设置网络上的数据包如何被路由等策略。 注意这个操作并不完善,有时得不所愿。它在Internet上还不能使用,而且很多路由器不会注意到 这个域值。换句话说,不要设置发往Internet的包,除非你打算依靠TOS来路由,比如用iproute2。
TTL操作用来改变数据包的生存时间域,我们可以让所有数据包只有一个特殊的TTL。它的存在有 一个很好的理由,那就是我们可以欺骗一些ISP。为什么要欺骗他们呢?因为他们不愿意让我们共享 一个连接。那些ISP会查找一台单独的计算机是否使用不同的TTL,并且以此作为判断连接是否被共享 的标志。
MARK用来给包设置特殊的标记。iproute2能识别这些标记,并根据不同的标记(或没有标记) 决定不同的路由。用这些标记我们可以做带宽限制和基于请求的分类。
nat 表
此表仅用于NAT,也就是转换包的源或目标地址。注意,就象我们前面说过的,只有流的第一个 包会被这个链匹配,其后的包会自动被做相同的处理。实际的操作分为以下几类:
-
DNAT
-
SNAT
-
MASQUERADE
DNAT操作主要用在这样一种情况,你有一个合法的IP地址,要把对防火墙的访问 重定向到其他的机子上(比如DMZ)。也就是说,我们改变的是目的地址,以使包能重路由到某台主机。
SNAT改变包的源地址,这在极大程度上可以隐藏你的本地网络或者DMZ等。一个 很好的例子是我们知道防火墙的外部地址,但必须用这个地址替换本地网络地址。有了这个操作,防火墙就 能自动地对包做SNAT和De-SNAT(就是反向的SNAT),以使LAN能连接到Internet。如果使用类似 192.168.0.0/24这样的地址,是不会从Internet得到任何回应的。因为IANA定义这些网络(还有其他的)为 私有的,只能用于LAN内部。
MASQUERADE的作用和MASQUERADE完全一样,只是计算机 的负荷稍微多一点。因为对每个匹配的包,MASQUERADE都要查找可用的IP地址,而 不象SNAT用的IP地址是配置好的。当然,这也有好处,就是我们可以使用通过PPP、 PPPOE、SLIP等拨号得到的地址,这些地址可是由ISP的DHCP随机分配的。
filer 表
filter 表用来过滤数据包,我们可以在任何时候匹配包并过滤它们。 我们就是在这里根据包的内容对包做DROP或ACCEPT的。当然,我们也可以预先在其他地方做些过滤,但是这 个表才是设计用来过滤的。几乎所有的target都可以在这儿使用。大量具体的介绍在后面,现在你只要知道 过滤工作主要是在这儿完成的就行了。
总结:
Table (表名) | Explanation (注释) |
---|---|
nat | nat表的主要用处是网络地址转换,即Network Address Translation,缩写为NAT。做过NAT操作的数据包的地址就被改变了,当然这种改变是根据我们的规则进行 的。属于一个流的包只会经过这个表一次。如果第一个包被允许做NAT或Masqueraded,那么余下的包都会自 动地被做相同的操作。也就是说,余下的包不会再通过这个表,一个一个的被NAT,而是自动地完成。这就 是我们为什么不应该在这个表中做任何过滤的主要原因,对这一点,后面会有更加详细的讨论。PREROUTING 链的作用是在包刚刚到达防火墙时改变它的目的地址,如果需要的话。OUTPUT链改变本地产生的包的目的地 址。POSTROUTING链在包就要离开防火墙之前改变其源地址。 |
mangle | 这个表主要用来mangle数据包。我们可以改变不同的包及包 头的内容,比如 TTL,TOS或MARK。 注意MARK并没有真正地改动数据包,它只是在内核空间为包设了一个标记。防火墙 内的其他的规则或程序(如tc)可以使用这种标记对包进行过滤或高级路由。这个表有五个内建的链: PREROUTING,POSTROUTING, OUTPUT,INPUT和 FORWARD。PREROUTING在包进入防火墙之后、路由判断之前改变 包,POSTROUTING是在所有路由判断之后。 OUTPUT在确定包的目的之前更改数据包。INPUT在包被路由到本地 之后,但在用户空间的程序看到它之前改变包。FORWARD在最初的路由判 断之后、最后一次更改包的目的之前mangle包。注意,mangle表不能做任何NAT,它只是改变数据包的 TTL,TOS或MARK,而不是其源目地 址。NAT是在nat表中操作的。 |
filter | filter表是专门过滤包 的,内建三个链,可以毫无问题地对包进行DROP、LOG、ACCEPT和REJECT等操作。FORWARD 链过滤所有不是本地产生的并且目的地不是本地(所谓本地就是防火墙了)的包,而 INPUT恰恰针对那些目的地是本地的包。OUTPUT 是用来过滤所有本地生成的包的。 |
ipatbles 规则
规则就是指向标,在一条链上,对不同的连接和数据包阻塞 或允许它们去向何处。插入链的每一行都是一条规则。我们也会讨论基本的matche及其用法,还有各种各样 的target,以及如何建立我们自己的target(比如,一个新的子链)。
基础
在内核看来,规则就是决定如何处理一个包的语句。如果一个包符合所有 的条件(就是符合matche语句),我们就运行target或jump指令。书写规则的语法格式是:
iptables [-t table] command [match] [target/jump]
对于这个句法没什么可说的,但注意target指令必须在最后。为了易读,我们一般用这种语法。总之, 你将见到的大部分规则都是按这种语法写的。因此,如果你看到别人写的规则,你很可能会发现用的也是这 种语法,当然就很容易理解那些规则了。
如果你不想用标准的表,就要在[table]处指定表名。一般情况下没有必要指定使用的表,因为iptables 默认使用filter表来执行所有的命令。也没有必要非得在这里指定表名,实际上几乎可在规则的任何地方。 当然,把表名在开始处已经是约定俗成的标准。
尽管命令总是放在开头,或者是直接放在表名后面,我们也要考虑考虑到底放在哪儿易读。command告诉 程序该做什么,比如:插入一个规则,还是在链的末尾增加一个规则,还是删除一个规则,下面会仔细地介 绍。
match细致地描述了包的某个特点,以使这个包区别于其它所有的包。在这里,我们可以指定包的来源IP 地址,网络接口,端口,协议类型,或者其他什么。下面我们将会看到许多不同的match。
最后是数据包的目标所在。若数据包符合所有的match,内核就用target来处理它,或者说把包发往 target。比如,我们可以让内核把包发送到当前表中的其他链(可能是我们自己建立的),或者只是丢弃这 个包而没有什么处理,或者向发送者返回某个特殊的应答。下面有详细的讨论。
iptables [-t table] command [match] [target/jump]
table
目前已知的有三个表:nat、filter、mangle,具体介绍,前面已经说明。
command
Command | -A, --append |
Example | iptables -A INPUT ... |
Explanation | 在所选择的链末添加规则。当源地址或目的地址是以名字而 不是ip地址的形式出现时,若这些名字可以被解析为多个地址,则这条规则会和所有可用的地址结合。 |
Command | -D, --delete |
Example | iptables -D INPUT --dport 80 -j DROP或iptables -D INPUT 1 |
Explanation | 从所选链中删除规则。有两种方法指定要删除的规则:一是 把规则完完整整地写出来,再就是指定规则在所选链中的序号(每条链的规则都各自从1被编号)。 |
Command | -R, --replace |
Example | iptables -R INPUT 1 -s 192.168.0.1 -j DROP |
Explanation | 在所选中的链里指定的行上(每条链的规则都各自从1被编 号)替换规则。它主要的用处是试验不同的规则。当源地址或目的地址是以名字而不是ip地址的形式出现 时,若这些名字可以被解析为多个地址,则这条command会失败。 |
Command | -I, --insert |
Example | iptables -I INPUT 1 --dport 80 -j ACCEPT |
Explanation | 根据给出的规则序号向所选链中插入规则。如果序号为1, 规则会被插入链的头部,其实默认序号就是1。 |
Command | -L, --list |
Example | iptables -L INPUT |
Explanation | 显示所选链的所有规则。如果没有指定链,则显示指定表中 的所有链。如果什么都没有指定,就显示默认表所有的链。精确输出受其它参数影响,如-n 和-v等参数,下面会介绍。 |
Command | -F, --flush |
Example | iptables -F INPUT |
Explanation | 清空所选的链。如果没有指定链,则清空指定表中的所有 链。如果什么都没有指定,就清空默认表所有的链。当然,也可以一条一条地删,但用这个command会快些。 |
Command | -Z, --zero |
Example | iptables -Z INPUT |
Explanation | 把指定链(如未指定,则认为是所有链)的所有计数器归 零。 |
Command | -N, --new-chain |
Example | iptables -N allowed |
Explanation | 根据用户指定的名字建立新的链。上面的例子建立了一个名 为allowed的链。注意,所用的名字不能和已有的链、target同名。 |
Command | -X, --delete-chain |
Example | iptables -X allowed |
Explanation | 删除指定的用户自定义链。这个链必须没有被引用,如果被 引用,在删除之前你必须删除或者替换与之有关的规则。如果没有给出参数,这条命令将会删除默认表所有 非内建的链。 |
Command | -P, --policy |
Example | iptables -P INPUT DROP |
Explanation | 为链设置默认的target(可用的是DROP 和ACCEPT,如果还有其它的可用,请告诉我),这个target称作策略。所有不 符合规则的包都被强制使用这个策略。只有内建的链才可以使用规则。但内建的链和用户自定义链都不能被 作为策略使用,也就是说不能象这样使用:iptables -P INPUT allowed(或者是内建的链)。 |
Command | -E, --rename-chain |
Example | iptables -E allowed disallowed |
Explanation | 对自定义的链进行重命名,原来的名字在前,新名字在后。 如上,就是把allowed改为disallowed。这仅仅是改变 链的名字,对整个表的结构、工作没有任何影响。 |
matches 匹配
Match | -p, --protocol |
Example | iptables -A INPUT -p tcp |
Explanation | 匹配指定的协议。指定协议的形式有以下几种: 1、名字,不分大小写,但必须是在/etc/protocols中定 义的。 2、可以使用它们相应的整数值。例如,ICMP的值是1,TCP是6,UDP是17。 3、缺省设置,ALL,相应数值是0,但要注意这只代表匹配TCP、UDP、ICMP,而不是/etc/protocols中定义的所有协议。 4、可以是协议列表,以英文逗号为分隔符,如:udp,tcp 5、可以在协议前加英文的感叹号表示取反,注意有空格,如: --protocol ! tcp 表示非tcp协议,也就是UDP和ICMP。可以看出这个取反的范围只是TCP、UDP和ICMP。 |
Match | -s, --src, --source |
Example | iptables -A INPUT -s 192.168.1.1 |
Explanation | 以IP源地址匹配包。地址的形式如下: 1、单个地址,如192.168.1.1,也可写成 192.168.1.1/255.255.255.255或192.168.1.1/32 2、网络,如192.168.0.0/24,或 192.168.0.0/255.255.255.0 3、在地址前加英文感叹号表示取反,注意空格,如--source ! 192.168.0.0/24 表示除此地址外的所有地址 4、缺省是所有地址 |
Match | -d, --dst, --destination |
Example | iptables -A INPUT -d 192.168.1.1 |
Explanation | 以IP目的地址匹配包。地址的形式和 -- source完全一样。 |
Match | -i, --in-interface |
Example | iptables -A INPUT -i eth0 |
Explanation | 以包进入本地所使用的网络接口来匹配包。要注意这个匹配 操作只能用于INPUT,FORWARD和 PREROUTING这三个链,用在其他任何地方都会提示错误信息。指定接口有一下方 法: 1、指定接口名称,如:eth0、ppp0等 2、使用通配符,即英文加号,它代表字符数字串。若直接用一个加号,即iptables -A INPUT -i +表示匹配所有的包,而不考虑使用哪个接口。这也是不指定接口的默认行为。通配符还 可以放在某一类接口的后面,如:eth+表示所有Ethernet接口,也就是说,匹配所有从Ethernet接口进入的 包。 3、在接口前加英文感叹号表示取反,注意空格,如:-i ! eth0意思是匹配来自 除eth0外的所有包。 |
Match | -o, --out-interface |
Example | iptables -A FORWARD -o eth0 |
Explanation | 以包离开本地所使用的网络接口来匹配包。使用的范围和指 定接口的方法与--in-interface完全一样。 |
Match | -f, --fragment |
Example | iptables -A INPUT -f |
Explanation | 用来匹配一个被分片的包的第二片或及以后的部分。因为它 们不包含源或目的地址,或ICMP类型等信息,其他规则无法匹配到它,所以才有这个匹配操作。要注意碎片 攻击哦。这个操作也可以加英文感叹号表示取反,但要注意位置,如:! -f 。取反 时,表示只能匹配到没有分片的包或者是被分片的包的第一个碎片,其后的片都不行。现在内核有完善的碎 片重组功能,可以防止碎片攻击,所以不必使用取反的功能来防止碎片通过。如果你使用连接跟踪,是不会 看到任何碎片的,因为在它们到达任何链之前就被处理过了。 |
除了上面这些通用的匹配,还包括隐式匹配:TCP matches,UDP matches,ICMP matches 。显示匹配:limit match,mac match等
taget/jump
target/jump决定符合条件的包到何处去,语法是--jump target或-j target。(译者注:本文中,原作者把target细分为两类,即Target和Jump。它们 唯一的区别是jump的目标是一个在同一个表内的链,而target的目标是具体的操作。)
iptables -N tcp_packets 新建一个链
iptables -A INPUT -p tcp -j tcp_packets 符合tcp协议的从INPUT链跳转到tcp_packets 链
如果到达了tcp_packets链的结尾(也 就是未被链中的任何规则匹配),则会退到INPUT链的下一条规则继续它的旅行。如 果在子链中被ACCEPT了,也就相当于在父链中被ACCEPT了,那么它不会再经过父链中的其他规则。
target指定我们要对包做的操作,比如DROP和ACCEPT,还有很多,我们后面会介绍。不同的target有不 同的结果。一些target会使包停止前进,也就是不再继续比较当前链中的其他规则或父链中的其他规则,最 好的例子就是DROP和ACCEPT。
DNAT target
Option | --to-destination |
Example | iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10 |
Explanation | 指定要写入IP头的地址,这也是包要被转发到的地方。上面 的例子就是把所有发往地址15.45.23.67的包都转发到一段LAN使用的私有地址中,即192.168.1.1到 192.168.1.10。如前所述,在这种情况下,每个流都会被随机分配一个要转发到的地址,但同一个流总是使 用同一个地址。我们也可以只指定一个IP地址作为参数,这样所有的包都被转发到同一台机子。我们还可以 在地址后指定一个或一个范围的端口。比如:--to-destination 192.168.1.1:80或 --to-destination 192.168.1.1:80-100。SNAT的语法和这 个target的一样,只是目的不同罢了。要注意,只有先用--protocol指定了TCP或 UDP协议,才能使用端口。 |
MASQUERADE和SNAT一样,只能用于nat表的 POSTROUTING链,dnat可以用于POSTROUTING链和OUTPUT链
DROP target
顾名思义,如果包符合条件,这个target就会把它丢掉,也就是说包的生命到此结束,不会再向前走一 步,效果就是包被阻塞了。在某些情况下,这个target会引起意外的结果,因为它不会向发送者返回任何信 息,也不会向路由器返回信息,这就可能会使连接的另一方的sockets因苦等回音而亡:) 解决这个问题的较 好的办法是使用REJECT target,(译者注:因为它在丢弃包的同时还会向发送者返 回一个错误信息,这样另一方就能正常结束),尤其是在阻止端口扫描工具获得更多的信息时,可以隐蔽被 过滤掉的端口等等(译者注:因为扫描工具扫描一个端口时,如果没有返回信息,一般会认为端口未打开或 被防火墙等设备过滤掉了)。还要注意如果包在子链中被DROP了,那么它在主链里也不会再继续前进,不管 是在当前的表还是在其他表里。总之,包死翘翘了。
MASQUERADE target
这个target和SNAT target的作用是一样的,区别就是它不需要指定--to-source 。MASQUERADE是被专门设计用于那些动态获取IP地址的连接的,比如,拨号上网、DHCP连接等。如果你 有固定的IP地址,还是用SNAT target吧。
伪装一个连接意味着,我们自动获取网络接口的IP地址,而不使用--to-source 。当接口停用时,MASQUERADE不会记住任何连接,这在我们kill掉接口时是有 很大好处的。如果我们使用SNAT target,连接跟踪的数据是被保留下来的,而且时 间要好几天哦,这可是要占用很多连接跟踪的内存的。一般情况下,这种处理方式对于拨号上网来说是较好 的(这有利于已有那连接继续使用)。如果我们被分配给了一个不同于前一次的IP,不管怎样已有的连接都 要丢失,但或多或少地还是有一些连接记录被保留了(真是白痴,是吧)。
即使你有静态的IP,也可以使用MASQUERADE,而不用SNAT 。不过,这不是被赞成的,因为它会带来额外的开销,而且以后还可能引起矛盾,比如它也许会影响你 的脚本,使它们不能用
SNAT target
Option | --to-source |
Example | iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to-source 194.236.50.155-194.236.50.160:1024-32000 |
Explanation | 指定源地址和端口,有以下几种方式: 1、单独的地址。 2、一段连续的地址,用连字符分隔,如194.236.50.155-194.236.50.160,这样可以实现负载平衡。每 个流会被随机分配一个IP,但对于同一个流使用的是同一个IP。 3、在指定-p tcp 或 -p udp的前提下,可以指定源端口的范围,如194.236.50.155:1024-32000,这样 包的源端口就被限制在1024-32000了。 注意,如果可能,iptables总是想避免任何的端口变更,换句话说,它总是尽力使用建立连接时所用的 端口。但是如果两台机子使用相同的源端口,iptables 将会把他们的其中之一映射到另外的一个端口。如 果没有指定端口范围, 所有的在512以内的源端口会被映射到512以内的另一个端口,512和1023之间的将会 被映射到 1024内,其他的将会被映射到大于或对于1024的端口,也就是说是同范围映射。还要注意,这种 映射和目的端口无关。因此,如果客户想和防火墙外的HTTP服务器联系,它是不会被映射到FTP control所用的端口的。 |