1 基础概念

Firewall:防火墙,隔离工具;工作于主机或网络边缘,对于进出本主机或本网络的报文根据事先定义的检查规则作匹配检测,对于能够被规则匹配到的报文作出相应处理的组件;

  • 逻辑分类:主机防火墙 、网络防火墙

主机防火墙:将下图绿色虚线的数据流向经过的路径看作是主机防火墙,用来防护主机自身;
网络防火墙:将下图紫色虚线的数据流量经过的路径看作是网络防火墙,用来对局域网内部其他的主机 进行的防护;

  • 物理分类:软件防火墙(软件逻辑)、硬件防火墙(硬件和软件逻辑)

image.png

iptables: 包过滤型的防火墙,是Linux主机内核的内置的模块,其实iptables本身不是防火墙,正真实现防火墙功能的叫netfilter(CentOS6/7),位于内核中,专业上称之为”安全框架”。iptables只是netfilter的代理客户端,通过iptables提供的命令行接口,将用户的安全配置设定执行到netfilter对应的安全框架中。在CentOS8之后,这套安全框架的名字叫nftables
链:在这套安全框架之中,根据数据包流经的各个方向netfilter设计了五道”关卡”,没道关卡可以对数据包采取一定的动作,这五道关卡也就是我们俗称的五链
PREROUTING——->路由前
INPUT——————->入栈,数据包流入主机
FORWARD————>转发,将数据包经转发到其他主机
OUTPUT—————>出栈,数据包经主机流出主机
POSTROUTING—->路由后
表:在每一道链上,我们会通过各种各样的规则来对数据包采取相应的动作,根据各种动作实现的功能我们可以将其分为五种类型。
filter————>过滤,防火墙;
nat————->network address translation;用于修改源IP或目标IP,也可以改端口;
mangle——>拆解报文,做出修改,并重新封装起来;
raw————>关闭nat表上启用的连接追踪机制;
链和表的对应机制:
raw:PREROUTING, OUTPUT
mangle:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
nat:PREROUTING,INPUT,OUTPUT,POSTROUTING
filter:INPUT,FORWARD,OUTPUT
报文流向:
流入本机:PREROUTING —> INPUT
由本机流出:OUTPUT —> POSTROUTING
转发:PREROUTING —> FORWARD —> POSTROUTING
路由功能发生的时刻:
报文进入本机后:
判断目标主机是否为本机,如果是则进入INPUT,然后数据包向上流入主机用户空间的应用;
报文离开本机之前:
判断经由哪个接口送往下一站,路由确定之后,进入POSTROUTING链,最后数据包流出本机;
规则:
组成部分:根据规则匹配条件来尝试匹配报文,一旦匹配成功,就由规则定义的处理动作作出处理;
匹配条件:
基本匹配条件:内建
扩展匹配条件:由扩展模块定义;
处理动作:
基本处理动作:内建
扩展处理动作:由扩展模块定义;
自定义处理机制:自定义链
iptables的链:
内置链:对应于hook function
自定义链接:用于内置链的扩展和补充,可实现更灵活的规则管理机制;
添加规则时的考量点:
1、要实现哪种功能:判断添加到哪个表上;
2、报文流经的路径:判断添加到哪个链上;
3、链上的规则次序,即为检查的次序;因此,隐含一定的应用法则:
1)同类规则(访问同一应用),匹配范围小的放上面;
2)不同类的规则(访问不同应用),匹配到报文频率较大的放在上面;
3)将那些可由一条规则描述的多个规则合并起来;
4)设置默认策略;

2 命令详解

2.1 语法格式

