昨晚不小心踩了一个坑,当开启 ufw 之后,电脑与外网的连接断开,明明 ufw 设置中 incoming 是 allow、outgoing 是 deny,按理说应该能 ping 的… 结果却全面断网,当然 SSH 也连不进来了… 当把 ufw 禁用、或者把 outgoing 设置成 allow,网络通信就恢复了,如动图所示。这是为啥捏?
不好意思,动图被我删了,只能自己想象了?
别说我 "没加 ping 的 allow 规则",我家 ping 是 ICMP 协议的,我家的 ICMP 协议是网络层的要比传输层的 TCP、UDP 低,所以我家 ping 是没有端口这一说法的。
解决方案
我尝试的无效方案
我先尝试了iptables -F
来 " 清空全部规则 ",无效;
重启无效;
之后我尝试了apt remove –-purge iptables ufw gufw
然后再安装,依旧无效。
天呐 purge 都无效了?
真正的解决方案
我从 DigitalOcean 找到了解决方案
首先,我们先把 INPUT、FORWARD、OUTPUT 这三个链的规则设置成 ACCEPT 免得把自己锁在门外:
- sudo iptables -P INPUT ACCEPT
- sudo iptables -P FORWARD ACCEPT
- sudo iptables -P OUTPUT ACCEPT
然后,我们清除 NAT、Mangle 表,清除链,删除所有的非默认链
- sudo iptables -t nat -F #清除NAT表
- sudo iptables -t mangle -F #清除mangle表
- sudo iptables -F #清除所有链的规则
- sudo iptables -X #删除非默认链
此时如果我们iptables -L
列出链和规则,会发现只剩下 INPUT、FORWARD、OUTPUT 这三个链了,如图:
此时我们再ufw enable
启用 ufw,如果 SSH 请先ufw allow 22
,就会发现没断网。
如果这个时候iptables -L
,会看到多出来很多链和规则
童鞋们是不是觉得很奇怪,为啥这次就行了?我是咋重现的这个问题?
在回答这个问题之前,我们首先要了解下 ufw、iptables 是什么,之后以及这二者之间的关系,简单的了解 iptables 的基本概念和基本运作原理。
ufw
Uncomplicated FireWall,不是 Ubuntu FireWall 哦,是 debian 系发行版中为了轻量化配置 iptables 而开发的一款工具。
UFW 和 iptables 一样都是匹配原则,匹配到了则忽略剩下的规则,这点就不废话了。
iptables
我们习惯性的会把 iptables 认为是 Linux 上的防火墙,自从 Linux 内核 2.4 之后就集成进主线内核。实际上准确是说,iptables 是一个通过控制 Linux 内核的 netfilter 模块来管理网络数据包的流动与转送的应用软件,其功能包括不仅仅包括防火墙的控制出入流量,还有端口转发等等。
iptables 内部有表 tables、链 chains、规则 rules 这三种概念。
iptables 的每一个 "表" 都和不同的数据包处理有关、决定数据包是否可以穿越的是 "链"、而一条 "规则" 在链里面则可以决定是否送往下一条链(或其它的动作)
那一个包到达网卡的时候,Linux 的如何处理的呢?
我们提到了 iptables 是可以控制 netfilter 模块的,netfilter 内部(主要、常用的)分为三个表,分别是 filter, nat, mangle,每个表又有不同的链(Chains),每个链下可以有不同的规则(rules)。
filter
在 filter(过滤)表中,也就是防火墙功能的表,定义了三个链。分别是 INPUT, FORWARD, OUTPUT。也就是对包的入、转发、出进行定义的三个过滤链。对于这个 filter 表的操作和控制也是我们实现防火墙功能的一个重要手段;
nat
在 nat(网络地址转换) 表中,也就是我们用以实现地址转换和端口转发功能的这个表,定义了 PREROUTING, POSTROUTING,OUTPUT 三个链;
mangle
netfilter 的 mangle 表则是一个自定义表,里面包括上面 的 filter 以及 nat 表中的各种 chains,它可以让我们进行一些自定义的操作,同时这个 mangle 表中的 chains 在 netfilter 对包 的处理流程中比较优先。
包在 Linux 中的前世今生
图片来自维基百科(太大了,戳大图吧)
我们大致可以看出:包首先要由 bridge check 来判断属于链路层还是网络层,之后包都会遇到 NAT 或者 mangle 表的 PREROUTING 链,从这 pre 前缀咱能才出来,这是要在路由之前要过的链。
接着当包通过了 PREROUTING 之后,便到了 decision 这个分支点,这里有一个对目的地址的判断,如果包的目的地是本地, 那么包向上走,走入 INPUT 链处理,然后进入 LOCAL PROCESS,之后再进入对应的 OUTPUT、POSTROUTING;
如果非本地,那么就进入 FORWARD 链进行转发,之后再走 POSTROUTING,我们在这里就不说 FORWARD 链的事了。
我们可以看到,filter 表在包的处理流程中,处于中间的位置,这部分也就是防火墙的主要功能所在。
ufw 怎么和 iptables 一起合作的
在稍微理解了包是怎么走的之后,回到我们iptables -L
的时候,我们看 filter 表,可以看到,ufw 在 INPUT、FORWARD、OUTPUT 添加了好些自定义规则,并且添加了好些自己的链和链的规则,还把把 INPUT、FORWARD 默认策略设置成 DROP
如图,当你有这些 ufw 定义的链的时候,是能够匹配到 ufw 链和规则,也就是正常入网的。
当我们执行iptables -F
的时候,会发生什么呢?
所有链的规则都被清空了!包括 ufw 的链!并且 INPUT、FORWARD 依旧是 DROP
再想想包的前世今生,OUTPUT 我们发出了 ping,但是却因为 INPUT 的 DROP 而永远无法收到 ICMP echo,只能往出发包而不能接收任何类型的包,毫无疑问自然就断网了。
此时ufw status
还会告诉你在运行,但是当你使用ufw disable
关闭 ufw 时,INPUT 会被设置成 ACCEPT,自然就恢复网络通信了;
当你使用ufw default allow
把默认出网规则设置成 allow 时,INPUT 也会被设置成 ACCEPT,当然网络通信恢复了。
所以童鞋们自此应该理解了刚开始理解动图能够 ping 通和不通的原因吧!
使用 ufw 和 iptables 的警告
最后给大家一个警告,当你使用了 ufw 这类前端时,就最好不要再碰 iptables 了,尤其要慎重使用 iptables - 来清空所有链的规则。在不了解 iptables 的表、链、规则之前,盲目的清空 iptables"规则" 就是耍流氓!
试想,假如你在服务器上ufw enable
,那么 INPUT 和 FORWARD 就是 DROP,那么当你iptables -F
时,不仅仅是 SSH 的例外规则没了,所有出网的包也都出不去了!此时唯一能做的事情就是去 VNC、或者去机房插鼠标键盘显示器。
假如你是买的服务器,为了安全考虑使用密钥认证,并且把用户名设置成了从 openssl 生成的随机密码,并且你是由 Windows 重装成的 Linux,那么控制台也是没有用的…… 重装或者快照吧。
参考资料:
https://www.digitalocean.com/community/tutorials/how-to-list-and-delete-iptables-firewall-rules
http://xstarcd.github.io/wiki/Linux/iptables_FORWARD_internetshare.html