8.4 特殊状况:路由器两边界面是同一个 IP 网段: ARP Proxy

如果你一开始设计的网络环境就是同一个 Class C 的网域,例如 192.168.1.0/24 , 后来因为某些因素必须要将某些主机搬到比较内部的环境中,例如图 8.2-1的 clientlinxu, winxp, win7。 然后又因为某些因素,所以你不能变更这些计算机的 IP,此时你的同一网域就会横跨在一个路由器的左右两边了! 举例来说,联机图示有点像底下这样:

图 8.4-1、在路由器两个界面两边的 IP 是在同一个网域的设定情况

初次见面~看到眼睛快要掉下来哩!怎么路由器的两边的主机 IP 设定都在同一个网域内?而且还被规定不能够更改原先的 IP 设定, ...真是一个头两个大啊~如此一来,在 Linux Router 两边要如何制作路由啊?好问题!真是好问题~ 因为 OSI 第三层网络层的路由是一条一条去设定比对的,所以如果两块网卡上面都是同一个网域的 IP 时, 就会发生错误。那如何处理啊?

我们先从两方面来说,第一个,当从正确的网段 (PC1) 要联机到 PC2~PC4 时,他应该是要透过 Linux Router 那部主机的对外 IP (192.168.1.100) 才行!而且 Linux Router 还必须要让该封包透过内部 IP (192.168.1.200) 联机到 PC2~PC4 。 此时,封包传递的图示有点像这样:

图 8.4-2、正常的网段想要传送到内部计算机去的封包流向

在这个阶段,我们可以设定PC2~PC4 的 IP 所对应的网卡卡号 (MAC) 都设定在 router 的对外网卡上, 因此, router 的对外接口可以将给 PC2~PC4 的封包给『骗』过来。接下来,就简单的透过路由设定,让封包转个接口发送出去即可。 这样 PC1 --> PC2 的问题解决了,但是 PC2 怎么传送到 PC1 呢?我们可以透过底下的图示来想象一下:

图 8.4-3、内部计算机想要传送到正常网域时的封包流向

当 PC2 要传送的封包是给 PC3, PC4 的,那么这个封包得要能够直接传递。但是如果需要传送到正常网域的封包,就得要透过 router 的对内网卡,再透过路由规则来将该封包导向外部接口来传递才行!这个时候就变成内部的接口欺骗 PC2 说, PC1 与 Router A 的 IP 是在内部这张接口上就是了,然后再透过路由判断将该封包透过外部接口来对外传递出去即可。 假设 Linux router 的对外界面为 eth0 而对内为 eth1 时,我们可以这样说:

  1. 当 Linux Router 的 eth0 那个网域主机想要连接到 PC2~PC4 的主机时,由 Linux Router 负责接收;
  2. 当 Linux Router 要传送数据到 PC2~PC4 时,务必要由 eth1 来传送;
  3. 当内部计算机想要连接到 PC1 或 Router A 时,由 Linux router 的 eth1 负责接收;
  4. 当 Linux Router 要传送的数据为 192.168.1.0/24 ,但并非 PC2~PC4 时,需由 eth0 传送。

上列的步骤与图示内的线条上的顺序相符合呦!得要对照着看看。其中的 (1) 与 (3) 就是透过 ARP Proxy (代理) 的功能啦! 那啥是 ARP Proxy 呢?简单的说,就是让我的某张适配卡的 MAC 代理其他主机的 IP 对应,让想要连接到这个 IP 的 MAC 封包由我帮他接下来的意思。举我们图 8.4-1 的例子来说,就是在 Linux Router 的 eth0 界面上,规定 192.168.1.10, 192.168.1.20, 192.168.1.30 这三个 IP 都对应到 eth0 的 MAC 上,所以三个 IP 的封包就会由 eth0 代为收下,因此才叫做 ARP 代理人嘛!所以啦,每一部在 eth0 那端的主机都会『误判』那三个 IP 是 Linux Router 所拥有,这样就能够让封包传给 Linux Router 啦!