iptables [-t table] COMMAND chain [-m matchname [per-match-options]] -j targetname [per-target-options]
1、-t table:
raw, mangle, nat, [filter],默认为filter表
2、COMMAND:
链管理:
-N:new, 自定义一条新的规则链;
-X: delete,删除自定义的规则链;
注意:仅能删除 用户自定义的 引用计数为0的 空的 链;
-P:Policy,设置默认策略;对filter表中的链而言,其默认策略有:
ACCEPT:接受
DROP:丢弃
REJECT:拒绝
-E:重命名自定义链;引用计数不为0的自定义链不能够被重命名,也不能被删除;
规则管理:
-A:append,追加;
-I:insert, 插入,要指明位置,省略时表示第一条;
-D:delete,删除;
(1) 指明规则序号;
(2) 指明规则本身;
-R:replace,替换指定链上的指定规则;
-F:flush,清空指定的规则链;
-Z:zero,置零;
iptables的每条规则都有两个计数器:
(1) 匹配到的报文的个数;
(2) 匹配到的所有报文的大小之和;
查看:
-L:list, 列出指定鏈上的所有规则;
-n:numberic,以数字格式显示地址和端口号;
-v:verbose,详细信息;-vv, -vvv可进一步查看信息
-x:exactly,显示计数器结果的精确值;
—line-numbers:显示规则的序号;
3、chain:
PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
4、匹配条件:
基本匹配条件:无需加载任何模块,由iptables/netfilter自行提供;
[!] -s, —source address[/mask],检查报文中的源IP地址是否符合此处指定的地址或范围;
[!] -d, —destination address[/mask],检查报文中的目标IP地址是否符合此处指定的地址或范围;
所有地址:0.0.0.0/0,写规则时如果地址为所有,则可以省略不写
[!] -p, —protocol protocol
protocol: tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh or “all”
[!] -i, —in-interface name:数据报文流入的接口;只能应用于数据报文流入的环节
即:PREROUTING,INPUT和FORWARD链;
[!] -o, —out-interface name:数据报文流出的接口;只能应用于数据报文流出的环节
即:FORWARD、OUTPUT和POSTROUTING链;
5、处理动作:
-j targetname [per-target-options]
ACCEPT
DROP
REJECT

2.2 匹配条件

  1. 基本匹配条件:PARAMETERS<br /> 扩展匹配条件:<br /> 隐式扩展:在使用-p选项指明了特定的协议时,无需再同时使用-m选项指明扩展模块的扩展机制;<br /> 显式扩展:必须使用-m选项指明要调用的扩展模块的扩展机制;

2.2.1 隐式扩展

不需要手动加载扩展模块;因为它们是对协议的扩展,所以,但凡使用-p指明了协议,就表示已经指明了要扩展的模块;
tcp:
[!] —source-port, —sport port[:port]:匹配报文的源端口;可以是端口范围;
[!] —destination-port,—dport port[:port]:匹配报文的目标端口;可以是端口范围;
[!] —tcp-flags mask comp
mask is the flags which we should examine, written as a comma-separated list,例如
SYN,ACK,FIN,RST
comp is a comma-separated list of flags which must be set,例如SYN
例如:“—tcp-flags SYN,ACK,FIN,RST SYN”表示,要检查的标志位为SYN,ACK,FIN,RST四个,其 中SYN必须为1,余下的必须为0;
[!] —syn:用于匹配第一次握手,相当于”—tcp-flags SYN,ACK,FIN,RST SYN“;
udp
[!] —source-port, —sport port[:port]:匹配报文的源端口;可以是端口范围;
[!] —destination-port,—dport port[:port]:匹配报文的目标端口;可以是端口范围;
icmp
[!] —icmp-type {type[/code]|typename}
echo-request:8
echo-reply:0

2.2.2 显式扩展

