最近一台老的 Oracle 数据库因为漏扫被搞崩了,因为是老服务器,资源分的很小,只有4核6G,为防止被不明原因的测试冲掉,开启了 iptables 防火墙,只放行了数据库端口。
刚开始写的规则为
iptables -I INPUT -s 192.168.100.8 -j ACCEPTiptables -A INPUT -p tcp -m tcp --dport 1521 -j ACCEPTiptables -A INPUT -j DROP
先放行管理员的IP 192.168.100.8,不然ssh会话就断掉了
再放行 Oracle 数据库端口 1521
最后阻止所有入站的数据包
因为 iptables 是基于包过滤,虽然出站是放行的,只要把入站禁掉,数据包出去也回不来,除非是符合规则的包才能进来。
这点与 Windows 防火墙有点不同,Windows 防火墙是基于会话的,放行会话就行了,不用写在入出站各写一条。如果iptables INPUT 和 OUTPUT 默认策略是阻止的话,那么要让一个会话通,必须 INPUT 和 OUTPUT 各写一条允许策略。Windows 出站放行的话,会话中回来的数据包是可以进来的,这点儿 iptables 防火墙和 Windows 是站在不同的层级上看问题,iptables 在更低一层处理网络数据包,Windows 将数据包封装成会话,出站允许,那么基于出站的会话,回来的数据包也能通。
现在回到初始问题,当设置了三条 iptables 策略后,业务方反应连不上数据库。于是检查数据库状态:
$ su - oracle$ ps -eaf| grep ora_pmon$ echo ORACLE_SID$ sqlplus as sysdbaSQL> select name, open_mode from v$database;NAME OPEN_MODE--------- ----------ORCL READ WRITE

数据库是启动状态的,再次检查监听,发现查询监听状态时好慢,要卡一会才会显示:
$ su - oracle$ lsnrctl status

查看 listerner.log 和 listener.ora,数据库采用的是动态监听,但此时检查监听状态,没有注册成功。于是在数据库中反复多次注册监听:
SQL> alter system register;SQL>SQL>SQL>
再次查看动态监听相关的配置
SQL> show parameter service_namesSQL> show parameter instance_nameSQL> show parameter local_listener

动态监听是pmon进程读取参数文件中的 instance_name, service_names参数,然后注册到listener中。默认动态监听只会注册到 1521 端口,如果使用的是非默认端口,此时才会用到 LOCAL_LISTENER 参数。为加快 pmon 进程注册速度,可以使用以下命令刷新监听状态。
SQL> alter system register;
全部检查了一遍之后,查看监听状态,还没有没注册上。此时发现执行 lsnrctl status 比平时慢了很多倍,猜想是不是被 iptables 阻止掉了。于是试着添加本机IP至iptables中,放行本机IP
iptables -I INPUT -s 127.0.0.1 -j ACCEPTiptables -I INPUT -s 192.168.10.31 -j ACCEPT

当放行了本机IP之后,查询监听状态立马变快了很多,看来的确是 iptables 把本机的请求阻止掉了。
总结:
在写 iptables 策略时,如果有本机请求本机的网络应用,一定要放行 loop_back 地址,以及 docker 内部地址,不然业务会中断。




