昨晚不小心踩了一个坑,当开启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