荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: freeson (天地), 信区: Linux
标  题: 谈虚拟IP
发信站: 荔园晨风BBS站 (Sun May 13 14:10:34 2001), 转信

(摘自linuxbyte)
谈虚拟 IP
2001-03-23 6:06

发布者:Crystal 阅读次数:231
本文作者: thhsieh

这几天花了不少时间在研究这个,发现这真是相当实用而且强大,相信是所有网管
人员都不可不知道的。因此,我试图将它整理成文件,让大家参考。

「虚拟 IP 」其实是我自创的名词。在 Linux 中,它指的是 IP-Masq, 而在
FreeBSD 中,它指的是 NAT service,在我看来二者功能很相近,因此我就用这样
的名词来统称它们。至於在其他的 UNIX 中能否找到类似的东东,我不清楚,如果
有人知道的麻烦为我补充一下。关於这项技术,我算是相当後知後觉的了,早在一
年多前,Linux 就已开始发展,而 FreeBSD 更是在 2.1.X 版发展的中期就有了,
网络上已有相当多且不错的文件在讨论它们。如果大家觉得我这里写得不够详尽可
以去各大 BBS 精华区去找资料。


1.什麽是虚拟 IP

首先来谈谈什麽是「虚拟 IP」。我们都知道在 TCP/IP 的架构下,所有想连网络
的电脑,不论是用何种方式连连网络,都必须要有一个 *唯一* 的 IP-address。
举两个最常见的例子: 学校的电脑用网络线连在一起,是经由 ethernet 介面连连
网络,则该 ethernet 介面必须要有 IP-addr., 如 freebsd.phys.ntu.edu.tw的
 ethernet IP 为 140.112.52.20 。另一个常见的网络介面为 PPP, 通常是用在
modem 拨接上,当您从家里透过 modem 拨接上远端的 modem server 时,有些
server 会从中建立起远端与您的电脑间的 PPP 连线协定,於是,您的电脑就会有
一个 PPP 介面,而它的 IP-addr. 则由远端 server 指定给您 (这一切都是全自
动进行) ,於是您就可以透过 modem (PPP) 对外连线,就好像您的电脑直接接在
网络上一样。

在我们系上的计算机室,目前有两部机器可以做 PPP modem server (但规定只有
老师才能使用) ,一是 freebsd.phys, 另一是 linux.phys。 freebsd.phys 用的
是一条独立电话线,可以 24 小时全天候服务;而 linux.phys 用的是机房的电话
分机,故只有下班才能用。按照上头所述,如果同时要提供两个 modem 的 PPP 拨
接服务,就必须要有两个空的 IP-addr. 留下来,以便 PPP 连线建立时设定给用
户的电脑。因此,在过去计算机室就为此保留了两个 IP: 140.112.52.250 及
140.112.52.252, 让 ppp server 使用。然而,这样一来就造成了 IP 的浪费,很
明显的,当无人拨进来时这两个 IP 根本没有人使用,而且 modem server 也不是
无时无刻都会有人要拨进来。这时候,所谓的「虚拟 IP 」就派上用场了。

简单的说,虚拟 IP 就是假的 IP, 也就是未经注册的 IP, 但 server 端有能力将
这假的 IP 变成真的 IP 送往互连网,通行无阻,就好像有真的 IP 一样。以下是
简单的架构图:

也就是说,在实做上我们必须将网络分成两块,一块就是使用虚拟 IP 的电脑群,
它们不能与使用真正已注册过的 IP 的电脑 (或 Internet) 混在一起。而二者之
间的桥梁要靠一部拥有 IP-Masq 的 Linux 或 NAT 的 FreeBSD 连起来。注意到用
做「桥梁」的 server 拥有两个 (以上) 的网络介面,分别接 local net 与
internet,该 server 即称之为 "gateway" 或 "router",这些不同的网络介面可
以有不同的IP-addr.。所以,我们常说某某的电脑的 IP 是多少,其实不是百分之
百正确,如果该电脑拥有多个网络介面的话,那它不同的介面可能会有不同的
IP-addr.。眼前的例子就是 linux.phys 与 freebsd.phys, 在使用者拨接上来时
它就会自动建立起ppp0 这个介面,加上原来的 ethernet 介面就是两个。在过去
,它们的 ppp0 介面与 ethernet 介面的 IP 是设得一样的,以 freebsd.phys 来
说:

其中 ed0 即为 FreeBSD 的 ethernet 介面。现在要使用虚拟 IP 的技术,我们将
会设定其 ppp0 为不同 (虚拟) 的 IP。同理,一部电脑如果装两张网络卡同时接
两个网络,则它就会有两个 ethernet 介面:

