常見問題 登入
搜尋 個人資料
會員列表 會員群組
登入檢查您的私人訊息
會員註冊
Linux 上多條對外連線(Multi-Path)實作
發表新主題   回覆主題
UnixCafe 首頁 » Linux BBS » Linux 上多條對外連線(Multi-Path)實作
上一篇主題 :: 下一篇主題  
發表人 內容
juan
Site Admin


註冊時間: 2004-03-31
文章: 54
來自: Taiwan

 發表 發表於: 星期四 四月 15, 2004 10:57 am    文章主題: Linux 上多條對外連線(Multi-Path)實作
引言回覆

原文出處: http://www.study-area.net/tips/multipath.htm

Linux 上多條對外連線(Multi-Path)實作

--------------------------------------------------------------------------------
作者﹕網中人 <netman@study-area.org>



version 0.02
date 2004-03-31


一、前言

由於 ADSL 及 Cable Modem 的普及,越來越多企業或個人所擁有的對外連線早已超過一條了,
不管是固接還是撥接,相信不少人都在思考如何用最有效的方式將多條連線作整合,
將所有連線的使用發揮至最大極限及最佳的使用率。
除了起到負載的分攤之外,還能達到斷線備援目的,以提供更靈活的連線整合方案。

本文將以實作的方式試圖在 Linux 上做到上述要求。


二、環境

我先說明一下我的測試環境:

2.1 系統方面:
我目前測試的系統是 RedHat 9.0 Linux ,採用"伺服器"類型安裝,並沒提供 X 界面。
透過 APT 更新至最新修補,並沒安裝 distro 之外的套件。
事實上,只要實作所需的套件滿足的話,並不需要安裝任何伺服器套件。
甚至,核心版本也不需作任何修改,只是某些連線特徵會有些差異(後文[7.1]再詳述)。

2.2 網路方面:
原本的 seednet adsl 是五個 IP 撥接的, 除了之前透過 ip share 來使用外,我再起了另外一個 ppp0 界面。
此外另外再牽了一條 hinet 固一 adsl 。
如此環境,基本上能夠分別測試到如下這幾種連線方式:
* 固接(固定 IP)
* 撥接(非固定 IP)
* ip share(非固定 IP)
見圖:


/\__/\__/\
,--| internet |--.
/ \/--\/--\/ \
| |
| |
+--[seednet ADSL] [hinet ADSL]
| (非固定) (固一)
| | 220.130.96.254
| [ ip share ] |
| 192.168.100.1 |
| | |
| 192.168.100.2 220.130.96.21
| +----------------------------------+
+---| (eth1) (eth0) |
ppp0| kernel 2.4.23 |
+----------------------------------+
(my linux box RH9.0)

2.3 測試方式
雖然,撥接adsl 都是同一設備,或許還不十分理想,目前也只能如此了...
我採用的是拔線的方式來測斷線的,暫還沒想到其他方式,或許大家可以幫忙想想的...
我的測試基本上是用 ping 來做:
* 若是 ppp 或不指定測試目標,我會用 next hop 來測。
* 否則,我會用 traceroute 找出 ISP 端機房的 router ip ,
而不用 next hop ,是因為怕不準,比方說斷線是外部線路之類的。

若大家有更好提議,也歡迎提供....


三、設計目標

實作方案基本上要做到如下這些要求:

3.1 外向負載分流
所有連線在正常情況下,將共同分攤由內對外產生的連線流量。
對於固定連線,可指定權重(weight),否則使用相同權重( weight 1)。

3.2 斷線偵測
若有連線斷掉,需自動從路由中移除。
當連線恢復時,則自動增加路由。

3.3 內向負載分流(額外需求)
外部連線進來,儘可能的將流量分攤在每一條連線上。


四、設計構思

4.1 出向負載分流
利用 Linux iproute 程式,將每一條連線的 gateway 及其權重增加至路由表的 default route 中。
其中的固接 adsl 及 ip share 連線,需靜態指定其 gateway 位址及權重。
其於撥接或非固接連線,則用 iproute 程式抓出當時的 gateway ,權重分配為 1 。

