讓 Mac OS X 成為一部 Router
03/24/2005, 02:59
若是您的 Mac 有二個網路介面,不管是PCI 或者是802.11x Apple Airport wireless 的,您有想過可以用這些網路卡
組成一個網路動態交換網路路由資料,或者是只是要讓您的網路可以自動調整網路由?
OS X Server 好像可以,不過我沒有 Server 版,所以不清楚,但是也可以在 OS X 中加裝
GNU Zebra routing process 來達到動態更新網路由的工作,而且只要花一點點時間就可以作到。

要先到將 zebra source 拿回來,zebra 目前停在 0.94 版有段時間了,
不過沒有更新,不代表就不能用,您可以 ftp 到 ftp.zebra.org/pub/zebra/zebra-0.94.tar.gz 。
還有一個叫Quagga 的是 修改 Zebra 而來的,也可以用,而且還在更新中。
compile 程式,當然要有 compiler,您可以在 terminal 試試,沒用過 terminal?
那就對不起了,這篇專題是一定要用到 terminal 的。
打開 terminal

$ gcc -v
Reading specs from /usr/libexec/gcc/darwin/ppc/3.3/specs
Thread model: posix
gcc version 3.3 20030304 (Apple Computer, Inc. build 1666)

$ ld -v
Apple Computer, Inc. version cctools-525.obj~1

有出現像類似的資料的話,代表您有裝 Developer Tool (10.2)或 XCode(10.3),
不然的話請用隨機原版 CD ,安裝它。若是沒有 Developer Tool 或 XCode 可以到
Apple Developer網站 去註冊後 download 回來,300多 MB,
但是免費的。

先拿回 source code,解開 zebra-0.94.tar.gz