要注意的是,如果 server 中的各网络介面 IP 的号码如果相同,或前几码相同(
如 freebsd.phys 的例子),则代表它所连接的子网络属同一个网域,否则为不同
网域。例如 freebsd.phys 的 ed0 是属於 140.112.52.0 这个网域,而拨接上来
的用户其 gateway 为 140.112.52.20 (ppp0 的 IP), 其本身的 IP 为 140.112.
52.252, 则它们也都属於 140.112.52.0 这个网域。

前面提过,使用像 140.112.52.252 这种已注册、合法的 IP 来给拨接用户使用会
造成浪费,因此,底下我们就用虚拟 IP 并透过 FreeBSD 的 NAT 来做拨接服务。
在 RCF 1597 的定义中,可以不经注册而任意使用的 IP 为:

10.0.0.0 - 10.255.255.255

172.16.0.0 - 172.31.255.255

192.168.0.0 - 192.168.255.255

依规定,凡是这类的 IP 都不能直接出现在互连网上,因此当我们私底下 (不直接
连上互连网) 用这些 IP 时,不必担心与别人冲到。在此,我们的虚拟 IP 就选用
 192.168.0.0 这一组,则以 FreeBSD 为例,其 PPP 与 ethernet 的架构就变为:



也许有人会问,为什麽 FreeBSD 一定要有 NAT? 若没有不是一样可以通吗? 没错
,一样可以通,但这样一来就违反了规定, 192.168.1.X 就不再是虚拟 IP, 而变
成真实 IP, 直接连上 internet 了 (仅管 modem 的连线是很短暂的)。 NAT 所做
的工作,就是将 192.168.1.X 这类虚拟 IP ,变成真实的 IP 出去,让外界永远
不知道实际上有这些虚拟 IP 存在。举个例子,假设您是在此架构下的用户端,您
可以经由 FreeBSD (或 Linux) 自由地连往 internet, 不论是 telnet, ftp, www
 ....假设您现在用 telnet 连往 bbs, 则虽然您用的是虚拟 IP, 但如果您去看
bbs 的资讯看您是来自何方时,显示却会是真实的 IP (以上头的例子,即为
140.112.52.20)

这就是虚拟 IP 最奇妙的地方! 在外界,您永远是以「真实 IP」出现,但人家永
远不会知道,其实您是来自 Linux/FreeBSD 底下的一部用「虚拟 IP」的电脑。因
此,我只要在 Linux/FreeBSD server 端注册一个真实 IP, 则透过此技术我可以
 *合法地*在後头串接一大串使用虚拟 IP 的电脑。这麽做,其优点就如前所述,
且使用虚拟IP 的电脑等於是隐藏在 Linux/FreeBSD server 身後,受到 server
端完全的保护。而缺点是,使用虚拟 IP 的电脑不能公开,也就是,它不能架
server (谁知道世上有这麽一台 www 或 ftp server 存在?),也不能接 mail (在
外头的电脑怎麽知道mail 要送到这里来?),当然,也不能被外头的电脑 telnet
进来。请特别注意我这「公开」与「外头」的字眼,事实上使用虚拟 IP 还是可以
架 server, 接 mail 等,但只有同在同一个虚拟 IP 网域下的机器才知道,因为
同在一部 Linux/FreeBSDserver 的管理下,它会为大家做好沟通的工作。但外头
的电脑则不行了。

再来谈「网域」的问题。例如,利用这样的技术,我们可以将机房中 PPP 拨接
server规划如下:大家会奇怪,这样如果 client 1 与 client 2 若同时上来, IP
 不是冲到了吗?不会! 第一: client 1 与 client 2 属於不同网域,分别由
freebsd 与 linux掌管。第二: freebsd 用 NAT, linux 用 IP-Masq 将这两个网
域藏起来了,所以实际上它们谁也瞧不见对方。假设双方连上来的人在 bbs 上碰
面,则在我们看来,如前所述, client 1 是来自 140.112.52.20 这个 IP, 而
client 2 是来自140.112.52.122 这个 IP。

讲了这麽多,我们已可以约略看出虚拟 IP 的应用了。前面所提的 PPP 拨接是一
个,另一个就是同一实验室里头的电脑。并非所有的电脑都需要对外公开的,尤其
是用做平行计算的电脑群。现在将十多部甚至一、两百部电脑透过网络连起来做平
行计算已成风潮,像我们系上有许多老师听说就是此道的高手。但是,如果说一个
实验室要搞平行计算而申请十多个或上百个 IP 的话,是相当浪费的 (事实上根本
不可能,因为没那麽多 IP),因此,使用虚拟 IP 技术,可以大大地节省网络资源


