1、前言
笔者阿里云后端增加一台windows的主机,为了安全与降低成本,后端主机没有公网网卡,于是笔者实战阿里云的端口转发(解决前端主机以路由模式工作并做端口映射问题)。
实践过程中笔者发现网络很多文章都说是经过测试可用,但是照搬却发现根本无法使用,深究其原因,笔者发现原作者的代码其实没有错,问题出在原作者负略了iptables每台服务器配置不一样,或者原作者本身就倾向于制造理想的环境,但实际生产环境不允许这样做。
故而解决问题的重点在于思路,本文将会提供标准的服务器路由模式环境和设置脚本给你使用并提供故障的排查思路。
2、理论知识
2.1、DNAT
作用:重写数据包的目标地址
范例:路由器的内部服务器端口映射
链条:只能用于PREOUTING、OUTPUT链
常用参数:
--to-destination #数据包转发目标地址
2.2、SNAT
作用:重写数据包的源IP地址
范例:多主机经过路由NAT上网
链条:只能用于POSTROUTING
2.3、PREOUTING
配合参数:
PREOUTING -i #进站
2.4、POSTROUTING
POSTROUTING -o #出站
3、实战部分
3.1、实践环境:
SerA
eth1:ipaddress=121.48.81.22 #防火墙对外IP
eth0:ipaddress=10.170.235.201 #防火墙对内IP
SerC
eth0:ipaddress=10.168.198.47
注:基于安全需求,以上不能给真实地址。
3.2、创建配置脚本:
3.2.1、创建脚本存放文件夹
1
|
mkdir
~
/script
|
3.2.2、创建脚本
vim编辑~/script/nat.sh创建以下脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#!/bin/bash
WAN_IP=121.48.81.22
#防火墙对外IP地址
WAN_PORT=3389
#防火墙对外映射的端口
LAN_IP=10.170.235.201
#防火墙对内IP地址
SER_IP=10.168.198.47
#内部服务器的IP地址
SER_PORT=3389
#内部服务器被映射的端口
#下一行可创造理想的NAT环境
#iptables -F -t nat
iptables -t nat -A PREROUTING --dst $WAN_IP -p tcp --dport $WAN_PORT -j DNAT --to-destination $SER_IP:$SER_PORT
iptables -t nat -A POSTROUTING -p tcp --dst $SER_IP --dport $SER_PORT -j SNAT --to-
source
$LAN_IP
iptables -t nat -A OUTPUT --dst $WAN_IP -p tcp --dport $WAN_PORT -j DNAT --to-destination $SER_IP:$SER_PORT
echo
1 >
/proc/sys/net/ipv4/ip_forward
#下一行去掉行注释需INPUT、FORWARD、OUTPUT三链为ACCEPT状态
#iptables -F -t filter
#以下检查语句
iptables -L -n -
v
-t nat
iptables -L -n -
v
|
3.2.3、使用须知
1)如果启用“iptables -F -t nat”语句清空NAT链表,会制造理想的环境,以便测试
2)“echo 1 > /proc/sys/net/ipv4/ip_forward”语句用于临时开启路由转发,重启后失效。
3)如果启用“iptables -F -t filter”清空filter链表,请确认INPUT、FORWARD、OUTPUT三链为ACCEPT状态,否则你远程主机将不能连接。
4)以上两句都启用并符合要求使用需求你将能够正常NAT,但会有安全隐患,所以你还得配置你的充当防火墙的服务器的filter。
3.3、标准的服务器路由模式环境
3.3.1、创建路由模式环境
如果你不会配置路由环境,请使用一下标准环境:
注:以下是笔者多年的积累,如果你认为不够标准,请提出修改建议,笔者欢迎。
vim编辑/etc/sysconfig/iptables
清空当前的配置并插入如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
# Generated by iptables-save v1.4.7 on Sat Nov 14 10:08:49 2015
*nat
:PREROUTING ACCEPT [2:80]
:POSTROUTING ACCEPT [4:304]
:OUTPUT ACCEPT [4:304]
COMMIT
# Completed on Sat Nov 14 10:08:49 2015
# Generated by iptables-save v1.4.7 on Sat Nov 14 10:08:49 2015
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [209:32916]
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -j ACCEPT
-A INPUT -i eth1 -p icmp -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -i eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o lo -j ACCEPT
-A FORWARD -o eth1 -j ACCEPT
-A FORWARD -o eth0 -j ACCEPT
COMMIT
# Completed on Sat Nov 14 10:08:49 2015
|
3.3.2、使用须知
1)标准环境不完全符合你当前服务器的服务(缺少允许服务语句)
2)注意修改网卡接口名称,本范例为eth0(内)和eth1(外)
3.3.3、增加服务
假设笔者的服务器需要增加允许httpd(apache)的tpc/80端口供外部访问,增加如下语句:
1
|
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
|
3.3.4、重启iptables服务
1
|
/etc/init
.d
/iptables
restart
|
3.4、执行脚本
执行以下命令:
1
|
sh ~
/script/nat
.sh
|
3.5、测试:
3.5.1、使用标准方法测试(TCP端口适用)
1
|
telnet 121.48.81.22 3389
|
3.5.2、使用服务协议方式测试
1
|
mstsc
/v
:121.48.81.22:3389
|
3.6、修改为永久路由转发
vim编辑/etc/sysctl.conf
修改前:
1
|
net.ipv4.ip_forward = 0
|
修改后:
1
|
net.ipv4.ip_forward = 1
|
3.7、保存设置
1
|
/etc/init
.d
/iptables
save
|
3.8、保存后的结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
# Generated by iptables-save v1.4.7 on Sat Nov 14 10:08:49 2015
*nat
:PREROUTING ACCEPT [2:80]
:POSTROUTING ACCEPT [4:304]
:OUTPUT ACCEPT [4:304]
-A PREROUTING --dst 121.48.81.22 -p tcp --dport 3389 -j DNAT --to-destination 10.168.198.47:3389
-A POSTROUTING -p tcp --dst 10.168.198.47 --dport 3389 -j SNAT --to-
source
10.170.235.201
-A OUTPUT --dst 121.48.81.22 -p tcp --dport 3389 -j DNAT --to-destination 10.168.198.47:3389
COMMIT
# Completed on Sat Nov 14 10:08:49 2015
# Generated by iptables-save v1.4.7 on Sat Nov 14 10:08:49 2015
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [209:32916]
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -j ACCEPT
-A INPUT -i eth1 -p icmp -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -i eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o lo -j ACCEPT
-A FORWARD -o eth1 -j ACCEPT
-A FORWARD -o eth0 -j ACCEPT
COMMIT
# Completed on Sat Nov 14 10:08:49 2015
|
4、故障排查
4.1、故障排查思路
排除故障思路:由表到表中规则(先测试大范围,确认方向后找小范围)
4.2、故障排查范例
4.2.1、排查filter表的影响
iptables -F -t filter
注:以上代码是清空filter的设置
4.2.2、定位filter表的链条故障
1)重启iptables还原当前环境
1
|
/etc/init
.d
/iptables
restart
|
2)定位链条故障
方法1:
查看/etc/sysconfig/iptables发现两条拒绝规则,通过注释测试发现原因在于FORWARD链条的拒绝。
方法2:
1
|
iptables -L -
v
-n
|
通过以上同样可以发现两条拒绝规则,我们尝试删除FORWARD:
1
|
iptables -D FORWARD -j REJECT --reject-with icmp-host-prohibited
|
删除以上规则测试正常
3)编写针对于FORWARD的放行规则
1
|
iptables -A FORWARD --dst 10.168.0.170 -p tcp --dport 3389 -j ACCEPT
|