$ tar -zxvf zebra-0.94.tar.gz
zebra-0.94/
zebra-0.94/vtysh/
zebra-0.94/vtysh/Makefile.in
zebra-0.94/vtysh/Makefile.am
zebra-0.94/vtysh/vtysh.h
zebra-0.94/vtysh/vtysh_user.h
zebra-0.94/vtysh/ChangeLog
zebra-0.94/vtysh/vtysh_main.c
zebra-0.94/vtysh/vtysh.c
zebra-0.94/vtysh/vtysh_cmd.c
......
......
zebra-0.94/init/redhat/zebra.init
zebra-0.94/init/redhat/zebra.logrotate
zebra-0.94/init/redhat/zebra.spec.in
$
$ cd zebra-0.94
[zebra-0.94] $ ./configure --help : more
`configure' configures this package to adapt to many kinds of systems.

Usage: ./configure [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
......
......

headers in a nonstandard directory <include dir>
CPP C preprocessor

Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.

[zebra-0.94] $ ./configure --prefix=/usr --sysconfdir=/etc/zebra
--localstatedir=/var --enable-zebra --enable-tcp-zebra --enable-ripd
--enable-ospfd --enable-ipv6 --enable-ripngd --enable-ospf6d
--enable-bgpd --enable-lsa-opaque --enable-nssa --enable-ospf-te
--enable-multipath=6

.....
.....

[zebra-0.94] $ sudo -s
Password:
[zebra-0.94] # make; make check; make install

......
......

安裝好之後可以檢查一下 /usr/sbin 及 /etc/zebra。

[zebra-0.94] # ls /usr/sbin/zebra
/usr/sbin/zebra
[zebra-0.94] # ls /etc/zebra
bgpd.conf.sample ripd.conf.sample ripngd.conf.sample
zebra.conf.sample ospf6d.conf.sample ospfd.conf.sample

看您要用那些 routing protocol,將設定檔案的 sample 拿掉。
若要用 IS-IS ISO routing protocol,您可以到
ISISD for zebra找到patch,
但只有 support 到 zebra 0.93b。

[zebra-0.94] # mv zebra.conf.sample zebra.conf
[zebra-0.94] # mv ripd.conf.sample ripd.conf

就用 RIP 吧,那個 Zebra 是一定要的,負責在各 protocol 及 kernel routing table 間
作資料傳遞及轉換用的。而大部份的 IP 分享器都只有支援 RIP。
先看看 /etc/zebra.conf 及 /etc/ripd.conf 這兩個設定檔案內容:

[zebra-0.94] # cat /etc/zebra/zebra.conf
! -*- zebra -*-
!
! zebra sample configuration file
!
! $Id: zebra.conf.sample,v 1.14 1999/02/19 17:26:38 developer Exp $
!
hostname Router
password zebra
enable password zebra
!
! Interface's description.
!
!interface lo
! description test of desc.
!
!interface sit0
! multicast

!
! Static default route sample.
!
!ip route 0.0.0.0/0 203.181.89.241
!

!log file zebra.log

[zebra-0.94] # cat /etc/zebra/ripd.conf
! -*- rip -*-
!
! RIPd sample configuration file
!
! $Id: ripd.conf.sample,v 1.11 1999/02/19 17:28:42 developer Exp $
!
hostname ripd
password zebra
!
! debug rip events
! debug rip packet
!
router rip
! network 11.0.0.0/8
! network eth0
! route 10.0.0.0/8
! distribute-list private-only in eth0
!
!access-list private-only permit 10.0.0.0/8
!access-list private-only deny any
!
!log file ripd.log
!
log stdout

先記得密碼: "zebra",手動啟動看看吧!

/usr/sbin/zebra -d
/usr/sbin/ripd -d

檢查系統的 routing table 用

netstat -rn
Routing tables

Internet:
Destination Gateway Flags Refs Use Netif Expire
default 192.168.7.254 UGSc 21 588 en0
127.0.0.1 127.0.0.1 UH 10 32794 lo0
169.254 link#4 UCS 0 0 en0
172.16.47/24 192.168.7.129 UG1c 0 0 en0
172.16.50/30 192.168.7.254 UG1c 0 0 en0
172.16.100/24 192.168.7.244 UG1c 0 0 en0
172.16.200/24 192.168.7.245 UG1c 0 0 en0
172.17.17/24 192.168.7.2 UG1c 0 0 en0
192.168.0 192.168.7.254 UG1c 0 0 en0 =>
192.168.0/16 link#4 UCS 25 0 en0
192.168.1.14 0:2:b3:ca:5e:14 UHLW 0 16 en0 1109
192.168.1.31 0:d:60:16:1d:1a UHLW 0 1 en0 1162
192.168.1.35 0:0:e2:2a:3:e9 UHLW 0 18 en0 1194
192.168.1.41 0:50:ba:bc:d5:2c UHLW 0 18 en0 1172
192.168.1.117 0:c0:26:8d:6d:b2 UHLW 0 3 en0 795
192.168.1.183 0:0:e2:13:96:14 UHLW 0 4 en0 1076
192.168.1.201 0:2:b3:ca:60:13 UHLW 0 2 en0 1194
192.168.1.210 0:11:85:b8:6b:b1 UHLW 0 18 en0 1192
192.168.1.253 0:d0:58:ad:42:cb UHLW 2 2 en0 1152
192.168.1.254 0:50:bf:51:cd:46 UHLW 1 164 en0 1193
192.168.7.2 link#4 UHLW 1 0 en0
192.168.7.12 0:5:65:70:3:e8 UHLW 0 2 en0 1179
192.168.7.100 127.0.0.1 UHS 0 22 lo0
192.168.7.129 link#4 UHLW 1 0 en0
192.168.7.180 0:d:61:30:89:a6 UHLW 1 20 en0 974
192.168.7.243 0:1:29:40:7c:74 UHLW 0 48 en0 1199
192.168.7.244 0:90:cc:40:25:f9 UHLW 3 532 en0 1179
192.168.7.245 0:90:cc:27:14:a5 UHLW 1 3 en0 1184
192.168.7.246 0:40:95:9:c4:d1 UHLW 0 2 en0 1091
192.168.7.254 0:90:cc:40:31:bf UHLW 22 883 en0 1200
192.168.8.89 0:80:c8:6e:5c:e8 UHLW 0 1 en0 638
192.168.8.107 0:d:93:ca:a1:5c UHLW 0 4 en0 665
192.168.8.132 0:e0:18:7f:dd:80 UHLW 0 105503 en0 1127
192.168.8.152 0:7:40:1c:ff:2 UHLW 0 89 en0 755
192.168.8.188 0:d:61:5f:52:84 UHLW 0 14 en0 814
192.168.8.193 0:80:c8:94:9c:e1 UHLW 0 18 en0 1176
192.168.9 192.168.7.244 UG1c 0 0 en0
192.168.44 192.168.7.180 UG1c 0 0 en0
192.168.100 192.168.1.253 UG1c 0 0 en0

Internet6:
Destination Gateway Flags Netif Expire
fe80::%en0/64 link#4 UC en0
0:5:2:fd:2c:ef UHL lo0
0:90:cc:40:31:bf UHLW en0
ff02::%en0/32 link#4 UC en0

看 routing 己經從 router 交換進來了。
再來您可以用telnet localhost 2601 去設定 zebra 或 2602 設定 ripd

daemon port IP version
----------------------------------
zebra 2601 --
ripd 2602 v4
ripngd 2603 v6
ospfd 2604 v4
bgpd 2605 v4/v6
ospf6d 2606 v6

而操作方法和 Cisco router 一樣,只不過命令比較少。設定好了之後,
以後就可以由手動啟動。

$ /usr/sin/zebra -d
$ /usr/sbin/ripd -d

以上,在 UNIX 機器上都一樣的步驟,下面就是在 OS X 上不同的地方了,
您可以設定在 OS X 開機後自動啟動 routing 。
先看 /etc/hostconfig

$ cat /etc/hostconfig
##
# /etc/hostconfig
##
# This file is maintained by the system control panels
##

# Network configuration
HOSTNAME=-AUTOMATIC-
ROUTER=-AUTOMATIC-

# Services
AFPSERVER=-YES-
APPLETALK=en0
AUTHSERVER=-NO-
AUTOMOUNT=-YES-
CONFIGSERVER=-NO-
CUPS=-YES-
IPFORWARDING=-YES-
IPV6=-YES-
MAILSERVER=-NO-
NETBOOTSERVER=-NO-
NETINFOSERVER=-AUTOMATIC-
NISDOMAIN=-NO-
RPCSERVER=-AUTOMATIC-
TIMESYNC=-YES-
QTSSERVER=-NO-
SSHSERVER=-YES-
WEBSERVER=-NO-
SMBSERVER=-NO-
DNSSERVER=-NO-
APPLETALK_HOSTNAME=PowerBook G3"

ARDAGENT=-YES-
CRASHREPORTER=-YES-
ZEBRA=-YES-
OSPF=-NO-
RIP=-YES-
RIPNG=-NO-
OSPF6=-NO-
BGP=-NO-

加上從 ZEBRA 開始的資料。要起動的就設為 -YES-。存回去。

再來就是到 /System/Library/StartupItems
建立一個目錄叫 Zebra
建立二個檔案 StartupParameters.plist 及 Zebra
要建立一個檔案您可以用文字編輯器來建立,個人是比較喜歡用vi 在 terminal 上使用。

$ cd /System/Library/StartupItems
$ mkdir Zebra
$ cd Zebra
$ cat StartupParameters.plist

{
Description = "Zebra daemon";
Provides = ("ZEBRA");
Requires = ("Network");
Uses = ("Network");
OrderPreference = "None";
Messages =
{
start = "Starting Zebra daemon";
stop = "Stopping Zebra daemon";
restart = "Restart Zebra Routing";
};
}

$ cat Zebra

#!/bin/sh

. /etc/rc.common

StartService ()
{
if [ "${ZEBRA:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Starting Zebra routing services"
/usr/sbin/zebra -d
if [ "${RIP:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Starting RIP routing services"
/usr/sbin/ripd -d
fi
if [ "${OSPF:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Starting OSPF routing services"
/usr/sbin/ospfd -d
fi
if [ "{$IPV6:=-NO-}" = "-YES-" ]; then
if [ "${RIPNG:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Starting RIPng routing services"
/usr/sbin/ripngd -d
fi
if [ "${OSPF6:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Starting OSPF6 routing services"
/usr/sbin/ospf6d -d
fi
fi
if [ "${BGP:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Starting BGP routing services"
/usr/sbin/bgpd -d
fi
fi
}

StopService ()
{
if [ "${ZEBRA:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Stopping Zebra routing services"
killall -1 zebra 2> /dev/null
if [ "${RIP:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Stopping RIP routing services"
killall -1 ripd 2> /dev/null
fi
if [ "${IPV6:=-NO-}" = "-YES-" ]; then
if [ "${RIPNG:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Stopping RIPng routing services"
killall -1 ripngd 2> /dev/null
fi
if [ "${OSPF6:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Stopping OSPF6 routing services"
killall -1 ospf6d 2> /dev/null
fi
fi
if [ "${OSPF:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Stopping OSPF routing services"
killall -1 ospfd 2> /dev/null
fi
if [ "${BGP:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Stopping BGP routing services"
killall -1 bgpd 2> /dev/null
fi
fi
}

RestartService ()
{
if [ "${ZEBRA:=-NO-}" = "-YES-" ]; then
StopService
StartService
else
StopService
fi
}

RunService "$1"



好了,下次重開機時就會起動 Zebra 了,可以用

$ ps -ax :grep zebra;ps -ax:grep ripd。

不過不要忘了要去設定您的 Router 喔!
若要 Forward 二個網路間的資料,要記得在 /etc/hostconfig 中的 IPFORWARD 要 YES。
要用 IPv6 就設定 IPV6 為 -YES-
其他關於 Routing 及設定的部份請自行參考相關資料。