4.2 斷線偵測
不管是固接還是非固接連線,用手工方式(如 traceroute)抓出 ISP 端的機房 router 位址,
並確定用 ping 可以獲得回應。
然後用靜態路由指定通向 router 的 nexthop gateway ,定期使用 ping 來偵察連線。
每次偵測後都重跑 iproute 程式,並重新設定路由表。
若 ping 不成功,則抓出連線界面,且在重設路由表時忽略改界面連線。

4.3 進向負載分流(額外需求)
使用動態 dns(ddns) 將為每一界面位址分配一個 A 記錄,以達到輪詢回應結果,
從而讓不同的外部連線請求輪流使用每一條連線進入。

本實作方案中,ddns server 建議部署於外部的穩定連線的主機上。
關於動態 dns 的 server 設定,不含在本次實作方案之內。可請參考:
http://www.study-area.org/tips/ddns.htm

設計難點在於 ipshare :
其中 ipshare 部份需另行設定 nat 轉線。
否則需從清單中移除。

若 nat 設定正確,接下來的難點是獲得 ipshare 的 IP (因為也是非固接的),
這需要在外部的 web server 另行開發 php 程式來獲取(可置於 ddns server)。
關於這部份設計,請參考:
http://phorum.study-area.org/viewtopic.php?p=108638
或使用如下代碼:
----------------------- cut here ----------------------
<?php

//Get the real client IP ("bullet-proof"???)

function GetProxyIP()
{
if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
$ip = getenv("REMOTE_ADDR");
else
$ip = "unknown";
return($ip);
}/*-------GetIP()-------*/


function GetClientIP()
{
if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
$ip = getenv("HTTP_CLIENT_IP");
else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
$ip = getenv("HTTP_X_FORWARDED_FOR");
else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
$ip = getenv("REMOTE_ADDR");
else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
$ip = $_SERVER['REMOTE_ADDR'];
else
$ip = "unknown";
return($ip);
}

printf("proxy IP: ");
print_r(GetProxyIP());
printf("<br>\n");
printf("client IP: ");
print_r(GetClientIP());

?>
----------------------- cut here ----------------------


五、實作指令

5.1 獲取當前各界面之 ip :
# ip address show
1: lo: <LOOPBACK,UP> mtu 16436 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:02:44:84:26:4f brd ff:ff:ff:ff:ff:ff
inet 220.130.96.21/24 brd 220.130.96.255 scope global eth0
3: eth1: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:20:ed:36:f9:74 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.2/24 brd 192.168.100.255 scope global eth1
4: eth2: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:02:b3:4b:69:49 brd ff:ff:ff:ff:ff:ff
inet 10.1.2.3/24 brd 10.1.2.255 scope global eth2
15: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1492 qdisc pfifo_fast qlen 3
link/ppp
inet 210.64.33.27 peer 210.64.33.1/32 scope global ppp0

5.2 設定 ip rule :
# ip rule add pref 10 from 220.130.96.21 table 10
# ip rule add pref 20 from 192.168.100.2 table 20
# ip rule add pref 30 from 210.64.33.27 table 30

5.3 設定 ip route 各 table :
# ip route replace default via 220.130.96.254 dev eth0 table 10
# ip route replace default via 192.168.100.1 dev eth1 table 20
# ip route replace default via 210.64.33.1 dev ppp0 table 30

5.4 設定 ip route main table:
# ip route replace default \
> nexthop via 220.130.96.254 dev eth0 weight 4 \
> nexthop via 192.168.100.1 dev eth1 weight 1 \
> nexthop via 210.64.33.1 dev ppp0 weight 1

5.5 檢視 main table 規則:
# ip route show
210.64.33.1 dev ppp0 proto kernel scope link src 210.64.33.27
192.168.100.0/24 dev eth1 scope link
220.130.96.0/24 dev eth0 scope link
10.1.2.0/24 dev eth2 scope link
169.254.0.0/16 dev eth2 scope link
127.0.0.0/8 dev lo scope link
default
nexthop via 220.130.96.254 dev eth0 weight 4
nexthop via 192.168.100.1 dev eth1 weight 1
nexthop via 210.64.33.1 dev ppp0 weight 1

