先整理一下他们之间的关系
netfilter 项目是一个社区驱动的协作 FOSS 项目,为Linux 2.4.x 和更高版本的内核系列提供包过滤软件。netfilter 项目通常与iptables及其后继者nftables相关联。
netfilter 项目支持数据包过滤、网络地址 [和端口] 转换 (NA[P]T)、数据包日志记录、用户空间数据包排队和其他数据包处理。
这是个linux内核的东西。
iptables 是一个配置 Linux 内核 防火墙 的命令行工具,是 Netfilter 项目的一部分。术语 iptables 也经常代指该内核级防火墙。iptables 可以直接配置,也可以通过许多 控制台 和 图形化 前端配置。iptables 用于 ipv4,ip6tables 用于 IPv6。iptables和ip6tables 拥有相同的语法,但是有些特别的选项,对 IPv4 和 IPv6 有些不同的。
这个东西工作在用户空间。
还有ip6tables,arptables ,ebtables。
4表5链
- filter表——过滤数据包
- Nat表——用于网络地址转换(IP、端口)
- Mangle表——修改数据包的服务类型、TTL、并且可以配置路由实现QOS
- Raw表——决定数据包是否被状态跟踪机制处理
- INPUT链——进来的数据包应用此规则链中的策略
- OUTPUT链——外出的数据包应用此规则链中的策略
- FORWARD链——转发数据包时应用此规则链中的策略
- PREROUTING链——对数据包作路由选择前应用此链中的规则(所有的数据包进来的时侯都先由这个链处理)
- POSTROUTING链——对数据包作路由选择后应用此链中的规则(所有的数据包出来的时侯都先由这个链处理)
nftables取代了流行的{ip,ip6,arp,eb}tables。该软件提供了一个新的内核数据包分类框架,该框架基于特定于网络的虚拟机 (VM) 和新的nft用户空间命令行工具。nftables重用了现有的 Netfilter 子系统,例如现有的钩子基础设施、连接跟踪系统、NAT、用户空间队列和日志子系统。
Firewalld 提供动态管理的防火墙,支持定义网络连接或接口的信任级别的网络/防火墙区域。它支持 IPv4、IPv6 防火墙设置、以太网桥和 IP 集。运行时和永久配置选项是分开的。它还为服务或应用程序提供直接添加防火墙规则的接口。
firewalld是centos自带的防火墙软件,当然Ubuntu也可以安装。
ufw是Ubuntu自带的防火墙软件,也是管理netfilter的一个软件。使用方式非常简单。
centos也可以安装。
归根结底,不管是ufw还是firewalld,还是iptables最后都是操作内核的netfilter。
ufw [--dry-run] enable|disable|reload
# ufw防火墙关闭
root@node2:~# systemctl stop ufw
# ufw防火墙状态
root@node2:~# systemctl status ufw
● ufw.service - Uncomplicated firewall
Loaded: loaded (/lib/systemd/system/ufw.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Sat 2022-01-08 10:49:50 UTC; 17s ago
# ufw防火墙打开
root@node2:~# systemctl start ufw
# ufw防火墙状态
root@node2:~# systemctl status ufw
● ufw.service - Uncomplicated firewall
Loaded: loaded (/lib/systemd/system/ufw.service; enabled; vendor preset: enabled)
Active: active (exited) since Sat 2022-01-08 10:51:09 UTC; 3s ago
# ufw防火墙无效
root@node2:~# ufw disable
Firewall stopped and disabled on system startup
# ufw防火墙状态-无效
root@node2:~# ufw status
Status: inactive
# ufw防火墙生效
root@node2:~# ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
# ufw防火墙状态-有效
root@node2:~# ufw status
Status: active
这里要注意一下,开启ufw防火墙可能会中断正在连接中的ssh。
ufw [--dry-run] default allow|deny|reject [incoming|outgoing|routed]
allow 是默认允许所有访问,也就是我们所说的黑名单。有要拒绝的访问,就要加到规则中。
deny 是默认拒绝所有访问,也就是我们所说的白名单。有要允许的访问,就要加到规则中。
reject跟deny一样也是拒绝所有访问。但是跟deny不一样的是 会提醒访问者 访问被拒绝,而deny只会提示访问超时。
ufw [--dry-run] [delete] [insert NUM] [prepend] allow|deny|reject|limit [in|out] [log|log-all] [ PORT[/PROTOCOL] | APPNAME ] [comment COMMENT]
ufw [--dry-run] [rule] [delete] [insert NUM] [prepend] allow|deny|reject|limit [in|out [on INTERFACE]] [log|log-all] [proto PROTOCOL] [from ADDRESS [port PORT | app APPNAME ]] [to ADDRESS [port PORT | app APPNAME ]] [comment COMMENT]
下面开始用实验来说明ufw的使用方法
2.3.1 首先开启ufw的默认模式为deny
在此之前最好先把端口22 设置为allow,要不然在没有规则的情况下,把模式设置为deny,会导致你的远程连接被断开。
ufw allow 22
root@node2:~# ufw default deny
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)
2.3.2 查看防火墙的访问规则
root@node2:~# ufw status
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
22 (v6) ALLOW Anywhere (v6)
2.3.3 添加新的规则
当前机器的端口开放情况,可以看到本机的nginx服务是开启状态,然后在本机用curl命令也可以访问服务。
200root@node2:lsof -i4:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1083 root 6u IPv4 37452 0t0 TCP *:http (LISTEN)
nginx 1084 www-data 6u IPv4 37452 0t0 TCP *:http (LISTEN)
nginx 1085 www-data 6u IPv4 37452 0t0 TCP *:http (LISTEN)
root@node2:~# curl -s localhost -w '%{http_code}' -o /dev/null
200
但是在node1机器上测试nginx,发现经过5秒然后连接超时。
root@node1:~# curl 192.168.0.203 --connect-timeout 5
curl: (28) Connection timed out after 5002 milliseconds
原因就是因为默认deny状态下,80端口未被开放,所以从外面来的访问被拒绝。
如果用reject,会直接告诉访问者,端口拒绝访问,而不是timeout。
root@node2:~# ufw reject 80/tcp
Rule added
Rule added (v6)
root@node2:~# ufw status
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
80/tcp REJECT Anywhere
22 (v6) ALLOW Anywhere (v6)
80/tcp (v6) REJECT Anywhere (v6)
然后在node1机器上,再次测试,发现直接被拒绝。这就是reject和deny的区别。
root@node1:~# curl 192.168.0.203 --connect-timeout 5
curl: (7) Failed to connect to 192.168.0.203 port 80: Connection refused
用allow来开启80端口的访问
root@node2:~# ufw allow 80/tcp
Rule updated
Rule updated (v6)
然后在node1机器上,再次测试,发现可以访问80
root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200
以上就是最基本的端口开闭。
有的时候可能需要更加复杂的规则来约束访问。
比如说只允许某个ip的机器来访问某个端口。
root@node2:~# ufw allow from 192.168.0.202 to any port 80 proto tcp
Rule added
# 这里已经把之前的规则删除了,只留下端口22,然后添加80端口的访问规则
# 可以看到80端口的规则from 变成 固定的IP地址
root@node2:~# ufw status
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
80/tcp ALLOW 192.168.0.202
22 (v6) ALLOW Anywhere (v6)
然后在node1机器上测试,访问成功。
root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200
在centos机器上测试,访问失败。
[root@centos ~]# curl 192.168.0.203 --connect-timeout 2
curl: (28) Connection timed out after 2045 milliseconds
只开放UDP的端口,然后用tcp来访问该端口也会失败。
root@node2:~# ufw allow 8090/udp
Rule added
Rule added (v6)
root@node2:~# ufw status
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
80/tcp ALLOW 192.168.0.202
8090/udp ALLOW Anywhere
22 (v6) ALLOW Anywhere (v6)
8090/udp (v6) ALLOW Anywhere (v6)
root@node2:~# nc -l 8090
# 用nc命令去扫描8090端口
root@node1:~# nc -v -w 2 192.168.0.203 -z 8090
nc: connect to 192.168.0.203 port 8090 (tcp) failed: Connection refused
协议+IP(from to)+端口(from to)可以识别成一个唯一的链接。然后根据这个规则,可以随意的设计防火墙的访问规则。
2.3.4 ufw的限流规则
ufw除了单纯的拒绝,允许以外,还有一个限流的规则,防止同一个IP的暴力访问。使用方式如下:
root@node2:~# ufw limit 80
Rule added
Rule added (v6)
然后在centos上访问80端口,可以看到第6次访问就失败了。前面的5次都访问成功。
[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
000[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
ufw supports connection rate limiting, which is useful for protecting against brute-force login attacks. When a limit rule is used, ufw will normally allow the connection but will deny connections if an IP address attempts to initiate 6 or more connections within 30 seconds
也就是说 30秒内大于等于6次访问就会被拒绝。
2.3.5 删除规则
推荐使用序号删除,从后往前删除,要是从前面删除,序号重新排序。
root@node2:~# ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22 ALLOW IN Anywhere
[ 2] 80/tcp ALLOW IN 192.168.0.202
[ 3] 8090/udp REJECT IN Anywhere
[ 4] 8090/tcp ALLOW IN Anywhere
[ 5] 80 LIMIT IN Anywhere
[ 6] 22 (v6) ALLOW IN Anywhere (v6)
[ 7] 8090/udp (v6) REJECT IN Anywhere (v6)
[ 8] 8090/tcp (v6) ALLOW IN Anywhere (v6)
[ 9] 80 (v6) LIMIT IN Anywhere (v6)
# 根据序号删除
root@node2:~# ufw delete 8
Deleting:
allow 8090/tcp
Proceed with operation (y|n)? y
Rule deleted (v6)
root@node2:~# ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22 ALLOW IN Anywhere
[ 2] 80/tcp ALLOW IN 192.168.0.202
[ 3] 8090/udp REJECT IN Anywhere
[ 4] 8090/tcp ALLOW IN Anywhere
[ 5] 80 LIMIT IN Anywhere
[ 6] 22 (v6) ALLOW IN Anywhere (v6)
[ 7] 8090/udp (v6) REJECT IN Anywhere (v6)
[ 8] 80 (v6) LIMIT IN Anywhere (v6)
root@node2:~#
2.3.6 ufw的规则生效顺序
ufw的规则是,序号最小的先生效。
root@node2:~# ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22 ALLOW IN Anywhere
[ 2] 80/tcp ALLOW IN 192.168.0.202
[ 3] 80 LIMIT IN Anywhere
[ 4] 22 (v6) ALLOW IN Anywhere (v6)
[ 5] 80 (v6) LIMIT IN Anywhere (v6)
来个试验。
访问80端口
序号2 从192.168.0.202访问没有任何限制。
序号3 从别的机器访问是有ratelimit的。
可以看到centos30秒内第6次访问被决绝。 序号3生效
[root@centos ~curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200[root@centos ~]# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
000[root@centos ~]#
从node1访问,30秒内10次全部成功。对于192.168.0.202来说序号2 先生效。
root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~#
现在调整80端口的规则顺序,limit 80 在 allow 80 的前面了。
root@node2:~# ufw delete 5
Deleting:
limit 80
Proceed with operation (y|n)? y
Rule deleted (v6)
root@node2:~# ufw delete 3
Deleting:
limit 80
Proceed with operation (y|n)? y
Rule deleted
root@node2:~# ufw insert 1 limit 80
Rule inserted
Rule inserted (v6)
root@node2:~# ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 80 LIMIT IN Anywhere
[ 2] 22 ALLOW IN Anywhere
[ 3] 80/tcp ALLOW IN 192.168.0.202
[ 4] 80 (v6) LIMIT IN Anywhere (v6)
[ 5] 22 (v6) ALLOW IN Anywhere (v6)
再次在node1测试,第6次访问被决绝!对于192.168.0.202 来说 序号1 先生效!
root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
200root@node1:~# curl -s 192.168.0.203 -w '%{http_code}' -o /dev/null
000root@node1:~#
以上就是ufw的基本用法,ufw还有路由功能,还没研究,有空补上。