再接下来,咱们的 Linux Router 必须要额外指定路由,设定情况为:

  • 若目标是 PC2 ~ PC4 时,该路由必须要由内部的 eth1 发送出去才行,
  • 若目标不为 PC2 ~ PC4 ,且目标在 192.168.1.0/24 的网域时,需由 eth0 发送出去才行。

也就是说,你必须要指定路由规则当中,那个 PC2~PC4 具有优先选择权,然后其他的同网域封包才由 eth0 来传送。 这样就能够达成我们所想要的结局啦!^_^!看样子似乎很难,其实设定方面还挺简单的,你可以透过 arp 以及 route 这两个指令来达成喔!

  • 外部接口 eth0:08:00:27:71:85:BD
  • 内部接口 eth1:08:00:27:2A:30:14
# 1\. 先设定外部 eth0 的 ARP Proxy,让三个 IP 对应到自己的 MAC
[root@www ~]# arp -i eth0 -s 192.168.1.10 08:00:27:71:85:BD pub
[root@www ~]# arp -i eth0 -s 192.168.1.20 08:00:27:71:85:BD pub
[root@www ~]# arp -i eth0 -s 192.168.1.30 08:00:27:71:85:BD pub
[root@www ~]# arp -n
Address             HWtype  HWaddress      Flags Mask       Iface
192.168.1.30        *       *              MP               eth0
192.168.1.10        *       *              MP               eth0
192.168.1.20        *       *              MP               eth0
# 首先需要让外部接口拥有三个 IP 的操控权,透过这三个指令来建立 ARP 对应!

# 2\. 开始处理路由,增加 PC2~PC4 的单机路由经过内部的 eth1 来传递
[root@www ~]# route add -host 192.168.1.10 eth1
[root@www ~]# route add -host 192.168.1.20 eth1
[root@www ~]# route add -host 192.168.1.30 eth1
[root@www ~]# route -n
Kernel IP routing table
Destination    Gateway        Genmask         Flags Metric Ref    Use Iface
192.168.1.20   0.0.0.0        255.255.255.255 UH    0      0        0 eth1
192.168.1.10   0.0.0.0        255.255.255.255 UH    0      0        0 eth1
192.168.1.30   0.0.0.0        255.255.255.255 UH    0      0        0 eth1
192.168.1.0    0.0.0.0        255.255.255.0   U     0      0        0 eth0
192.168.1.0    0.0.0.0        255.255.255.0   U     0      0        0 eth1
0.0.0.0        192.168.1.254  0.0.0.0         UG    0      0        0 eth0
# 这样就处理好单向的单机路由啰!不过有个问题啊!那就是 192.168.1.0/24
# 的网域,两个接口都可以传送!因此,等一下第四个步骤得要将 eth1 删除才行!

3\. 设定一下内部的 ARP Proxy 工作 (绑在 eth1 上头啰)!
[root@www ~]# arp -i eth1 -s 192.168.1.101 08:00:27:2A:30:14 pub
[root@www ~]# arp -i eth1 -s 192.168.1.254 08:00:27:2A:30:14 pub
# 这样可以骗过 PC2 ~ PC4 ,让这三部主机传递的封包可以透过 router 来传递!

4\. 开始清除掉 eth1 的 192.168.1.0/24 路由
[root@www ~]# route del -net 192.168.1.0 netmask 255.255.255.0 eth1

所有的计算机都在同一个网域内,因此 default gatway 都是 192.168.1.254 ,而 netmask 都是 255.255.255.0, 只有 IP 不一样而已。最后,所有的计算机都可以直接跟对方联机,也能够顺利的连上 Internet ! 这样的设定就能够满足上述的功能需求啰!如果一切都没有问题,那么将上述的指令写成一个脚本档, 例如 /root/bin/network.sh ,然后将该档案设定为可执行,并将它写入 /etc/rc.d/rc.local , 同时每次重新启动网络后,就得要重新执行一次该脚本,即可达到你的需求啰!

透过这个案例你也可以清楚的知道,能不能联机其实与路由的关系才大哩! 而路由是双向的,你必须要考虑到这个封包如何回来的问题喔!