5.6 刷新 route cache:
# ip route flush cache

5.7 測試及確認連線生效:
基本上,若在輸入上述命令中沒遇到 error ,那設定就已完成。
接下來可起用多個對外連線(或用 ping),
然後使用 tcpdump -i any 來查看封包是否能分攤在每一條連線上。


六、撰寫 script :
若前述設定經測試成功後,接下來就是撰寫 script 以讓工作自動進行。

6.1 run_ip.sh

* 說明:
此 script 用來抓出系統全部界面及 nexthop gateway ,
並完成路由規則及路由表設定。

* 代碼:
----------------------- cut here ----------------------
#!/bin/bash
#
# script name: run_ip.sh
# purpose: changning route table.
# author: netman(netman@study-area.org)
# license: GPL(http://www.gnu.org/licenses/gpl.html)
#
# date: 2004-03-24
# version: v0.02
#
# caveate:
# 1) tested on redhat 9.0 linux only
# 2) iproute program is required
#
#------------------------------------------------------------
# change log:
# 1) 2004-03-23 v0.01
# * first beta release
# 2) 2004-03-24 v0.02
# * BUGFIXED:
# Add IPIF and GWIP checking before change route
#
#------------------------------------------------------------


IPTABLES=/sbin/iptables
LSMOD=/sbin/lsmod
GREP=/bin/grep
AWK=/bin/awk
SED=/bin/sed
CUT=/bin/cut
WC=/usr/bin/wc
SEQ=/usr/bin/seq
ECHO=/bin/echo
IP=/sbin/ip
LS=/bin/ls

#-- define fixed interface & gateway --#
fixed_if="eth0 eth1"
#-- format: if:gw:weight --#
fixed_gw="eth0:220.130.96.254:4 eth1:192.168.100.1:1"
#-- define internal interface, or comment out for none --#
int_if="eth2"

#-- route command prefix --#
DEFGW='/sbin/ip route replace default equalize'

#-- define dead interface --#
while getopts "d:" opt; do
case $opt in
d) dead_dev=$OPTARG ;;
esac
done

#-- determine active interfaces --#
interfaces=$($IP address | $GREP -E 'ppp|eth' | \
$AWK -F': ' '/^[0-9][0-9]*:/{print $2}')
if [ -n "$dead_dev" ]; then
interfaces=$(echo "$interfaces" | grep -Ev "${dead_dev// /|}")
fi

#-- define table_id --#
init_num=10
offset=`$ECHO -e "${interfaces// /\n}" | $WC -l`
last_num=$(($init_num + $((offset * 10)) ))
tb_num=`$SEQ $init_num 10 $last_num | xargs echo`

#-- delete old rule table --#
$IP rule list | $GREP -E `$ECHO ${tb_num// /|} | $SED 's/[^|][^|]*/^&:/g'` \
| while read line; do
TABID=`echo $line | awk -F: '{print $1}'`
OLDIP=`echo $line | awk '{print $3}'`
PREID=`echo $line | awk '{print $5}'`
$IP rule del pref $PREID from $OLDIP table $TABID
done

#-- FUNCTION: determine gw --#
dgw() {
#-- for fixed if --#
if $ECHO "$fixed_if" | $GREP -wq $1 ; then
GWIP=`$ECHO -e "${fixed_gw// /\n}" | $GREP "^$1:" | \
$CUT -d: -f2`
WEIGHT=`$ECHO -e "${fixed_gw// /\n}" | $GREP "^$1:" | \
$CUT -d: -f3`
#-- for ppp if --#
elif $ECHO $1 | $GREP -q ppp ; then
GWIP="`$IP address show dev $i | $AWK '/inet/{print $4}' | \
$CUT -d'/' -f1`"
#-- for unkown, point back to itself --#
else
GWIP=$IFIP
fi
}

