linux单网卡ip转发,CentOS6.5基于iptables实现单网卡端口转发

一,情景再现

今早7点多接到客户的一个需求,要求做Linux下的单网卡的端口转发,给了如下一张图:

9cca41d73b7c7cbc49ee222bdfa80f3a.png

这里假定左侧的IP为服务器A,右侧为服务器B,现在需要将到A服务器的某些IP和端口的访问转发至服务器B上的相关IP和端口,服务器A和服务器B不在同一网段(这里有个小坑,后面再说)。需求说完,下面我用一个实验来还原下这个需求的实现过程。

二,实验拓扑

a59d7b0a9199cb948e5a782b3f564750.png

这里说明一下,Server A就是负责转发的服务器,Server B上安装有Apache提供服务,现在让Client通过Server A的81端口来访问Server B的80端口,注意,这里虽然是内网环境,但原理跟客户的真实需求是一致的。

三,实验过程

(1) 首先在Server B上安装好Apache:[root@serverB ~]# yum install httpd -y

[root@serverB ~]# rpm -q httpd

httpd-2.2.15-29.el6.centos.x86_64

(2)启动服务,创建测试页面:[root@serverB ~]# service httpd start

[root@serverB ~]# echo "

iptables nat test.

" > /var/www/html/index.html

(3)客户端测试:

6bff96aaf8a7ff9452d92e9d56751a8b.png

(4)开启Server A的ip转发功能,编写iptables规则:[root@serverA ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

这一步一定要记得,之前被坑过好几次!!!iptables -t nat -A PREROUTING -d 192.168.1.34 -p tcp -m tcp --dport 81 -j DNAT --to-destination 192.168.1.32:80

iptables -t nat -A POSTROUTING -s 192.168.1.32 -j SNAT --to-source 192.168.1.34

这两条规则就是我想当然的在生产服务器上敲得,做完之后发现不成功,于是开始排查原因:

首先看第一条规则,这个规则是在服务器路由决策之前,将客户端发来的目的地址和端口改为192.168.1.32:80,从而达到访问服务器B的目的,这样看的话,这个规则是没有问题的,我来验证一下:

如果第一条语句生效,那么在Server B上将会收到来自Client端192.168.1.185的请求报文,我在Server B上用tcpdump抓包看一下:[root@serverB ~]# tcpdump -vv -nn -X tcp port 80

tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

05:58:58.681487 IP (tos 0x0, ttl 127, id 3204, offset 0, flags [DF], proto TCP (6), length 52)

192.168.1.185.61777 > 192.168.1.32.80: Flags [S], cksum 0x15c0 (correct), seq 2693866233, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0

0x0000:  4500 0034 0c84 4000 7f06 6b16 c0a8 01b9  E..4..@...k.....

0x0010:  c0a8 0120 f151 0050 a091 22f9 0000 0000  .....Q.P..".....

0x0020:  8002 2000 15c0 0000 0204 05b4 0103 0302  ................

0x0030:  0101 0402                                ....

05:58:58.838172 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52)

192.168.1.32.80 > 192.168.1.185.61777: Flags [S.], cksum 0xb6a9 (correct), seq 4286269053, ack 2693866234, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 6], length 0

0x0000:  4500 0034 0000 4000 4006 b69a c0a8 0120  E..4..@.@.......

0x0010:  c0a8 01b9 0050 f151 ff7b 467d a091 22fa  .....P.Q.{F}..".

0x0020:  8012 3908 b6a9 0000 0204 05b4 0101 0402  ..9.............

0x0030:  0103 0306                                ....

没错,确实抓到了,说明第一条语句生效了,而且仔细看,会发现Server B也的确给Client回包,但为什么Client端访问失败呢?

我在客户端上用wireshark抓包看下

99c07d11e424d78808ff9946bc337ec9.png

发现客户端的回包中RST位置为1,表示异常中止,由于是TCP协议,所以Server B会有重传,结果也是一样,Client端全部拒收了。想了半天,原来Server B的回包地址和我请求的地址不一致,我请求的Server A的81端口,结果Server B的80端口给我回的包,作为Client当然不会接收了。

原因找到了,接下来让我们看一下第二条规则错在哪里iptables -t nat -A POSTROUTING -s 192.168.1.32 -j SNAT --to-source 192.168.1.34

这条语句表示将源地址为192.168.1.32的数据包在路由决策后将要发送之前把它的源地址改为192.168.1.34,在本例中,由于是内网环境,Server B也没有将网关指向Server A(指了也没用,局域网通信靠的是MAC地址),因此,Server B在回包的时候并不会经过Server A,于是规则二并没有生效,接下来的解决思路就是要让,Server B的数据包一定要经过Server A,于是我们删除上述第二条规则,并添加一条新规则。iptables -t nat -D POSTROUTING 1

iptables -t nat -A POSTROUTING -d 192.168.1.32 -p tcp --dport 80 -j SNAT --to-source 192.168.1.34

我们把访问Server B 80端口的源地址改成192.168.1.34,这样Server B在回包时就一定会经过Server A,然后通过查询连接跟踪表,找到请求的真正ip和端口进行回应。

查看连接追踪表:[root@serverA ~]# cat /proc/net/nf_conntrack

ipv4     2 tcp      6 116 TIME_WAIT src=192.168.1.185 dst=192.168.1.34 sport=63612 dport=81 src=192.168.1.32 dst=192.168.1.34 sport=80 dport=63612 [ASSURED] mark=0 secmark=0 use=2

ipv4     2 tcp      6 431997 ESTABLISHED src=192.168.1.185 dst=192.168.1.34 sport=63613 dport=81 src=192.168.1.32 dst=192.168.1.34 sport=80 dport=63613 [ASSURED] mark=0 secmark=0 use=2

至此,Client的访问就应该可以了。

94a688fb792e80e86bd54b3b839de846.png

通过这次实验,对iptables中nat表的理解又加深了一步,最后放一张关于netfilter处理顺序的图帮助理解。

bd07147ad868904f5b5824f8645816a3.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值