你是否也被Centos下默认iptables规则坑过

in 互联网技术 with 0 comment  访问: 5,558 次

事件需求


今天让同事去Beta环境实践模拟线上环境多机房异地备份,我们有一个统一登录的数据库,很多产品的登录都基于这个库做的统一登录,所以是比较重要的一个数据库,所以让他做前端代码和数据库的异地备份,代码好说,跟上线一样,从git库pull代码做同步更新就好,数据库则需要跨机房做异地远程同步并备份。

MYSQL异地主从同步情况说明


MYSQL异地同步架构大致如下:
march.png
如上图所示我们的需求就是B机房的DB2服务器MYSQL的3307实例,通过公网去同步A机房的DB2的3307的MYSQL实例中的一个数据库(ulogin),这里关于MYSQL主从同步的原理我就不详细介绍了,我想这是运维人员应该必备掌握的知识点。

但是有一点大家都是清楚的,那就是B机房MYSQL实例要同步A机房的MYSQL实例的数据,那就是B机房的DB2 MYSQL实例必须要能够连接到A机房的DB2 MYSQL实例,那问题就来了,A、B两个机房的MYSQL实例都是没有公网IP地址的,但是都可以通过路由访问公网。

所以需要解决的就是B机房MYSQL实例可以连接到A机房MYSQL实例即可,具体的做法就是,我们在A机房的路由器上做了一个端口隐射:121.123.90.83:16543 ---> 10.0.0.8:3307, 这样B机房的MYSQL实例去做同步的时候通过连接IP:121.123.90.83的16543端口即可了,到现在网络连接的问题解决了。

但是这样的话,虽然变异了MYSQL实例隐射暴露的端口,但是万一被黑客扫到这端口,然后利用MYSQL的漏洞做脱裤或者其他操作还是不好,所以我们还得利用iptables在A机房DB2服务器上做一层简单防护,控制访问来源IP地址,这样就有下面的事件发生了。

跳坑过程


告诉了同事大致的做这件事情的过程和思路,那台就开始去做了。

默认我们内网的机器是不开启iptables服务的,因为内网服务器没有公网ip,走内网路由只能出不能进,所以不存在安全性问题。

等我把A机房端口映射工作做完之后,通知到同事,他就开始设置iptabels规则了。 同事跳坑最终导致的结果就是A机房的服务器DB2不能远程连接上去,然后所有的服务端口也被屏蔽了。事后问题具体的跳坑过程如下:

1、清理iptables规则


# iptables -F

2、设置input表规则


# iptables -A INPUT -p tcp -s 121.134.33.89 --dport 3307 -j ACCEPT
# iptables -A INPUT -p tcp -s 10.0.0.0/16 --dport 3307 -j ACCEPT
# iptables -A INPUT -p tcp --dport 3307 -j DROP

3、保存添加的规则


# /etc/init.d/iptables save

4、编辑确认规则


# vim /etc/sysconfig/iptables
# Generated by iptables-save v1.4.7 on Thu Jul 13 09:17:19 2017
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [787:76250]
-A INPUT -m state —state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -p icmp -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A INPUT -j REJECT —reject-with icmp-host-prohibited 
-A INPUT -s 121.134.33.89/32 -p tcp -m tcp —dport 3307 -j ACCEPT 
-A INPUT -s 10.0.0.0/16 -p tcp -m tcp —dport 3307 -j ACCEPT  
-A INPUT -p tcp -m tcp —dport 3307 -j DROP 
-A FORWARD -j REJECT —reject-with icmp-host-prohibited 
-A INPUT -p tcp -m state —state NEW -m tcp —dport 22000 -j ACCEPT 
COMMIT
# Completed on Thu Jul 13 09:17:19 2017

5、重启iptables服务


他认为没有问题,所有的准备工作和设置都ok了,然后重启服务:

# /etc/init.d/iptables restart

经过上面5个步骤他认为没有事情了,一切ok,然后退出服务器了,但是踩坑后的悲剧发生了:A、网站告警了,报500内部错误,然后监控MYSQL实例的端口监控也报价了,接收到告警之后,他想登陆服务器查看具体原因,但是悲剧的是他发现远程登陆也登陆不了,这是为什么,从他的不走上看没有多大问题啊,下面我给大家分析一下,默认的一条input规则的坑。

分析入坑过程


首先经过上面的背景介绍和他具体的操作过程,我们来一一分析他的操作过程:

第一步,他利用iptables -F来清理iptables的规则,他认为这样会清理掉默认的规则,但是他错了,因为这个命令只有在你iptables服务启动的状态下,才会清理掉的,因为默认规则已经在文件/etc/sysconfig/iptables中保存着呢,这样做是没用的,所以这步是无用功

第二步,设置iptables的input规则没有问题,因为他是基于第一步的思考之上的(认为默认规则已经清空了)。

第三步,保存规则这步也没有问题,也是基于第一步的先觉条件