#-- config rule & routing --#
for i in $interfaces ; do
unset IFIP GWIP WEIGHT
IFIP="`$IP address show dev $i | $AWK '/inet/{print $2}' | \
$CUT -d'/' -f1`"
dgw $i
[ "$tb_num" ] && tb_id=${tb_num%% *}
[ "$IFIP" -a "$GWIP" ] || continue
# set rule
$IP rule add pref $tb_id from $IFIP table $tb_id
# set default gw
$IP route replace default via $GWIP dev $i table $tb_id
echo "$int_if" | grep -qw "$i" || {
DEFGW=$DEFGW" nexthop via $GWIP dev $i weight ${WEIGHT:=1}"
}
tb_num=${tb_num#* }
done


#-- apply routing --#
$DEFGW

#-- flush cache --#
$IP route flush cache

#-- show routing
$IP route list

#-- FINISH --#
exit 0
----------------------- cut here ----------------------

* 變數設定說明:
fixed_if=
固定界面名稱,可設定多個。
fixed_gw=
固定界面之閘道及權重,格式為 "界面名稱:閘道位址:權重"。
int_if=
內部界面名稱,可設定多個。改界面將不會用來設定 default route 。

* 參數說明:
-d "<interface...>"
指定失效界面,可設定多個。


6.2 chk_ip.sh

* 說明:
此 script 用來偵測連線是否正常,並定期執行 run_ip.sh 及 ddns.sh(可不選用)。
若抓出失效界面,再用 -d 參數傳給 run_ip.sh ,該界面將被忽略。

* 代碼:
----------------------- cut here ----------------------
#!/bin/bash
#
# script name: chk_ip.sh
# purpose: checking outbound link and change route and dns.
# author: netman(netman@study-area.org)
# license: GPL(http://www.gnu.org/licenses/gpl.html)
#
# date: 2004-03-24
# version: v0.02
#
# caveate:
# 1) tested on redhat 9.0 linux only
# 2) using PING for link detection
# 3) iproute program is required
# 4) scripts run_ip.sh & ddns.sh are required too
#
#------------------------------------------------------------
# change log:
# 1) 2004-03-23 v0.01
# * first beta release
# 2) 2004-03-24 v0.02
# * add script path detection
#
#------------------------------------------------------------

#-- set commands --#
SH=/bin/bash
IP=/sbin/ip
SED=/bin/sed
GREP=/bin/grep
AWK=/bin/awk
CUT=/bin/cut
PING=/bin/ping

# change working directory
cd ${0%/*}

INTERVAL=60 # check time interval in seconds
RUN_SCRIPT=./run_ip.sh # script to run ip route
DDNS_SCRIPT=./ddns/ddns.sh # script to run ddns update
for script in $RUN_SCRIPT $DDNS_SCRIPT; do
[ -f $script ] || {
echo "${0##*/}: Error: required script $script is missing."
}
done

#-- define fixed ping destination --#
#-- tips: doing a traceroute may help you find out the proper target.
#-- format: if:dest:gw --#
fixed_dest="eth0:168.95.38.194:220.130.96.254 eth1:139.175.169.254:192.168.100.1"

#-- determine gateways --#
get_gw () {
defaults=$($IP route show | $SED -n '/default/,$p' | $GREP via)
if_n_gw=$(echo -en "$defaults" | $AWK '{print $5":"$3}')
}

