一、iptables防火墙设置
Netfilter组件
内核空间,集成在linux内核中;
官网文档:https://netfilter.org/documentation/
扩展各种网络服务的结构化底层框架;
内核中选取五个位置放了五个hook(勾子) function(INPUT、OUTPUT、FORWARD、PREROUTING、POSTROUTING),而这五个hook function向用户开放,用户可以通过一个命令工具 (iptables)向其写入规则;
iptables由信息过滤表(table)组成,包含控制IP包处理的规则集(rules),规则被分组放在链(chain)上;
iptables的结构
iptables -> Tables -> Chains -> Rules. 简单地讲,tables由chains组成,而chains又由rules组成。如下图所示:
三种报文流向
流入本机:PREROUTING --> INPUT–>用户空间进程;
流出本机:用户空间进程 -->OUTPUT–> POSTROUTING;
转发:PREROUTING --> FORWARD --> POSTROUTING;
iptables的组成
iptables由五个表和五个链以及一些规则组成。
五个表table:filter、nat、mangle、raw、security:
filter表:数据包过进行滤,用户防火墙规则,过滤规则默认表,根据预定义的规则过滤符合条件的数据包;
它具有以下三种内建链:
- INPUT链
- OUTPUT链
- FORWARD链
nat表:network address translation 地址转换规则表,用于网关路由器。
它具有以下三种内建链:
- PREROUTING链
- POSTROUTING链
- OUTPUT链
mangle:修改数据标记位规则表,数据包修改,用户实现服务质量;
Mangle表具有五个内建链:
- PREROUTING
- OUTPUT
- FORWARD
- INPUT
- POSTROUTING
raw:处理异常,关闭NAT表上启用的连接跟踪机制,加快封包穿越防火墙速度,提高性能并提供高级功能,如网址过滤;
它具有以下两种内建链:
- PREROUTING
- OUTPUT
五个内置链chain:
INPUT链:处理输入数据包(来自外部的数据);
OUTPUT链:处理输出数据包(向外发送的数据);
PORWARD链:处理转发数据包(将数据转发到本机的其他网卡设备上);
PREROUTING链:用于目标地址转换(处理刚到达本机并在路由转发前的数据包。它会转换数据包中的目标IP地址,通常用于DNAT);
POSTOUTING链:用于源地址转换(处理即将离开本机的数据包。它会转换数据包中的源IP地址,通常用于SNAT);
动作:
accept:接收数据包;
DROP:丢弃数据包;
REDIRECT:重定向,映射,透明代理;
SNAT:原地址转换;
DNAT:目标地址转换;
MASQUERADE:IP伪装(NAT),用户ADSL;
LOG:日志记录。
常用操作命令 | 说明 |
---|---|
-A | 在指定链尾部添加规则 |
-D | 删除匹配的规则 |
-R | 替换匹配的规则 |
-I | 在指定位置插入规则(例:iptables -I INPUT 1 --dport 80 -j ACCEPT(将规则插入到filter表INPUT链中的第一位上) |
-L/S | 列出指定链或所有链的规则 |
-F | 删除指定链或所有链的规则 |
-N | 创建用户自定义链[例:iptables -N allowed] |
-X | 删除指定的用户自定义链 |
-P | 为指定链设置默认规则策略,对自定义链不起作用 |
-Z | 将指定链或所有链的计数器清零 |
-E | 更改自定义链的名称[例:iptables -E allowed disallowed] |
-n | ip地址和端口号以数字方式显示[例:iptables -nL] |
常用规则匹配器 | 说明 |
---|---|
-p tcp/udp/icmp/all | 匹配协议,all会匹配所有协议 |
-s addr[/mask] | 匹配源地址 |
-d addr[/mask] | 匹配目标地址 |
--sport port1[:port2] | 匹配源端口(可指定连续的端口) |
--dport port1[:port2] | 匹配目的端口(可指定连续的端口) |
-o interface | 匹配出口网卡,只适用FORWARD、POSTROUTING、OUTPUT(例:iptables -A FORWARD -o eth0) |
-i interface | 匹配入口网卡,只使用PREROUTING、INPUT、FORWARD。 |
--icmp-type | 匹配icmp类型(使用iptables -p icmp -h可查看可用的ICMP类型) |
--tcp-flags mask comp | 匹配TCP标记,mask表示检查范围,comp表示匹配mask中的哪些标记。(例:iptables -A FORWARD -p tcp --tcp-flags ALL SYN,ACK -j ACCEPT 表示匹配SYN和ACK标记的数据包) |
目标动作 | 说明 |
---|---|
ACCEPT | 允许数据包通过 |
DROP | 丢弃数据包 |
REJECT | 丢弃数据包,并且将拒绝信息发送给发送方 |
SNAT | 源地址转换(在nat表上)例:iptables -t nat -A POSTROUTING -d 192.168.0.102 -j SNAT --to 192.168.0.1 |
DNAT | 目标地址转换(在nat表上)例:iptables -t nat -A PREROUTING -d 202.202.202.2 -j DNAT --to-destination 192.168.0.102 |
REDIRECT | 目标端口转换(在nat表上)例:iptables -t nat -D PREROUTING -p tcp --dport 8080 -i eth2.2 -j REDIRECT --to 80 |
MARK | 将数据包打上标记;例:iptables -t mangle -A PREROUTING -s 192.168.1.3 -j MARK --set-mark 60 |
防火墙功能的原理
当主机收到一个数据包后,数据包先在内核空间中处理,若发现目的地址是自身,则传到用户空间中交给对应的应用程序处理,若发现目的不是自身,则会将包丢弃或进行转发。
在数据包经过内核的过程中有五处关键地方,分别是PREROUTING、INPUT、OUTPUT、FORWARD、POSTROUTING,称为钩子函数,iptables这款用户空间的软件可以在这5处地方写规则,对经过的数据包进行处理,规则一般的定义为“如果数据包头符合这样的条件,就这样处理数据包”。
iptables中定义有5条链,说白了就是上面说的5个钩子函数,因为每个钩子函数中可以定义多条规则,每当数据包到达一个钩子函数时,iptables就会从钩子函数中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合钩子函数中任一条规则,iptables就会根据该函数预先定义的默认策略来处理数据包。
iptables中定义有表,分别表示提供的功能,有filter表(实现包过滤)、nat表(实现网络地址转换)、mangle表(实现包修改)、raw表(实现数据跟踪),这些表具有一定的优先级:raw-->mangle-->nat-->filter。
一条链上可定义不同功能的规则,检查数据包时将根据上面的优先级顺序检查:
1、目的地址是本地,则发送到INPUT,让INPUT决定是否接收下来送到用户空间,流程为①--->②;
2、若满足PREROUTING的nat表上的转发规则,则发送给FORWARD,然后再经过POSTROUTING发送出去,流程为: ①--->③--->④--->⑥
3、主机发送数据包时,流程则是⑤--->⑥
内核中数据包的传输过程:
1、当一个数据包进入网卡时,数据包首先进入PREROUTING链,内核根据数据包目的IP判断是否需要转送出去;
2、如果数据包就是进入本机的,数据包就会沿着图向下移动,到达INPUT链。数据包到达INPUT链后,任何进程都会收到它。本机上运行的程序可以发送数据包,这些数据包经过OUTPUT链,然后到达POSTROUTING链输出;
3、如果数据包是要转发出去的,且内核允许转发,数据包就会向右移动,经过FORWARD链,然后到达POSTROUTING链输出;
iptables规则
规则rule:根据规则的匹配条件尝试匹配报文,对匹配成功的报文根据规则定义的处理动作作出处理。
匹配条件:默认为与条件,同时满足:
1、基本匹配:IP,端口,TCP的Flags(SYN,ACK等);
2、扩展匹配:通过复杂高级功能匹配;
处理动作:称为target,跳转目标:
1、内建处理动作:ACCEPT,DROP,REJECT,SNAT,DNATMASQUERADE,MARK,LOG…;
2、自定义处理动作:自定义chain,利用分类管理复杂情形;
规则要添加在链上,才生效;添加在自定义上不会自动生效:
链chain:
1、内置链:每个内置链对应于一个钩子函数;
2、自定义链:用于对内置链进行扩展或补充,可实现更灵活的规则组织管理机制;只有Hook钩子调用自定义链时,才生效;
iptables规则添加时考量点:
1、要实现哪种功能:判断添加在哪张表上;
2、报文流经的路径:判断添加在哪个链上;
3、报文的流向:判断源和目的;
4、匹配规则:业务需要;
牢记以下三点式理解iptables规则的关键:
- rules包括一个条件和一个目标(target)
- 如果满足条件,就执行目标(target)中的规则或者特定值。
- 如果不满足条件,就判断下一条rules。
iptables使用
man 8 iptables
iptables [-t table] {-A|-C|-D} chain rule-specification
iptables [-t table] -I chain [rulenum] rule-specification
iptables [-t table] -R chain rulenum rule-specification
iptables [-t table] -D chain rulenum
iptables [-t table] -S [chain [rulenum]]
iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
iptables [-t table] -N chain
iptables [-t table] -X [chain]
iptables [-t table] -P chain target
iptables [-t table] -E old-chain-name new-chain-name
rule-specification = [matches...] [target]
match = -m matchname [per-match-options]
target = -j targetname [per-target-options]
iptables命令
规则格式:
iptables [-t table] SUBCOMMAND chain [-m matchname [per-match-options]] -j targetname [per-target-options]
iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作
-t table:
raw, mangle, nat, [filter]默认。
SUBCOMMAND (规则):
1、链管理
-N:new, 自定义一条新的规则链
-X:delete,删除自定义的空的规则链
-P:Policy,设置默认策略;对filter表中的链而言,其默认策略有:
ACCEPT:接受
DROP:丢弃
-E:重命名自定义链;引用计数不为0的自定义链不能够被重命名,也不能被删除
2、查看
-L:list, 列出指定鏈上的所有规则,本选项须置后
-n:numberic,以数字格式显示地址和端口号
-v:verbose,详细信息
-vv 更详细
-x:exactly,显示计数器结果的精确值,而非单位转换后的易读值
–line-numbers:显示规则的序号,常用组合:
-vnL
-vvnxL --line-numbers
-S selected,以iptables-save 命令格式显示链上规则
3、规则管理
-A:append,追加;
-I:insert, 插入,要指明插入至的规则编号,默认为第一条;
-D:delete,删除;
(1) 指明规则序号。
(2) 指明规则本身。
-R:replace,替换指定链上的指定规则编号;
-F:flush,清空指定的规则链;
-Z:zero,置零;
iptables的每条规则都有两个计数器:
(1) 匹配到的报文的个数;
(2) 匹配到的所有报文的大小之和;
4、chain
PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
5、-p 协议(protocol)
指定规则的协议,如tcp, udp, icmp等,可以使用all来指定所有协议。
如果不指定-p参数,则默认是all值。这并不明智,请总是明确指定协议名称。
可以使用协议名(如tcp),或者是协议值(比如6代表tcp)来指定协议,映射关系请查看/etc/protocols。
还可以使用–protocol参数代替-p参数
6、-s 源地址(source)
指定数据包的源地址。
参数可以使IP地址、网络地址、主机名。
例如:-s 192.168.1.101指定IP地址。
例如:-s 192.168.1.10/24指定网络地址。
如果不指定-s参数,就代表所有地址。
还可以使用–src或者–source。
7、-d 目的地址(destination)
指定目的地址
参数和-s相同
还可以使用–dst或者–destination
8、-j targetname [per-target-options]
-j指定了当与规则(Rule)匹配时如何处理数据包。
简单:
ACCEPT:允许防火墙接收数据包
DROP: 防火墙丢弃包
QUEUE:防火墙将数据包移交到用户空间
扩展:
REJECT:–reject-with:icmp-port-unreachable 默认
RETURN:防火墙停止执行当前链中的后续Rules,并返回到调用链(the calling chain)中。
REDIRECT:端口重定向
LOG:记录日志,dmesg
MARK:做防火墙标记
DNAT:目标地址转换
SNAT:源地址转换
MASQUERADE:地址伪装
9、-i 输入接口(input interface)
-i代表输入接口(input interface)。
-i指定了要处理来自哪个接口的数据包。
这些数据包即将进入INPUT, FORWARD, PREROUTE链。
例如:-i eth0指定了要处理经由eth0进入的数据包。
如果不指定-i参数,那么将处理进入所有接口的数据包。
如果出现! -i eth0,那么将处理所有经由eth0以外的接口进入的数据包。
如果出现-i eth+,那么将处理所有经由eth开头的接口进入的数据包。
还可以使用–in-interface参数。
10、-o 输出(out interface)
-o代表”output interface”。
-o指定了数据包由哪个接口输出。
这些数据包即将进入FORWARD, OUTPUT, POSTROUTING链。
如果不指定-o选项,那么系统上的所有接口都可以作为输出接口。
如果出现! -o eth0,那么将从eth0以外的接口输出。
如果出现-i eth+,那么将仅从eth开头的接口输出。
还可以使用–out-interface参数。
iptables基本应用
若iptables停止后,查看仍有信心,需卸除虚拟网卡。
[root@iptables ~]# yum remove libvirt-daemon -y
[root@iptables ~]# reboot
[root@iptables ~]# iptables -vnL #清空配置
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
[root@iptables ~]# iptables -t filter -A INPUT -s 192.168.8.17 -j DROP 扔掉
-t filter(默认,可以不写,其他表示需要指定,如-t nat)
-A INPUT (在INPUT链上-A增加规则;-R替换,-I插入、-D删除 )
-s 192.168.8.17(-s 源地址 -d目标地址)
-j DROP (ACCETP接受 DROP扔掉 REJECT拒绝)
[root@hostB ~]# ping 192.168.8.7 ping没反应,可以抓包看到没到对方主机
PING 192.168.8.7 (192.168.8.7) 56(84) bytes of data.
[root@hostB ~]# tcpdump -i ens33 -nn host 192.168.8.7
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
04:05:46.404941 IP 192.168.8.27 > 192.168.8.7: ICMP echo request, id 2203, seq 99, length 64
04:05:47.406525 IP 192.168.8.27 > 192.168.8.7: ICMP echo request, id 2203, seq 100, length 64
04:05:48.406995 IP 192.168.8.27 > 192.168.8.7: ICMP echo request, id 2203, seq 101, length 64
04:05:49.408410 IP 192.168.8.27 > 192.168.8.7: ICMP echo request, id 2203, seq 102, length 64
04:05:50.408741 IP 192.168.8.27 > 192.168.8.7: ICMP echo request, id 2203, seq 103, length 64
没有回来的报文
[root@hostB ~]# tcpdump -i ens33 -nn src 192.168.8.7 查看7发过来的没有
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
[root@iptables ~]# iptables -vnL #查看规则(filter表)
Chain INPUT (policy ACCEPT 46 packets, 3393 bytes)
链 默认规则 接收包
pkts bytes target prot opt in out source destination
30 3972 DROP all -- * * 192.168.8.17 0.0.0.0/0
281 23604 DROP all -- * * 192.168.8.27 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 27 packets, 2652 bytes)
pkts bytes target prot opt in out source destination
[root@iptables ~]# iptables -t nat -vnL #查看nat规则
[root@iptables ~]# iptables -vnL --line-number #显示优先级(优先级从上至下)
Chain INPUT (policy ACCEPT 145 packets, 10821 bytes)
num pkts bytes target prot opt in out source destination
1 30 3972 DROP all -- * * 192.168.8.17 0.0.0.0/0
2 449 37716 DROP all -- * * 192.168.8.27 0.0.0.0/0
[root@iptables ~]# iptables -D INPUT 2 删除第二条规则
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 10 packets, 772 bytes)
num pkts bytes target prot opt in out source destination
1 30 3972 DROP all -- * * 192.168.8.17 0.0.0.0/0
[root@iptables ~]# iptables -F 清空规则
[root@iptables ~]# iptables -vnL --line-number
Chain INPUT (policy ACCEPT 14 packets, 1020 bytes)
num pkts bytes target prot opt in out source destination
[root@iptables ~]# iptables -A INPUT -s 192.168.8.27 -j REJECT 拒绝
[root@iptables ~]# iptables -Aiptables -vnL --line-number
Chain INPUT (policy ACCEPT 10 packets, 724 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 REJECT all -- * * 192.168.8.27 0.0.0.0/0
[root@hostB ~]# ping 192.168.8.7 ping有回应
PING 192.168.8.7 (192.168.8.7) 56(84) bytes of data.
From 192.168.8.7 icmp_seq=1 Destination Port Unreachable
From 192.168.8.7 icmp_seq=2 Destination Port Unreachable
[root@hostB ~]# tcpdump -i ens33 -nn host 192.168.8.7
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
04:28:35.208379 IP 192.168.8.27 > 192.168.8.7: ICMP echo request, id 2840, seq 28, length 64
04:28:35.208781 IP 192.168.8.7 > 192.168.8.27: ICMP 192.168.8.7 protocol 1 port 51751 unreachable, length 92
[root@hostB ~]# tcpdump -i ens33 -nn src 192.168.8.7
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
04:28:46.218676 IP 192.168.8.7 > 192.168.8.27: ICMP 192.168.8.7 protocol 1 port 28151 unreachable, length 92
[root@iptables ~]# systemctl start httpd
[root@iptables ~]# echo welcome to magedu > /var/www/html/index.html
[root@hostB ~]# ping -f 192.168.8.7 暴力ping
PING 192.168.8.7 (192.168.8.7) 56(84) bytes of data.
[root@hostA ~]# curl 192.168.8.7 访问不了
[root@iptables ~]# iptables -A INPUT -s 192.168.8.0/24 -j REJECT 拒绝网段
[root@iptables ~]# iptables -I INPUT -s 192.168.8.0/24 -j REJECT 插入第一行
[root@iptables ~]# iptables -I INPUT 3 -s 192.168.8.0/24 -j REJECT 插入第3行
[root@iptables ~]# iptables -R INPUT 3 -s 192.168.8.0/24 -j REJECT 替换第3行
[root@iptables ~]# iptables -Z INPUT 包计数清零,重新计数
查看iptables防火墙策略
iptables -L -n -v
Chain INPUT (policy DROP 48106 packets, 2690K bytes)
pkts bytes target prot opt in out source destination
5075 589K ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
191K 90M ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
1499K 133M ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
4364K 6351M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
6256 327K ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 3382K packets, 1819M bytes)
pkts bytes target prot opt in out source destination
5075 589K ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
以上命令是查看默认的 FILTER 表,如果你只希望查看特定的表,可以在 -t 参数后跟上要单独查看的表名。例如只查看 NAT 表中的规则,可以使用如下命令:
iptables -t nat -L -v –n
追加iptables规则
可以使用iptables -A 命令追加新规则,其中 -A表示 Append。因此, 新的规则将追加到链尾。
一般而言,最后一条规则用于丢弃(DROP)所有数据包。如果你已经有这样的规则了,并且使用 -A参数添加新规则,那么就是无用功。
开放指定的端口:
iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT #允许本地回环接口(即运行本机访问本机)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT #允许已建立的或相关连的通行
iptables -A OUTPUT -j ACCEPT #允许所有本机向外的访问
iptables -A INPUT -p tcp --dport 22 -j ACCEPT #允许访问22端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT #允许访问80端口
iptables -A INPUT -p tcp --dport 21 -j ACCEPT #允许ftp服务的21端口
iptables -A INPUT -p tcp --dport 20 -j ACCEPT #允许FTP服务的20端口
iptables -A INPUT -j reject #禁止其他未允许的规则访问
iptables -A FORWARD -j REJECT #禁止其他未允许的规则访问
TCP和UDP链
TCP和UDP链包含用于接受新的传入TCP连接和UDP流到特定端口的规则。
要在Web服务器的端口80上接受传入TCP连接:
iptables -A TCP -p tcp --dport 80 -j ACCEPT
要在Web服务器(HTTPS)的端口443上接受传入TCP连接:
iptables -A TCP -p tcp --dport 443 -j ACCEPT
允许远程SSH连接(在端口22上):
iptables -A TCP -p tcp --dport 22 -j ACCEPT
要在DNS服务器的端口53上接受传入的UDP流:
iptables -A UDP -p udp --dport 53 -j ACCEPT
更改默认策略
当我们使用-L选项验证当前规则是发现,所有的链旁边都有 policy ACCEPT标注,这表明当前链的默认策略为ACCEPT:
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp – anywhere anywhere tcp dpt:ssh
DROP all – anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
这种情况下,如果没有明确添加DROP规则,那么默认情况下将采用ACCEPT策略进行过滤。除非:
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
我们已经把OUTPUT链策略更改为DROP了。此时虽然服务器能接收数据,但是无法发送数据:
# iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp – anywhere anywhere tcp dpt:ssh
DROP all – anywhere anywhere
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy DROP)
target prot opt source destination
屏蔽某个IP地址
如果你发布有某个 IP 向服务器导入攻击或非正常流量,可以使用如下规则屏蔽其 IP 地址:
iptables -I INPUT -s 123.45.6.7 -j DROP #屏蔽单个IP的命令
iptables -I INPUT -s 123.0.0.0/8 -j DROP #封整个段即从123.0.0.1到123.255.255.254的命令
iptables -I INPUT -s 124.45.0.0/16 -j DROP #封IP段即从123.45.0.1到123.45.255.254的命令
iptables -I INPUT -s 123.45.6.0/24 -j DROP #封IP段即从123.45.6.1到123.45.6.254的命令是
注意需要将上述的 XXX 改成要屏蔽的实际 IP 地址,其中的 -A 参数表示在 INPUT 链的最后追加本条规则。(iptables中的规则是从上到下匹配的,一旦匹配成功就不再继续往下匹配)
如果你只想屏蔽 TCP 流量,可以使用 -p 参数的指定协议,例如:
iptables -A INPUT -p tcp -s xxx.xxx.xxx.xxx -j DROP
解封某个IP地址
要解封对 IP 地址的屏蔽,可以使用如下命令进行删除:
iptables -D INPUT -s xxx.xxx.xxx.xxx -j DROP
其中 -D 参数表示从链中删除一条或多条规则。
屏蔽指定MAC地址
使用如下规则可以屏蔽指定的 MAC 地址:
iptables -A INPUT -m mac --mac-source 00:00:00:00:00:00 -j DROP
使用iptables关闭特定端口
很多时候,我们需要阻止某个特定端口的网络连接,可以使用 IPtables 关闭特定端口。
阻止特定的传出连接:
iptables -A OUTPUT -p tcp --dport xxx -j DROP
阻止特定的传入连接:
iptables -A INPUT -p tcp --dport xxx -j ACCEPT
防止策略配错导致不能访问,可以备份后30分钟后还原:
[root@iptables ~]# echo wall warning |at now+30 minutes
[root@iptables ~]# echo iptables -F |at now+30 minutes 30分钟配置清空
在规则中使用 IP 地址范围
在iptables中 IP 地址范围是可以直接使用 CIDR 进行表示的,例如:
iptables -A OUTPUT -p tcp -d 192.168.100.0/24 --dport 22 -j ACCEPT
拒绝所有IP,自己除外:
[root@iptables ~]# iptables -A INPUT -j REJECT 拒绝所有IP(一般在最下面)自己也不行
[root@iptables ~]# iptables -I INPUT -d 192.168.8.7,127.0.0.1 -j ACCEPT 排除自己,放前面
[root@iptables ~]# iptables -I INPUT -i ens33 -j ACCEPT 网卡接收
[root@iptables ~]# iptables -P INPUT REJECT 更改默认配置为拒绝
配置端口转发
有时我们需要将 Linux 服务器的某个服务流量转发到另一端口,此时可以使用如下命令:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j REDIRECT --to-port 2525
上述命令会将所有到达 eth0 网卡 25 端口的流量重定向转发到 2525 端口。
允许访问回环网卡。
环回访问(127.0.0.1)是比较重要的,建议大家都开放:
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
删除已添加的iptables规则
将所有iptables以序号标记显示,执行:
iptables -L -n --line-numbers
比如要删除INPUT里序号为8的规则,执行:
iptables -D INPUT 8
清空iptables规则
要清空 IPtables 链可以使用如下命令:
iptables –flush
Or
iptables -F
要清空特定的表可以使用 -t 参数进行指定,例如:
iptables -t nat –F
保存iptables规则
1)Ubuntu
默认情况下,管理员对iptables规则的操作会立即生效。但由于规则都是保存在内存当中的,所以重启系统会造成配置丢失,要永久保存iptables规则可以使用 iptables-save 命令:
iptables-save > ~/iptables.rules
保存的名称大家可以自己改。
还原iptables规则
有保存自然就对应有还原,大家可以使用 iptables-restore 命令还原已保存的规则:
iptables-restore < ~/iptables.rules
注意:不要尝试在.bashrc或者.profile中执行以上命令,因为用户通常不是root,而且这只能在登录时加载iptables规则。
2)CentOS, RedHat
保存iptables规则:
service iptables save
service iptables stop
service iptables start
cat /etc/iptables/iptables.rules
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:TCP - [0:0]
:UDP - [0:0]
-A INPUT -m conntrack -ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
还原iptables规则:
iptables-restore</etc/sysconfig/iptables_save
阻止连接到某块网卡
如果你的系统有多块网卡,我们可以限制 IP 范围访问某块网卡:
iptables -A INPUT -i eth0 -s xxx.xxx.xxx.xxx -j DROP
扩展匹配
对规则有了一个基本描述之后,有时候我们还希望指定端口、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
隐式扩展(不指定模块)
当使用-p指定某一协议之后,协议自身所支持的扩展就叫做隐式扩展、使用[tcp|udp|icmp]指定某特定协议后、自动能对协议进行扩展,可省略 -m 选项。
当协议和模块一致时,使用协议不需加载模块。
tcp协议的扩展选项:
[!] --source-port, --sport port[:port]:匹配报文源端口,可为端口范围
[!] --destination-port,–dport port[:port]:匹配报文目标端口,可为范围
[!] --tcp-flags mask comp:
mask 需检查的标志位列表,用,分隔
例如 SYN,ACK,FIN,RST
comp在mask列表中必须为1的标志位列表,无指定则必须为0,用,分隔
-p udp
--dport
--sport
-p icmp
--icmp-type
0: echo-reply
8: echo-request
示例:
–tcp-flags SYN,ACK,FIN,RST SYN 表示要检查的标志位为SYN,ACK,FIN,RST四个,其中SYN必须为1,余下的必须为0;
–tcp-flags SYN,ACK,FIN,RST SYN,ACK;
–tcp-flags ALL ALL;
–tcp_flags ALL NONE;
[!] --syn:用于匹配第一次握手。
相当于:–tcp-flags SYN,ACK,FIN,RST SYN
[root@iptables ~]# rpm -ql iptables
/usr/lib64/xtables/libipt_icmp.so
/usr/lib64/xtables/libxt_tcp.so
/usr/lib64/xtables/libxt_udp.so
[root@iptables ~]# iptables -A INPUT -s 192.168.8.27 -p tcp --dport 80 -j ACCEPT 允许访问tcp80端口(其他不能访问)
[root@iptables ~]# iptables -A INPUT -s 192.168.8.1,127.0.0.1 -j ACCEPT
[root@iptables ~]# iptables -A INPUT -j REJECT
[root@iptables ~]# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 192.168.8.27 0.0.0.0/0 tcp dpt:80
136 10924 ACCEPT all -- * * 192.168.8.1 0.0.0.0/0
0 0 ACCEPT all -- * * 127.0.0.1 0.0.0.0/0
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
[root@iptables ~]# iptables -I INPUT 3 -s 192.168.8.27 -p tcp --syn -j REJECT tcp三次握手第一次就拒绝
[root@nginx etc]# iptables -I INPUT -d 10.2.61.22 -p tcp --dport 22 -j ACCEPT
[root@nginx etc]#
[root@nginx etc]# iptables -I OUTPUT -s 10.2.61.22 -p tcp --sport 22 -j ACCEPT
[root@nginx etc]# iptables -L -n -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
158 12612 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 tcp dpt:22
1153 83636 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22
9 700 ACCEPT all -- ens192 * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
18 1688 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 tcp spt:22
895 90672 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0
13 1004 ACCEPT all -- * ens192 0.0.0.0/0 0.0.0.0/0
[root@nginx etc]# iptables -I INPUT -d 10.2.61.22 -p tcp --dport 22:8080 -j ACCEPT #多个端口
icmp
- [!] --icmp-type {type[/code]|typename}
- type/code
- 0/0 echo-reply icmp应答
- 8/0 echo-request icmp请求
只允许本机ping ,不响应 ping 包:
iptables -I INPUT -d 192.168.100.230 -p icmp --icmp-type 0 -j ACCEPT
能ping hostB,hostB 不能ping本机:
[root@iptables ~]# iptables -I INPUT -s 192.168.8.27 -p icmp --icmp-type 0 -j ACCEPT
[root@iptables ~]# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
2 168 ACCEPT icmp -- * * 192.168.8.27 0.0.0.0/0 icmptype 0
543 38229 ACCEPT all -- * * 192.168.8.1 0.0.0.0/0
1 60 REJECT tcp -- * * 192.168.8.27 0.0.0.0/0 tcp flags:0x17/0x02 reject-with icmp-port-unreachable
0 0 ACCEPT all -- * * 127.0.0.1 0.0.0.0/0
2 168 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
INPUT 允许应答报文 ,只能自己ping 别人,不响应ping:
iptables -A INPUT -d 10.2.61.22 -p icmp --icmp-type 0 -j ACCEPT
OUTPUT 允许请求报文:
iptables -A OUTPUT -s 10.2.61.22 -p icmp --icmp-type 8 -j ACCEPT
显示扩展(指定模块)
必须要明确指定的扩展模块。
multiport扩展,以离散方式定义多端口匹配,最多15 个端口。
参数 | 说明 |
---|---|
--sports port1[,port2,port3] | 匹配源端口 |
--dports port1[,port2,port3] | 匹配目的端口 |
--ports port1[,port2,port3] | 匹配源端口或目的端口 |
指定多个源端口:
[!] --source-ports,–sports port[,port|,port:port]…
指定多个目标端口:
[!] --destination-ports,–dports port[,port|,port:port]…
多个源或目标端口:
[!] --ports port[,port|,port:port]…
同一类型规则针对不同的端口须加多条规则,利用multiport模块可以写成一条,最多指定15个端口。
[root@CentOS7 ~]# iptables -I INPUT -s 192.168.8.6 -p tcp --dport 80 -j REJECT
[root@CentOS7 ~]# iptables -I INPUT -s 192.168.8.6 -p tcp --dport 3306 -j REJECT
[root@CentOS7 ~]# iptables -vnL
Chain INPUT (policy ACCEPT 24 packets, 1584 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT tcp -- * * 192.168.8.6 0.0.0.0/0 tcp dpt:3306 reject-with icmp-port-unreachable
0 0 REJECT tcp -- * * 192.168.8.6 0.0.0.0/0 tcp dpt:80 reject-with icmp-port-unreachable
[root@CentOS7 ~]# iptables -I INPUT -s I INPUT -s 192.168.8.6 -p tcp -m multiport --dport 3306,80 -j REJECT
[root@CentOS7 ~]# iptables -I INPUT -s vnL
Chain INPUT (policy ACCEPT 8 packets, 576 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT tcp -- * * 192.168.8.6 0.0.0.0/0 multiport dports 3306,80 reject-with icmp-port-unreachable
0 0 REJECT tcp -- * * 192.168.8.6 0.0.0.0/0 tcp dpt:3306 reject-with icmp-port-unreachable
0 0 REJECT tcp -- * * 192.168.8.6 0.0.0.0/0 tcp dpt:80 reject-with icmp-port-unreachable
[root@nginx /]# iptables -I INPUT -d 10.2.61.22 -p tcp -m multiport --dports 22,80 -j ACCEPT #同时限制22,80 端口
[root@nginx /]# iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 10.2.61.22 multiport dports 22,80
[root@nginx /]# iptables -I OUTPUT -s 10.2.61.22 -p tcp -m multiport --sports 22,80 -j ACCEPT
[root@nginx /]# iptables -L -n -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
446 38871 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 22,80
2341 192K ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 tcp dpts:22:8080
732 57576 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 tcp dpt:22
0 0 ACCEPT icmp -- * * 0.0.0.0/0 10.2.61.22 icmptype 0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
4 544 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 22,80
2499 463K ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 tcp spt:22
0 0 ACCEPT icmp -- * * 10.2.61.22 0.0.0.0/0 icmptype 8
[root@nginx /]#
iprange
指明连续的(但一般不是整个网络)ip地址范围。
- [!] --src-range from[-to] 源IP地址范围
- [!] --dst-range from[-to] 目标IP地址范围
iptables -I INPUT -d 192.168.100.230 -p tcp -m multiport --dports 22:23,25,80 -m iprange --src-range 192.168.100.2-192.168.100.199 -j ACCEPT
iptables -I OUTPUT -s 192.168.100.230 -p tcp -m multiport --sports 22:23,25,80 -m iprange --dst-range 192.168.100.2-192.168.100.199 -j ACCEPT
mac
指明源MAC地址。
适用于:PREROUTING, FORWARD,INPUT chains
- [!] --mac-source XX:XX:XX:XX:XX:XX
[root@CentOS7 ~]# iptables -A INPUT -s 172.16.0.100 -m mac --mac-source 00:50:56:12:34:56 -j ACCEPT
[root@CentOS7 ~]# iptables -A INPUT -s 172.16.0.100 -j REJECT
string
对报文中的应用层数据做字符串模式匹配检测。
–algo {bm|kmp} 字符串匹配检测算法:
bm:Boyer-Moore
kmp:Knuth-Pratt-Morris
–from offset 开始偏移
–to offset 结束偏移
[!] --string pattern 要检测的字符串模式
[!] --hex-string pattern要检测字符串模式,16进制格式
[root@CentOS7 ~]# iptables -A OUTPUT -s 172.16.100.10 -d 0/0 -p tcp --sport 80 -m string --algo bm --string “google" -j REJECT
源IP为172.168.10.10,内容中含有google就拒绝
iptables -I OUTPUT -m string --algo bm --string 'test' -j LOG
iptables -A INPUT -p tcp --dport 80 -m string --algo bm --string 'GET /index.html' -j LOG
iptables -I OUTPUT -s 192.168.100.150 -m string --algo bm --string 'test' -j REJECT
[root@nginx ~]# iptables -I INPUT -p tcp --dport 80 -m string --algo bm --string 'GET /' -j LOG
[root@nginx ~]# tail -f /var/log/messages
Feb 19 02:50:54 nginx systemd-logind: New session 1882 of user root.
Feb 19 02:50:54 nginx systemd: Starting Session 1882 of user root.
Feb 19 03:01:01 nginx systemd: Started Session 1883 of user root.
Feb 19 03:01:01 nginx systemd: Starting Session 1883 of user root.
Feb 19 03:24:42 nginx systemd-logind: Removed session 1882.
Feb 19 03:24:58 nginx systemd: Started Session 1884 of user root.
Feb 19 03:24:58 nginx systemd-logind: New session 1884 of user root.
Feb 19 03:24:58 nginx systemd: Starting Session 1884 of user root.
Feb 19 03:53:52 nginx kernel: IN=ens192 OUT= MAC=00:0c:29:a9:72:71:00:0c:29:73:98:2f:08:00 SRC=10.2.61.21 DST=10.2.61.22 LEN=114 TOS=0x00 PREC=0x00 TTL=64 ID=59396 DF PROTO=TCP SPT=36804 DPT=80 WINDOW=229 RES=0x00 ACK PSH URGP=0
Feb 19 03:56:36 nginx kernel: IN=ens192 OUT= MAC=00:0c:29:a9:72:71:00:0c:29:73:98:2f:08:00 SRC=10.2.61.21 DST=10.2.61.22 LEN=114 TOS=0x00 PREC=0x00 TTL=64 ID=7382 DF PROTO=TCP SPT=36806 DPT=80 WINDOW=229 RES=0x00 ACK PSH URGP=0
mark:
匹配带有指定mark值的数据包。
参数 | 说明 |
---|---|
--mark value | 匹配mark标记为value的数据包 |
iptables -t mangle -A INPUT -m mark --mark 1 -j DROP
ttl
匹配符合规则的ttl值的数据包。
参数 | 说明 |
---|---|
--ttl -eq 100 | 匹配TTL值为100的数据包 |
--ttl -gt 100 | 匹配TTL值大于100的数据包 |
--ttl -lt 100 | 匹配TTL值小于100的数据包 |
iptables -A OUTPUT -m ttl --ttl-eq 100 -j ACCEPT
time
定时执行策略,根据将报文到达的时间与指定的时间范围进行匹配。
–datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]] 日期 #起始日期
–datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]] #结束日期
–timestart hh:mm[:ss] 时间
–timestop hh:mm[:ss]
[!] --monthdays day[,day…] 每个月的几号
[!] --weekdays day[,day…] 星期几,1 – 7 分别表示星期一到星期日
–kerneltz:内核时区,不建议使用,CentOS7系统默认为UTC
注意: centos6 不支持kerneltz ,–localtz指定本地时区(默认)。
-m time | 说明 |
---|---|
--monthdays day1[,day2] | 在每个月的特定天匹配 |
--timestart hh:mm:ss | 在每天的指定时间开始匹配 |
--timestop hh:mm:ss | 在每天的指定时间停止匹配 |
--weekdays day1[,day2] | 在每个星期的指定工作日匹配,值可以是1-7 |
-m time --weekdays Sa,Su
-m time --datestart 2007-12-24 --datestop 2007-12-27
-m time --datestart 2007-01-01T17:00 --datestop 2007-01-01T23:59:59
-m time --timestart 12:30 --timestop 13:30
-m time --weekdays Fr --monthdays 22,23,24,25,26,27,28
-m time --weekdays Mo --timestart 23:00 --timestop 01:00
[root@CentOS7 ~]# iptables -A INPUT -s 172.16.0.0/16 -d 172.16.100.10 -p tcp --dport 80 -m time --timestart 14:30 --timestop 18:30 --weekdays Sat,Sun --kerneltz -j DROP
iptables -A INPUT -i eth0 -m time --weekdays 1,2,3,4 -jACCEPT
iptables -A INPUT -i eth0 -j DROP
限制在某个时间段内拒绝某些请求:
iptables -IINPUT -d 192.168.100.230 -p tcp --dport 80 -m time --timestart 14:00 --timestop 16:00 -j REJECT
一周内固定时间限制:
iptables -I FORWARD -s 172.17.1.132 -d 192.168.1.119 -m time --timestart 09:40 --timestop 09:59 --weekdays Wed,Thu -j DROP
晚上八点早上6点禁止访问:
iptables -I INPUT -p tcp -d 10.2.61.22 --dport 80 -m time --timestart 20:00 --timestop 06:00 -j REJECT
connlimit
并发连接限制 ,单个地址或者地址块,根据每客户端IP做并发连接数数量匹配。
- 可防止Dos(Denial of Service,拒绝服务)攻击
- --connlimit-upto n #连接的数量小于等于时匹配
–connlimit-above n #连接的数量大于时匹配 - 通常分别与默认的拒绝或允许策略配合使用
连接数超过2过以上就拒绝:
[root@CentOS7 ~]# iptables -A INPUT -d 172.16.100.10 -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 2 -j REJECT
iptables -I INPUT -d 192.168.100.230 -p tcp --syn --dport 22 -m connlimit --connlimit-above 4 -j REJECT
限制ssh 新建链接数量为3 ,首先需要有放行的策略 ,否则拒绝:
[root@nginx ~]# iptables -L -n -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
3 152 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x17/0x02 #conn src/32 > 3 reject-with icmp-port-unreachable
514 42092 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
0 0 REJECT tcp -- * * 0.0.0.0/0 10.2.61.22 tcp dpt:80 TIME from 20:00:00 to 06:00:00 UTC reject-with icmp-port-unreachable
0 0 REJECT tcp -- * * 0.0.0.0/0 10.2.61.22 tcp dpt:80 TIME from 20:00:00 to 06:00:00 UTC reject-with icmp-port-unreachable
2 228 LOG tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 STRING match "GET /" ALGO name bm TO 65535 LOG flags 0 level 4
7 379 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080,8090 source IP range 10.2.61.1-10.2.61.100
23 1189 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080,8090 source IP range 10.2.61.1-10.2.61.100
0 0 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080,8090 source IP range 10.0.0.1-10.0.0.255
0 0 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080:8090 source IP range 10.0.0.1-10.0.0.255
0 0 tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080
0 0 ACCEPT icmp -- * * 0.0.0.0/0 10.2.61.22 icmptype 0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy DROP 15 packets, 1106 bytes)
pkts bytes target prot opt in out source destination
6 1102 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 8080,8090 destination IP range 10.2.61.1-10.2.61.100
16 2176 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 8080,8090 destination IP range 10.2.61.1-10.2.61.100
0 0 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 8080,8090 destination IP range 10.0.0.1-10.0.0.255
0 0 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 8080:8090 destination IP range 10.0.0.1-10.0.0.255
3521 586K ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 22,80
2499 463K ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 tcp spt:22
0 0 ACCEPT icmp -- * * 10.2.61.22 0.0.0.0/0 icmptype 8
[root@nginx ~]# iptables -I INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 3 -j REJECT
[root@nginx ~]# iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT #插入序号为1 的规则
limit
基于收发报文的速率做匹配,限制流量。
令牌桶过滤器
- –limit # [/second|/minute|/hour|/day]
- –limit-burst number
ping172.16.100.10每分钟限制8个,广播报文5个,其余ping拒绝:
[root@CentOS7 ~]# iptables -I INPUT -d 172.16.100.10 -p icmp --icmp-type 8 -m limit --limit 10/minute --limit-burst 5 -j ACCEPT
[root@CentOS7 ~]# iptables -I INPUT 2 -p icmp -j REJECT
限制 icmp ping 包峰值 5 个 ,每分钟30 个:
iptables -A INPUT -d 192.168.100.230 -p icmp --icmp-type 8 -m limit --limit-burst 5 --limit 30/minute -j ACCEPT
limit和limit-burst
-m limit --limit 1000/s #设置最大平均匹配速率
-m limit --limit-burst 15 #设置一开始匹配的最大数据包数量
-m limit --limit 5/m --limit-burst 15 #表示一开始能匹配的数据包数量为15个,每匹配到一个,limit-burst的值减1,所以匹配到15个时,该值为0,以后每过12s,limit-burst的值会加1,表示又能匹配1个数据包。
注意要点:
A、--limit-burst的值要比--limit的大;
B、limit本身没有丢弃数据包的功能,因此,需要第二条规则一起才能实现限速的功能;
这个匹配操作必须由-m limit明确指定才能使用。有了他的帮助,就能对指定的规则的日志数量加以限制,以免你被信息的洪流淹没哦。比如,你能事先设定一个限定值,当符合条件的包的数量不超过他时,就记录;超过了,就不记录了。我们能控制某条规则在一段时间内的匹配次数(也就是能匹配的包的数量),这样就能够减少DoS syn flood攻击的影响。这是他的主要作用,当然,更有非常多其他作用(注:比如,对于某些不常用的服务能限制连接数量,以免影响其他服务)。limit match也能用英文感叹号取反,如:-m limit ! --limit 5/s表示在数量超过限定值后,所有的包都会被匹配。
limit match的工作方式就像一个单位大门口的保安,当有人要进入时,需要找他办理通行证。早上上班时,保安手里有一定数量的通行证,来一个人,就签发一个,当通行证用完后,再来人就进不去了,但他们不会等,而是到别的地方去(在iptables里,这相当于一个包不符合某条规则,就会由后面的规则来处理,如果都不符合,就由缺省的策略处理)。但有个规定,每隔一段时间保安就要签发一个新的通行证。这样,后面来的人如果恰巧赶上,也就能进去了。如果没有人来,那通行证就保留下来,以备来的人用。
如果一直没人来,可用的通行证的数量就增加了,但不是无限增大的,最多也就是刚开始时保安手里有的那个数量。也就是说,刚开始时,通行证的数量是有限的,但每隔一段时间就有新的通行证可用。limit match有两个参数就对应这种情况,--limit-burst指定刚开始时有多少通行证可用,--limit指定要隔多长时间才能签发一个新的通行证。要注意的是,我这里强调的是“签发一个新的通行证”,这是以iptables的角度考虑的。
在你自己写规则时,就要从这个角度考虑。比如,你指定了--limit 3/minute --limit-burst 5 ,意思是开始时有5个通行证,用完之后每20秒增加一个(这就是从iptables的角度看的,要是以用户的角度看,说法就是每一分钟增加三个或每分钟只能过三个)。你要是想每20分钟过一个,只能写成--limit 3/hour --limit-burst 5,也就是说你要把时间单位凑成整的。
为limit match设置最大平均匹配速率,也就是单位时间内limit match能匹配几个包。他的形式是个数值加一个时间单位,能是/second /minute /hour /day 。默认值是每小时3次(用户角度),即3/hour ,也就是每20分钟一次(iptables角度)。
iptables -A INPUT -m limit --limit 3/hour
这里定义的是limit match的峰值,就是在单位时间(这个时间由上面的--limit指定)内最多可匹配几个包(由此可见,--limit-burst的值要比--limit的大)。默认值是5。
iptables -A INPUT -m limit --limit-burst 5
假设如下的规则:
iptables -A INPUT -p icmp -m limit --limit 6/m --limit-burst 5 -j ACCEPT
iptables -P INPUT DROP
然后从另一部主机上ping这部主机,就会发生如下的现象:
首先我们能看到前四个包的回应都非常正常,然后从第五个包开始,我们每10秒能收到一个正常的回应。这是因为我们设定了单位时间(在这里是每分钟)内允许通过的数据包的个数是每分钟6个,也即每10秒钟一个;其次我们又设定了事件触发阀值为5,所以我们的前四个包都是正常的,只是从第五个包开始,限制规则开始生效,故只能每10秒收到一个正常回应。
假设我们停止ping,30秒后又开始ping,这时的现象是:
前两个包是正常的,从第三个包开始丢包,这是因为在这里我的允许一个包通过的周期是10秒,如果在一个周期内系统没有收到符合条件的包,系统的触发值就会恢复1,所以如果我们30秒内没有符合条件的包通过,系统的触发值就会恢复到3,如果5个周期内都没有符合条件的包通过,系统都触发值就会完全恢复。
state
根据”连接追踪机制“去检查连接的状态,较耗资源。
参数 | 说明 |
---|---|
--state value | value可以为NEW、RELATED(有关联的)、ESTABLISHED、INVALID(未知连接) |
conntrack机制:追踪本机上的请求和响应之间的关系
可追踪链接状态有如下几种:
NEW:新发出请求;连接追踪信息库中不存在此连接的相关信息条目,因此,将其识别为第一次发出的请求;
ESTABLISHED:NEW状态之后,连接追踪信息库中为其建立的条目失效之前期间内所进行的通信状态;
RELATED:新发起的但与已有连接相关联的连接,如:ftp协议中的数据连接与命令连接之间的关系;
INVALID:无效的连接,如flag标记不正确;
UNTRACKED:未进行追踪的连接,如raw表中关闭追踪;
新发起和已有的接收:
[root@CentOS7 ~]# iptables -A INPUT -d 172.16.1.10 -p tcp -m multiport --dports 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT
已经连接的接收,其余不接受:
[root@CentOS7 ~]# iptables -A OUTPUT -s 172.16.1.10 -p tcp -m multiport --sports 22,80 -m state --state ESTABLISHED -j ACCEPT
追踪信息,已经追踪到的并记录下来的连接信息库:
/proc/net/nf_conntrack
调整连接追踪功能所能够容纳的最大连接数量:
/proc/sys/net/nf_conntrack_max
[root@nginx ~]# cat /proc/sys/net/netfilter/nf_conntrack_max #centos7 查看链接追中最大限制
65536
不同的协议的连接追踪时长:
/proc/sys/net/netfilter/
注意:CentOS7 需要加载模块: modprobe nf_conntrack_ipv4
iptables的链接跟踪表最大容量为/proc/sys/net/nf_conntrack_max,各种状态的超时链接会从表中删除;当模板满载时,后续连接可能会超时。
解决方法两个:
(1) 加大nf_conntrack_max 值:
vi /etc/sysctl.conf
net.nf_conntrack_max = 393216
net.netfilter.nf_conntrack_max = 393216
(2) 降低 nf_conntrack timeout时间:
vi /etc/sysctl.conf
net.netfilter.nf_conntrack_tcp_timeout_established = 300
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
iptables -t nat -L -n
对于访问本机的80 端口 ,只允许NEW 和ESTABLISHED 状态链接,访问 对于 80 端口的回应只允许回应ESTABLISHED:
iptables -I INPUT -p tcp -d 192.168.100.230 --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
[root@nginx ~]# iptables -I INPUT -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
[root@nginx ~]# iptables -I OUTPUT -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
[root@nginx ~]# iptables -L -n -v
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 state NEW,ESTABLISHED
7 374 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 state NEW,ESTABLISHED
1619 129K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
3 152 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x17/0x02 #conn src/32 > 3 reject-with icmp-port-unreachable
0 0 REJECT tcp -- * * 0.0.0.0/0 10.2.61.22 tcp dpt:80 TIME from 20:00:00 to 06:00:00 UTC reject-with icmp-port-unreachable
0 0 REJECT tcp -- * * 0.0.0.0/0 10.2.61.22 tcp dpt:80 TIME from 20:00:00 to 06:00:00 UTC reject-with icmp-port-unreachable
2 228 LOG tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 STRING match "GET /" ALGO name bm TO 65535 LOG flags 0 level 4
7 379 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080,8090 source IP range 10.2.61.1-10.2.61.100
23 1189 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080,8090 source IP range 10.2.61.1-10.2.61.100
0 0 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080,8090 source IP range 10.0.0.1-10.0.0.255
0 0 ACCEPT tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080:8090 source IP range 10.0.0.1-10.0.0.255
0 0 tcp -- * * 0.0.0.0/0 10.2.61.22 multiport dports 8080
0 0 ACCEPT icmp -- * * 0.0.0.0/0 10.2.61.22 icmptype 0
252 25105 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
0 0 ACCEPT icmp -- * * 0.0.0.0/0 192.168.100.230 icmptype 8 limit: avg 30/min burst 5
151 12612 ACCEPT icmp -- * * 0.0.0.0/0 10.2.61.22 icmptype 8 limit: avg 30/min burst 5
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp spt:80 state ESTABLISHED
6 1102 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp spt:80 state ESTABLISHED
6 1102 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 8080,8090 destination IP range 10.2.61.1-10.2.61.100
16 2176 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 8080,8090 destination IP range 10.2.61.1-10.2.61.100
0 0 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 8080,8090 destination IP range 10.0.0.1-10.0.0.255
0 0 ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 8080:8090 destination IP range 10.0.0.1-10.0.0.255
5219 899K ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 multiport sports 22,80
2499 463K ACCEPT tcp -- * * 10.2.61.22 0.0.0.0/0 tcp spt:22
0 0 ACCEPT icmp -- * * 10.2.61.22 0.0.0.0/0 icmptype 8
125 10428 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
[root@nginx ~]# iptables -L -n --line-number
Chain INPUT (policy DROP)
num target prot opt source destination
1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED #iptables 规则匹配从上往下,NEW 状态第一次,把 ESTABLISHED 放在第一位增加后续访问的命中率,提升速度
2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 state NEW
3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 80,8080,8090,8888 state NEW
4 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 0
5 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy DROP)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED #OUTPUT 规则中允许进入的数据就允许出去,
2 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmptype 8
开放被动模式的ftp服务:
yum install vsftpd
systemctl start vsftpd
vim /etc/sysconfig/iptables-config
IPTABLES_MODULES=“nf_conntrack_ftp"
modprobe nf_conntrack_ftp
iptables -F
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -vnL
-j LOG 记录日志
LOG:非中断target,本身不拒绝和允许,放在拒绝和允许规则前并将日志记录在/var/log/messages系统日志中:
–log-level level 级别: debug,info,notice, warning, error, crit, alert,emerg
–log-prefix prefix 日志前缀,用于区别不同的日志,最多29个字符
iptables -I INPUT -s 10.0.1.0/24 -p tcp -m multiport --dports 80,21,22,23 -m state --state NEW -j LOG --log-prefix "new connections: "
规则
任何不允许的访问,应该在请求到达时给予拒绝;
规则在链接上的次序即为其检查时的生效次序;
基于上述,规则优化:
1 安全放行所有入站和出站的状态为ESTABLISHED状态连接
2 谨慎放行入站的新请求
3 有特殊目的限制访问功能,要在放行规则之前加以拒绝
4 同类规则(访问同一应用),匹配范围小的放在前面,用于特殊处理
5 不同类的规则(访问不同应用),匹配范围大的放在前面
6 应该将那些可由一条规则能够描述的多个规则合并为一条
7 设置默认策略,建议白名单(只放行特定连接)
1) iptables -P,不建议
2) 建议在规则的最后定义规则做为默认策略
备份及重新加载
CentOS 7 重新载入预存规则文件中规则:
iptables-restore < /PATH/FROM/SOME_RULES_FILE
-n, --noflush:不清除原有规则
-t, --test:仅分析生成规则集,但不提交
CentOS 6:
service iptables restart #会自动从/etc/sysconfig/iptables 重新载入规则。
开机自动重载规则文件中的规则:
(1) 用脚本保存各iptables命令;让此脚本开机后自动运行/etc/rc.d/rc.local文件中添加脚本路径
/PATH/TO/SOME_SCRIPT_FILE;
(2) 用规则文件保存各规则,开机时自动载入此规则文件中的规则。
/etc/rc.d/rc.local文件添加:
iptables-restore < /PATH/FROM/IPTABLES_RULES_FILE
路由
搭建环境如下:
1、开启转发功能,使centos6和centos7互通:
[root@firewalld ~]# vim /etc/sysctl.conf
net.ipv4.ip_forward=1
[root@CentOS7 ~]# sysctl -p
2、centos6能ping通centos7,但centos7不能ping通centos6:
[root@firewalld ~]# iptables -A FORWARD -j REJECT 拒绝所有
[root@firewalld ~]# iptables -I FORWARD -s 192.168.8.0/24 -p icmp --icmp-type 8 -j ACCEPT
源地址192.168.8.0/24ICMP请求报文通过
[root@firewalld ~]# iptables -I FORWARD -d 192.168.8.0/24 -p icmp --icmp-type 0 -j ACCEPT
目标地址192.168.8.0/24ICMP响应报文通过
------------------------------------------------------------------------------------------
第二种方式实现
[root@firewalld ~]# iptables -vnL
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT icmp -- * * 0.0.0.0/0 192.168.8.0/24 icmptype 0
0 0 ACCEPT icmp -- * * 192.168.8.0/24 0.0.0.0/0 icmptype 8
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
[root@firewalld ~]# iptables -D FORWARD 1
[root@firewalld ~]# iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
添加状态,建立了连接的就接受(ping出去请求报文已经发出)
[root@firewalld ~]# iptables -vnL
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
0 0 ACCEPT icmp -- * * 192.168.8.0/24 0.0.0.0/0 icmptype 8
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
3、centos7httpd服务,centos6能访问
[root@firewalld ~]# iptables -I FORWARD -s 192.168.8.0/24 -p tcp --dport 80 -j ACCEPT
返回的规则已经建立state
添加443端口
[root@firewalld ~]# iptables -R FORWARD 1 -s 192.168.8.0/24 -p tcp -m multiport --dport 80,443 -j ACCEPT
4、centos7可以访问centos6http
[root@firewalld ~]# iptables -I FORWARD 5 -d 192.168.8.6 p tcp -m multiport --dport 80,443 -j ACCEPT
[root@CentOS6 ~]# yum install mod_ssl 安装ssl模块,重启服务
[root@CentOS7 ~]# curl -k https://192.168.8.6
/var/www/html/index.html
自定义链
相当于函数,可以引用,方便管理。
- -N:new, 自定义一条新的规则链
- -X:delete,删除自定义的空的规则链
- -P:Policy,设置默认策略;对filter表中的链而言,其默认策略有:
- ACCEPT:接受
- DROP:丢弃
- -E:重命名自定义链;引用计数不为0的自定义链不能够被重命名,也不能被删除
[root@firewalld ~]# iptables -F
[root@firewalld ~]# iptables -A FORWARD -j REJECT
[root@firewalld ~]# iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@firewalld ~]# iptables -N fromlantointernet
[root@firewalld ~]# iptables -E fromlantointernet TOINT
[root@firewalld ~]# iptables -A TOINT -s 192.168.8.0/24 -p tcp -m multiport --dport 80,443 -j ACCEPT
[root@firewalld ~]# iptables -A TOINT 2 -s 192.168.8.0/24 -p icmp --icmp-type 8 -j ACCEPT
[root@firewalld ~]# iptables -I FORWARD -vnL
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 TOINT all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain TOINT (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 192.168.8.0/24 0.0.0.0/0 multiport dports 80,443
0 0 ACCEPT icmp -- * * 192.168.8.0/24 0.0.0.0/0 icmptype 8
修改规则可以修改自定义链,方便管理,如增加22端口
[root@firewalld ~]# iptables -R TOINT 1 -s 192.168.8.0/24 -p tcp -m multiport --dport 80,443,22 -j ACCEPT
[root@firewalld ~]# iptables -vnL
Chain TOINT (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 192.168.8.0/24 0.0.0.0/0 multiport dports 80,443,22
0 0 ACCEPT icmp -- * * 192.168.8.0/24 0.0.0.0/0 icmptype 8
删除自定义链
[root@firewalld ~]# iptables -D FORWARD 1 删除连接
[root@firewalld ~]# iptables -F TOINT 清空规则
[root@firewalld ~]# iptables -X TOINT 删除链
[root@firewalld ~]# iptables -vnL
Chain INPUT (policy ACCEPT 10 packets, 724 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT 6 packets, 696 bytes)
pkts bytes target prot opt in out source destination
查出网络出口的公网IP:
[root@CentOS7 ~]# curl http://ipinfo.io/ip
125.85.172.57
[root@CentOS7 ~]# curl ifconfig.me
125.85.172.57
SNAT
1)NAT: network address translation
PREROUTING,INPUT,OUTPUT,POSTROUTING
请求报文:修改源/目标IP,由定义如何修改;
响应报文:修改源/目标IP,根据跟踪机制自动实现;
2)SNAT:source NAT POSTROUTING, INPUT
让本地网络中的主机通过某一特定地址访问外部网络,实现地址伪装;
请求报文:修改源IP;
3)DNAT:destination NAT PREROUTING , OUTPUT
把本地网络中的主机上的某服务开放给外部网络访问(发布服务和端口映射),但隐藏真实IP;
请求报文:修改目标IP;
4)PNAT: port nat
端口和IP都进行修改;
环境搭建(centos7不配网关)。
内网ping外网,源IP需替换,为SNAT,分为固定IP和ADSL拨号上网。
- 固定IP
[root@CentOS7 ~]# vieth0
IPADDR=172.16.8.17
NETMASK=255.255.255.0
DNS1=114.114.114.114
DNS2=222.222.222.222
[root@firewalld ~]# iptables -t nat -A POSTROUTING -s 192.168.8.0/24 -j SNAT --to-source 172.16.8.7
[root@firewalld ~]# iptables -vnL -t nat
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 SNAT all -- * * 192.168.8.0/24 0.0.0.0/0 to:172.16.8.7
centos6连接centos7,centos主机认为时防火墙在连他
[root@CentOS6 ~]# ssh 172.16.8.17
[root@CentOS6 ~]# ss -nt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 192.168.8.6:43954 172.16.8.17:22
[root@CentOS7 ~]# ss -nt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 52 172.16.8.17:22 172.16.8.1:65342
ESTAB 0 0 172.16.8.17:22 172.16.8.7:43954
- ADSL
[root@firewalld ~]# iptables -t nat -I POSTROUTING 1 -s 192.168.8.0/24 -j MASQUERADE 插入
[root@firewalld ~]# iptables -t nat -D POSTROUTING 2 删除
[root@firewalld ~]# iptables -vnL -t nat 查看
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * * 192.168.8.0/24 0.0.0.0/0
DNAT
外部网络连接局域网内部IP时,需要将目标IP替换。
[root@firewalld ~]# iptables -t nat -A PREROUTING -d 172.16.8.7 -j DNAT --to-destination 192.168.37.6
替换端口一致
[root@firewalld ~]# iptables -t nat -A PREROUTING -d 172.16.8.7 -p tcp --dport 80 -j DNAT --to-destination 192.168.37.6:8080
外网80端口映射成8080,相当于防火墙配置端口映射:192.168.8.6:8080-----172.16.8.7:80
NAT(转发)
跟防火墙没有关系,是自己主机配置,如别人访问本主机时,将80端口转换成8080。
[root@CentOS6 ~]# iptables -t nat -A PREROUTING -d 192.168.8.6 -p tcp --dport 80 -j REDIRECT --to-ports 8080
只要别人访问80端口自动转成8080
[root@CentOS6 ~]# vim /etc/httpd/conf/httpd.conf
Listen 8080
[root@CentOS6 ~]# service httpd restart
[root@firewalld ~]# iptables -t nat -R PREROUTING 1 -d 172.16.8.7 -p tcp --dport 80 -j DNAT --to-destination 192.168.8.6:80
[root@CentOS7 ~]# curl 172.16.8.7
/var/www/html/index.html
[root@CentOS7 ~]# curl 192.168.8.6
/var/www/html/index.html
其他操作
service iptables save
• 注:链路规则表保存在:/etc/sysconfig/iptables •
iptables –t filter –nvL #查看防火墙链状态
• 注:标黄的部分是开机到现在所访问的流量。
二、firewalld防火墙设置
Centos7以上的发行版都试自带了firewalld防火墙的,firewalld去带了iptables防火墙。其原因是iptables的防火墙策略是交由内核层面的netfilter网络过滤器来处理的,而firewalld则是交由内核层面的nftables包过滤框架来处理。
相较于iptables防火墙而言,firewalld支持动态更新技术并加入了区域(zone)的概念。
firewalld将所有的网络流量都分类汇聚到zones中,它通过zones管理防火墙规则,每一个进入系统的数据包,都会首先检查源IP地址和接口,如果与某个zone匹配,则该zone的规则将生效。而每个zone都会有开启或关闭服务和端口的列表,以实现允许或拒绝链接服务和端口。如果数据包的源IP地址和网卡接口都不能和任何zone匹配,则该数据包将匹配默认zone,一般情况下是一个public的默认zone。firewalld会提供block,dmz,drop,external,home,internal,public,trusted,work这九个zone。比如有一个数据包从eno1网卡进入本机,根据规则进入work这个zone而在work这和zone中有允许访问http服务的规则,则最后该数据包将可以进入本机并访问http服务
大部分zone都定义的有自己的允许规则,规则通过端口/协议(631/udp)或者预定义的服务(ssh)这种形式设置,如果数据包没有匹配这些允许的规则,则该数据包一般会被防火墙拒绝。但是如果有名为trusted的zone,默认会运行所有的数据流量,如果有一个数据包进入了该zone,则被允许访问所有的资源。
firewalld服务由firewalld包提供,firewalld支持划分区域zone,每个zone可以设置独立的防火墙规则。
归入zone顺序:
1)先根据数据包中源地址,将其纳为某个zone
2)纳为网络接口所属zone
3)纳入默认zone,默认为public zone,管理员可以改为其它zone
网卡默认属于public zone,lo网络接口属于trusted zone。
firewalld zone分类
从上图我们可以看到,firewalld默认出口是全放开的。
动静态更新技术之间的区别:iptables每一个更改都需要先清除所有旧有的规则,然后重新加载所有的规则(包括新的和修改后的规则);而firewalld任何规则的变更都不需要对整个防火墙规则重新加载。
firewalld服务的主配置文件是firewalld.conf,防火墙策略的配置文件是以xml格式为主,存放在以下两个目录里:
/etc/firewalld # 用户配置文件
/usr/lib/firewalld #系统配置文件,预定义配置文件
预定义服务
firewall-cmd --get-services 查看预定义服务列表。
/usr/lib/firewalld/services/*.xml预定义服务的配置。
firewalld三种配置方法:
有基于CLI(命令行界面)和基于GUI(图形用户界面)两种管理方式。
firewall-config (firewall-config包)图形管理工具
firewall-cmd (firewalld包)终端命令行管理工具
/etc/firewalld 配置文件,一般不建议
配置文件说明
firewalld 存放配置文件有两个目录,/usr/lib/firewalld 和 /etc/firewalld,前者存放了一些默认的文件,后者主要是存放用户自定义的数据,所以我们添加的service或者rule都在后者下面进行。
server 文件夹存储服务数据,就是一组定义好的规则。
zones 存储区域规则。
firewalld.conf 默认配置文件,可以设置默认使用的区域,默认区域为 public,对应 zones目录下的 public.xml。
vim /etc/firewalld/zones/public.xml
<rule family="ipv4">
<source address="192.168.5.14"/> ----如果对所有ip开放此端口可以把这行删了
<port protocol="tcp" port="80"/>
<accept/>
</rule>
systemctl restart firewalld
配置文件设置:
1、添加需要的规则,开放通源ip为122.10.70.234,端口514,协议tcp;
2、开放通源ip为123.60.255.14,端口10050-10051,协议tcp;
3、开放通源ip为任意,端口9527,协议tcp;
<?xml version="1.0" encoding="utf-8"?>
<zone>
<short>Public</short>
<description>For use in public areas.</description>
<rule family="ipv4">
<source address="122.10.70.234"/>
<port protocol="udp" port="514"/>
<accept/>
</rule>
<rule family="ipv4">
<source address="123.60.255.14"/>
<port protocol="tcp" port="10050-10051"/>
<accept/>
</rule>
<rule family="ipv4">
<source address="192.249.87.114"/> 放通指定ip,指定端口、协议
<port protocol="tcp" port="80"/>
<accept/>
</rule>
<rule family="ipv4"> 放通任意ip访问服务器的9527端口
<port protocol="tcp" port="9527"/>
<accept/>
</rule>
</zone>
firewall-cmd命令使用
firewalld的参数一般都是以“长格式”来提供的,但是在RHEL7系统里支持部分命令的参数补齐,其中就包括firewall-cmd命令,也就是说可以用Tab键来补齐长格式参数,很酷吧。
firewall-cmd命令中使用的参数以及作用:
参数 作用
–get-default-zone 查访默认的区域名称
–set-default-zone=<区域名称> 设置默认的区域,使其永久生效
–get-zones 显示可用的区域
–get-services 显示预定义的服务
–get-active-zones 显示当前正在使用的区域、来源地址和网卡名称
–add-source= 将源自此IP或子网的流量导向指定的区域
–remove-source= 不再将源自此IP或子网的流量导向这个区域
–add-interface=<网卡名称> 将源自该网卡的所有流量都导向某个指定区域
–change-interface=<网卡名称> 将某个网卡与区域进行关联
–list-all 显示当前区域的网卡配置参数、资源、端口以及服务等信息
–list-all-zones 显示所有区域的网卡配置参数、资源、端口以及服务等信息
–add-service=<服务名> 设置默认区域允许该服务的流量
–add-port=<端口号/协议> 设置默认区域允许该端口的流量
–remove-service=<服务名> 设置默认区域不再允许该服务的流量
–remove-port=<端口号/协议> 设置默认区域不再允许该端口的流量
–reload 让“永久生效”的配置规则立即生效,并覆盖当前的配置规则
–panic-on 开启应急状况模式
–panic-off 关闭应急状况模式
firewalld配置的防火墙策略默认为运行时(Runtime)模式,又称为当前生效模式,而且随着系统的重启会失效。如果想让配置策略一直存在,就需要使用永久(Permanent)模式了,方法就是在firewall-cmd命令后面添加–permanent参数,这样配置的防火墙策略就可以永久生效了。但是,永久生效模式有一个“不近人情”的特点,就是使用它设置的策略只有在系统重启后才会生效。如果想让配置的永久策略立即生效,需要手动执行firewall-cmd --reload命令。
firewall-config图形工具配置时,需注意runtime模式下配置为运行模式,保存有几种操作,permanent下再操作一遍保存,或者options下操作。
注:remove掉ssh服务或者ssh端口,当前远程登陆会话不会断开,退出后就无法远程连接了。
firewalld服务启动、重启、停止:
systemctl start firewalld
systemctl restart firewalld
systemctl stop firewalld
重新加载防火墙配置:
firewall-cmd --reload
查看firewalld的运行状态:
firewall-cmd --state
查看默认当前使用的区域:
firewall-cmd --get-default-zone
查看系统默认活动区域名称、来源地址和关联的网卡:
firewall-cmd --get-active-zones
查看指定接口所属区域:
firewall-cmd --get-zone-of-interface=eth0
查看所有可用区域:
firewall-cmd --get-zones
查看区域的所有设置:
firewall-cmd --zone=internal --list-all # 查看指定区域设置
firewall-cmd --list-all # 查看默认区域设置
Target:目标
icmp-block-inversion:ICMP协议类型黑白名单开关(yes/no)
Interfaces:关联的网卡接口
sources:来源,可以是IP地址,也可以是mac地址
services:允许的服务
ports:允许的目标端口,即本地开放的端口
protocols:允许通过的协议
masquerade:是否允许伪装(yes/no),可改写来源IP地址及mac地址
forward-ports:允许转发的端口
source-ports:允许的来源端口
icmp-blocks:可添加ICMP类型,当icmp-block-inversion为no时,这些ICMP类型被拒绝;当icmp-block-inversion为yes时,这些ICMP类型被允许。
rich rules:富规则,即更细致、更详细的防火墙规则策略,它的优先级在所有的防火墙策略中也是最高的。
查看所有预设的服务:
firewall-cmd --get-services
此时将会列出/usr/lib/firewalld/services/目录中所有的服务名称。
查看所有区域的设置:
firewall-cmd --list-all-zones
查看指定网卡所在的区域:
firewall-cmd --get-zone-of-interface=ens192
把firewalld的当前默认区域设置为drop,此为永久设置:
firewall-cmd --set-default-zone=drop
把ens32网卡关联的区域修改为drop:
firewall-cmd --permanent --zone=drop --change-interface=ens32 # 永久设置
firewall-cmd --zone=drop --change-interface=ens32 # 当前生效
我们后面的设置命令将全部使用运行时模式,即当前生效模式。
将来自ens33网卡的流量都作用到默认的drop区域:
firewall-cmd --zone=drop -add-interface=ens33 # 作用在指定区域
firewall-cmd -add-interface=ens33 # 作用在默认区域
firewall-cmd -remove-interface=ens33 # 禁止ens33网卡作用在drop区域
注:不指定–zone参数的话,将会对默认区域进行设置。
启动关闭firewalld防火墙服务的应急状况模式,远程连接服务器时请慎用:
firewall-cmd --panic-on # 拒绝所有流量,远程连接会立即断开,只有本地能登陆
firewall-cmd --panic-off # 取消应急模式,但需要重启firewalld后才可以远程ssh
firewall-cmd --query-panic # 查看是否为应急模式
设置一个来源地址作用在drop区域上面:
firewall-cmd --zone=drop --add-source=192.168.1.12 # 作用在指定区域
firewall-cmd --add-source=192.168.1.12 # 作用在默认区域
firewall-cmd --remove-source=192.168.1.12 # 取消源IP为192.168.1.12的包作用在drop区域
说明:凡是IP为192.168.1.12发来包将会使用drop区域设置的规则。
对于一个接收到的请求具体使用哪个zone,firewalld是通过三种方式来判断的:
1、source,来源地址
2、Interface,接收请求的网卡
3、firewalld配置的默认区域(zone)
这三个方式的优先级按顺序依次降低,也就是说如果按照source可以找到就不会再按interface去找,如果前两个都找不到才会使用第三个默认区域。
查询drop区域是否允许请求ssh和https服务的流量:
firewall-cmd --zone=drop --query-service=ssh
firewall-cmd --zone=drop --query-service=https
在drop区域开放https服务:
firewall-cmd --zone=drop --add-service=https
取消开放https服务,即禁止https服务:
firewall-cmd --zone=drop --remove-service=https
放8010端口:
firewall-cmd --zone=public --permanent --add-port=8010/tcp
--zone=public:指定的zone为public;
--permanent:表示设置为持久;
结果如下:
--zone=drop这样设置的话,会在drop.xml文件中新增一条。
查看:
firewall-cmd --zone=public --query-port=8010/tcp && firewall-cmd --reload
取消开放8010端口
firewall-cmd --zone=public --remove-port=8010/tcp
开放8080和8081端口:
firewall-cmd --zone=drop --add-port=8080-8081/tcp
查询drop区域开放了哪些端口:
firewall-cmd --zone=drop --list-ports
允许icmp协议流量,即允许ping:
firewall-cmd --zone=drop --add-protocol=icmp
取消允许icmp协议的流量,即禁ping:
firewall-cmd --zone=drop --remove-protocol=icmp
查询drop区域开放了哪些协议:
firewall-cmd --zone=drop --list-protocols
将原本访问本机888端口的流量转发到本机22端口:
firewall-cmd --zone=drop --add-forward-port=port=888:proto=tcp:toport=22
将原本访问本机888端口的流量转发到ip为192.168.2.208的主机的22端口,需要开启masquerade:
firewall-cmd --zone=drop --add-masquerade
firewall-cmd --zone=drop --add-forward-port=port=888:proto=tcp:toport=22:toaddr=192.168.2.208
测试端口转发功能是否生效。
在客户端尝试访问192.168.2.210主机的888端口,连上去后发现实际连接的是192.168.2.208主机,测试OK。
富规则
允许指定ip的所有流量:
firewall-cmd --add-rich-rule="rule family="ipv4" source address="<ip>" accept"
firewall-cmd --add-rich-rule="rule family="ipv4" source address="192.168.2.1" accept" # 表示允许来自192.168.2.1的所有流量
允许指定ip的指定协议:
firewall-cmd --add-rich-rule="rule family="ipv4" source address="<ip>" protocol value="<protocol>" accept"
firewall-cmd --add-rich-rule="rule family="ipv4" source address="192.168.2.208" protocol value="icmp" accept" # 允许192.168.2.208主机的icmp协议,即允许192.168.2.208主机ping
允许指定ip访问指定服务:
firewall-cmd --add-rich-rule="rule family="ipv4" source address="<ip>" service name="<service name>" accept"
firewall-cmd --add-rich-rule="rule family="ipv4" source address="192.168.2.208" service name="ssh" accept" # 允许192.168.2.208主机访问ssh服务
允许指定ip访问指定端口:
firewall-cmd --add-rich-rule="rule family="ipv4" source address="<ip>" port protocol="<port protocol>" port="<port>" accept"
firewall-cmd --add-rich-rule="rule family="ipv4" source address="192.168.2.1" port protocol="tcp" port="22" accept" # 允许192.168.2.1主机访问22端口
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="21.20.3.33" port protocol="tcp" port="11211" accept" #memcached端口设置,允许主机21.20.3.33访问11211端口
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="21.20.3.33" port protocol="tcp" port="6379" accept" #redis端口设置,允许主机21.20.3.33访问6379端口
允许192.168.2.0/24网段的主机访问22端口 :
firewall-cmd --zone=drop --add-rich-rule="rule family="ipv4" source address="192.168.2.0/24" port protocol="tcp" port="22" accept"
禁止指定ip/网段:
将 accept 设置为 reject 表示拒绝,设置为 drop表示直接丢弃(会返回timeout连接超时)。
firewall-cmd --zone=drop --add-rich-rule="rule family="ipv4" source address="192.168.2.0/24" port protocol="tcp" port="22" reject"
拒绝192.168.10.0/24网段的所有用户访问本机的ssh服务(22端口):
firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.10.0/24" service name="ssh" reject"
//显示
success
firewall-cmd --reload
//显示
success
删除规则:
firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="21.20.3.33" port protocol="tcp" port="3306" accept"
firewall-cmd --list-all
最初配置3306端口允许访问,后来根据业务需求,需要严格限制仅允许指定IP访问3306端口:
#Step1:删除原有的3306端口访问规则
firewall-cmd --permanent --remove-port=3306/tcp
#Step2:添加规则
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address=" 192.168.1.100" port protocol="tcp" port="3306" accept"
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="127.0.0.1" port protocol="tcp" port="3306" accept"
#Step3:生效规则
firewall-cmd --reload
#Step4:查看结果
firewall-cmd --list-all
#附:如果需要删除规则,参考
firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address=" 192.168.1.100" port protocol="tcp" port="3306" accept"
firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="127.0.0.1" port protocol="tcp" port="3306" accept"
实验
服务:
firewall-cmd --add-service=<service name> #添加服务
firewall-cmd --remove-service=<service name> #移除服务
端口:
firewall-cmd --add-port=<port>/<protocol> #添加端口/协议(TCP/UDP)
firewall-cmd --remove-port=<port>/<protocol> #移除端口/协议(TCP/UDP)
firewall-cmd --list-ports #查看开放的端口
协议:
firewall-cmd --add-protocol=<protocol> # 允许协议 (例:icmp,即允许ping)
firewall-cmd --remove-protocol=<protocol> # 取消协议
firewall-cmd --list-protocols # 查看允许的协议
[root@firewalld ~]# firewall-cmd --get-zones 列出所有可用区域
block dmz drop external home internal public trusted work
[root@firewalld ~]# firewall-cmd --get-default-zone 查询默认区域
public
[root@firewalld ~]# firewall-cmd --set-default-zone=trusted 设置默认区域
success
[root@firewalld ~]# firewall-cmd --get-default-zone
trusted
[root@firewalld ~]# firewall-cmd --get-active-zones 列出当前正使用的区域及网卡
trusted
interfaces: ens33 ens37
[root@firewalld ~]# firewall-cmd --add-service=ftp 增加服务
success
[root@firewalld ~]# firewall-cmd --list-services
ftp
[root@firewalld ~]# firewall-cmd --permanent --add-service=ftp 保存
[root@firewalld ~]# firewall-cmd --list-all --zone=trusted 列出该域所有配置
trusted (active)
target: ACCEPT
icmp-block-inversion: no
interfaces: ens33 ens37
sources:
services: ftp
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
[root@firewalld ~]# firewall-cmd --permanent --zone=internal --add-source=192.168.0.0/24 在internal zone中增加源地址192.168.0.0/24的永久规则
[root@firewalld ~]# firewall-cmd --permanent --zone=internal --add-service=mysql 在internal zone中增加协议mysql的永久规则
success
[root@firewalld ~]# firewall-cmd --list-all --zone=internal 没有生效
internal
[root@firewalld ~]# firewall-cmd --reload 加载
success
[root@firewalld ~]# firewall-cmd --list-all --zone=internal 生效
internal (active)
配置firewalld:
systemctl mask iptables 禁止手动启动服务,启动需要先停止 systemctl umask iptables
systemctl mask ip6tables
systemctl status firewalld
systemctl enable firewalld
systemctl start firewalld
firewall-cmd --get-default-zone
firewall-cmd --set-default-zone=public
firewall-cmd --permanent --zone=public --list-all
firewall-cmd --permanent --zone=public --add-port 8080/tcp
firewall-cmd —reload
富规则 rich rule:
允许192.168.2.208主机的所有流量:
firewall-cmd --zone=drop --add-rich-rule="rule family="ipv4" source address="192.168.2.208" accept"
允许192.168.2.208主机的icmp协议,即允许192.168.2.208主机ping:
firewall-cmd --add-rich-rule="rule family="ipv4" source address="192.168.2.208" protocol value="icmp" accept"
取消允许192.168.2.208主机的所有流量:
firewall-cmd --zone=drop --remove-rich-rule="rule family="ipv4" source address="192.168.2.208" accept"
允许192.168.2.208主机访问ssh服务:
firewall-cmd --zone=drop --add-rich-rule="rule family="ipv4" source address="192.168.2.208" service name="ssh" accept"
禁止192.168.2.208访问https服务,并返回错误信息:
firewall-cmd --zone=drop --add-rich-rule="rule family="ipv4" source address="192.168.2.208" service name="https" reject"
注:如果是drop的话是直接丢弃,会返回timeout(连接超时)。
允许192.168.2.0/24网段的主机访问22端口:
firewall-cmd --zone=drop --add-rich-rule="rule family="ipv4" source address="192.168.2.0/24" port protocol="tcp" port="22" accept"
拒绝从192.168.0.11的所有流量,当address 选项使用source 或 destination时,必须用family= ipv4 |ipv6:
firewall-cmd --permanent --zone=public --add-rich-rule=‘rule family=ipv4 source address=192.168.0.11/32 reject’
限制每分钟只有两个连接到ftp服务:
firewall-cmd --add-rich-rule=‘rule service name=ftp limit value=2/m accept’
允许新的ipv4和ipv6连接ftp,并使用日志和审核,每分钟允许访问一次:
firewall-cmd --add-rich-rule="rule service name=ftp log limit value="1/m" audit accept"
拒绝来自192.168.2.0/24网段的连接,10秒后自动取消:
firewall-cmd --add-rich-rule="rule family=ipv4 source address=192.168.2.0/24 reject" --timeout=10
允许ipv6地址为2001:db8::/64子网的主机访问dns服务,并且每小时审核一次,300秒后自动取消:
firewall-cmd --add-rich-rule="rule family=ipv6 source address="2001:db8::/64" service name="dns" audit limit value="1/h" reject" --timeout=300
抛弃esp( IPsec 体系中的一种主要协议)协议的所有数据包:
firewall-cmd --permanent --add-rich-rule=‘rule protocol value=esp drop’
接受所有192.168.1.0/24子网端口5900-5905范围的TCP流量:
firewall-cmd --permanent --zone=trusted --add-rich-rule=‘rule family=ipv4 source address=192.168.1.0/24 port port=5900-5905 protocol=tcp accept’
接受ssh新连接,记录日志到syslog的notice级别,每分钟最多三条信息:
firewall-cmd --permanent --zone=work --add-rich-rule='rule service name=“ssh” log prefix="ssh " level=“notice” limit value=“3/m” accept
从2001:db8::/64子网的DNS连接在5分钟内被拒绝,并记录到日志到audit,每小时最大记录一条信息:
firewall-cmd --add-rich-rule=‘rule family=ipv6 source address=“2001:db8::/64” service name=“dns” audit limit value=“1/h” reject’ --timeout=300
接受172.25.X.10/32 httpd新连接,记录日志到syslog的notice级别,每秒钟最多三条信息:
firewall-cmd --permanent --add-rich-rule=‘rule family=ipv4 source address=172.25.X.10/32 service name=“http” log level=notice prefix="NEW HTTP " limit value=“3/s” accept’
伪装和端口转发
伪装NAT:
firewall-cmd --permanent --zone= --add-masquerade
firewall-cmd --query-masquerade 检查是否允许伪装
firewall-cmd --add-masquerade 允许防火墙伪装IP
firewall-cmd --remove-masquerade 禁止防火墙伪装IP
伪装,将来自局域网192.168.2.0/24网段访问外网的流量映射为网络出口公网IP,即修改源IP地址:
firewall-cmd --zone=drop --add-masquerade
firewall-cmd --zone=drop --add-rich-rule="rule family=ipv4 source address=192.168.2.0/24 masquerade"
转发传入的连接9527/TCP,到防火墙的80/TCP到public zone 的192.168.0.254:
firewall-cmd --add-masquerade 启用伪装
firewall-cmd --zone=public --add-forward-port=port=9527:proto=tcp:toport=80:toaddr=192.168.0.254
将来自192.168.2.0/24网段访问本机80端口的流量转发到本机的22端口:
firewall-cmd --zone=drop --add-rich-rule="rule family=ipv4 source address=192.168.2.0/24 forward-port port=80 protocol=tcp to-port=22"
转发从192.168.0.0/24来的,发往80/TCP的流量到防火墙的端口8080/TCP:
firewall-cmd --zone=work --add-rich-rule=‘rule family=ipv4 source address=192.168.0.0/24 forward-port port=80 protocol=tcp to-port=8080’
将来自192.168.2.0/24网段访问本地80端口的流量转发到192.168.2.208主机的22端口:
firewall-cmd --zone=drop --add-rich-rule="rule family=ipv4 source address=192.168.2.0/24 forward-port port=80 protocol=tcp to-port=22 to-addr=192.168.2.208"
图形管理工具
在RHEL7之前的发行版本默认的防火墙中,几乎没有图形化的防火墙管理工具,但是firewalld却有,firewall-config是firewalld防火墙配置管理工具的GUI(图开用户界面)版本,几乎可以实现所有命令行执行的操作。即使没有扎实的Linux命令基础,也完合可以通过它来妥善配置firewalld防火墙策略。Firewall-config的界面如下图所示,功能具体如下:
1、选择运行时(Runtime)模式或永久(Permanent)模式。
2、可选的策略集合区域列表。
3、常用的系统服务列表。
4、当前正在使用的区域。
5、管理当前被选中区域中的服务。
6、管理当前被选中区域中的端口。
7、开启或关闭SNAT(源地址转换协议)技术。
8、设置端口转发策略。
9、控制请求icmp服务的流量。
10、管理防火墙的富规则。
11、管理网卡设备。
12、被选中区域的服务,若勾选了相应服务前面的复选框,则表示允许与之相关的流量。
13、Firewall-config工具的运行状态。
对外开放http服务,如下图:
添加一条防火墙规则,使其放行访问8080-8088端口(TCP协议)的流量,并且永久生效:
单击Options菜单中的Reload Firewalld选项,让上面配置的永久规则立即生效,这与在命令行中执行–reload参数的效果一样。
SNAT技术相信很多人都知道,那现在我们来开启SNAT技术,其实就是命令行下的masquerade。
下面我们来配置一个端口转发规则,将888端口的流量转发到其他主机的22端口上。
注:转发本机端口不需要开启masquerade,转发到别的主机才需要开启masquerade。
配置富规则,允许192.168.2.206主机访问本机的1234端口号:
最后来看一下区域和网卡的关联,增加网卡的话只需要输入网卡名称即可。
三、firewalld防火墙切换为iptables
一般在实际运维中,我们主要使用 iptables做为防火墙,将firewalld服务禁用,避免干扰。
CentOS切换为iptables防火墙
切换到iptables首先应该关掉默认的firewalld,然后安装iptables服务。
1、关闭firewall:
systemctl stop firewalld # 关闭
systemctl disable firewalld # 取消开机启动
2、安装iptables防火墙
yum install iptables-services #安装
3、编辑iptables防火墙配置
vi /etc/sysconfig/iptables
下边是一个完整的配置文件:
vi /etc/sysconfig/iptables
Firewall configuration written by system-config-firewall
Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
:wq! #保存退出
service iptables start #开启
systemctl enable iptables.service #设置防火墙开机启动
四、防火墙应用场景
开放指定端口
直接添加:
#允许本地回环接口(即运行本机访问本机)
iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
#允许已建立的或相关连的通行
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#允许所有本机向外的访问
iptables -A OUTPUT -j ACCEPT
#允许访问22端口
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
#允许访问80端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
#允许ftp服务的21端口
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
#允许FTP服务的20端口
iptables -A INPUT -p tcp --dport 20 -j ACCEPT
#禁止其他未允许的规则访问
iptables -A INPUT -j reject
#禁止其他未允许的规则访问
iptables -A FORWARD -j REJECT
/etc/rc.d/init.d/iptables save
修改防火墙文件:
vi /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
service iptables restart
屏蔽IP
#屏蔽单个IP的命令
iptables -I INPUT -s 123.45.6.7 -j DROP
#封整个段即从123.0.0.1到123.255.255.254的命令
iptables -I INPUT -s 123.0.0.0/8 -j DROP
#封IP段即从123.45.0.1到123.45.255.254的命令
iptables -I INPUT -s 124.45.0.0/16 -j DROP
#封IP段即从123.45.6.1到123.45.6.254的命令是
iptables -I INPUT -s 123.45.6.0/24 -j DROP
查看已添加的iptable规则
iptables -L -n -v
Chain INPUT (policy DROP 48106 packets, 2690K bytes)
pkts bytes target prot opt in out source destination
5075 589K ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
191K 90M ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
1499K 133M ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
4364K 6351M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
6256 327K ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 3382K packets, 1819M bytes)
pkts bytes target prot opt in out source destination
5075 589K ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
删除已添加的iptable规则
# 打印iptables 表 方便查看序列
[root@localhost ~]# iptables -nvL --line-num
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 106 8992 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
5 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT 77 packets, 9496 bytes)
num pkts bytes target prot opt in out source destination
# iptables -D 表名 重上往下数 多少个的序号 进行删除
[root@localhost home]# iptables -D INPUT 8
配置SSH应用程序规则
允许接收远程主机的SSH请求:
iptables -A INPUT -i eth0 -p tcp –dport 22 -m state –state NEW,ESTABLISHED -j ACCEPT
允许发送本地主机的SSH响应:
iptables -A OUTPUT -o eth0 -p tcp –sport 22 -m state –state ESTABLISHED -j ACCEPT
- -m state: 启用状态匹配模块(state matching module)
- –-state: 状态匹配模块的参数。当SSH客户端第一个数据包到达服务器时,状态字段为NEW;建立连接后数据包的状态字段都是ESTABLISHED
- –sport 22: sshd监听22端口,同时也通过该端口和客户端建立连接、传送数据。因此对于SSH服务器而言,源端口就是22
- –dport 22: ssh客户端程序可以从本机的随机端口与SSH服务器的22端口建立连接。因此对于SSH客户端而言,目的端口就是22
如果服务器也需要使用SSH连接其他远程主机,则还需要增加以下配置。
送出的数据包目的端口为22:
iptables -A OUTPUT -o eth0 -p tcp –dport 22 -m state –state NEW,ESTABLISHED -j ACCEPT
接收的数据包源端口为22:
iptables -A INPUT -i eth0 -p tcp –sport 22 -m state –state ESTABLISHED -j ACCEPT
配置HTTP应用程序规则
允许接收远程主机的HTTP请求:
iptables -A INPUT -i eth0 -p tcp –dport 80 -m state –state NEW,ESTABLISHED -j ACCEPT
允许发送本地主机的HTTP响应:
iptables -A OUTPUT -o eth0 -p tcp –sport 80 -m state –state ESTABLISHED -j ACCEPT
完整的配置:
# 1.删除现有规则
iptables -F
# 2.配置默认链策略
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP
# 3.允许远程主机进行SSH连接
iptables -A INPUT -i eth0 -p tcp –dport 22 -m state –state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp –sport 22 -m state –state ESTABLISHED -j ACCEPT
# 4.允许本地主机进行SSH连接
iptables -A OUTPUT -o eth0 -p tcp –dport 22 -m state –state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp –sport 22 -m state –state ESTABLISHED -j ACCEPT
# 5.允许HTTP请求
iptables -A INPUT -i eth0 -p tcp –dport 80 -m state –state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp –sport 80 -m state –state ESTABLISHED -j ACCEPT
利用iptables防止syn flood攻击
iptables -N syn-flood
iptables -A syn-flood -m limit --limit 50/s --limit-burst 10 -j RETURN
iptables -A syn-flood -j DROP
iptables -I INPUT -j syn-flood
-N 创建一个条新的链
--limit 50/s 表示每秒50次;1/m 则为每分钟一次。
--limit-burst 表示允许触发 limit 限制的最大包个数 (预设5),它就像是一个容器,最多装10个,超过10个就装不下了,这些包就给后面的规则了。
-I INPUT -j syn-flood 把INPUT的包交给syn-flood链处理。
这里的--limit-burst=10相当于说最开始有10个可以匹配的包去转发,然后匹配的包的个数是根据--limit=50/s进行限制的,也就是每秒限制转发50个数据包,多余的会被下面符合要求的DROP规则去处理,进行丢弃,这样就实现了对数据包的限速问题。
屏蔽HTTP服务Flood攻击
有时会有用户在某个服务,例如 HTTP 80 上发起大量连接请求,此时我们可以启用如下规则:
iptables -A INPUT -p tcp --dport 80 -m limit --limit 100/minute --limit-burst 200 -j ACCEPT
上述命令会将连接限制到每分钟 100 个,上限设定为 200。
禁止PING
对 Linux 禁 PING 可以使用如下规则屏蔽 ICMP 传入连接:
iptables -A INPUT -p icmp -i eth0 -j DROP
通过防火墙禁用指定用户通过ssh登录linux防火墙
iptables -A INPUT -p tcp -s 192.168.1.2 --destination-port 22 -j ACCEPT
iptables -A INPUT -p tcp --destination-port 22 -j DROP
限制并发连接数
如果你不希望来自特定端口的过多并发连接,可以使用如下规则:
iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 3 -j REJECT
以上规则限制每客户端不超过 3 个连接。
单个IP的最大连接数为 20
iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 20 -j REJECT
单个IP在一定的时间(比如60秒)内允许新建立的连接数
iptables -I INPUT -p tcp --dport 80 -m recent --name BAD_HTTP_ACCESS --update --seconds 60 --hitcount 20 -j REJECT
允许建立相关连接
随着网络流量的进出分离,要允许建立传入相关连接,可以使用如下规则:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
允许建立传出相关连接的规则:
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
丢弃无效数据包
很多网络攻击都会尝试用黑客自定义的非法数据包进行尝试,我们可以使用如下命令来丢弃无效数据包:
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables屏蔽邮件发送规则
如果你的系统不会用于邮件发送,我们可以在规则中屏蔽 SMTP 传出端口:
iptables -A OUTPUT -p tcp --dports 25,465,587 -j REJECT
SNAT
使用SNAT共享上网,服务器作为软路由,内部所有的192.168.0.0/24网端内的主机连接外网时,防火墙自动将所有源地址修改为公网IP,最后互联网将信息返回给路由后,由路由再转交给真正的后端主机。防火墙源地址转换(SNAT)规则需要被写入到NAT表中的POSTROUTING链:
vim /etc/sysctl.conf
systctl -p #重新加载内核参数配置文件
iptables -t nat -I POSTROUTING -s 192.168.0.0/24 -j SNAT --to-source 124.125.199.84 #配置nat表,使用snat方式将源地址段192.168.0.0/24 转换为124.125.199.84公网地址
配置DNAT,外部网络公网IP访问内网业务服务器:
sed -i '$a\net.ipv4.ip_forward = 1' /etc/sysctl.conf #配置文件最后一行添加
systctl -p #重新加载内核配置文件
iptables -t nat -I PREROUTING -d 124.126.199.84 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.100 #配置nat表,使用dnat方式,访问公网地址80端口转换192.168.0.100
iptables -t nat -I PREROUTING -d 124.126.199.84 -p tcp --dport 25 -j DNAT --to-destination 192.168.0.101
限制单位时间内数据包的个数,防止网络攻击发送大量无效的数据包给服务器,造成服务器无法响应正常的请求包:
iptables -I INPUT -m limit --limit 500/sec -j ACCCEPT #当每秒数据包个数为500的时候接收入站连接,否则拒绝连接
iptables -P INPURT DROP
根据数据连接状态设置防火墙规则,放行所有的出站数据包,拒绝入站的新连接请求与无效链接,放行入站的回应请求:
iptables -F
iptables -A INPUT -m state --state NEW -j DROP
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -P OUTPUT ACCEPT
防火墙设置规则,记录192.168.0.1 到192.168.0.22地址段内所有的主机发送给路由要求转发的数据包,并允许转发这些数据包:
iptables -A FORWARD -m iprange --src-range 192.168.0.1-192.168.0.10 -p tcp --dport 80 -j LOG
iptables -A FORWARD -m iprange --src-range 192.168.0.1-192.168.0.10 -p tcp --dport 80 -j ACCEPT
生产环境iptables配置
一定要给自己留好后路,留VNC一个管理端口和ssh的管理端口和80服务端口。
vi /etc/sysconfig/iptables
# Firewall configuration written by system-config-securitylevel
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp –icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT
-A RH-Firewall-1-INPUT -p 51 -j ACCEPT
-A RH-Firewall-1-INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
-A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport 53 -j ACCEPT
-A RH-Firewall-1-INPUT -m state –state NEW -m udp -p udp –dport 53 -j ACCEPT
-A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport 22 -j ACCEPT
-A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport 25 -j ACCEPT
-A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEPT
-A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport 443 -j ACCEPT
-A RH-Firewall-1-INPUT -j REJECT –reject-with icmp-host-prohibited
COMMIT
service iptables restart
iptables -L
iptables安全加固脚本
在我们的Web服务器上,系统的默认策略是INPUT为DROP,OUTPUT;FORWARD链为ACCEPT,DROP则设置得比较宽松,因为我们知道出去的数据包比较安全。
为了验证脚本的通用性,我特地查看了服务器的内核及iptables版本:
# uname -a
Linux ud50041 2.6.9-34.ELsmp #1 SMP Fri Feb 24 16:54:53 EST 2006 i686 i686 i386 GNU/Linux
# iptables -V
iptables v1.2.11
# lsb_release -a
LSB Version: :core-3.0-ia32:core-3.0-noarch:graphics-3.0-ia32:graphics-3.0-noarch
Distributor ID: RedHatEnterpriseAS
Description: Red Hat Enterprise Linux AS release 4 (Nahant Update 3)
Release: 4
Codename: NahantUpdate3
大家可以发现,这台服务器的系统、内核和iptables版本是比较老的。本文中介绍的脚本涉及到recent安全模块,这对系统内核有要求(recent模块在主机防护脚本中也经常用到)。因此,如果大家要采用iptables作为主机防火墙时,建议用CentOS 5.6 x86_64或更高级版本,不然系统会有如下提示错误信息:
iptables: Unknown error 18446744073709551615
iptables:Invalid argument
在tail -f /var/log/messages时会有如下出错提示:
ip_tables: connlimit match: invalid size 32 != 16
ip_tables: connlimit match: invalid size 32 != 24
另外,在生产环境下进行iptables脚本的调试之前,强烈建议编写crontab任务,每5分钟关闭一次iptables脚本,防止操作失误而将自己的SSH客户端锁在外面:
*/5 * * * * root /etc/init.d/iptables stop
准备工作就是这些,下面是iptables脚本内容:
#!/bin/bash
iptables -F
iptables -F -t nat
iptables -X
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
#load connection-tracking modules
modprobe iptable_nat
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
iptables -A INPUT -f -m limit --limit 100/sec --limit-burst 100 -j ACCEPT
iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 10 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m limit --limit 20/sec --limit-burst 200 -j ACCEPT
iptables -A INPUT -s 122.70.x.x -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dport 80,22 -j ACCEPT
保存脚本文件后用:
# sh iptables.sh
执行脚本。运行脚本之后最好检查一下:
# iptables -nv -L
脚本说明
由于此Web服务器是置于负载均衡器后面,所以我们要允许数据源地址为负载均衡器的数据包通过:
iptables -A INPUT -s 122.70.x.x -j ACCEPT
如果配置了Nagios等监控系统的话在这里也要加上,如果监控和LB都没做的话,这行可以不用。
另外,我的许多基于LNMP的小网站上面也部署了此脚本,由于Web服务和MySQL数据库同时安装在一台机器上,所以没有开放3306端口。
在本脚本中,我们配置了一些安全措施,以防止外部的ping和SYN洪水攻击,并且考虑到外部的疯狂端口扫描软件可能会影响服务器的入口带宽,所以在这里也做了限制:
iptables -A INPUT -p tcp --syn -m limit --limit 100/s --limit-burst 100 -j ACCEPT
上面的命令每秒钟最多允许100个新连接。请注意这里的新连接指的是state为New的数据包,在后面我们也配置了允许状态为ESTABLISHED和RELATED的数据通过;另外,100这个阀值则要根据服务器的实际情况来调整,如果是并发量不大的服务器这个数值就要调小,如果是访问量非常大且并发数不小的服务器,这个值则还需要调大。
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s –limit-burst 10 -j ACCEPT
这是为了防止ping洪水攻击,限制每秒的ping包不超过10个:
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m limit --limit 20/sec --limit-burst 200 -j ACCEPT
上面的命令防止各种端口扫描,将SYN及ACK SYN限制为每秒钟不超过200个,免得把数务器带宽耗尽了。
后续加固工作
iptables防火墙运行后,运行nmap工具进行扫描:
# nmap -P0 -sS 211.143.6.x
Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2009-03-29 16:21 CST
Interesting ports on 211.143.6.X:
Not shown: 1668 closed ports
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
80/tcp open http
110/tcp open pop3
111/tcp open rpcbind
143/tcp open imap
443/tcp open https
465/tcp open smtps
587/tcp open submission
993/tcp open imaps
995/tcp open pop3s
1014/tcp open unknown
在这里,我们发现一个1014端被某个进程打开了,用lsof -i:1014查看发现是rpc.statd打开的,这服务每次用的端口都不一样啊!本来想置之不理的,但是如果rpc.statd不能正确处理SIGPID信号,远程攻击者可利用这个漏洞关闭进程,进行拒绝服务攻击,所以还是得想办法解决掉。我们发现rpc.statd是由服务nfslock开启的,进一步查询得知它是一个可选的进程,它允许NFS客户端在服务器上对文件加锁。这个进程对应于nfslock服务,于是我们关掉了此服务:
service nfslock stop
chkconfig nfslock off
如果没有硬件防火墙保护的话,请尽量在每一台有公网IP的机器上部署iptables防火墙吧!
防火墙初始化脚本
5210是ssh端口号,192.168.2.208是保垒机,192.168.2.206是备用ssh机器:
#!/bin/bash
systemctl stop firewalld
\cp -p /usr/lib/firewalld/zones/drop.xml /etc/firewalld/zones/
systemctl start firewalld
firewall-cmd --set-default-zone=drop
firewall-cmd --permanent --zone=drop --change-interface=ens32
firewall-cmd --permanent --zone=drop --add-service=https
firewall-cmd --permanent --zone=drop --add-protocol=icmp
firewall-cmd --permanent --zone=drop --add-masquerade
firewall-cmd --permanent --zone=drop --add-rich-rule="rule family="ipv4" source address="192.168.2.208" port protocol="tcp" port="5210" accept"
firewall-cmd --permanent --zone=drop --add-rich-rule="rule family="ipv4" source address="192.168.2.206" port protocol="tcp" port="5210" accept"
firewall-cmd --permanent --zone=drop --add-rich-rule="rule family="ipv4" source address="116.226.230.115" port protocol="tcp" port="8023" accept"
firewall-cmd --reload