第四步,编辑确认规则,这步最重要,所以的过错都来源于这步。当他编辑文件/etc/sysconfig/iptables的时候,他看到了默认规则的存在,但是他发现都是input规则(当时心里想,应该没有太大问题,也没有注意到一条input表的REJECT记录),他只是把-A INPUT -p tcp -m state —state NEW -m tcp —dport 22 -j ACCEPT这条规则的22改为了22000端口(因为我们的服务器都是修改了默认ssh远程端口为22000的),然后放到了FORWARD表规则后面。

第五步 ,重启iptables服务,退出服务器。

结果上面的分析,我可以清晰的告诉大家的是,出现问题就是出现在第四步,第四步就是真正忽略了默认iptables规则中的-A INPUT -j REJECT —reject-with icmp-host-prohibited记录,下面我贴出默认的iptables的规则,然后一一解释出来,你一看就知道为什么了,默认规则如下:

# Generated by iptables-save v1.4.7 on Thu Jul 13 09:17:19 2017
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [787:76250]
-A INPUT -m state —state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -p icmp -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A INPUT -p tcp -m state —state NEW -m tcp —dport 22 -j ACCEPT 
-A INPUT -j REJECT —reject-with icmp-host-prohibited  
-A FORWARD -j REJECT —reject-with icmp-host-prohibited   
COMMIT
# Completed on Thu Jul 13 09:17:19 2017

:INPUT ACCEPT [0:0]: 该规则表示INPUT表默认策略是ACCEPT

:FORWARD ACCEPT [0:0]: 该规则表示FORWARD表默认策略是ACCEPT

:OUTPUT ACCEPT [787:76250]: 该规则表示OUTPUT表默认策略是ACCEPT

-A INPUT -m state —state RELATED,ESTABLISHED -j ACCEPT: 改规则意思是允许进入的数据包只能是刚刚我发出去的数据包的回应,ESTABLISHED:已建立的链接状态。RELATED:该数据包与本机发出的数据包有关。

-A INPUT -p icmp -j ACCEPT: 改规则指的是icmp协议的包都接受通过(ping命名发出的就是icmp的包)。

-A INPUT -i lo -j ACCEPT: -i参数是指定接口,这里的接口是lo ,lo就是Loopback(本地环回接口),意思就允许本地环回接口在INPUT表的所有数据通信。

-A INPUT -p tcp -m state —state NEW -m tcp —dport 22 -j ACCEPT: 该规则的意思就是新连接ssh默认端口22的允许进入。

重点来了
-A INPUT -j REJECT —reject-with icmp-host-prohibited: 该规则的意思是说在INPUT表中拒绝所有其他不符合上述任何一条规则的数据包。并且发送一条host prohibited的消息给被拒绝的主机。

-A FORWARD -j REJECT —reject-with icmp-host-prohibited: 该规则的意思是说在FORWARD表中拒绝所有其他不符合上述任何一条规则的数据包。并且发送一条host prohibited的消息给被拒绝的主机。

咋们在回头看看我同事最终save生效的规则情况:

# Generated by iptables-save v1.4.7 on Thu Jul 13 09:17:19 2017
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [787:76250]
-A INPUT -m state —state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -p icmp -j ACCEPT 
-A INPUT -i lo -j ACCEPT 
-A INPUT -j REJECT —reject-with icmp-host-prohibited 
-A INPUT -s 121.134.33.89/32 -p tcp -m tcp —dport 3307 -j ACCEPT 
-A INPUT -s 10.0.0.0/16 -p tcp -m tcp —dport 3307 -j ACCEPT  
-A INPUT -p tcp -m tcp —dport 3307 -j DROP 
-A FORWARD -j REJECT —reject-with icmp-host-prohibited 
-A INPUT -p tcp -m state —state NEW -m tcp —dport 22000 -j ACCEPT 
COMMIT
# Completed on Thu Jul 13 09:17:19 2017

我想现在你应该一目了然的知道问题的所在了吧!

总结(亮了)

不管你是运维菜鸟还是运维老鸟,如果你也有这样相同的遭遇,我想对你说很庆幸,你已经遭遇过了,我想你应该知道怎么规避了,但是我个人总结几点建议,希望对你有帮助。

  1. 运维做线上的变更或者操作的时候,一定要预先实战演练,做好充分准备工作;
  2. 运维做线上的变更或者操作的时候,有思路了一定不要只是存放在脑子里,按照脑子所想去做,而是写出详细的操作文档,然后审核操作过程,最后根据文档一步一步的做变更;
  3. 增强自己对运维基础知识的认知,这个案例很明显就是一个简单的iptables的默认规则的问题,如果你之前就对默认规则认知很清楚,我想这个坑在你这里是不存在的;
  4. 运维应该有意识的去提升自我的英文单词认识能力和阅读能力,如果你了解到了REJECT单词是拒绝的意思,我想你也不会跳进坑里,你会持有怀疑态度。
  5. 细节决定成败,运维时时刻刻都在监控告警和背锅的准备中,保持认真、谨慎的态度,时刻保持对运维工作持有敬畏之心。

最后希望你读完这篇文章有所收获哦!
pit.png

WeZan