#-- configure static route --#
s_route () {
cmd=$1
for i in $fixed_dest; do
if=${i%%:*}
dest=$(echo -$i | $CUT -d: -f2)
gw=${i##*:}
$IP route $cmd $dest via $gw
done
unset i
}

#-- determine destinations --#
get_dest () {
[ -n "$_if" ] && all_pair=$(echo "$if_n_gw" | $GREP -Ev "${_if// /|}")
all_pair=$(echo $fixed_dest $all_pair)
a_dest=$(echo -en "${all_pair// /\n}" | $CUT -d: -f2)
}

#-- determine dead destinations --#
get_dev () {
for i in $a_dest; do
$PING -c1 -w2 $i &>/dev/null || {
echo -en "${all_pair// /\n}" | $GREP $i | $CUT -d: -f1
}
done
unset i
}

#-- main --#
main () {
get_gw # have gw
s_route replace # set static route
get_dest # have destination
d_dev=$(echo $(get_dev)) # have dead link
s_route del # remove static route
}

#-- run loop --#
while : ; do
main
$SH $RUN_SCRIPT -d "$d_dev"
[ -f "$DDNS_SCRIPT" ] && $SH $DDNS_SCRIPT
unset _if _dest _gw all_pair
sleep $INTERVAL
done
----------------------- cut here ----------------------

* 變數設定說明:
INTERVAL=
偵測動作之時間間隔,以秒數作單位。
RUN_SCRIPT=
執行路由設定 script 之路逕。執行時可使用 -d 選項排除不必要之界面。
DDNS_SCRIPT=
執行動態更新 script 之路逕。執行時可使用 -e 選項排除不必要之界面。
fixed_dest=
偵測固定界面連線用的 ping 目表位址。建議為 ISP 機房端 router ,可用 traceroute 抓取。
格式為 "界面名稱:目標位址:閘道位址"。

* 注意要點:
1) 若不想設定或暫無條件設定 ddns ,可將 DDNS_SCRIPT= 註解不用。
2) 必需定期檢查確認 fixed_dest= 之正確性,因為 ISP 端可能會更換位址。或另行使用固定目標。


6.3 ddns.sh (可不選用)

* 說明:
此 script 用來動態偵測連線位址,並動態更新 dns 位址記錄。

* 代碼:
----------------------- cut here ----------------------
#!/bin/bash
#
# script name: ddns.sh
# purpose: updating dns record
# author: netman(netman@study-area.org)
# license: GPL(http://www.gnu.org/licenses/gpl.html)
#
# date: 2004-03-24
# version: v0.03
#
# caveate:
# 1) tested on redhat 9.0 linux only.
# 2) iproute program is required.
# 3) a php webpage to show ip, and the lynx program are required.
# 4) ddns server and ddns key are required.
#
#------------------------------------------------------------
# change log:
# 1) 2004-03-23 v0.01
# * first beta release
# 2) 2004-03-23 v0.02
# * add EXCL_IF list for exception
# 3) 2004-03-23 v0.03
# * add -e option for appending EXCL_IF
#
#------------------------------------------------------------

# set commands
HOST=/usr/bin/host
GREP=/bin/grep
CAT=/bin/cat
IP=/sbin/ip
SED=/bin/sed
AWK=/bin/awk
LYNX=/usr/bin/lynx
TOUCH=/bin/touch
DIFF=/usr/bin/diff
NSUPDATE=/usr/bin/nsupdate
MV=/bin/mv

# set variables
if echo $0 | $GREP '^/' ; then
w_dir=${0%/*}
else
w_dir=$PWD/${0%/*}
fi
KEY_FILE=$w_dir/Ktestddns.+157+14615.key
UPDATE_DATA=$w_dir/nsupdate.data
UPDATE_OLD=$UPDATE_DATA.old
HOST_NAME=testddns.study-area.org
NS_SERVER=dns.study-area.org
IP_SERVER=dns.study-area.org
IP_SERVER_IP=$(echo $($HOST $IP_SERVER) | tail -n 1 | $AWK '{print $NF}')
IP_URL="http://$IP_SERVER/ip.php"
CLIENT_TYPE="client" # if no proxy or using ISP's proxy
#CLIENT_TYPE="proxy" # if use local proxy
MASQ_IF="eth1" # which masqueraded behine NAT
#EXCL_IF="eth1" # note: also use -e options to append list

# have exception
while getopts "e:" opt; do
case $opt in
e) EXCL_IF=$(echo $EXCL_IF $OPTARG) ;;
esac
done

# ensure key files
for file in $KEY_FILE ${KEY_FILE%key}private
do
if [ ! -r $file ]; then
echo "$(basename $0): ERROR: $file is not readable."
exit 1
fi
done

# ensure the server is connectable
$HOST $NS_SERVER $NS_SERVER | $GREP -q "^$NS_SERVER has address" || {
echo "$(basename $0): ERROR: could not contact nameserver $NS_SERVER."
exit 2
}

# prepare initial script
$CAT >| $UPDATE_DATA <<END
server $NS_SERVER
update delete $HOST_NAME A
END
test "$?" = "0" || {
echo "$(basename $0): ERROR: could not create $UPDATE_DATA."
exit 3
}

# get interfaces
ALL_IF=$($IP route show | $SED -n '/default/,$p' | $AWK '/nexthop/{print $5}')
[ "$EXCL_IF" ] && ALL_IF=$(echo "$ALL_IF" | $GREP -Ev "${EXCL_IF// /|}")

# get masqueraded ip
get_mip () {
for M_IF in $MASQ_IF; do
echo $ALL_IF | $GREP -qw "$M_IF" || continue
m_gw=$($IP route show | $SED -n '/default/,$p' |\
$AWK '/'$M_IF'/{print $3}')
$IP route replace $IP_SERVER_IP via $m_gw
sleep 2
M_IP=$($LYNX --dump $IP_URL | $GREP "$CLIENT_TYPE" |\
$GREP -Eo '([0-9]{1,3}\.){3}[0-9]+')
[ -z "$M_IP" ] && {
echo "${0##*/}: Error: can't determine IP for $M_IF."
exit 4
}
echo $M_IF:$M_IP
$IP route del $IP_SERVER_IP via $m_gw
unset m_gw M_IP
done
}