好了,以下我简述实作的方法: 不论是用 Linux 的 IP-Masq 或 FreeBSD 的
NAT,其设定的道理都相同,主要有以下四个步骤:

设定好 server 端的网络介面。就我们的例子,一为 ethernet 介面,另一即为供
 modem 拨接上来的 PPP 介面。其设定方式算是另一个专题,这里不详述。
设定 Kernel, 使其拥有 IP-Masq (for Linux) 或 IP-Divert (for FreeBSD) 的
能力。於 FreeBSD, 还要同时起动 natd server。
设定 IP-Firewall rule ,建立虚拟 IP 与真实 IP 之间的连线。
设定 client 端以使用 server 端的虚拟 IP。就我们的例子而言,如果原本
client 端已能顺利地由 modem 拨接上线,则理论上 server 端改用虚拟 IP 後
client 不需要改变任何设定,原因是 client 端的 IP 与 gateway 设定是每次在
 PPP 连线建立时即全自动进行 (由 server 端控制)。但如果 client 端是用
ethernet 与 server 端连线的话,则必须进行这一步的设定。
以下我就简述第 2, 3 步的实作, Linux 与 FreeBSD 分别讲,同时也讲一下使用
了虚拟 IP 之後, client 端所呈现的网域环境 (第 4 步)。
有一点要稍作补充: 不论是 IP-Masq 或 IP-Divert & NAT, 其设计上都是基於
IP-Firewall 的。所谓 IP-Firewall 即俗称「防火墙」,是一种相当强大的网络
防护系统,它可以在网络封包的层级直接控制封包的传输,如是否让来自某 IP的
封包进入、通过、输出此 Firewall server。在很多私人网络中,其网域与外界网
络之间常常会装设一台 Firewall server, 以限定、或完全隔绝内外网络的流通,
以达到保护内部网络的目的。因此,如有外来的入侵者想入侵内部网络的话,则第
一步就是要突破 Firewall server 这一关,而这通常是很不容易办到的。文件上
说, IP-Masq *也许是* 比起 IP-Firewall 安全等级更高的防护,我猜原因可能
是内部网络的虚拟 IP 是靠 IP-Masq server 建立起来的,如果外来入侵者在千辛
万苦之後终於破坏了 server, 但这也等於破坏了 IP-Masq 的架构,也就等於整个
虚拟 IP 网络都不存在了 (连不通),他还是无法进而入侵内部网络的电脑。正因
为 IP-Masq 或 IP-Divert 是架构在 IP-Firewall 之上,因此我们必须要有第
3 步的「设定 IP-Firewall rule」,而且设定这一步时要特别小心,如果设错了
有可能造成 server 端网络完全不通。


2.Linux 的做法

我们从第二步设定 Kernel, 并打开 IP-Masq 的功能开始。文件上说只要是
Kernel-2.0.x 的版本再加 patch 皆可,我这里所用的 Kernel 版本为 2.0.34,
完全不需 patch 即可使用,所以建议用这个版本 (或以上)的 kernel。在 make
config 时,请打开以下的选项 (节录自 IP-Masquerade MiniHOWTO):


* Prompt for development and/or incomplete code/drivers
CONFIG_EXPERIMENTAL
- 如此您即可选取 *正在实验中的* IP-Masq 功能。

* Enable loadable module support
CONFIG_MODULES
- 如此您可使用 kernel 的模组功能。

* Networking support
CONFIG_NET

* Network firewalls
CONFIG_FIREWALL

* TCP/IP networking
CONFIG_INET

* IP: forwarding/gatewaying
CONFIG_IP_FORWARD

* IP: firewalling
CONFIG_IP_FIREWALL

* IP: masquerading (EXPERIMENTAL)
CONFIG_IP_MASQUERADE
- 虽然它被归类为 experimental, 但您一定要选它。

* IP: ipautofw masquerade support (EXPERIMENTAL)
CONFIG_IP_MASQUERADE_IPAUTOFW
- 建议您选这个。

* IP: ICMP masquerading
CONFIG_IP_MASQUERADE_ICMP
- 支援 ICMP 的封包,主要用於从虚拟 IP ping 外头的世界,可选可不选。

* IP: always defragment
CONFIG_IP_ALWAYS_DEFRAG
- 强烈建议您选这个。

* Dummy net driver support
CONFIG_DUMMY
- 建议您选这个。



Compile 完 kernel 与 module 之後,重新启动电脑,请将 IP-Masq 所需的
module载入。例如,我希望虚拟 IP 可以对外用 ftp 传档,则我就必须载入
ftp 的 module:
modprobe ip_masq_ftp