必须要手动加载扩展模块, [-m matchname [per-match-options]];
1、multiport
This module matches a set of source or destination ports. Up to 15 ports can be specified. A port range (port:port) counts as two ports. It can only be used in conjunction with one of the following protocols: tcp, udp, udplite, dccp and sctp.
以离散或连续的方式定义多端口匹配条件,最多15个;
[!] —source-ports,—sports port[,port|,port:port]…:指定多个源端口;
[!] —destination-ports,—dports port[,port|,port:port]…:指定多个目标端口;
# iptables -I INPUT -d 172.16.0.7 -p tcp -m multiport —dports 22,80,139,445,3306 -j ACCEPT
2、iprange
以连续地址块的方式来指明多IP地址匹配条件;
[!] —src-range from[-to]
[!] —dst-range from[-to]
# iptables -I INPUT -d 172.16.0.7 -p tcp -m multiport —dports 22,80,139,445,3306 -m iprange —src-range 172.16.0.61-172.16.0.70 -j REJECT
3、time
This matches if the packet arrival time/date is within a given range.
—timestart hh:mm[:ss]
—timestop hh:mm[:ss]
[!] —weekdays day[,day…]
[!] —monthdays day[,day…]
—datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
—datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
—kerneltz:使用内核配置的时区而非默认的UTC
]# iptables -t filter -R OUTPUT 1 -s 10.0.0.5 -p tcp —sport 23 -m iprange —dst-range 10.0.0.250-10.0.0.254 -m time —timestart 9:00:00 —timestop 22:00:00 —weekdays 1,2,3,4,5 —kerneltz -j ACCEPT
4、string
This modules matches a given string by using some pattern matching strategy.
—algo {bm|kmp}
[!] —string pattern
[!] —hex-string pattern
—from offset
—to offset
]# iptables -I OUTPUT -s 10.0.0.5 -m string —algo bm —string “gay” -j REJECT
5、connlimit
Allows you to restrict the number of parallel connections to a server per client IP address (or client address block).
—connlimit-upto n
—connlimit-above n
]# iptables -I INPUT -d 172.16.0.7 -p tcp —syn —dport 22 -m connlimit —connlimit-above 2 -j REJECT
6、limit
This module matches at a limited rate using a token bucket filter.
—limit rate[/second|/minute|/hour|/day]
—limit-burst number
~]# iptables -I OUTPUT -s 172.16.0.7 -p icmp —icmp-type 0 -j ACCEPT
限制本机某tcp服务接收新请求的速率:—syn, -m limit
7、state
“state”扩展是“conntrack”模块的一个子集。”state”允许访问此数据包的连接跟踪状态
[!] —state state
INVALID, ESTABLISHED, NEW, RELATED or UNTRACKED.
NEW: 新连接请求;
ESTABLISHED:已建立的连接;
INVALID:无法识别的连接;
RELATED:相关联的连接,当前连接是一个新请求,但附属于某个已存在的连接;
UNTRACKED:未追踪的连接;
state扩展:
内核模块装载:
nf_conntrack
nf_conntrack_ipv4
手动装载:
nf_conntrack_ftp
追踪到的连接:
/proc/net/nf_conntrack
调整可记录的连接数量最大值:
/proc/sys/net/nf_conntrack_max
超时时长:
/proc/sys/net/netfilter/timeout
]# iptables -R INPUT 3 -d 10.0.0.5 -p tcp -m multiport —dports 80,3306 -m state —state NEW -j ACCEPT
]# iptables -R INPUT 1 -d 10.0.0.5 -m state —state ESTABLISHED,RELATED -j ACCEPT

2.3 处理动作

  1. -j targetname [per-target-options] <br /> 简单target:<br /> ACCEPTDROP <br /> 扩展target:<br /> **REJECT**<br /> 这用于返回一个错误包来响应匹配的包:否则它相当于DROP,因此它是一个终止的TARGET,结束规则遍历<br /> **--reject-with type**<br /> 指定的类型可以是ICMP -net-unreachableICMP -host-unreachableICMP -port-unreachableICMP -proto- unreachableICMP -net-prohibitedICMP -host-prohibitedICMP -admin-prohibited(*),它们返回相应的ICMP错误消息(ICMP -port-unreachable是默认值)。<br /> **LOG**<br /> Turn on kernel logging of matching packets.<br /> --log-level<br /> --log-prefix<br /> 默认日志保存于/var/log/messages<br /> **RETURN**<br /> 返回调用者 <br /> **自定义链做为target**

2.4 配置保存

  1. 保存:iptables-save > /PATH/TO/SOME_RULE_FILE<br /> 重载:iptabls-restore < /PATH/FROM/SOME_RULE_FILE<br /> -n, --noflush:不清除原有规则<br /> -t, --test:仅分析生成规则集,但不提交 <br />CentOS 6:<br /> 保存规则:<br /> service iptables save<br /> 保存规则于/etc/sysconfig/iptables文件,覆盖保存;<br /> 重载规则:<br /> service iptables restart<br /> 默认重载/etc/sysconfig/iptables文件中的规则 <br /> 配置文件:/etc/sysconfig/iptables-config <br /> CentOS 7:<br /> (1) 自定义Unit File,进行iptables-restore;<br /> (2) firewalld服务;<br /> (3) 自定义脚本;<br /> 规则优化的思路:<br /> 使用自定义链管理特定应用的相关规则,模块化管理规则;<br /> (1) 优先放行双方向状态为ESTABLISHED的报文;<br /> (2) 服务于不同类别的功能的规则,匹配到报文可能性更大的放前面;<br /> (3) 服务于同一类别的功能的规则,匹配条件较严格的放在前面;<br /> (4) 设置默认策略:白名单机制<br /> (a) iptables -P,不建议;<br /> (b) 建议在规则的最后定义规则做为默认策略;