# get current ip
for IF in $ALL_IF; do
if echo "$MASQ_IF" | $GREP -wq "$IF"; then
NEW_IP=$(get_mip | $AWK -F: '/'$IF'/{print $2}')
else
NEW_IP=$($IP address show dev $IF | $AWK '/inet/{print $2}')
fi
NEW_IP=$(echo $NEW_IP | $GREP -Eo '([0-9]{1,3}\.){3}[0-9]+')
[ "$NEW_IP" ] && echo "update add $HOST_NAME 0 A $NEW_IP"
unset NEW_IP
done >> $UPDATE_DATA
echo "send" >> $UPDATE_DATA

# do a test then update
$TOUCH $UPDATE_OLD
if ! $DIFF $UPDATE_OLD $UPDATE_DATA; then
$NSUPDATE -k $KEY_FILE -v $UPDATE_DATA && {
$MV $UPDATE_DATA $UPDATE_OLD
}
fi

#-- end of script --#
----------------------- cut here ----------------------

* 變數設定說明:
KEY_FILE=
用以更新 dns 記錄的 key 。
UPDATE_DATA=
儲存 nsupdate 所需的命令稿。
UPDATE_OLD=
上一次 nsupdate 所需的命令稿。
script 會比對前一份命令稿內容,若相同,則不做 update ,否則才做。
HOST_NAME=
主機名稱。需於 ddns 所設定的記錄一致。
NS_SERVER=
ddns server 之主機名稱。
IP_SERVER=
偵測 IP 用的主機名稱。
IP_SERVER_IP=
偵測 IP 用的主機位址。
IP_URL=
偵測 IP 用的網頁 URL 。
CLIENT_TYPE=
主機連線類型。其值為 "client" 或 "proxy" 二者之一。
若主機沒有使用 proxy 或使用 ISP 提供的 proxy,請設為 "client"。
若主機使用 local LAN 的 proxy ,則請設為 "proxy"。
MASQ_IF=
連線將會經過 NAT 的界面,但其偽裝位址需作 ddns 更新。
(注意:NAT 必須要有相應的 port mapping 設定。)
EXCL_IF=
排除在 ddns 更新之外的界面。
通常是連線將會經過 NAT 的界面,但其偽裝位址不作 ddns 更新。

* 參數說明:
-e "<interface...>"
排除在 ddns 更新之外的界面,可設定多個。
若為多個界面,其值必須至於雙引號(" ")或單引號(' ')之中,如:
-e "eth0 eth1"
參數值將會擴充至 $ESCL_IF 變數裡面。

* 注意要點:
1) 關於動態 ddns 的 server 及 client 端設定,請另行參考:
http://www.study-area.org/tips/ddns.htm
2) 請定期檢測及確認 ddns server 能夠連線及正常運作。
3) 當前實作範例,是將 ddns.sh 與相關的 keys 置於 ddns 子目錄中。

