按网络协议划分:
Linux防火墙是由Netfilter组件提供的,Netfilter工作在内核空间,集成在Linux内核中
Netfilter是Linux 2.4.x之后新一代的Linux防火墙机制,是Linux内核的一个子系统。Netfilter采用模块化设计,具有良好的可扩充性,提供扩展网络服务的结构化底层框架。Netfilter与IP协议栈是无缝契合,并允许对数据进行过滤、地址转换、处理等操作
Netfilter官网文档:https://netfilter.org/documentation/
由软件包iptables提供的命令行工具,工作在用户空间,用来编写规则,写好的规则被送往netfilter,告诉内核如何去处理信息包
从CentOS 7 版开始引入了新的前端管理工具
软件包:
此软件是CentOS 8 新特性,它重用了netfilter框架的许多部分,例如连接跟踪和NAT功能。它还保留了命令法和基本iptables设计的几个部分,例如表,链和规则。就像iptables一样,表充当链的容器,并且链包含单独的规则,这些规则可以执行操作,例如丢弃数据包,移至下一个规则或跳至新链。
从用户的角度来看,nftables添加了一个名为nft的新工具,该工具替代了iptables,arptables和etables所有其它工具。从体系结构的角度来看,它还替换了内核中处理数据包过滤规则集运行时评估的那些部分。
CentOS 8 支持三种防火墙服务:iptables,firewalld,nftables
Netfilter在内核中选取五个位置放了五个hook(勾子)function(INPUT、OUTPUT、FORWARD、PREROUTING、POSTROUTING),而这五个hook function向用户开放,用户可以通过一个命令工具(iptables)向其写入规则
由信息过滤表(table)组成,包含控制IP包处理的规则集(rules),规则被分组放在链(chain)上
提示:从Linux kernel 4.2版以后,Netfilter在prerouting前加了一个ingress勾子函数。可以使用这个新的入口挂钩来过滤来自第二层的流量,这个新挂钩比预路由要早,基本上是tc命令(流量控制工具)的替代品
三种报文流向
iptables由五个表table和五个链chain以及一些规则组成
链 chain:
五个内置链chain:
INPUT,OUTPUT,FORWARD,PREROUTING,POSTROUTING
五个表table: filter、nat、mangle、raw、security
表和链的对应关系
数据包过滤匹配流程
内核中数据包的传输过程
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@centos8 ~]#iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (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@centos8 ~]#iptables -vnL -t mangle
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
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
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
[root@centos8 ~]#iptables -vnL -t raw
Chain PREROUTING (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@centos8 ~]#iptables -vnL -t security
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
#CentOS 6 不支持INPUT链
[root@centos6 ~]# iptables -vnL -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (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
规则rule:根据规则的匹配条件尝试匹配报文,对匹配成功的报文根据规则定义的处理动作作出处理,规则在链接上的次序即为其检查时的生效次序
匹配条件:默认为与条件,同时满足
基本匹配:IP,端口,TCP的Flags(SYN,ACK等)
扩展匹配:通过复高级功能匹配
处理动作:称为target,跳转目标
CentOS 7,8:
systemctl stop firewalld.service
systemctl disable firewalld.service
或者
systemctl disable --now firewalld.service
CentOS 6
service iptables stop
chkconfig iptables off
帮助:man 8 iptables
格式:
iptables [-t table] {-A|-C|-D} chain rule-specification
ip6tables [-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]
范例:filter表中的INPUT规则
iptables命令格式详解
iptables [-t table] SUBCOMMAND chain [-m matchname [per-match-options]]
-j targetname [per-target-options]
1、-t table:指定表
nat,mangle,raw,security,filter默认
2、SUBCOMMAND:子命令
链管理类:
-N:new,自定义一条新的规则链
-E:重命名自定义链;引用计数不为0的自定义链不能够被重命名,也不能被删除
-X:delete,删除自定义的空的规则链
-P:policy,设置默认策略;对filter表中的链而言,其默认策略由:ACCEPT:接受,DROP:丢弃
创建自定义链:
创建自定义链
添加链规则
将自定义链关联至对应的内置链
删除自定义链:
删除内置链中的自定义链
清空自定义链
删除自定义链
范例:
[root@centos8 ~]#iptables -N web_chain
[root@centos8 ~]#iptables -N web_chain -t nat
[root@centos8 ~]#iptables -X web_chain -t nat
[root@centos8 ~]#iptables -E web_chain WEB_CHAIN
[root@centos8 ~]#iptables -A WEB_CHAIN -s 10.0.0.6 -p tcp -m multiport --dports 80,443 -j REJECT
[root@centos8 ~]#iptables -R WEB_CHAIN 1 -s 10.0.0.6 -p tcp -m multiport --dports 80,443,8080 -j REJECT
[root@centos8 ~]#iptables -vnL WEB_CHAIN
Chain WEB_CHAIN (0 references)
pkts bytes target prot opt in out source destination
0 0 REJECT tcp -- * * 10.0.0.6 0.0.0.0/0 multiport dports 80,443,8080 reject-with icmp-port-unreachable
[root@centos8 ~]#iptables -A INPUT -j WEB_CHAIN
[root@centos8 ~]#iptables -D INPUT 1
[root@centos8 ~]#iptables -D WEB_CHAIN 1
[root@centos8 ~]#iptables -X WEB_CHAIN
范例:创建自定义链实现WEB的访问控制
[root@centos8 ~]#iptables -A INPUT -s 10.0.0.1 -j ACCEPT
[root@centos8 ~]#iptables -A INPUT -i lo -j ACCEPT
[root@centos8 ~]#iptables -A INPUT -j REJECT
[root@centos8 ~]#iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
250 14636 ACCEPT all -- * * 10.0.0.1 0.0.0.0/0
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
1 76 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
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@centos8 ~]#iptables -N web_chain
[root@centos8 ~]#iptables -E web_chain WEB_CHAIN
[root@centos8 ~]#iptables -A WEB_CHAIN -p tcp -m multiport --dports 80,443,8080 -j ACCEPT
[root@centos8 ~]#iptables -I INPUT 3 -s 10.0.0.0/24 -j WEB_CHAIN
[root@centos8 ~]#iptables -A WEB_CHAIN -p icmp -j ACCEPT
[root@centos8 ~]#iptables -I WEB_CHAIN 2 -s 10.0.0.6 -j RETURN
[root@centos8 ~]#iptables -vnL --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 1281 84673 ACCEPT all -- * * 10.0.0.1 0.0.0.0/0
2 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
3 41 3420 WEB_CHAIN all -- * * 10.0.0.0/24 0.0.0.0/0
4 39 3076 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
Chain WEB_CHAIN (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 80,443,8080
2 15 1252 RETURN all -- * * 10.0.0.6 0.0.0.0/0
3 24 2016 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
[root@centos6 ~]#curl 10.0.0.8
centos8 website
[root@centos6 ~]# ping -c1 10.0.0.8
PING 10.0.0.8 (10.0.0.8) 56(84) bytes of data.
From 10.0.0.8 icmp_seq=1 Destination Port Unreachable
--- 10.0.0.8 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
范例:删除自定义链
#无法直接删除自定义链,删除自定义链和创建的顺序相反
[root@centos8 ~]#iptables -D INPUT 3
[root@centos8 ~]#iptables -F WEB_CHAIN
[root@centos8 ~]#iptables -X WEB_CHAIN
[root@centos8 ~]#iptables -vnL --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 2209 137K ACCEPT all -- * * 10.0.0.1 0.0.0.0/0
2 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
3 280 26444 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
查看类:
-L:List,列出指定链上的所有规则,本选项须置后
-n:numberic,以数字格式显示地址和端口号
-v:verbose,详细信息
-vv:更详细
-x:exactly,显示计数器结果的精确值,而非单位转换后的易读值
–line-numbers:显示规则的序号
-S selected,以iptables-save 命令格式显示链上规则
常用组合:
-vnL
-vvnxL --line-numbers
规划管理类:
-A:append,追加
-I:insert,插入,要指明插入至的规则编号,默认为第一条
-D:delete,删除
(1)指明规则序号
(2)指明规则本身
-R:replace,替换指定链上的指定规则编号
-F:flush,清空指定的规则链
-Z:zero,置零
iptables的每条规则都有两个计数器
(1)匹配到的报文的个数
(2)匹配到的所有报文的大小之和
范例:
[root@centos8 ~]#iptables -F OUTPUT
3、chain:
PREROUTING,INPUT,OUTPUT,FORWARD,POSTROUTING
4、匹配条件
5、处理动作:
-j targetname [per-target-options]
简单动作:
ACCEPT
DROP
扩展动作:
REJECT:–reject-with:icmp-port-unreachable默认
RETURN:返回调用链
REDIRECT:端口重定向
LOG:记录日志,dmesg
MARK:做防火墙标记
DNAT:目标地址转换
SNAT:源地址转换
MASQUERADE:地址伪装
自定义链
基本匹配条件:无需加载模块,由iptables/netfilter自行提供
[!] -s, --source address[/mask][,...]:源IP地址或者不连续的IP地址
[!] -d, --destination address[/mask][,...]:目标IP地址或者不连续的IP地址
[!] -p, --protocol protocol:指定协议,可使用数字如0(all)
protocol: tcp, udp, icmp, icmpv6, udplite,esp, ah, sctp, mh or“all“
参看:/etc/protocols
[!] -i, --in-interface name:报文流入的接口;只能应用于数据报文流入环节,只应用于INPUT、FORWARD
、PREROUTING链
[!] -o, --out-interface name:报文流出的接口;只能应用于数据报文流出的环节,只应用于FORWARD、
OUTPUT、POSTROUTING链
范例:
[root@centos8 ~]#iptables -A INPUT -s 10.0.0.6,10.0.0.10 -j REJECT
[root@centos8 ~]#iptables -I INPUT -i lo -j ACCEPT
[root@centos8 ~]#curl 10.0.0.8
www.kobe.com on 10.0.0.8
[root@centos8 ~]#curl 127.0.0.1
www.kobe.com on 10.0.0.8
[root@centos6 ~]# ping -c1 10.0.0.8
PING 10.0.0.8 (10.0.0.8) 56(84) bytes of data.
64 bytes from 10.0.0.8: icmp_seq=1 ttl=64 time=0.769 ms
--- 10.0.0.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.769/0.769/0.769/0.000 ms
[root@centos6 ~]# curl 10.0.0.8
www.kobe.com on 10.0.0.8
[root@centos7 ~]# ping -c1 10.0.0.8
PING 10.0.0.8 (10.0.0.8) 56(84) bytes of data.
64 bytes from 10.0.0.8: icmp_seq=1 ttl=64 time=1.43 ms
--- 10.0.0.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.435/1.435/1.435/0.000 ms
[root@centos7 ~]# curl 10.0.0.8
www.kobe.com on 10.0.0.8
扩展匹配条件:需要加载扩展模块(/usr/lib64/xtables/*.so),方可生效
扩展模块的查看帮助:man iptables-extensions
扩展匹配条件:
iptables 在使用-p选项指定了特定的协议时,无需再用-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,用,分隔tcp协议的扩展选项
范例:
--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@centos8 ~]#iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -j REJECT
等价于
[root@centos8 ~]#iptables -A INPUT -p tcp --syn -j REJECT
udp 协议的扩展选项
[!] --source-port, --sport port[:port]:匹配报文的源端口或端口范围
[!] --destination-port,--dport port[:port]:匹配报文的目标端口或端口范围
icmp 协议的扩展选项
[!] --icmp-type {type[/code]|typename}
type/code
0/0 echo-reply icmp应答
8/0 echo-request icmp请求
范例:
[root@centos8 ~]#iptables -A INPUT -s 10.0.0.6 -p tcp --dport 21:23 -j REJECT
[root@centos8 ~]#iptables -A INPUT -s 10.0.0.6 -p icmp --icmp-type 8 -j REJECT
[root@centos6 ~]# ping 10.0.0.8 -c1
PING 10.0.0.8 (10.0.0.8) 56(84) bytes of data.
From 10.0.0.8 icmp_seq=1 Destination Port Unreachable
--- 10.0.0.8 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 1ms
[root@centos8 ~]#ping 10.0.0.6 -c1
PING 10.0.0.6 (10.0.0.6) 56(84) bytes of data.
64 bytes from 10.0.0.6: icmp_seq=1 ttl=64 time=0.500 ms
--- 10.0.0.6 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.500/0.500/0.500/0.000 ms
显示扩展即必须使用-m选项指明要调用的扩展模块名称,需要手动加载扩展模块
[-m matchname [per-match-options] ]
**扩展模块的使用帮助:**
* CentOS 7,8: man iptables-extensions
* CentOS 6: man iptables
#### 3.4.2.1 multiport 扩展
以离散方式定义多端口匹配,最多指定15个端口
```sh
#指定多个源端口
[!] --source-ports,--sports port[,port|port:port]...
#指定多个目标端口
[!] --destination-ports,--dports port[,port|,port:port]...
#多个源或目标端
[!] --ports port[,port|,port:port]...
范例:
[root@centos8 ~]#iptables -A INPUT -s 172.16.0.0/16 -d 172.16.100.10 -p tcp -m multiport --dports 20:23,80 -j ACCEPT
[root@centos8 ~]#iptables -A INPUT -s 10.0.0.6 -p tcp -m multiport --dports 445,139 -j REJECT
指明连续的(但一般不是整个网络)IP地址范围
[!] --src-range from[-to] 源IP地址范围
[!] --dst-range from[-to] 目标IP地址范围
范例:
[root@centos8 ~]#iptables -A INPUT -d 172.16.1.100 -p tcp --dport 80 -m iprange --src-range 172.16.1.5-172.16.1.10 -j DROP
mac模块可以指明源MAC地址,适用于:PREROUTING,FORWARD,INPUT chains
[!] --mac-source xx:xx:xx:xx:xx:xx
范例:
[root@centos8 ~]#iptables -A INPUT -s 10.0.0.6 -m mac --mac-source 00:0c:29:1a:fd:94 -j REJECT
[root@centos8 ~]#iptables -A INPUT -s 10.0.0.6 -j REJECT
对报文中的应用层数据做字符串模式匹配检测
--algo {bm|kmp} 字符串匹配检测算法
--from offset 开始偏移
--to offset 结束偏移
[!] --string pattern 要检测的字符串模式
[!] --hex-string pattern 要检测的字符串模式,16进制格式
范例:
[root@centos8 ~]#iptables -A OUTPUT -p tcp --sport 80 -m string --algo bm --from 62 --string "kobe" -j REJECT
[root@centos6 ~]# curl 10.0.0.8
^C
注意:CentOS 8 此模块有问题
根据将报文到达的时间与指定的时间范围进行匹配
--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:内核时区(当地时间),不建议使用此选项,CentOS 7 系统默认为 UTC
注意: centos6 不支持kerneltz ,--localtz指定本地时区(默认)
范例:CentOS 8 的time模块有问题
[root@centos8 ~]#rpm -ql iptables|grep time
/usr/lib64/xtables/libxt_time.so
[root@centos8 ~]#iptables -A INPUT -m time --timestart 12:30 --timestop 13:30 -j ACCEPT
iptables v1.8.2 (nf_tables): Couldn't load match `time':No such file or directory
Try `iptables -h' or 'iptables --help' for more information.
范例:每周的周六和周日的9点到18点禁止上网
[root@centos7 ~]# iptables -A INPUT -s 172.16.0.0/16 -d 10.0.0.8 -p tcp --dport 80 -m time --timestart 1:00 --timestop 10:00 --weekdays Sat,Sun -j REJECT
根据每客户端IP做并发连接数数量匹配
可防止Dos(Denial of service,拒绝服务)攻击
--connlimit-upto N #连接的数量小于等于N时匹配
--connlimit-above N #连接的数量大于N时匹配
范例:
[root@centos8 ~]#iptables -A INPUT -d 10.0.0.8 -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
基于收发报文的速率做匹配,令牌桶过滤器
--limit-burst number #前多少个包不限制
--limit #[/second|/minute|/hour|/day]
范例:
[root@centos8 ~]#iptables -A INPUT -d 10.0.0.8 -p icmp --icmp-type 8 -m limit --limit 10/minute --limit-burst 5 -j ACCEPT
[root@centos8 ~]#iptables -A INPUT -p icmp -j REJECT
[root@centos8 ~]#iptables -A INPUT -p icmp -m limit --limit-burst 10 --limit 20/minute -j ACCEPT
[root@centos8 ~]#iptables -A INPUT -p icmp -j REJECT
[root@centos6 ~]# ping 10.0.0.8
PING 10.0.0.8 (10.0.0.8) 56(84) bytes of data.
64 bytes from 10.0.0.8: icmp_seq=1 ttl=64 time=0.429 ms
64 bytes from 10.0.0.8: icmp_seq=2 ttl=64 time=1.26 ms
64 bytes from 10.0.0.8: icmp_seq=3 ttl=64 time=0.416 ms
64 bytes from 10.0.0.8: icmp_seq=4 ttl=64 time=0.453 ms
64 bytes from 10.0.0.8: icmp_seq=5 ttl=64 time=0.435 ms
64 bytes from 10.0.0.8: icmp_seq=6 ttl=64 time=0.487 ms
64 bytes from 10.0.0.8: icmp_seq=7 ttl=64 time=0.570 ms
64 bytes from 10.0.0.8: icmp_seq=8 ttl=64 time=0.684 ms
64 bytes from 10.0.0.8: icmp_seq=9 ttl=64 time=0.505 ms
64 bytes from 10.0.0.8: icmp_seq=10 ttl=64 time=0.883 ms
64 bytes from 10.0.0.8: icmp_seq=11 ttl=64 time=0.486 ms
64 bytes from 10.0.0.8: icmp_seq=12 ttl=64 time=0.734 ms
64 bytes from 10.0.0.8: icmp_seq=13 ttl=64 time=0.457 ms
64 bytes from 10.0.0.8: icmp_seq=14 ttl=64 time=0.778 ms
From 10.0.0.8 icmp_seq=15 Destination Port Unreachable
From 10.0.0.8 icmp_seq=16 Destination Port Unreachable
64 bytes from 10.0.0.8: icmp_seq=17 ttl=64 time=0.529 ms
From 10.0.0.8 icmp_seq=18 Destination Port Unreachable
From 10.0.0.8 icmp_seq=19 Destination Port Unreachable
From 10.0.0.8 icmp_seq=20 Destination Port Unreachable
64 bytes from 10.0.0.8: icmp_seq=21 ttl=64 time=0.700 ms
From 10.0.0.8 icmp_seq=22 Destination Port Unreachable
From 10.0.0.8 icmp_seq=23 Destination Port Unreachable
64 bytes from 10.0.0.8: icmp_seq=24 ttl=64 time=0.632 ms
From 10.0.0.8 icmp_seq=25 Destination Port Unreachable
From 10.0.0.8 icmp_seq=26 Destination Port Unreachable
state 扩展模块,可以根据“连接追踪机制”去检查连接的状态,较耗资源
conntrack机制:追踪本机上的请求和响应之间的关系
状态类型:
[root@centos8 ~]#iptables -A INPUT -s 10.0.0.1 -j ACCEPT
[root@centos8 ~]#iptables -A INPUT -i lo -j ACCEPT
#下面两条规则是综合实现已经建立连接的可以保持连接,但新请求拒绝
[root@centos8 ~]#iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@centos8 ~]#iptables -A INPUT -m state --state NEW -j REJECT
[root@centos6 ~]# ping 10.0.0.8
PING 10.0.0.8 (10.0.0.8) 56(84) bytes of data.
64 bytes from 10.0.0.8: icmp_seq=1 ttl=64 time=0.868 ms
[root@centos7 ~]# ping -c1 10.0.0.8
PING 10.0.0.8 (10.0.0.8) 56(84) bytes of data.
From 10.0.0.8 icmp_seq=1 Destination Port Unreachable
--- 10.0.0.8 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
[root@centos8 ~]#ping 10.0.0.6
PING 10.0.0.6 (10.0.0.6) 56(84) bytes of data.
64 bytes from 10.0.0.6: icmp_seq=1 ttl=64 time=0.319 ms
^C
--- 10.0.0.6 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.319/0.319/0.319/0.000 ms
[root@centos8 ~]#ping 10.0.0.7
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
64 bytes from 10.0.0.7: icmp_seq=1 ttl=64 time=0.813 ms
^C
--- 10.0.0.7 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.813/0.813/0.813/0.000 ms
[root@centos7 ~]# curl 10.0.0.8
curl: (7) Failed connect to 10.0.0.8:80; Connection refused
[root@centos8 ~]#cat /proc/net/nf_conntrack
ipv4 2 icmp 1 29 src=10.0.0.6 dst=10.0.0.8 type=8 code=0 id=62214 src=10.0.0.8 dst=10.0.0.6 type=0 code=0 id=62214 mark=0 zone=0 use=2
ipv4 2 tcp 6 299 ESTABLISHED src=10.0.0.1 dst=10.0.0.8 sport=4088 dport=22 src=10.0.0.8 dst=10.0.0.1 sport=22 dport=4088 [ASSURED] mark=0 zone=0 use=2
ipv4 2 tcp 6 431945 ESTABLISHED src=10.0.0.8 dst=10.0.0.1 sport=22 dport=10285 src=10.0.0.1 dst=10.0.0.8 sport=10285 dport=22 [ASSURED] mark=0 zone=0 use=2
调整连接追踪功能所能够容纳的最大连接数
[root@centos8 ~]#cat /proc/sys/net/netfilter/nf_conntrack_max
26624
[root@centos8 ~]#cat /proc/sys/net/nf_conntrack_max
26624
查看连接跟踪有多少条目
[root@centos8 ~]#cat /proc/sys/net/netfilter/nf_conntrack_count
2
不同的协议的连接追踪时长
[root@centos8 ~]#ll /proc/sys/net/netfilter/
total 0
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_acct
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_buckets
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_checksum
-r--r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_count
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_dccp_loose
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_dccp_timeout_closereq
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_dccp_timeout_closing
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_dccp_timeout_open
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_dccp_timeout_partopen
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_dccp_timeout_request
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_dccp_timeout_respond
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_dccp_timeout_timewait
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_events
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_expect_max
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_generic_timeout
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_helper
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_icmp_timeout
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_log_invalid
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_max
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_sctp_timeout_closed
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_sctp_timeout_cookie_echoed
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_sctp_timeout_cookie_wait
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_sctp_timeout_established
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_sctp_timeout_heartbeat_acked
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_sctp_timeout_heartbeat_sent
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_sctp_timeout_shutdown_ack_sent
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_sctp_timeout_shutdown_recd
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_sctp_timeout_shutdown_sent
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_be_liberal
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_loose
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_max_retrans
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_close
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_close_wait
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_established
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_fin_wait
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_last_ack
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_max_retrans
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_syn_recv
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_syn_sent
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_time_wait
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_tcp_timeout_unacknowledged
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_timestamp
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_udp_timeout
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_conntrack_udp_timeout_stream
dr-xr-xr-x 1 root root 0 Sep 16 20:47 nf_log
-rw-r--r-- 1 root root 0 Sep 16 20:47 nf_log_all_netns
说明:
[root@centos8 ~]#echo 1 > /proc/sys/net/netfilter/nf_conntrack_max
[root@centos8 ~]#tail -1 /var/log/messages
Sep 16 20:58:10 centos8 kernel: nf_conntrack: nf_conntrack: table full, dropping packet
连接过多的解决方法两个:
(1)加大nf_conntrack_max值
net.nf_conntrack_max = 393216
net.netfilter.nf_conntrack_max = 393216
(2)降低nf_conntrack timeout 时间
vim /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
格式:
[!] --state state
范例:不允许10.0.0.7 访问本机,但本机可以访问10.0.0.7
[root@centos8 ~]#iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -s 10.0.0.1/32 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT ! -s 10.0.0.7/32 -m state --state NEW -j ACCEPT
-A INPUT -m state --state ESTABLISHED -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-port-unreachable
[root@centos8 ~]#
范例:
#实现其他主机可以访问本机的ssh和httpd服务
[root@centos8 ~]#iptables -A INPUT -d 10.0.0.8/32 -p tcp -m multiport --dports 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT
[root@centos8 ~]#iptables -A OUTPUT -s 10.0.0.8/32 -p tcp -m multiport --sports 22,80 -m state --state ESTABLISHED -j ACCEPT
#实现其他主机不能访问本机的任何服务,本机可以访问其他的主机
[root@centos8 ~]#iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
[root@centos8 ~]#iptables -A INPUT -m state --state NEW -j REJECT
案例:开放被动模式的ftp服务
CentOS 8 此模块有bug
(1)装载ftp连接追踪的专用模块:
跟踪模块路径:/lib/modules/kernelversion/kernel/net/netfilter
vim /etc/sysconfig/iptables-config
IPTABLES_MODULES="nf_conntrack_ftp"
modprobe nf_conntrack_ftp
(2)放行请求报文:
命令连接:NEW,ESTABLISHED
数据连接:RELATED,ESTABLISHED
iptables -I INPUT -d LocalIP -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -d LocalIP -p tcp --dport 21 -m state --state NEW -j ACCEPT
(3)放行响应报文:
iptables -I OUTPUT -s LocalIP -p tcp -m state --state ESTABLISHED -j ACCEPT
范例:开放被动模式的ftp服务示例
yum install vsftpd
systemctl start vsftpd
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
target 包括以下类型:
自定义链:ACCEPT,DROP,REJECT,RETURN,LOG,SNAT,DNAT,REDIRECT,MASQUERADE
LOG:非中断target,本身不拒绝和允许,放在拒绝和允许规则前,并将日志记录在/var/log/messages系统日志中
--log-level level 级别:debug,info,notice,warning,error,crit,alert,emerg
--log-prefix prefix 日志前缀,用于区别不同的日志,最多29个字符
范例:
[root@centos8 ~]#iptables -A INPUT -s 10.0.0.0/24 -p tcp -m multiport --dports 80,21:23 -m state --state NEW -j LOG --log-prefix "New connection: "
[root@centos8 ~]#tail -f /var/log/messages
Sep 16 22:06:39 centos8 kernel: New connection: IN=eth0 OUT= MAC=00:0c:29:8d:3e:41:00:0c:29:94:f3:95:08:00 SRC=10.0.0.7 DST=10.0.0.8 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=55621 DF PROTO=TCP SPT=55560 DPT=80 WINDOW=29200 RES=0x00 SYN URGP=0
Sep 16 22:07:14 centos8 kernel: New connection: IN=eth0 OUT= MAC=00:0c:29:8d:3e:41:00:0c:29:1a:fd:94:08:00 SRC=10.0.0.6 DST=10.0.0.8 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=679 DF PROTO=TCP SPT=50962 DPT=22 WINDOW=14600 RES=0x00 SYN URGP=0
Sep 16 22:07:30 centos8 kernel: New connection: IN=eth0 OUT= MAC=00:0c:29:8d:3e:41:00:0c:29:1a:fd:94:08:00 SRC=10.0.0.6 DST=10.0.0.8 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=47809 DF PROTO=TCP SPT=53598 DPT=80 WINDOW=14600 RES=0x00 SYN URGP=0
Sep 16 22:07:34 centos8 kernel: New connection: IN=eth0 OUT= MAC=00:0c:29:8d:3e:41:00:0c:29:1a:fd:94:08:00 SRC=10.0.0.6 DST=10.0.0.8 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=53331 DF PROTO=TCP SPT=53600 DPT=80 WINDOW=14600 RES=0x00 SYN URGP=0
范例:
[root@centos8 ~]#iptables -R INPUT 2 -p tcp --dport 21 -m state --state NEW -j
LOG --log-prefix "ftp new link: "
[root@centos8 ~]#tail -f /var/log/messages
Dec 21 10:02:31 centos8 kernel: ftp new link: IN=eth0 OUT=
MAC=00:0c:29:f9:8d:90:00:0c:29:10:8a:b1:08:00 SRC=192.168.39.6 DST=192.168.39.8
LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=15556 DF PROTO=TCP SPT=53706 DPT=21
WINDOW=14600 RES=0x00 SYN URGP=0
1.安全放行所有入站和出站的状态为ESTABLISHED状态连接,建议放在第一条,效率更高
2.谨慎放行入站的请求
3.有特殊目的限制访问功能,要在放行规则之前加以拒绝
4.同类规则(访问同一应用,比如:http),匹配范围小的放在前面,用于特殊处理
5.不同类的规则(访问不同应用,一个是http,另一个是mysql),匹配范围大的放在前面,效率更高
-s 10.0.0.6 -p tcp --dport 3306 -j REJECT
-s 172.16.0.0/16 -p tcp --dport 80 -j REJECT
6.应该将那些可由一条规则能够描述的多个规则合并为一条,减少规则数量,提高检查效率
7.设置默认策略,建议白名单(只放行特定连接)
使用iptables命令定义的规则,手动删除之前,其生效期限为kernel存活期限
持久保存规则:
CentOS 7,8
iptables-save > /PATH/TO/SOME_RULES_FILE
CentOS 6
#将规则覆盖保存至/etc/sysconfig/iptables文件中
service iptables save
加载规则
CentOS 7,8 重新载入预存规则文件中规则:
iptables-restore < /PATH/FROM/SOME_RULES_FILE
iptables-restore选项
-n,--noflush:不清除原有规则
-t,--test:仅分析生成规则集,但不提交
CentOS 6:
#会自动从/etc/sysconfig/iptables 重新载入规则
service iptables restart
开机自动重载规则
iptables-restore < /PATH/FROM/IPTABLES_RULES_FILE
定义Unit File,CentOS 7,8 可以安装iptables-services 实现iptables.service
范例:CentOS 7,8 使用iptables-services
[root@centos8 ~]#yum -y install iptables-services
[root@centos8 ~]#cp /etc/sysconfig/iptables{,.bak}
#保存现在的规则到文件中方法1
[root@centos8 ~]#/usr/libexec/iptables/iptables.init save
#保存现在的规则到文件中方法2
[root@centos8 ~]#iptables-save > /etc/sysconfig/iptables
#开机启动
[root@centos8 ~]#systemctl enable iptables.service
[root@centos8 ~]#systemctl mask firewalld.service nftables.service
iptables/netfilter 利用filter表的FORWARD链,可以充当网络防火墙
注意的问题:
(1)请求-响应报文均会经由FORWARD链,要注意规则的方向性
(2)如果要启用conntrack机制,建议将双方向的状态为ESTABLISHED的报文直接放行
#环境准备
[root@internet ~]#hostname -I
192.168.0.6
[root@internet ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
0.0.0.0 192.168.0.8 0.0.0.0 UG 0 0 0 eth0
[root@firewall ~]#hostname -I
10.0.0.8 192.168.0.8
[root@firewall ~]#vim /etc/sysctl.conf
net.ipv4.ip_forward=1
[root@firewall ~]#sysctl -p
[root@lanserver1 ~]#hostname -I
10.0.0.7
[root@lanserver1 ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.8 0.0.0.0 UG 100 0 0 eth0
10.0.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
[root@lanserver2 ~]#hostname -I
10.0.0.17
[root@lanserver2 ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.8 0.0.0.0 UG 100 0 0 eth0
10.0.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
#方法1 通过标准模块实现内网访问外网,反之禁止
[root@firewall ~]#iptables -AFORWARD -j REJECT
[root@firewall ~]#iptables -IFORWARD -s 10.0.0.0/24 -p tcp --dport 80 -j
ACCEPT
[root@firewall ~]#iptables -IFORWARD -d 10.0.0.0/24 -p tcp --sport 80 -j
ACCEPT
[root@firewall ~]#iptables -I FORWARD -s 10.0.0.0/24 -p icmp --icmp-type 8 -j
ACCEPT
[root@firewall ~]#iptables -I FORWARD -d 10.0.0.0/24 -p icmp --icmp-type 0 -j
ACCEPT
[root@firewall ~]#iptables -vnL --line-numbers
#方法2 利用state模块实现内网访问可以访问外网,反之禁止
[root@firewall ~]#iptables -DFORWARD 1
[root@firewall ~]#iptables -DFORWARD 2
[root@firewall ~]#iptables -vnL --line-numbers
[root@firewall ~]#iptables -IFORWARD -m state --state RELATED,ESTABLISHED -j
ACCEPT
[root@firewall ~]#iptables -vnL --line-numbers
[root@lanserver1 ~]#ping 192.168.0.6 -c1
PING 192.168.0.6 (192.168.0.6) 56(84) bytes of data.
64 bytes from 192.168.0.6: icmp_seq=1 ttl=63 time=2.20 ms
[root@lanserver2 ~]#curl 192.168.0.6
internet
[root@internet ~]#ping 10.0.0.7 -c1
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
From 192.168.0.8 icmp_seq=1 Destination Port Unreachable
[root@internet ~]#curl 10.0.0.7
curl: (7) couldn't connect to host
#利用state模块实现允许内网可以访问外网所有资源
[root@firewall ~]#iptables -DFORWARD 2
[root@firewall ~]#iptables -DFORWARD 2
[root@firewall ~]#iptables -IFORWARD 2 -s 10.0.0.0/24 -m state --state NEW -j
ACCEPT
[root@firewall ~]#iptables -vnL --line-numbers
[root@lanserver1 ~]#ping 192.168.0.6 -c1
PING 192.168.0.6 (192.168.0.6) 56(84) bytes of data.
64 bytes from 192.168.0.6: icmp_seq=1 ttl=63 time=2.26 ms
[root@lanserver2 ~]#curl 192.168.0.6
internet
[root@lanserver2 ~]#ssh 192.168.0.6
The authenticity of host '192.168.0.6 (192.168.0.6)' can't be established.
RSA key fingerprint is SHA256:ldHMw3UFehPuE3bgtMHIX5IxRRTM7fwC4iZ0Qqglcys.
RSA key fingerprint is MD5:8c:44:d9:3d:22:54:62:d8:27:77:d5:06:09:58:76:92.
Are you sure you want to continue connecting (yes/no)?
[root@internet ~]#curl 10.0.0.7
curl: (7) couldn't connect to host
[root@internet ~]#ping 10.0.0.7 -c1
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
From 192.168.0.8 icmp_seq=1 Destination Port Unreachable
[root@internet ~]#ssh 10.0.0.7
ssh: connect to host 10.0.0.7 port 22: Connection refused
#允许内网指定主机被外网访问
[root@firewall ~]#iptables -IFORWARD 3 -d 10.0.0.7 -p tcp --dport 80 -j ACCEPT
[root@firewall ~]#iptables -vnL --line-numbers
[root@internet ~]#curl 10.0.0.7
lanserver1
[root@internet ~]#ping 10.0.0.7 -c1
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
From 192.168.0.8 icmp_seq=1 Destination Port Unreachable
[root@internet ~]#curl 10.0.0.17
curl: (7) couldn't connect to host
范例:内部可以访问外部,外部禁止访问内部
[root@internet-host ~]#hostname -I
10.0.0.6
[root@internet-host ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
0.0.0.0 10.0.0.8 0.0.0.0 UG 0 0 0 eth0
[root@firewall-host ~]#hostname -I
10.0.0.8 192.168.100.8
[root@lan-host ~]#hostname -I
192.168.100.7
[root@lan-host ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.100.8 0.0.0.0 UG 100 0 0 eth0
192.168.100.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
[root@firewall-host ~]#vim /etc/sysctl.conf
net.ipv4.ip_forward=1
[root@firewall-host ~]#sysctl -p
[root@firewall-host ~]#iptables -A FORWARD -d 192.168.100.0/24 -m state --state
NEW -j REJECT
范例:针对内部的特定服务可以允许外部访问,其它服务禁止访问
[root@firewall-host ~]#iptables -I FORWARD -d 192.168.100.0/24 -p tcp --dport 80
-j ACCEPT
[root@firewall-host ~]#iptables -vnL FORWARD --line-numbers
NAT: network address translation,支持PREROUTING,INPUT,OUTPUT,POSTROUTING四个链
请求报文:修改源/目标IP,由定义如何修改
响应报文:修改源/目标IP,根据跟踪机制自动实现
NAT的实现分为下面类型:
SNAT:基于nat表的target,适用于固定的公网IP
SNAT选项:
iptables -t nat -A POSTROUTING -s LocalNET ! -d LocalNET -j SNAT --to-source ExtIP
注意:需要开启ip_forward
范例:
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j SNAT --to-source 172.18.1.6-172.18.1.9
MASQUERADE:基于nat表的target,适用于动态的公网IP,如:拨号网络
MASQUERADE选项:
iptables -t nat -A POSTROUTING -s LocalNET ! -d LocalNET -j MASQUERADE
范例:
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j MASQUERADE
范例:查看本地主机访问公网时使用的IP
[root@centos8 ~]#curl http://ip.sb
39.164.140.134
[root@centos8 ~]#curl http://ipinfo.io/ip/
39.164.140.134
[root@centos8 ~]#curl http://ifconfig.me
39.164.140.134
[root@centos8 ~]#curl -L http://tool.lu/ip
当前IP: 39.164.140.134
归属地: 中国 河南 郑州
[root@centos8 ~]#curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress
39.164.140.134[root@centos8 ~]#
[root@centos8 ~]#curl cip.cc
IP : 39.164.140.134
地址 : 中国 河南 鹤壁
运营商 : 移动
数据二 : 河南省郑州市 | 移动
数据三 :
URL : http://www.cip.cc/39.164.140.134
#启用路由转发
[root@firewall ~]#vim /etc/sysctl.conf
net.ipv4.ip_forward=1
[root@firewall ~]#sysctl -p
#针对专线静态公共IP
[root@firewall ~]#iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j SNAT --tosource
192.168.0.8
#针对拨号网络和专线静态公共IP
[root@firewall ~]#iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE
#查看监听端口
[root@firewall ~]#ss -ntl
#内网可以访问外网
[root@lanserver1 ~]#curl 192.168.0.6
internet
#外网不可以访问内网
[root@internet ~]#curl 10.0.0.7
curl: (7) Failed to connect to 10.0.0.7: Network is unreachable
#在外网服务器查看到是firewalld的地址在访问
[root@internet ~]#tail -f /var/log/httpd/access_log
192.168.0.8 - - [08/Jul/2020:17:36:54 +0800] "GET / HTTP/1.1" 200 9 "-"
"curl/7.29.0"
#查看转换状态信息
[root@firewall ~]#cat /proc/net/nf_conntrack
ipv4 2 tcp 6 112 TIME_WAIT src=10.0.0.7 dst=192.168.0.6 sport=58384
dport=80 src=192.168.0.6 dst=192.168.0.8 sport=80 dport=58384 [ASSURED] mark=0
zone=0 use=2
范例:实现SNAT
[root@internet-host ~]#hostname -I
10.0.0.6
[root@internet-host ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
#启用路由转发
[root@firewall ~]#vim /etc/sysctl.conf
net.ipv4.ip_forward=1
[root@firewall ~]#sysctl -p
[root@firewall-host ~]#hostname -I
10.0.0.8 192.168.100.8
[root@firewall-host ~]#sysctl -a |grep net.ipv4.ip_forward
net.ipv4.ip_forward = 1
[root@lan-host ~]#hostname -I
192.168.100.7
[root@lan-host ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.100.8 0.0.0.0 UG 100 0 0 eth0
192.168.100.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
[root@firewall-host ~]#iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -j
SNAT --to-source 10.0.0.8
[root@firewall-host ~]#iptables -vnL -t nat
[root@lan-host ~]#curl 10.0.0.6
internet Server
[root@internet-host ~]#curl 192.168.100.7
curl: (7) Failed to connect to 192.168.100.7: Network is unreachable
[root@internet-host ~]#tail /var/log/httpd/access_log
10.0.0.8 - - [21/Mar/2020:16:31:35 +0800] "GET / HTTP/1.1" 200 16 "-"
"curl/7.29.0"
[root@lan-host ~]#ping 10.0.0.6
PING 10.0.0.6 (10.0.0.6) 56(84) bytes of data.
64 bytes from 10.0.0.6: icmp_seq=1 ttl=63 time=0.989 ms
64 bytes from 10.0.0.6: icmp_seq=2 ttl=63 time=0.544 ms
[root@internet-host ~]#tcpdump -i eth0 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
16:34:30.171222 IP 10.0.0.8 > 10.0.0.6: ICMP echo request, id 24718, seq 120,
length 64
16:34:30.171255 IP 10.0.0.6 > 10.0.0.8: ICMP echo reply, id 24718, seq 120,
length 64
[root@firewall-host ~]#iptables -t nat -R POSTROUTING 1 -s 192.168.100.0/24 -j
MASQUERADE
[root@firewall-host ~]#iptables -t nat -nvL
[root@firewall-host ~]#cat /proc/net/nf_conntrack
ipv4 2 tcp 6 32 TIME_WAIT src=192.168.100.7 dst=10.0.0.6 sport=39430
dport=80 src=10.0.0.6 dst=10.0.0.8 sport=80 dport=39430 [ASSURED] mark=0 zone=0
use=2
DNTA:nat表的target,适用于端口映射,即可重定向到本机,也可以支持重定向至不同主机的不同端口,但不支持多目标,即不支持负载均衡功能
DNAT选项:
iptables -t nat -A PREROUTING -d ExtIP -p tcp|udp --dport PORT -j DNAT --todestination
InterSeverIP[:PORT]
#启用路由转发
[root@firewall ~]#vim /etc/sysctl.conf
net.ipv4.ip_forward=1
[root@firewall ~]#sysctl -p
[root@firewall ~]#iptables -t nat -A PREROUTING -d 192.168.0.8 -p tcp --dport 80
-j DNAT --to-destination 10.0.0.7:8080
[root@internet ~]#curl 192.168.0.8
lanserver1
[root@lanserver1 ~]#tail /var/log/httpd/access_log
192.168.0.6 - - [08/Jul/2020:18:10:37 +0800] "GET / HTTP/1.1" 200 11 "-"
"curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3
libidn/1.18 libssh2/1.4.2"
[root@firewall ~]#cat /proc/net/nf_conntrack
ipv4 2 tcp 6 117 TIME_WAIT src=192.168.0.6 dst=192.168.0.8 sport=58170
dport=80 src=10.0.0.7 dst=192.168.0.6 sport=8080 dport=58170 [ASSURED] mark=0
zone=0 use=2
范例:
iptables -t nat -A PREROUTING -d 172.16.100.6 -p tcp --dport 22 -j DNAT --to-destination 10.0.1.22
iptables -t nat -A PREROUTING -d 172.16.100.6 -p tcp --dport 80 -j DNAT --to-destination 10.0.1.22:8080
范例:
[root@firewall-host ~]#iptables -t nat -A PREROUTING -d 10.0.0.8 -p tcp --dport
80 -j DNAT --to-destination 192.168.100.7
[root@internet-host ~]#curl 10.0.0.8
lan server
[root@internet-host ~]#telnet 10.0.0.8
Trying 10.0.0.8...
telnet: connect to address 10.0.0.8: Connection refused
[root@lan-host ~]#tail -f /var/log/httpd/access_log
10.0.0.6 - - [21/Mar/2020:17:32:37 +0800] "GET / HTTP/1.1" 200 11 "-"
"curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3
libidn/1.18 libssh2/1.4.2"
[root@lan-host ~]#tail -f /var/log/httpd/access_log
10.0.0.6 - - [21/Mar/2020:17:32:37 +0800] "GET / HTTP/1.1" 200 11 "-"
"curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3
libidn/1.18 libssh2/1.4.2"
[root@lan-host ~]#vim /etc/httpd/conf/httpd.conf
listen 8000
[root@lan-host ~]#systemctl restart httpd
[root@firewall-host ~]#iptables -t nat -R PREROUTING 1 -d 10.0.0.8 -p tcp --
dport 80 -j DNAT --to-destination 192.168.100.7:8000
REDIRECT,是NAT表的target,通过改变目标IP和端口,将接受的包转发至同一个主机的不同端口,可用于PREROUTING OUTPUT链
REDIRECT选项:
iptables -t nat -A PREROUTING -d 172.16.100.10 -p tcp --dport 80 -j REDIRECT --to-ports 8080
范例:
[root@centos8 ~]#iptables -t nat -A PREROUTING -t tcp --dport 8000 -j REDIRECT --to-ports 80
firewalld 是CentOS 7.0新推出的管理netfilter的用户空间软件工具
firewalld是配置和监控防火墙规则的系统守护进程。可以实现iptables,ip6tables,etables功能
firewalld服务由firewalld包提供
firewalld支持划分区域zone,每个zone可以设置独立的防火墙规则
归入zone顺序:
firewall-cmd格式
Usage: firewall-cmd [OPTIONS...]
常见选项
--get-zones 列出所有可用区域
--get-default-zone 查询默认区域
--set-default-zone= 设置默认区域
--get-active-zones 列出当前正使用的区域
--add-source=[--zone=] 添加源地址的流量到指定区域,如果无--zone= 选项,使
用默认区域
--remove-source= [--zone=] 从指定区域删除源地址的流量,如无--zone= 选项,
使用默认区域
--add-interface=[--zone=] 添加来自于指定接口的流量到特定区域,如果无-
-zone= 选项,使用默认区域
--change-interface=[--zone=] 改变指定接口至新的区域,如果无--zone=
选项,使用默认区域
--add-service= [--zone=] 允许服务的流量通过,如果无--zone= 选项,使用默
认区域
--add-port=[--zone=] 允许指定端口和协议的流量,如果无--zone= 选
项,使用默认区域
--remove-service= [--zone=] 从区域中删除指定服务,禁止该服务流量,如果
无--zone= 选项,使用默认区域
--remove-port=[--zone=] 从区域中删除指定端口和协议,禁止该端口
的流量,如果无--zone= 选项,使用默认区域
--reload 删除当前运行时配置,应用加载永久配置
--list-services 查看开放的服务
--list-ports 查看开放的端口
--list-all [--zone=] 列出指定区域的所有配置信息,包括接口,源地址,端口,服务等,
如果无--zone= 选项,使用默认区域
范例:
#查看默认zone
firewall-cmd --get-default-zone
#默认zone设为dmz
firewall-cmd --set-default-zone=dmz
#在internal zone 中增加源地址192.168.0.0/24的永久规则
firewall-cmd --permanent --zone=internal --add-source=192.168.0.0/24
#在internal zone中增加协议mysql的永久规则
firewall-cmd --permanent --zone=internal --add-service=mysql
#加载新规则以生效
firewall-cmd --reload
范例:配置firewalld
systemctl mask 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
当基本firewalld语法规则不能满足要求时,可以使用以下更复杂的规则
rich规则比基本的firewalld语法实现更强的功能,不仅实现允许/拒绝,还可以实现日志syslog和auditd,也可以实现端口转发,伪装和限制速率
规则实现顺序:
rule
[source]
[destination]
service|port|protocol|icmp-block|masquerade|forward-port
[log]
[audit]
[accept|reject|drop]
帮助:man 5 firewalld.richlanguage
rich规选项*
拒绝从192.168.0.100的所有流量,当address 选项使用source 或 destination时,必须用family= ipv4|ipv6
firewall-cmd --permanent --zone=public --add-rich-rule='rule family=ipv4 source address=192.168.0.100/32 reject'
限制每分钟只有两个连接到ftp服务
firewall-cmd --add-rich-rule='rule service name=ftp limit value=2/m accept'
抛弃esp(IPsec体系中的一种主要协议)协议的所有数据包
firewall-cmd --permanent --add-rich-rule='rule protocol value=esp drop'
接受所有192.68.1.0/24子网端口5900-5905范围的TCP流量
firewall-cmd --permanent --zone=vnc --add-rich-rule='rule family=ipv4 source
address=192.168.1.0/24 port port=5900-5905 protocol=tcp accept'
rich日志规则
log [prefix="" [level=] [limit value=""]
可以是emerg,alert, crit, error, warning, notice, info, debug.
s:秒, m:分钟, h:小时, d:天
audit [limit value=""]
范例:
#接受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
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'
firewall-cmd --reload
tail -f /var/log/messages
curl http://serverX.example.com
NAT网络地址转换,firewalld支持伪装和端口转发两种NAT方式
伪装NAT
firewall-cmd --permanent --zone= --add-masquerade
firewall-cmd --query-masquerade #检查是否允许伪装
firewall-cmd --add-masquerade #允许防火墙伪装IP
firewall-cmd --remove-masquerade #禁止防火墙伪装IP
范例:
firewall-cmd --add-rich-rule='rule family=ipv4 source address=192.168.0.0/24
masquerade'
端口转发
端口转发:将发往本机的特定端口的流量转发到本机或不同机器的另一个端口。通常要配合地址伪装才能实现
firewall-cmd --permanent --zone= --add-forward-port=port=
:proto=[:toport=][:toaddr=]
说明:toport= 和toaddr= 至少要指定一个
范例:
#转发传入的连接9527/TCP,到防火墙的80/TCP到public zone 的192.168.0.254
firewall-cmd --add-masquerade 启用伪装
firewall-cmd --zone=public --add-forwardport=
port=9527:proto=tcp:toport=80:toaddr=192.168.0.254
rich规则的port转发语法:
forward-port port= protocol=tcp|udp [to-port=] [to-addr=
]
范例:
#转发从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'
firewall-cmd --permanent --add-rich-rule 'rule family=ipv4 source
address=172.25.X.10/32 forward-port port=443 protocol=tcp to-port=22'
firewall-cmd --reload
ssh -p 443 serverX.example.com
范例:限制ssh服务非标准端口访问
cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/ssh.xml
vim /etc/firewalld/services/ssh.xml
systemctl restart sshd.service
systemctl status -l sshd.service
sealert -a /var/log/audit/audit.log
semanage port -a -t ssh_port_t -p tcp 999
systemctl restart sshd.service
ss -tulpn | grep sshd
firewall-cmd --permanent --zone=work --add-source=172.25.X.0/24
firewall-cmd --permanent --zone=work --add-port=999/tcp
firewall-cmd --reload
nftables是一个netfilter项目,旨在替换现有的{ip,ip6,arp,eb}tables 框架,为 {ip,ip6}tables 提供一个新的包过滤框架、一个新的用户空间实用程序(nft)和一个兼容层。它使用现有的钩子、链接跟踪系统、用户空间排队组件和 netfilter 日志子系统。
nftables主要由三个组件组成:内核实现、libnl netlink 通信和nftables 用户空间。其中内核提供了一个netlink 配置接口以及运行时规则集评估,libnl包含了与内核通信的基本函数,用户空间可以通过nft和用户进行交互。
在 Linux 内核版本高于 3.13 时可用。提供一个新的命令行工具 nft 语法与 iptables 不同。
官方Wiki:https://wiki.nftables.org
官方文档:https://www.netfilter.org/projects/nftables/manpage.html
参考文档:https://www.mankier.com/8/nft
nftables 和 iptables 一样,由表(table)、链(chain)和规则(rule)组成,其中表包含链,链包含规则,规则是真正的 action,规则由地址,接口,端口或包含当前处理数据包中的其他数据等表达式以及诸如drop, queue, continue等声明组成。
与 iptables 相比,nftables 主要有以下几个变化:
nftables 的每个表只有一个地址簇,并且只适用于该簇的数据包。表可以指定五个簇中的一个:
inet 同时适用于 IPv4 和 IPv6 的数据包,即统一了 ip 和 ip6 簇,可以更容易地定义规则,注:当
没有指定地址簇时,默认为ip
链是用来保存规则的,和表一样,链也需要被显示创建,因为 nftables 没有内置的链。链有以下两种类
型:
[root@centos8 ~]#rpm -qi nftables
Name : nftables
Epoch : 1
Version : 0.9.0
Release : 8.el8
Architecture: x86_64
Install Date: Wed 19 Aug 2020 06:31:07 AM CST
Group : Unspecified
Size : 758622
License : GPLv2
Signature : RSA/SHA256, Tue 02 Jul 2019 08:19:09 AM CST, Key ID 05b555b38483c65d
Source RPM : nftables-0.9.0-8.el8.src.rpm
Build Date : Sat 11 May 2019 11:06:46 PM CST
Build Host : x86-01.mbox.centos.org
Relocations : (not relocatable)
Packager : CentOS Buildsys
Vendor : CentOS
URL : http://netfilter.org/projects/nftables/
Summary : Netfilter Tables userspace utillites
Description :
Netfilter Tables userspace utilities.
[root@centos8 ~]#rpm -ql nftables
/etc/nftables
/etc/nftables/all-in-one.nft
/etc/nftables/arp-filter.nft
/etc/nftables/bridge-filter.nft
/etc/nftables/inet-filter.nft
/etc/nftables/ipv4-filter.nft
/etc/nftables/ipv4-mangle.nft
/etc/nftables/ipv4-nat.nft
/etc/nftables/ipv4-raw.nft
/etc/nftables/ipv6-filter.nft
/etc/nftables/ipv6-mangle.nft
/etc/nftables/ipv6-nat.nft
/etc/nftables/ipv6-raw.nft
/etc/sysconfig/nftables.conf
/usr/lib/.build-id
/usr/lib/.build-id/3a
/usr/lib/.build-id/3a/fa4045dde41ce6154a86f17bcc091fba562b50
/usr/lib/.build-id/6f
/usr/lib/.build-id/6f/e11fbe352ba378822d3e856ecbb2ba0fe8b8d8
/usr/lib/systemd/system/nftables.service
/usr/lib64/libnftables.so.0
/usr/lib64/libnftables.so.0.0.0
/usr/sbin/nft
/usr/share/licenses/nftables
/usr/share/licenses/nftables/COPYING
/usr/share/man/man8/nft.8.gz
[root@centos8 ~]#cat /etc/sysconfig/nftables.conf
#
# This this will contain your nftables rules and
# is read by the systemd service when restarting
#
# These provide an iptables like set of filters
# (uncomment to include)
# include "/etc/nftables/bridge-filter.nft"
# include "/etc/nftables/inet-filter.nft"
# include "/etc/nftables/ipv4-filter.nft"
# include "/etc/nftables/ipv4-mangle.nft"
# include "/etc/nftables/ipv4-nat.nft"
# include "/etc/nftables/ipv6-filter.nft"
# include "/etc/nftables/ipv6-mangle.nft"
# include "/etc/nftables/ipv6-nat.nft"
Usage: nft [ options ] [ cmds... ]
Options:
-h, --help 显示帮助
-v, --version 显示版本信息
-c, --check 检查命令的有效性,而不实际应用更改
-f, --file 包含文件内容
-i, --interactive 从命令行读取输入
-j, --json 以JSON格式化输出
-n, --numeric 指定一次后,以数字方式显示网络地址(默认行为)。指定两次以数字方式显示Internet
服务(端口号)。指定三次以数字方式显示协议,用户ID和组ID。
-s, --stateless 省略规则集的状态信息
-N 将IP地址转换为名称
-a, --handle 显示规则句柄handle
-e, --echo Echo what has been added, inserted or replaced.
-I, --includepath 添加目录到包含文件的搜索路径中。默认为: /etc
--debug 添加调试,在level处(scanner, parser, eval, netlink,
mnl, proto-ctx, segtree, all)
nft 命令基本格式
nft 操作符 操作目标 操作内容
1 操作符:增,删,改,查,清除,插入,创建
表操作:add,delete,list,flush
链操作:add,delete,rename,list,flush,create
规则:add,delete,insert
2 操作目标:链,表,链,规则
链类型:filter,route,nat
链勾子:hook
3 操作内容:...
nft list ruleset #列出所有规则
nft list tables #列出所有表
nft list table filter #列出ip簇的filter表
nft list table inet filter #列出inet簇的filter表
nft list chain filter INPUT #列出filter表input链
以上命令后面也可以加 -nn 用于不解析IP地址和端口
加 -a 用于显示 handles
范例:
[root@centos8 ~]#nft list tables
[root@centos8 ~]#vim /etc/sysconfig/nftables.conf
#删除此行前的注释
include "/etc/nftables/inet-filter.nft"
[root@centos8 ~]#systemctl restart nftables.service
[root@centos8 ~]#nft list tables
table inet filter
#默认为ip簇,无规则
[root@centos8 ~]#nft list table filter
Error: Could not process rule: No such file or directory
list table filter
^^^^^^
#指定inet簇才有规则
[root@centos8 ~]#nft list table inet filter
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
[root@centos8 ~]#nft list ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
增加表:nft add table filter
增加链:nft add chain filter input { type filter hook input priority 0 ; } #要和hook(勾子)相关链
增加规则:nft add rule filter input tcp dport 22 accept
只需要把上面的 add 改为 delete 即可
更改链名用rename
更改规则用replace
[root@centos8 ~]#nft add table inet test_table
[root@centos8 ~]#nft list tables
table inet filter
table inet test_table
[root@centos8 ~]#nft delete table inet test_table
[root@centos8 ~]#nft list tables
table inet filter
[root@centos8 ~]#nft add table inet test_table
列出所有的规则
[root@centos8 ~]#nft list ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
table inet test_table {
}
现在表中还没有任何规则,需要创建一个链来保存规则
创建基本链:
[root@centos8 ~]#nft add chain inet test_table test_filter_input_chain { type filter hook input priority 0 \; }
[root@centos8 ~]#nft add chain inet test_table test_chain
列出链:
[root@centos8 ~]#nft list table inet test_table
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
}
chain test_chain {
}
}
[root@centos8 ~]#nft list chain inet test_table test_chain
table inet test_table {
chain test_chain {
}
}
[root@centos8 ~]#nft list ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
}
chain test_chain {
}
}
有了表和链之后,就可以创建规则了,规则由语句或表达式构成,包含在链中
#创建常规链的规则
[root@centos8 ~]#nft add rule inet test_table test_chain tcp dport http reject
[root@centos8 ~]#nft list chain inet test_table test_chain
table inet test_table {
chain test_chain {
tcp dport http reject
}
}
#常规链规则默认不生效
[root@centos7 ~]#curl 10.0.0.8
rft Http Server
add 表示将规则添加到链的末尾,如果想将规则添加到链的开头,可以使用 insert
[root@centos8 ~]#nft insert rule inet test_table test_chain tcp dport mysql reject
列出规则:
[root@centos8 ~]#nft list chain inet test_table test_chain
table inet test_table {
chain test_chain {
tcp dport mysql reject
tcp dport http reject
}
}
[root@centos8 ~]#nft list table inet test_table
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
}
chain test_chain {
tcp dport mysql reject
tcp dport http reject
}
}
[root@centos8 ~]#nft add rule inet test_table test_filter_input_chain tcp dport http reject
[root@centos8 ~]#nft add rule inet test_table test_filter_input_chain ip saddr 10.0.0.6 reject
[root@centos8 ~]#nft list chain inet test_table test_filter_input_chain
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
tcp dport http reject
ip saddr 10.0.0.6 reject
}
}
[root@centos7 ~]#curl 10.0.0.8
curl: (7) Failed to connect to 10.0.0.8 port 80: Connection refused
将规则插入到链的指定位置,有两种方法:
index 类似于 iptables 的-I 选项,index的值是从0 开始的
index必须指定向一个存在的规则,比如nft insert rule … index 0 就是非法的
add 表示新规则添加在索引位置的规则后面
insert表示新规则添加在索引位置的规则前面
[root@centos8 ~]#nft insert rule inet test_table test_filter_input_chain index 0 tcp dport mysql reject
[root@centos8 ~]#nft list chain inet test_table test_filter_input_chain
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
tcp dport mysql reject
tcp dport http reject
ip saddr 10.0.0.6 reject
}
}
[root@centos8 ~]#nft insert rule inet test_table test_filter_input_chain index 1 udp dport 123 accept
[root@centos8 ~]#nft list chain inet test_table test_filter_input_chain
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
tcp dport mysql reject
udp dport ntp accept
tcp dport http reject
ip saddr 10.0.0.6 reject
}
}
在 nftables 中,句柄值是固定不变的,除非规则被删除,这就为规则提供了稳定的索引。而 index 的值是可变的,只要有新规则插入,就有可能发生变化。一般建议使用 handle 来插入新规则。
add 表示新规则添加在索引位置的规则后面, insert 表示新规则添加在索引位置的规则前面。
handle 的值可以通过参数 --handle 或者 -a 获取
[root@centos8 ~]#nft -a list chain inet test_table test_filter_input_chain
table inet test_table {
chain test_filter_input_chain { # handle 1
type filter hook input priority 0; policy accept;
tcp dport mysql reject # handle 8
udp dport ntp accept # handle 9
tcp dport http reject # handle 6
ip saddr 10.0.0.6 reject # handle 7
}
}
[root@centos8 ~]#nft add rule inet test_table test_filter_input_chain handle 7 tcp dport ftp reject
[root@centos8 ~]#nft -a list chain inet test_table test_filter_input_chain
table inet test_table {
chain test_filter_input_chain { # handle 1
type filter hook input priority 0; policy accept;
tcp dport mysql reject # handle 8
udp dport ntp accept # handle 9
tcp dport http reject # handle 6
ip saddr 10.0.0.6 reject # handle 7
tcp dport ftp reject # handle 10
}
}
[root@centos8 ~]#nft insert rule inet test_table test_filter_input_chain handle 8 udp dport 8080 reject[root@centos8 ~]#nft -a -nn list ruleset
table inet filter { # handle 1
chain input { # handle 1
type filter hook input priority 0; policy accept;
}
chain forward { # handle 2
type filter hook forward priority 0; policy accept;
}
chain output { # handle 3
type filter hook output priority 0; policy accept;
}
}
table inet test_table { # handle 3
chain test_filter_input_chain { # handle 1
type filter hook input priority 0; policy accept;
udp dport 8080 reject # handle 11
tcp dport 3306 reject # handle 8
udp dport 123 accept # handle 9
tcp dport 80 reject # handle 6
ip saddr 10.0.0.6 reject # handle 7
tcp dport 21 reject # handle 10
}
chain test_chain { # handle 2
tcp dport 3306 reject # handle 5
tcp dport 80 reject # handle 4
}
}
可以在创建规则时就获取到规则的句柄值,在创建规则时同时加上参数 --echo或者-e和–handle
[root@centos8 ~]#nft -a -e add rule inet test_table test_filter_input_chain tcp dport 6379 reject
add rule inet test_table test_filter_input_chain tcp dport 6379 reject # handle 12
[root@centos8 ~]#nft -a list chain inet test_table test_filter_input_chain
table inet test_table {
chain test_filter_input_chain { # handle 1
type filter hook input priority 0; policy accept;
udp dport http-alt reject # handle 11
tcp dport mysql reject # handle 8
udp dport ntp accept # handle 9
tcp dport http reject # handle 6
ip saddr 10.0.0.6 reject # handle 7
tcp dport ftp reject # handle 10
tcp dport 6379 reject # handle 12
}
}
单个规则只能通过其句柄删除,首先需要找到想要删除的规则句柄
[root@centos8 ~]#nft --handle list ruleset
table inet filter { # handle 1
chain input { # handle 1
type filter hook input priority 0; policy accept;
}
chain forward { # handle 2
type filter hook forward priority 0; policy accept;
}
chain output { # handle 3
type filter hook output priority 0; policy accept;
}
}
table inet test_table { # handle 3
chain test_filter_input_chain { # handle 1
type filter hook input priority 0; policy accept;
udp dport http-alt reject # handle 11
tcp dport mysql reject # handle 8
udp dport ntp accept # handle 9
tcp dport http reject # handle 6
ip saddr 10.0.0.6 reject # handle 7
tcp dport ftp reject # handle 10
tcp dport 6379 reject # handle 12
}
chain test_chain { # handle 2
tcp dport mysql reject # handle 5
tcp dport http reject # handle 4
}
}
然后使用句柄值来删除该规则:
[root@centos8 ~]#nft delete rule inet test_table test_filter_input_chain handle 8
[root@centos8 ~]#nft -a list chain inet test_table test_filter_input_chain
table inet test_table {
chain test_filter_input_chain { # handle 1
type filter hook input priority 0; policy accept;
udp dport http-alt reject # handle 11
udp dport ntp accept # handle 9
tcp dport http reject # handle 6
ip saddr 10.0.0.6 reject # handle 7
tcp dport ftp reject # handle 10
tcp dport 6379 reject # handle 12
}
}
[root@centos8 ~]#nft flush ruleset
[root@centos8 ~]#nft list ruleset
可以列出所有规则,也可以列出规则的一部分
[root@centos8 ~]#nft list ruleset
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
ip saddr 10.0.0.6 reject
tcp dport 6379 reject
udp dport http-alt reject
tcp dport 6379 reject
ip saddr 10.0.0.6 reject
}
}
[root@centos8 ~]#nft list table inet test_table
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
ip saddr 10.0.0.6 reject
tcp dport 6379 reject
udp dport http-alt reject
tcp dport 6379 reject
ip saddr 10.0.0.6 reject
}
}
[root@centos8 ~]#nft list chain inet test_table test_filter_input_chain
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
ip saddr 10.0.0.6 reject
tcp dport 6379 reject
udp dport http-alt reject
tcp dport 6379 reject
ip saddr 10.0.0.6 reject
}
}
规则都是临时的,要想永久生效,可以将规则备份,重启后自动加载恢复
查看service文件
[root@centos8 ~]#cat /lib/systemd/system/nftables.service
[Unit]
Description=Netfilter Tables
Documentation=man:nft(8)
Wants=network-pre.target
Before=network-pre.target
[Service]
Type=oneshot
ProtectSystem=full
ProtectHome=true
ExecStart=/sbin/nft -f /etc/sysconfig/nftables.conf
ExecReload=/sbin/nft 'flush ruleset; include "/etc/sysconfig/nftables.conf";'
ExecStop=/sbin/nft flush ruleset
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
备份配置并还原
[root@centos8 ~]#nft list ruleset
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
ip saddr 10.0.0.6 reject
tcp dport 6379 reject
udp dport http-alt reject
tcp dport 6379 reject
ip saddr 10.0.0.6 reject
}
}
[root@centos8 ~]#nft list ruleset > /etc/sysconfig/nftables.conf
#删除所有规则
[root@centos8 ~]#nft flush ruleset
[root@centos8 ~]#nft list ruleset
#重新启动后全部还原
[root@centos8 ~]#systemctl restart nftables.service
[root@centos8 ~]#nft list ruleset
table inet test_table {
chain test_filter_input_chain {
type filter hook input priority 0; policy accept;
ip saddr 10.0.0.6 reject
tcp dport 6379 reject
udp dport http-alt reject
tcp dport 6379 reject
ip saddr 10.0.0.6 reject
}
}
启用指定的配置文件
[root@centos8 ~]#cat nftables2.conf
table inet test2_table {
chain test2_filter_input_chain {
type filter hook input priority 0; policy accept;
ip saddr { 10.0.0.1, 10.0.0.10 } accept
tcp dport { http, nfs,ssh } reject
}
}
#-f 指定规则配置文件,如果已经有规则,是追加至现有规则后
[root@centos8 ~]#nft -f nftables2.conf
[root@centos8 ~]#nft list ruleset
table inet test2_table {
chain test2_filter_input_chain {
type filter hook input priority 0; policy accept;
ip saddr { 10.0.0.1, 10.0.0.10 } accept
tcp dport { ssh, http, nfs } reject
}
}
# iptables-save > rules.iptables
# iptables-restore-translate -f rules.iptables > rules.nft
# nft -f rules.nft ### load the rule via nft to nftables.
# nft list ruleset
You can see the rules have been migrated from CentOS/RHEL 6 or 7 to CentOS/RHEL 8 server now and can test them as well