0x01 前言

我的服务器在家里,其中一台虚拟机作为DMZ主机,我并没有打开过多的端口。有时候又不想通过VPN连接家里的服务器,这时候就需要通过SSH或RDP连接。

如果使用默认的SSH和RDP端口进行通讯,这将会引发安全问题,那通过iptables对端口和流量进行管理就变得无比重要。

0x02 禁止与放行

我的使用环境对安全的要求并不是很严格,我直接将进站的所有数据包设为全部丢弃,对需要使用的端口逐一放行。

在此之前需要先检查iptables的状态与目前所存有的规则。无论是centos7还是之前的版本,都可以使用service进行启动与关闭:

#iptables 未启动的状态
[root@test ~]# service iptables status
Redirecting to /bin/systemctl status  iptables.service
● iptables.service - IPv4 firewall with iptables
   Loaded: loaded (/usr/lib/systemd/system/iptables.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

#iptables 启动的状态
[root@test ~]# service iptables status
Redirecting to /bin/systemctl status  iptables.service
● iptables.service - IPv4 firewall with iptables
   Loaded: loaded (/usr/lib/systemd/system/iptables.service; disabled; vendor preset: disabled)
   Active: active (exited) since 五 2016-08-12 21:33:16 CST; 4s ago
  Process: 2802 ExecStart=/usr/libexec/iptables/iptables.init start (code=exited, status=0/SUCCESS)
 Main PID: 2802 (code=exited, status=0/SUCCESS)

8月 12 21:33:16 test.t.com systemd[1]: Starting IPv4 firewall with iptables...
8月 12 21:33:16 test.t.com iptables.init[2802]: iptables: Applying firewall rules: [  OK  ]
8月 12 21:33:16 test.t.com systemd[1]: Started IPv4 firewall with iptables.

将iptables设为开机启动并立即启动iptables:

#将iptables 设为开机启动
[root@test ~]# systemctl enable iptables
Created symlink from /etc/systemd/system/basic.target.wants/iptables.service to /usr/lib/systemd/system/iptables.service.

#立即启动iptables
[root@test ~]# systemctl start iptables

检查iptables现有的规则:

[root@test ~]# iptables -L -vn --line-number
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
#此条规则意为对已存在的连接的数据包作放行处理
1      294 20768 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
#此条规则意为对icmp数据包作放行处理
2        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
#此条规则意为对内部lo数据包作放行处理           
3        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
#此条规则意为对SSH默认的TCP协议,端口22的数据包作放行处理           
4        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
#如果入站数据包不符合以上任何一条规则,则返还host prohibited信息给源主机。
5        8  1846 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 160 packets, 25600 bytes)
num   pkts bytes target     prot opt in     out     source               destination

在将入站数据包默认规则修改为丢弃之前,请确认你的SSH端口在放行规则之列。否则你将失去对系统的连接:

[root@test ~]# iptables -P INPUT DROP 
[root@test ~]# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]

[root@test ~]# iptables -L -vn --line-number
Chain INPUT (policy DROP 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1      553 41713 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
2        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
3        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
4        1    60 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
5       26  6040 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 56 packets, 6736 bytes)
num   pkts bytes target     prot opt in     out     source               destination

从上面两端代码高亮处可看出,默认的规则已经从ACCEPT修改为DROP。接下来需要将默认的两段reject-with icmp-host-prohibited删掉。

#删掉INPUT链中第5行的规则
[root@test ~]# iptables -D INPUT 5

#删掉FORWARD链中第1行的规则
[root@test ~]# iptables -D FORWARD 1

#保存修改
[root@test ~]# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]

#查看现有规则
[root@test ~]# iptables -L -vn --line-number
Chain INPUT (policy DROP 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1      986 67722 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
2        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
3        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
4        1    60 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 25 packets, 2568 bytes)
num   pkts bytes target     prot opt in     out     source               destination

#重启iptables
[root@test ~]# service iptables restart

如果想开放某个端口或对某个IP开放某个端口,可以参考:

# -A INPUT 将规则附加到INPUT链中
# -s [ip] 源主机ip
# -d [ip] 目标主机ip
# -p 协议,可以是tcp或udp
# --dport 目标端口
# -j 规则
# 下面这段的意思是:对源主机ip为10.1.1.0/24发送到主机192.168.1.0/24:8443的数据包作放行处理
[root@test ~]# iptables -A INPUT -s 10.1.1.0/24 -d 192.168.1.0/24 -p tcp --dport 8443 -j ACCEPT

#如果不需要使用那么详细的设置,也可以用下面的命令
[root@test ~]# iptables -A INPUT -p tcp --dport 8443 -j ACCEPT

添加规则后如果不保存,在使用service iptables restart重启iptables服务后,未保存的规则将会被抹掉。如果想保存新加入的iptables规则,可使用如下命令:

#保存iptables
[root@test ~]# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]

#重启iptables服务
[root@test ~]# service iptables reload
Redirecting to /bin/systemctl reload  iptables.service

0x03 转发

如果接触过VPN服务器,那么下面的命令你肯定了解:

iptables -t nat -A POSTROUTING -s 10.10.1.0/24 -o eth0 -j MASQUERADE

因为VPN客户端所获的的IP是服务器分配的内网IP,那么只需要使用POSTROUTING进行源地址转换,而MASQUERADE则可以自动获取eth0网卡的IP,自动将10.10.1.0/24这个网段的IP进行SNAT。

如果像我的使用环境:外网–>[8443]DMZ(10.1.1.12)–>[22]Server1(10.1.1.16),就需要下面这两条规则:

iptables -t nat -A PREROUTING -p tcp -m tcp --dport 8443 -j DNAT --to-destination 10.1.1.16:22

iptables -t nat -A POSTROUTING -p tcp -m tcp --dport 22 -j SNAT --to-source 10.1.1.12

因为我是处于DMZ主机外,不但要使用第一条规则将8443端口的数据包转发到10.1.1.16:22,还要将从10.1.1.1:22返还的数据包通过8443端口发出去。

0x04 结语

确实是有点复杂,但慢慢理解,也是能消化的。

源地址发送数据--> {PREROUTING-->路由规则-->POSTROUTING} -->目的地址接收到数据

上面的流程图说明了转发的过程。在VPN环境中,用户是处于路由规则之内,所以只需要用POSTROUTING;而在外网访问内网时,用户处于路由规则之外,就需要使用PREROUTING进行地址转换。