如此,使用虚拟网络的机器就拥有 telnet, ftp, www, ping .... 等这几项基本
能力了。除此之外, kernel 还提供其他的 module 以支援如 IRC, Raudio 等网
络功能,可以选择性地载入。这些可以写在开机启动档中在系统开机时一并完成。
接下来是第 3 步,设定 IP-Firewall rule。在 Linux 是用 ipfwadm 这指令,这
指令的用法相当多样,详细用法请见 man ipfwadm, 在这里只简述简单用法。
ipfwadm 在设定封包流通的规则主要有三个:


ipfwadm -I .... (设定流入 server 的封包)
ipfwadm -O .... (设定流出 server 的封包)
ipfwadm -F .... (设定由某网域经由本 server 流向另一网域的封包)



如在之後加上 -l 的参数,则会列出目前已设定的 rule 。例如在 linux.phys 中
,已设定的 rule 为:


$ /sbin/ipfwadm -I -l
IP firewall input rules, default policy: accept
type prot source destination ports
deny all 127.0.0.0/8 anywhere n/a
deny all 127.0.0.0/8 anywhere n/a
$ /sbin/ipfwadm -O -l
IP firewall output rules, default policy: accept
$ /sbin/ipfwadm -F -l
IP firewall forward rules, default policy: deny
type prot source destination ports
acc/m all 192.168.1.0/24 anywhere n/a



"default policy" 意思是,如果封包没有受限与其他的 rule, 则 kernel 就以此
预设值处理它。以 "Input rules" 为例,凡是来自 127.x.x.x 网域的封包完全被
档在server 之外 (deny), 而其他的封包则可以被 server 接受。原因是 127.x.
x.x 是属於 loop back 设定用的,按规定任何公开的电脑都不能将 IP 设成这个
,而在此设这个 rule 主要是预防某些粗心大意的系统管理者误设了这样的 IP,
而该电脑又试图与我们的 server 连线。

由於 linux.phys 使用的是 Debian-2.0 系统,在 kernel 起动 IP-Firrewall 功
能时,系统在每次重开机後都会自动设好以上的 "Input, Output rules", 使其
defaultpolicy 为 accept, 如此该 server 才能自由自在地对外连线、或接受外
来的连线。同时 "Forward rules" 的 default policy 亦为 accept, 即外头的网
络可以自由地经由本 server 连线到内部网络、反之亦然。现在要使用 IP-Masq
以连接内部的虚拟 IP 与外部的真实 IP, 我们必须改变此设定:


ipfwadm -F -p deny

将其 default policy 设成 deny, 从此以後内外网络无法自由连线


ipfwadm -F -a m -S 192.168.1.0/24 -D 0.0.0.0/0



将来自 192.168.1.x (内部、虚拟) 网域的封包,经由 IP-Masq (m)传送到外部网
络的任何地方 (0.0.0.0/0), 当然,在此之前我们必须先设好第一步,让 PPP 介
面接管 192.168.1.x 这个网域)

如此一来,虚拟 IP 与外头的世界就正确地建立连线了。这两行可以直接写入开机
启动档中以自动执行。

3.FreeBSD 的做法

同样的,我们先来看看第二步。重新 compile kernel 时,请将以下选项写入设定
档中 (节录自 man natd):


options IPFIREWALL
options IPDIVERT



同样的,我们先来看看第二步。重新 compile kernel 时,请将以下选项写入设定
档中 (节录自 man natd):


options IPFIREWALL
options IPDIVERT



并在 /etc/rc.conf 中写入这一行


gateway_enable=YES



以便在重开机时开启 gateway 的功能。与 Linux 最大的部同是, Linux 的
IP-Masq的运作完全是在 kernel 中进行,而 FreeBSD 的 NAT 还需要跑一苹 natd
 的程序来运作。请在 /etc/services 加入一行:


natd 6668/divert # Network Address Translation socket

然後在开机时执行这个程序:


natd -interface ed0



其意义为: 所有来自虚拟 (内部) 网络的封包,经转换後经由 ed0 (ethernet) 介
面对外传送。

第二步我们要设定 IP-Firewall rule 。在 FreeBSD 要用 ipfw 指令。使用 ipfw
 -a show 会列出目前所有的 rule:


# /sbin/ipfw -a show
01000 318 30934 allow ip from any to any via lo0
01010 0 0 deny ip from 127.0.0.0/8 to 127.0.0.0/8
06000 177084 47865019 divert 6668 ip from any to any
65000 241446 67969713 allow ip from any to any
65535 0 0 deny ip from any to any