2.5 NAT

请求报文:由管理员定义;
改源地址:SNAT,MASQUERADE
改目标地址:DNAT
响应报文:由NAT的conntrack机制自动实现;
NAT表可定义在哪些链上;
PREROUTING,INPUT,OUTPUT,POSTROUTING
SNAT:在常规的情况下,SNAT基本都是定义在POSTROUTING链上
DNAT:在常规的情况下,DNAT基本都是定义在PREROUTING链上
PAT:用来修改端口,端口映射
备注:
1、这里解释下为什么DNAT需要在PREROUTING链上做,因为只有做了地址转换之后,再进行路由,才能够最终决定数据包是流向本机的还是对数据包进行转发,路由之后在做DNAT这个动作就会导致本应该进行转发的报文而流向了本机,因此DNAT的动作一般只在PREROUTING链上做。
2、对于SNAT只在PREROUTING链上做,可以简单的理解成从FORWARD和OUTPUT过来的报文都需要经过路由之后然后统一在PREROUTING链上进行SNAT的转换动作。
image.png
target:
SNAT:
仅在nat表中有效,在POSTROUTING和INPUT链中有效,用户定义的链只能从这些链中调用。
—to-source [ipaddr[-ipaddr]]
DNAT:
仅在nat表、PREROUTING和OUTPUT链中有效,用户定义的链只能从这些链中调用。
—to-destination [ipaddr[-ipaddr]][:port[-port]]
MASQUERADE:
仅在接口地址不固定时,使用此target,如拨号获取IP地址的情况
REDIRECT
仅在nat表、PREROUTING和OUTPUT链中有效,用户定义的链只能从这些链中调用。
—to-ports port[-port]
layer7 需自己装载的扩展模块,该模块开源社区已不再维护
SNAT示例
]# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT —to-source 10.0.0.5
DNAT示例
]# iptables -t nat -A PREROUTING -d 10.0.0.5 -p tcp —port 80 -j DNAT —to-destination 192.168.1.10

3 规则示例

  1. 主机:10.0.0.5
  2. 1、开放本机的所有tcp服务给所有主机;
  3. # iptables -I INPUT -d 10.0.0.5 -p tcp -j ACCEPT
  4. # iptables -I OUTPUT -s 10.0.0.5 -p tcp -j ACCEPT
  5. 2、开放本机的所有udp服务给172.16.0.0/16网络中的主机,但不包含10.0.0.200
  6. # iptables -I INPUT 2 -d 10.0.0.5 -s 10.0.0.200 -p udp -j REJECT
  7. # iptables -I INPUT 3 -d 10.0.0.5 -s 10.0.0.0/16 -p udp -j ACCEPT
  8. # iptables -l OUTPUT 2 -s 10.0.0.5 -d 10.0.0.0/16 -p udp -j ACCEPT
  9. 3、开放主机22,80,3306端口,并拒绝其他服务
  10. # iptables -A INPUT -d 10.0.0.5 -p tcp -m multiport --dport 22,80,3306 -m state --state NEW -j ACCEPT
  11. # iptables -I INPUT -d 10.0.0.5 -m state --state ESTABLISHED -j ACCEPT
  12. # iptables -A OUTPUT -s 10.0.0.5 -m state --state ESTABLISHED -j ACCEPT
  13. # iptables -A INPUT -d 10.0.0.5 -j REJECT
  14. # iptables -A OUTPUT -s 10.0.0.5 -j REJECT
  15. 4、开放10.0.0.250-10.0.0.254这个IP段对主机23端口的访问,开放时间时周一到周五的早上九点至晚上十点
  16. # iptables -t filter -R INPUT 1 -d 10.0.0.5 -p tcp --dport 23 -m iprange --src-range 10.0.0.250-10.0.0.254 -m time --timestart 9:00:00 --timestop 22:00:00 --weekdays 1,2,3,4,5 --kerneltz -j ACCEPT
  17. # iptables -t filter -R OUTPUT 1 -s 10.0.0.5 -p tcp --sport 23 -m iprange --dst-range 10.0.0.250-10.0.0.254 -m time --timestart 9:00:00 --timestop 22:00:00 --weekdays 1,2,3,4,5 --kerneltz -j ACCEPT
  18. 5NAT
  19. # iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.0.0.5
  20. # iptables -t nat -A PREROUTING -d 10.0.0.5 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10