6.4 軟件包
我將本實作所用到的 script 及其它相關檔案包裝為 tarball ,其內容如下:
multipath/
工作目錄
multipath/run_ip.sh
路由更新 script
multipath/chk_line.sh
連線檢測 script
multipath/ddns/
ddns 子目錄
multipath/ddns/ddns.sh
ddns 更新 script
multipath/ddns/Ktestddns.+157+14615.key
ddns key
multipath/ddns/Ktestddns.+157+14615.private
ddns private key
multipath/kernel-patch/
kernel-patch 子目錄
multipath/kernel-patch/2.4.25-mp01
kernel 2.4.25 config 檔
multipath/kernel-patch/patch-2.4.25-ja2.diff
kernel 2.4.25 修補檔
大家可以從如下位址下載整個軟件包:
http://www.study-area.org/linux/src/multipath.tgz


七、關於 kernel patch

7.1 關於 patch-2.4.25-ja2.diff
本實作方案不一定需要進行 kernel path ,經測試是可用的。
只是因為 routing cache 的關係,通往同一個 site 的 routing 可能在某一段時間內是不變的。
參考 http://www.lartc.org/howto/lartc.rpdb.multiple-links.html 最後一段有提到:
Note that balancing will not be perfect, as it is route based, and routes are cached.
This means that routes to often-used sites will always be over the same provider.

這對於某些需要作 session 記憶的連線來說(如連接 phpBB 討論版),是不錯的。
但倘若多條 session 在某一特定時間內均為同一目標位址,其流量並不會分攤到其它線路上。
如果要做到將不同的 session 分攤開來,而不論其目標位址是否相同,則須要下載 patch 修補。

我在 RedHat 9.0 上另行下載 kernel 2.4.25 源始碼及 patch-2.4.25-ja2.diff 這支 patch 。
大家可從前面 6.4 章節提供的 tarball 獲取這次實作所用的 config 及 patch 。
或至官方網站下載:
http://www.ssi.bg/~ja/patch-2.4.25-ja2.diff

7.2 關於 equailze
雖然前述 patch 能夠將不同的 session 分攤至不同連線,但這仍然是 by session 的分攤,
並非做到 by packet 層級的分攤,也就是所謂的"均衡負載"(equailze)。
要做到這點,似乎還要下載另一支 patch:
http://www.teatime.com.tw/~tommy/linux/equalize.patch
不過,遺憾的是,這部份我並沒有測試成功。
且後來也沒在 kernel 2.4.25 上於另一支 patch 混合使用。

關於 equailze 的探討及設定,大家可參考 study-area 的討論:
http://phorum.study-area.org/viewtopic.php?t=10085
若有人成功測試起來,歡迎回報分享。謝謝﹗


八、展望

當前實作並沒提及頻寬控管。若日後有時間,再來探討 QOS 及 cbq 相關的題目。
在這之前,大家不妨先參考:
http://peterkim.cgucccc.org/document/MPath.html


九、參考資料

http://phorum.study-area.org/viewtopic.php?t=10085
http://phorum.study-area.org/viewtopic.php?t=9057
http://www.teatime.com.tw/~tommy/doc/multipath.txt
http://www.study-area.org/tips/m_routing.htm
http://www.lartc.org/howto/lartc.rpdb.multiple-links.html
http://peterkim.cgucccc.org/document/MPath.html


------- 本文結束 ------

_________________
This is Juan (http://juan.idv.tw)
I'd like to be a teardrop,
To be born in your eye,
To live my life on your cheek,
And on your lips to die.
 回頂端 »
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站 雅虎訊息通 MSN Messenger ICQ 號碼
從之前的文章開始顯示:   
UnixCafe 首頁 » Linux BBS » Linux 上多條對外連線(Multi-Path)實作
發表新主題   回覆主題 所有的時間均為 台北時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
You cannot attach files in this forum
You cannot download files in this forum




Solaris phpBB theme/template by Jakob Persson
Copyright © Jakob Persson 2003



Powered by phpBB 2.0.11 © 2001, 2002 phpBB Group
正體中文語系由 phpbb-tw 維護製作