与 Linux 的 ipfwadm 不一样,在 FreeBSD 中不特别区分 Input, Output,
Foreward这三项,也没有 default policy, 但它每一个 rule 都有一个号码,代
表 rule 的比对顺序。进来的封包会按此顺序一个个地比对,一旦比对符合就按此
 rule 来处理。以上的 rule 其意义是:


01000: 允许封包经由 lo0 (loop back) 互传
01010: 拒绝 127.0.0.0/8 到 127.0.0.0/8 的封包 (作用与上述 Linux 的
rule 类似)
06000: 使用 IP-Divert 建立虚拟与真实 IP 的连线
65000: 允许所有的封包自由流通 (如此 server 本身便能自由对外连线、接受连
线)
65535: 拒绝所有的封包



在 freebsd.phys 系统中,用的是 FreeBSD-2.2.5 操作系统,当启动
IP-Firewall之後,除了 06000 那个 rule 以外,其他的 rule 系统每次重开机时
便会帮我们自动建立。而要使用 IP-Divert & natd, 我们必须自行建立 06000 这
个 rule:


/sbin/ipfw add 06000 divert natd all from any to any

其中 06000 这个数字就决定了此 rule 在整个 rule table 的安插顺序。请注意
顺序非常重要! 它一定要在 65000 之前,否则的话,来自虚拟 IP 的封包因为满
足65000 rule, 系统就以此 rule 处理,而不再往下看有关 IP-Divert 的 rule,
 结果是,虚拟 IP 的封包未经处理就往外丢,连线无法正确建立,网络不通。并
在 /etc/rc.conf 中写入这一行


gateway_enable=YES



以便在重开机时开启 gateway 的功能。与 Linux 最大的部同是, Linux 的
IP-Masq的运作完全是在 kernel 中进行,而 FreeBSD 的 NAT 还需要跑一苹 natd
 的程序来运作。请在 /etc/services 加入一行:


natd 6668/divert # Network Address Translation socket



然後在开机时执行这个程序:


natd -interface ed0



其意义为: 所有来自虚拟 (内部) 网络的封包,经转换後经由 ed0 (ethernet) 介
面对外传送。

第二步我们要设定 IP-Firewall rule 。在 FreeBSD 要用 ipfw 指令。使用 ipfw
 -a show 会列出目前所有的 rule:


# /sbin/ipfw -a show
01000 318 30934 allow ip from any to any via lo0
01010 0 0 deny ip from 127.0.0.0/8 to 127.0.0.0/8
06000 177084 47865019 divert 6668 ip from any to any
65000 241446 67969713 allow ip from any to any
65535 0 0 deny ip from any to any



与 Linux 的 ipfwadm 不一样,在 FreeBSD 中不特别区分 Input, Output,
Foreward这三项,也没有 default policy, 但它每一个 rule 都有一个号码,代
表 rule 的比对顺序。进来的封包会按此顺序一个个地比对,一旦比对符合就按此
 rule 来处理。以上的 rule 其意义是:


01000: 允许封包经由 lo0 (loop back) 互传
01010: 拒绝 127.0.0.0/8 到 127.0.0.0/8 的封包 (作用与上述 Linux 的
rule 类似)
06000: 使用 IP-Divert 建立虚拟与真实 IP 的连线
65000: 允许所有的封包自由流通 (如此 server 本身便能自由对外连线、接受连
线)
65535: 拒绝所有的封包



在 freebsd.phys 系统中,用的是 FreeBSD-2.2.5 操作系统,当启动
IP-Firewall之後,除了 06000 那个 rule 以外,其他的 rule 系统每次重开机时
便会帮我们自动建立。而要使用 IP-Divert & natd, 我们必须自行建立 06000 这
个 rule:


/sbin/ipfw add 06000 divert natd all from any to any



其中 06000 这个数字就决定了此 rule 在整个 rule table 的安插顺序。请注意
顺序非常重要! 它一定要在 65000 之前,否则的话,来自虚拟 IP 的封包因为满
足65000 rule, 系统就以此 rule 处理,而不再往下看有关 IP-Divert 的 rule,
 结果是,虚拟 IP 的封包未经处理就往外丢,连线无法正确建立,网络不通。

来源:LinuxFab

[发布人] fuck you       [发布时间]  2001-03-23 19:08
[评论]   这样的垃圾,还好意思贴上来。少发明一些什么Virtual IP。我还以为
什么新东西来了,靠!

------------------------------------------------------------------------
--------
[发布人] skykiller       [发布时间]  2001-03-23 8:43
[评论]   太老了
linux2.4已经有nat了,和2.2的iochain相比,完善了很多

--
※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.46.2]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店