一直被双线访问内网服务器的路由问题困扰,也在网上找了不少资料,但有些方法比较复杂,对我这种懒人来说实在懒得去看去测试。最接近的方法是iptables+iproute2,但我比较杯具的木有测试成功。。。。。后来自己慢慢想,居然想出了这么个懒办法。
环境
server 1 (Centos5)
双网卡eth1和eth2,分别配置了电信和联通的ip,还有一个内网口eth0做为内网网关。
TEL="eth1"
TEL_IP="电信ip"
TEL_GW="电信网关"
CNC="eth2"
CNC_IP="联通ip"
CNC_GW="联通网关"
这台服务器上已经用策略路由做了数据包原路返回,即从外部访问电信ip则原路从电信ip返回,联通ip也原路返回。
/sbin/ip route replace default via $TEL_GW dev $TEL
/sbin/ip route flush table TEL
/sbin/ip route add 192.168.1.0/24 dev eth0 src 192.168.1.1 table TEL
/sbin/ip route add default via $TEL_GW dev $TEL src $TEL_IP table TEL
/sbin/ip rule add from $TEL_IP table TEL
/sbin/ip route flush table CNC
/sbin/ip route add 192.168.1.0/24 dev eth0 src 192.168.1.1 table CNC
/sbin/ip route add default via $CNC_GW dev $CNC src $CNC_IP table CNC
/sbin/ip rule add from $CNC_IP table CNC
然后做了iptables的端口映射到server 2机器的21端口。
$IPTABLES -t nat -A PREROUTING -p tcp --dport 4376 -j DNAT --to-destination 192.168.1.2:21
server 2 (Centos6)
应用服务器,只配置了一个内网ip,上面开了ftp服务。
eth0=192.168.1.20
现在的问题是,如果从电信ip访问则可以连接上ftp服务器,因为默认路由是从电信ip出,但从联通ip访问时,从上面的策略路由可以看到,只对是eth1和eth2做了策略路由,ftp服务器返回的数据是从eth0口进入,路由无法区分是从哪个外网ip访问的,所以出口还是会走默认的电信ip,最终被上层网关丢弃而无法正常访问。
此时该如何做才可以做到两个外网ip同时可以访问到内网ftp服务器呢
---------------------------------------------------
7月18日
几个月了,我都没找到一个能用的解决方案。
昨天在网上闲逛,看到有人提到这个问题,说是可以用特定ip做静态路由。
这个说得有些含糊,我理解是在内网ftp上再加一个ip,可以是同一段的内网ip,也可以是不同段的内网ip,然后在网关上做静态路由指向联通出口。这个方法理论上是可行的,但我还没有配置到工作环境里去,等过几天配置好再详细整理有关配置。
-------------------------------------------------------------------------------------
7月26日
几天前,我已经验证了上面的想法,是完全可行的。下面就是完整解决方法。
根据以前的配置,只要在ftp服务器上多加一个内网iip,这个内网ip最好和现有的内网同一段,当然也可以用不同段的内网ip。比如我就在server 2上加了一个。所以现在server2上就有两个内网ip了
eth0=192.168.1.20
eth1=192.168.1.25
对server2的改动就这些,其他的什么都不用动。
接下来再回到server1上
修改iptables的映射
$IPTABLES -t nat -A PREROUTING -p tcp -d 电信ip --dport 4376 -j DNAT --to-destination 192.168.1.20:21
$IPTABLES -t nat -A PREROUTING -p tcp -d 联通ip --dport 4376 -j DNAT --to-destination 192.168.1.25:21
这样就把从两个外网ip访问的流量分别映射到server2的两个ip上。
然后再添加基于源地址的策略路由
ip rule add from 192.168.1.20 table TEL
ip rule add from 192.168.1.25 table CNC
这样做的意思就是如果接收到源地址是192.168.1.20的数据包,就放到tel的路由表中,这样它就会从tel的网关出去了。
同理接收到192.168.1.25为源地址的数据包,就放到cnc路由表中,就从cnc网关出去了。
注意在server1上要同时有
$IPTABLES -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j SNAT --to-source 电信ip
$IPTABLES -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth2 -j SNAT --to-source 联通ip
到此,就解决了双线访问内网的问题。
一些补充:
server2用的是centos6,在做多ip的时候跟centos5有区别,不能再用eth0.1 eth0.2这样的了。只能bind。
本文是参考了http://bbs.chinaunix.net/thread-2042243-1-1.html写出的,我也想把里面的iptables+iproute2的方法拿出来做个比较。以下是从该贴摘出来的。
-----------------------------------------------------------
内核打补丁
如果你希望外网用户,不管通过哪个IP都可以访问到服务器或映射后的内网服务器,那么你就需要为内核打上补丁,
补丁在 http://www.ssi.bg/~ja/#routes 可以下载到,在 Static, Alternative Routes, Dead Gateway Detection, NAT 找和内核对应的 patch
下载后为内核打上,然后在
Networking ---> Networking options ---> IP: advanced router
把 IP: equal cost multipath with caching support (EXPERIMENTAL) 前面的勾去掉
如果你不想打补丁,或不想动内核,有个简单的办法来实现,即写一个脚本,每隔2秒钟刷新一次route cache
while : ; do
ip route flush cache
sleep 2
done
iptables打标记+iproute2 fwmark
1)使用 CONNMARK 对连接进行标记
外网进来数据
iptables -t mangle -A PREROUTING -i eth1 -m conntrack --ctstate NEW -j CONNMARK --set-mark 0x100
iptables -t mangle -A PREROUTING -i eth2 -m conntrack --ctstate NEW -j CONNMARK --set-mark 0x200
转发出去的数据
iptables -t mangle -A POSTROUTING -o eth1 -m conntrack --ctstate NEW -j CONNMARK --set-mark 0x100
iptables -t mangle -A POSTROUTING -o eth2 -m conntrack --ctstate NEW -j CONNMARK --set-mark 0x200
局域网进来数据
iptables -t mangle -A PREROUTING -i eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j CONNMARK --restore-mark
本地出去数据
iptables -t mangle -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j CONNMARK --restore-mark
2)在 IPROUTE2 中做基于 fwmark 的策略路由
ip rule add fwmark 0x100 table ctc prio 40
ip rule add fwmark 0x200 table cnc prio 40
3)添加原路返回路由
ip route add table ctc to $CTC_NET dev eth1 scope link
ip route add table ctc to $CNC_NET dev eth2 scope link
ip route add table ctc to 192.168.0.0/24 dev eth0 scope link
ip route add default via 电信网关 dev eth1 table ctc
ip route add table cnc to $CTC_NET dev eth1 scope link
ip route add table cnc to $CNC_NET dev eth2 scope link
ip route add table cnc to 192.168.0.0/24 dev eth0 scope link
ip route add default via 网通网关 dev eth2 table cnc
Iptables/NAT 规则
/sbin/iptables -t nat -A POSTROUTING -o eth1 -s 局域网网段 -j SNAT --to-source 电信外网IP
/sbin/iptables -t nat -A POSTROUTING -o eth2 -s 局域网网段 -j SNAT --to-source 网通外网IP
如果外网IP是动态的,可以用 MASQUERADE
/sbin/iptables -t nat -A POSTROUTING -o eth1 -s 局域网网段 -j MASQUERADE
/sbin/iptables -t nat -A POSTROUTING -o eth2 -s 局域网网段 -j MASQUERADE
端口映射
端口映射可以分别针对两条线做端口映射
比如 LAN口的IP为 192.168.0.1,内网服务器IP为 192.168.0.100,映射端口为 80
iptables -t nat -A PREROUTING -p tcp --dport 80 -d 电信IP -j DNAT --to-destination 192.168.0.100
iptables -t nat -A PREROUTING -p tcp --dport 80 -d 网通IP -j DNAT --to-destination 192.168.0.100
端口回流(内网可以通过外网IP访问映射后的服务器)
iptables -t nat -A POSTROUTING -p tcp -s 192.168.0.0/24 --dport 80 -d 192.168.0.100 -j SNAT --to-source 192.168.0.1
[注]:上述规则应放到 NAT 规则之前
--------------------------------------------------------------------------
其实这种方法我也已经测试过了。在centos6上没有测试成功,不知道哪里有问题,而且我也不清楚怎么去监控一个打了标记的连接。本人水平不高,请谅解,有兴趣的同学可以把测试结果告诉我,谢谢了!
我的方法比较简单,操作起来也不复杂。但并不是说就比iptables+iproute2的方法好。关键还是要看应用的实际情况。无论是哪种方法,归根结底就一个问题,如何区别从内网服务器返回的数据到底是从哪个外网ip进来的。无论是给连接打标记还是给服务器加ip都是在解决这个问题。所以很多技术上的问题,关键是要有思路,解决办法就不是那么重要了。