Linux作为一种新近崛起的操作
系统,由于其性能稳定,源码开放及
价格方面的优势而逐渐被广大用户所接受。现在Linux的主要用武之地在于
服务器领域,但是,经过适当的配置之后,它还可以担当
互联网的
物理基石--
路由器这一重要角色。
h- [# l* y1 H
3 t' {1 K" i9 s' M8 i8 N路由器是
通信子网中的通信节点,每个路由器都计算并维护一张路由表,并据此指导
数据报前往最佳路径中的下一站,这便是所谓的路由。这样,经过互联网上所有路由器的通力合作,
数据报就能够沿着一条"最佳"路径到达目的地。在GNU
软件Zebra的协助下,我们可以将Linux
机器打造成一台
功能完备的路由器,它能够同时支持RIPv1、RIPv2、RIPng、OSPFv2、OSPFv3、BGP-4和BGP-4等诸多
TCP/IP协议。现在我们首先了解一下OSPF和BGP协议的运行模式和基本原理,然后介绍Zebra的安装配置方法,让你的Linux机器变成支持OSPF与BGP的路由器。
. J u [& F* |) Q0 u( z6 V0 h) [- @( L7 G
BGP/OSPF概述
2 y6 \/ d+ a- k( z5 Q U6 |& s
* X8 {4 K- g8 s0 v ?( c" E如今,许多公司都建有多个
网络,如果这些网络的
类型不尽相同,则需要用路由器进行互联。路由器是与两个或两个以上的网络连接的
计算机,它根据路由协议生成并维护一个路由表,并按照该路由表中的
信息转发包。这些路由器对公司内部的网络
结构了如指掌,知道将分组送到目的地的全部细节,但对于其他公司的网络结构并不了解。像这样"在同一机构下
管理的一系列路由器和网络"被称为自治系统(AS)。由不同机构掌管的自治系统,可以采用不同的路由选择
算法;但同一自治系统内的所有路由器都使用同一路由协议,以便于自治系统内部各个路由器互换路由信息来维持相互的连通性。每一个自治系统都有一个16位的"自治系统(AS)编号"作为标志,就像IP地址一样,它是由专门机构来分配的。
3 M0 H! ~7 N' q; n9 s! F' N" W% B8 N
自治系统内的路由器称为"内部网关",所用的协议称为"内部网关协议"。内部网关协议大体上分为两类,一类是距离向量协议,如RIP,EIGRP协议;另一类是链路状态协议如OSPF协议。链路状态路由协议与距离向量协议的不同之处在于,采用链路状态路由协议的路由器不是交换到达目的地的距离,而是维护一张网络拓扑结构图。然后用
数据库表示该图,其中的表项对应网络的一条链路。路由器根据数据库的信息计算出"最佳路由",由此指导包的转发。当网络拓扑结构发生变化时,只需将相应纪录而非整个数据库通知其他节点。各路由器做出相应修改并重新计算路由后,就可以继续正常工作。
/ N: B& G- {5 x' o# q5 w% W: t! y4 N7 k
6 s! Y: n* z$ ]! w1 I7 e0 U
因为"开放式最短路径优先协议"的文档必须公开发表,所以它是"开放式的"(Open);又因为它采用"最短路径优先"(SPF)算法来计算一个节点到所有其它节点间的最短路径,故名为OSPF。OSPF具有支持多重度量制式和多重路径等诸多优点,因此成为因特网上推荐使用的内部网关协议,RIP却由于自身的局限性而被打入冷宫。现在,在性能上唯一能够与OSPF相匹敌的内部网关协议便是EIGRP--Cisco的一个专有协议,但OSPF的"开放"本身就是一个响亮的招牌,因为谁也不想受制于某家供应商。
2 ]& q7 [" P6 q: U0 ~; y+ w3 Z5 s
; L( d& u4 E2 E6 d& k6 Z
前面提到,自治系统内的路由器不必知道其他自治系统的内部结构细节,从而有效地节约了路由器的
内存和
CPU时间,并提高了网络带宽的利用率。但是,如果想与其他公司(自治系统)通信时该怎么办呢?很简单,我们可以在自治系统内指定一个与其他自治系统相连的路由器为"外部网关",通过它进入其他自治系统。该路由器使用的协议叫做"外部网关协议",如边界网关协议(BGP)。相邻的两个网关必须首先互换"邻机探测"报文,协商是否愿意成为"邻机"。成为邻机则意味着两个自治系统同意中转双方的通信流。同意后,两个邻机互换"邻机可达性报文",来监督他们之间的链路的工作情况。接下来便是最重要的工作,用"网络可达性报文"来交换通过各邻机所能到达的网络的信息,从而实现自治系统之间的连通性。在外部网关的眼里只由外部网关和连接他们的链路,如此以来,自治系统内的通信由内部网关处理,自治系统之间的通信交由外部网关处理--一个分级路由的景象已经展现在我们面前,实际上,因特网正是由大量自治系统组成的。
% K# C% m5 b7 ~0 Z9 Y U. Q! L% H& G |8 c; [0 j }( a- M
建立一个高级路由器
" ^% k* L6 P$ D3 T6 y1 y' h4 g( u$ }* ] e/ q3 A( B/ ]+ T
许多人对路由器感到比较陌生,事实上作为一个
防火墙使用的Linux系统已经是一个路由器了,只不过还有点"简陋"而已。然而,我们的目标是用Linux打造一个"高级"路由器,它必须能够利用动态路由协议(上文提到的协议皆为动态路由协议)工作。这些协议能够使路由器互换相关信息,从而
共享穿越网络时所用的那些路径--路由。这一点对于大型网络(比如Internet)而言是"异常"重要的,因为此时再用静态路由(也就是人工计算设置路由)是根本不现实的。
) l+ U- `) o9 {% I% U; ?
% s: a" U* G, E$ ~0 H7 H" N举例来说,即使在比较理想--即不考虑路由的变化的情况下,一个边界网关协议(BGP)路由表也至少包含100,000条以上的表项。这时,手工建立这样的静态路由是难以忍受的。很明显,即使我们的网络小于Internet--比如一个大型公司网络,我们还是更加喜欢动态路由协议。
0 h6 e, E$ x' k
' Q1 h# U0 z2 k# x5 R- J3 Q8 \外部网关协议BGP通常作为Internet的骨干使用,而其它的协议(如OSPF)则适于小型的互连网络。开放式最短路径优先(OSPF)协议是一个应用最广的内部网关协议(IGP)。Zebra是一个开放
源代码程序包,通过它你可以在Linux上运行BGP与/或OSPF。
8 \* g- m+ ~+ r: e7 A
; G1 d5 d% a: f$ f4 I; o安装Zebra
7 [" k3 B" O7 v6 n) W) t5 O* a' V+ m& H; ^, ~
你既可以从Zebra.org
网站下载Zebra的最新源程序,也能从
Redhat和Debian中获得它,但不一定是最新版的。从源代码中进行软件安装,你就会发现使用的是一些普通的安装过程。简介如下:
2 {% L+ |0 C2 s0 d3 e) g. c- N# A
* |: x7 z! `" d
' a5 }0 C+ _" R/ n
* i- g3 m1 i* {1 S, t4 F! `' @ H9 E! d7 m0 ]- N ]
代码:
5 X. ^( ?0 ]5 M, Y& g& H* }8 b* ]; A6 U0 [: B2 W: c- R, }
8 g+ O. V1 B9 s" E& q9 J1 ]7 i0 E
./configure
! ]& X, P' k) }! c* [( {
make
: K2 \% w# A! R$ i3 ]) ^makeinstall
% F7 {9 T. O6 w) l9 o# D4 K6 n! s7 }: Z) X
" L, X$ P0 S7 [! {配置脚本会搜索系统上已经安装的IP栈并且自动地设置成支持他们。当前,IP栈很可能仅仅是指IPv4,但是IPv6用户也不用担心,因为Zebra也会发现并且支持它。
& N7 l; z) { d" `. u3 G, g1 {7 y6 x/ k3 Z
程序安装之后,还可能必须在/etc/services中增加一些命令行。Zebra的守护程序在他们自己的虚拟终端连接(VTY)下运行,所以你的系统必须知道这些虚拟终端连接。这里是你应该增加的一些连接∶
0 y4 q- M3 E' @; l# P# y
. e" B! T" S7 e: c3 A4 r
: i, z& z% n; d: t9 g
- S9 O7 s# ]0 Y" b6 P( c
+ U1 C( R6 j: K% i5 r9 W2 u I! `- C8 E, ]% t3 A: M- w
代码:
: k4 v3 j; j+ Z1 b- H# c8 P& V; n, S; l; I
. p7 `1 v2 t9 c4 G b- Y& p( ~
zebrasrv2600/tcp#zebraservice
' K8 ~9 ]2 b2 M3 J4 r2 a2 m6 Ezebra2601/tcp#zebravty
* e8 J2 b {+ Y7 L& `
ripd2602/tcp#RIPdvty
0 b6 M0 a" r, ~1 \
ripngd2603/tcp#RIPngdvty
. { M$ b+ ?: u7 i
ospfd2604/tcp#OSPFdvty
. V! O, i3 C0 B7 Q# V; ubgpd2605/tcp#BGPdvty
9 R" |: g+ x$ R% k! kospf6d2606/tcp#OSPF6dvty
! b6 C* ?7 o2 e2 M* o& c# p
* c( p; K1 ]+ r' E4 y4 g3 d2 W4 A4 l! @( t. b
7 U- @; h; [: k3 j8 _2 [配置Zebra
* j; q+ G- d! N$ R; N& z4 B* J* w- s& D
: n; I+ V. [( E+ o如果你已经熟悉CiscoIOS,那你就能在短时间内掌握Zebra,因为你会发现两者极为相似。Zebra的每个守护程序使用一个单独的VTY,这些VTY可以通过一个远程登录会话进行动态配置。所以,如果你需要设置OSPF,简单地远程登录到该Linux上2604
端口;为了修改内核的路由表或设置路由协议间的再分发,你可以远程登录到端口2601,该Zebra守护程序充当内核管理器,管理其他的守护程序和系统本身之间的通信。
2 R" J, u# n+ L3 @, V* h
p& d" l( p" J+ N; Z3 c$ `* G$ B现在介绍如何在一个服务器上创建和运行OSPF和BGP。Zebra的守护程序运用纯文本文件储存它们的配置。对于OSPF/BGP路由器,将用到三个文件∶zebra.conf、ospfd.conf和bgpd.conf。举例来说,zebra.conf文件可能会是这样:
9 W' T( e/ }( T1 `6 @) j- x( T
5 S# C" q6 ?3 n5 H9 Z$ p
5 V0 B. T0 h/ x2 q& D7 J$ u* i3 H" X3 B" P/ y) b6 \. O
$ A* s: x! ^* ?, @' x
# x5 f6 n5 L; }* h$ H$ Q: V% K
代码:
4 W& i9 P7 ?4 L- l: L& C% [
1 l5 \& S# E5 z$ s: n, u* K8 `# f; r8 v, h) a- w5 X, E" N/ g, f
!Zebraconfigurationsavedfromvty
# P$ Z) e( ]/ U% a: U; q5 i!2002/02/2801:46:12
* E4 f- w6 q+ l5 R8 O
!
% p7 L# Q! r" _hostnameLinuxRouter/*主机名为LinuxRouter*/
" b) F5 C- b. h k. \passwordzebra/*口令为zebra*/
, [2 j$ w$ [1 ]% J; uenablepasswordz3bRa/*进入特权模式时的口令为z3bRa*/
: ~, K% _! c/ g# x: D5 z' h" A$ M[color=#FFFFFF']
0 v1 d; k; z$ c7 U$ m* ]' d. q
9 S1 Q( G" N) I5 {& s
logfile/var/log/zebra/zebra.log/*日志文件的地址*/
2 I( L- v& ?' l& e: F1 w/ ^3 n: y, u, ~!
) [6 y& h# \0 Z6 S1 l0 l! j; Winterfaceeth0/*以太接口eth0*/
0 y7 K; B5 m; ~descriptionInterfacetoExternalNetwork/*对接口的
描述*/
6 x- n# F5 w0 t9 r: c' Kipaddress10.0.0.1/24/*该接口的IP地址*/
% |5 |, [' {6 d& d4 k1 w! R
!
0 G Q; E9 k+ u/ }. j- a5 n* Linterfaceeth1/*以太接口eth0*/
1 x R: e- f: o+ `; w7 G* Y( ?8 Q
descriptionInterfacetoInternalNetwork/*对接口的描述*/
% S4 U% |! q+ a. H" b6 Iipaddress192.168.66.1/24/*该接口的IP地址*/
- u: n/ B4 g6 W3 n
% B* i4 K2 F- d/ F% V& I/ P6 Z% ?
; h B! T3 F1 g( I; o
这里的感叹号充当注解标识或分隔符。尽管存在大量不同的网络接口类型(Ethernet、ISDN等等),但只要是Linux内
核能够辨认的网络接口类型,Zebra都可以使用。
: Y( z5 @- k j6 S- @' U
3 V) l& Y+ d! s0 W; w7 l# C5 g; u1 b
子网掩码都带有网络位的位数(例如/24),默认掩码则不然(比如255.255.255.0)。注意存在两个口令,一个用于用户模式而另一个用于特权模式。这不仅有利于向非管理员提供访问权限,而且对于创建路由服务器或者路由探测镜也是非常重要的。所有BGP管理员都知道,这些探测镜是调试路由问题的关键,因为他们能够使你就象从一个外部AS(AS代表自治系统)一样查看路由。BGP路由需要用到AS编号,AS编号是一些由ARIN(
美国互联网络号码注册机构)控制的注册号码。
) `, Q3 z8 s+ D, L; L
8 w" w5 T. B6 i$ Z' J+ S
下一步将启动一些必要的程序。用以下命令完成∶
$ G; h+ W, s* J$ m) T: g6 b. h* G( t/ [$ r. I% U- Z
; _0 N9 {% y6 T8 r/ Z
; f* s) _ Z% ?0 w8 E
; P9 E7 k! y) ?2 q; g T% l& n! n2 X
代码:
8 N$ ]" ^9 J, h" I. d- V, g
# A( a% N8 r5 F7 Q" O: I7 l+ O3 Y. F! K7 j4 D5 |
/usr/sbin/zebra-dk
" t8 [& k* @# t
/usr/sbin/ospfd-d
, C& n- i' \2 c. i n0 u. k. h9 _/usr/sbin/bgpd-d
# T" i; f' {* m: `" c8 Y6 J: |
! E( W9 e8 }+ \4 d8 K9 H
! Q* R" o+ K! `/ W N& K# F6 Y第一个命令,启动zebra,该守护程序实际上用来更新内核的路由表。-dk告诉该程序作为一个守护程序运行(d),它的大部分时间在后台运行。k是另外的一个选项,告诉Zebra维护所有已配置的路由。它用来保证在你
测试Zebra的时候不会意外地删除路由表。一般情况下,设置路由和接口,需要将ifconfig和route这两个命令配合使用。而Zebra完全可以替代这种路由管理方式,使用起来更为简洁。
/ [( M2 [9 E1 w6 m0 o
2 K$ @6 F C9 y0 R+ N( ~$ u! m
设置OSPF
# b8 A9 ?' U* s
7 a* ?; I, v* @6 f3 y f e2 g
至此,基本的服务已经具备,现在让我们Telnet到本地机器的2604端口,开始配置OSPF。为进入特权模式,键入enable(正如在CiscoIOS中一样),然后键入特权模式口令。接下来,用configurationterminal命令切换到配置模式。值得一提的是Zebra也能接受命令缩写形式,这与Cisco极为相似,如configurationterminal可以简写为configt,这大大缩短了输入时间,使用起来更为方便。另外,如果输入list和?,它将显示一个当前可用命令的清单,并附有一些简略解释。除此之外,还可以键入tab用于命令的自动完成。这就是说,如果你想键入命令clock,只要键入前两个字母cl然后按tab键,机器就会自动"补全"这条命令--前提是你键入的字符足以唯一地确定这条命令。这是一个很好的功能,尤其是当你
习惯于这种用法时。
) S1 D- D/ X7 o+ p& A- E
" J3 i9 ^, i6 e! H) T3 X
接下来,我们还需要告诉守护程序将通过OSPF
广播哪些网络以及相关的域(area)。OSPF的可伸缩性允许它支持多个域。键入routerospf开始配置OSPF,然后键入network192.168.66.0/24area0。这告诉路由器,我们将使用OSPF广播一个子网掩码为255.255.255.0的192.168.66.0网络。
9 n O& F0 |( Y& \; |4 g
4 D+ B0 E. p: I在本例中,我们让eth0接口变成一个被动(passive)接口,以便使它不能发送路由更新。这对于实验是非常重要的,因为在那个方向上的其他的路由器可能监听到发送的路由更新,将接口变成一个被动(passive)接口,从而有效的避免扰乱网络的正常运行。为此,键入命令passive-interfaceeth0。如果打算将此路由器作为工作路由器使用时,就没有这个必要了。一旦你完成修改,用end命令从配置模式中退出,然后用writefile命令保存。这里是一个快照:
: E" Z% Q# y' `0 C7 l8 u1 [0 s
3 E7 ?' M* d" { z* n
3 g& J4 J3 ^- L# c- e, a- m3 _
6 n( K S9 `3 H) c& ]! t3 U8 A3 D
: q @: E; C9 j' Z/ I
! a; N7 |3 g* e7 h- L代码:- x- l. n/ |( w& x, \
/ i. t; n( j' w- \$ [4 m( i
1 ]4 A; n" a4 H! f& \labrat:"#telnet02604/*Telnet到本地机器的2604端口*/
& u3 Q% i1 u F5 Y- k' y% N: f
Trying0.0.0.0...
$ \ g8 ?5 c5 b$ b4 q+ c0 J Z1 ^Connectedto0.
6 K, y) I# ^4 `+ Y! s
Escapecharacteris'^]'./*用'^]'退出该会话*/
* f: Q# e, ]& C+ T* o2 D& r4 f9 [
: ^4 r7 m; {/ \" IHello,thisiszebra(version0.84b)
$ [' T- p# t9 [
Copyright1996-2000KunihiroIshiguro
) y2 T/ x3 d& z; b) k" q' ]- R
! k; {( q4 m/ m; K8 aUserAccessVerification
) Y1 e" P. ^+ ]6 X5 g" I& T( o j* k$ K& ? q- x/ B( j' g
Password:/*在此键入口令,如zebra*/
) e1 H) t2 [ j3 X, O: {8 U% ~
ospfd%26gt;enable/*进入特权模式*/
. v/ K' w& n7 S8 S3 Z) ~$ i) [/ I, `: {
Password:/*输入特权模式口令,如z3bRa*/
! q# M- J5 Y" C- E; b' \; wospfd#configureterminal/*从终端配置路由器*/
q! d: b. A% g& f; V
ospfd(config)#routerospf/*配置OSPF*/
7 X5 i' m( n6 I* r
ospfd(config-router)#network192.168.66.0/24area0/*通过OSPF广播网络network192.168.66.0,/24指出子网掩码为24位,area0指出该网络所在的域*/
t5 Z3 ~& f1 ]! }) L L u- ~ospfd(config-router)#passive-interfaceeth0/*将eth0接口设置成一个被动(passive)接口*/
7 J3 q$ A" x% i* |. G7 Y" t
ospfd(config-router)#end/*退出配置模式*/
M! k" C g5 @1 y; A1 b
ospfd#writefile/*保存修改*/
* w0 G, {/ E& a# NConfigurationsavedto/etc/zebra/ospfd.conf
) U+ G8 T# P3 P9 x/ t
! A% `/ B- K- R: b S6 w8 g" x) B
8 J% e. a' v) l- q: {0 G. n5 w% g4 O+ M I
请记住,为了让OSPF或BGP在某接口上工作,那么该接口必须处于"运行"状态。为手工运行一个接口,登录到端口2601并且在该接口上执行noshut命令。
0 L" D6 w. z: S& x
0 `8 B5 z3 U& f" J! \! |5 d建立BGP
2 L3 w% _0 z- A, M+ {' V% c
, I% b0 |# Y4 n$ hBGP与OSPF的配置大致相同。开始,打开一个远程登录会话到端口2605。之后执行configureterminal,输入routerbgp%26lt;AS#_%26gt;进入BGP配置模式。如前所述,BGP使用AS编号建立邻机关系并路由通信流。在我们的试验中,我们将使用一个范围在64512到65534之间的私有AS号码(换句话说,该号码旨在机构内部有效,而在因特网上无效)。用network命令设置由BGP广播的那些网络,如network192.168.66.0/24.。与OSPF不同的是,BGP邻机必须静态指定。如同下述∶neighbor%26lt;neighborIP%26gt;remote-as%26lt;remoteAS#%26gt;。这里是一个范例:
" C/ d# {4 M7 x" @* h: _ a, a/ g0 C# J- P& h- G% n" x
1 [ _8 {! X3 A9 \% B8 i% J
% P, M q+ [7 y& e( x0 P- u3 Q
; R7 [9 U& c Z; O" b
0 X5 B8 x& F' v% ~3 T9 K代码:
3 p1 a" F4 Y" Q9 `! h7 D. ]. b3 t& V% N# b G% |8 X8 ]& V6 O7 g/ i& g2 I
& b( F( b* P# |5 a, |) |
labrat:"#telnet02605
4 ]* l1 ]1 l5 c( f
Trying0.0.0.0...
4 I! [( L, _% ~$ T0 e( l: j; b& n
Connectedto0.
4 t4 j2 w$ S, l
Escapecharacteris'^]'.
) o. y9 b) o$ B8 `) ]
0 ?+ Q8 a2 k! p0 r9 N( b2 qHello,thisiszebra(version0.84b)
% y4 v. H6 v0 U/ z! Z w
Copyright1996-2000KunihiroIshiguro
. j# l' v5 z9 G+ {: D* d y. I
; n2 b7 S$ o% Y% o4 W" rUserAccessVerification
7 L- G7 \2 E1 Y$ U# I
' R$ [# R1 Q5 \Password:
& @6 d9 n+ z9 r) t0 s' p
bgpd%26gt;enable
2 q% X1 Q: S/ k0 c9 k& ~8 |% H
Password:
' a8 k. |9 f8 N* }$ a( Kbgpd#configureterminal
6 l* Y. D' g: ]% _
[color=#FFFFFF']
; u4 @! e, a8 Q/ [8 O3 F3 |
" e9 _! T2 d a1 d( R* p1 r) }bgpd(config)#routerbgp65530/*配置BGP,65530是自治系统编号。也就是将该系统配置成自治系统65530上的外部网关*/
- U' a! \$ u f6 x6 j
bgpd(config-router)#network192.168.66.0/24/*由BGP广播的网络*/
& x4 p4 ~% d, r! V+ xbgpd(config-router)#neighbor10.0.0.5remote-as65531/*静态指定自治系统65531上IP地址为10.0.0.5的路由器为本机的邻机*/
7 P$ M" @2 [8 Z3 G/ N9 vbgpd(config-router)#end
: M+ p" G a# I' q# C$ Z( e' m9 h( \
bgpd#writefile
5 P% p3 E9 Q, h+ M# ]Configurationsavedto/etc/zebra/bgpd.conf
$ V9 f8 ^3 ?7 q+ _& }( e2 }
0 d( p: }% B" w% G* ~7 ?! R
k: V4 V% c1 Z7 h( Q2 Z' {# l对于OSPF和BGP,有大量选项可用,限于篇幅不能在此一一介绍。对于每个协议,我建议在实际使用之前,不妨先研究一番。为此,可以参考GNUZebra文档,它会给你提供许多帮助。
5 W: K- D& W; I$ r1 Q5 V1 z) H% {5 i# [* |8 C2 g. x
结束语
, o% y- m- H }3 d' Z: v1 j4 ~0 Z6 T# g8 a4 X- O* }& \! F4 q7 `
在网络中,路由通信流的方法有若干种。就路由器而论,虽然有用各种
硬件可用,但是费用较高--人们自然就会想到运行一个用Linux系统构筑的功能丰富的路由器作为代替。Zebra路由守护程序已经使这一切变为现实。因为支持IPv4、IPv6和其它各式各样的协议,所以Zebra能够满足我们所有的路由
需求。它还有一个好处就是,因为CiscoIOS和Zabra极为相似,如果你以前在CiscoIOS
环境中工作,可以轻松的过渡到Zebra系统;同时,使用Zebra也能让你积累起丰富的类似于使用CiscoIOS路由器的经验和
知识。
2 V" B3 s- T* V2 _" ~' U6 Q$ J" F
( O5 T3 J6 {0 {+ ]+ s7 k+ U: `作者简介:
2 ~. q; x6 Y0 X& c8 b
* ?& ^- |9 {* m) f% G0 T1 L/ [: P. ~韩波,自由撰稿人,有近十年的C语言
编程经验,主要感兴趣的领域为TCP/IP协议以及Linux内核。个人认为自由撰稿人的价值在于:在不影响问题实质的前提下,用一种通俗的,易于理解的方式来阐述自己的见解。您可以通过Email:hbzz
x2001@
yahoo.com.cn与他取得联系。
, }9 k# P8 g1 n4 @" ^# z3 J# {, J
- D- k. [: C2 s- o' E转自:动态网制作
指南www.knowsky.com