關於部落格
最會的事 就是這個不會和那個不會此網誌以 轉貼 文章為主
  • 225072

    累積人氣

  • 13

    今日人氣

    2

    追蹤人氣

兩條 ADSL 上自動切換路由

最後更新日:2005/12/28
http://freebsd.ntut.idv.tw/


FreeBSD + PF + Shell Scritp + Load Sharing + Redundant 

Description :

        上星期做了在 兩條 ADSL 上自動切換路由 的測試後
有個朋友就跟我說光兩條線路做 Redundant 是不是有點浪費?我想想也對,於是我想到了FreeBSD 中的 PF 有個 round-robin 的功能,它可做 Triffic Outgoing 的 Load Balancing 流量平均的分配,因此再把這功能的應用加上,這下子不但不會斷線還可以於平常就同時使用兩條 ADSL,真的太棒了 ^^

        這次的 shell script  有些許的改變,我還是使用 ping 的方式來判斷是否斷線,但是所 ping 的標地物 IP 改變了不再是 ping 固網的 DNS而是改 ping 固網內部的 ADSL 之 ATM 設備的虛擬 IP 為判斷標準,這樣的用意是讓我們在切換路由到另一家固網時才能精準判斷是否 100% loss。

        以下我只把使用過的設定檔 pf.conf、pf2.conf 及 loadsharing.sh 這個 shell script  檔貼出來,至於 Firewall + NAT 的安裝過程就不贅述請參考之前的文章:兩條 ADSL 上自動切換路由  

Environment :

            硬體:i386 PC Intel P3 500
            記憶體網卡:
512M RAM 
            作業系統:
FreeBSD 6.0 Release
         網路卡三片:xl0 vr0 兩片對外 de0 一片對內

Drawing :

   

   Hinet ADSL ATM 內部的虛擬 IP:10.88.88.56          ext_gw1:210.xx.xx.254       xl0:210.xx.xx.8      de0:10.77.77.254
   TFN  ADSL  ATM 內部的
虛擬 IP10.36.128.10        ext_gw2:61.xx.xx.254         vr0:61.xx.xx.6


Setp 1.

#vi /usr/local/sbin/loadsharing.sh      #   開始編寫 5 秒鐘於背景跑一次的 shell script

#!/bin/sh

H_ATM_IP="10.88.88.50"
H_GW1_IP="210.xx.xx.254"
H_EXT_IP="210.xx.xx.8"
T_ATM_IP="10.36.128.10"
T_GW2_IP="61.xx.xx.254"
T_EXT_IP="61.xx.xx.6"

active="P"

while [ 1 ]; do
STATUS1=`ping -c 1 $H_ATM_IP |grep loss |awk '{ print $7; }'`
STATUS2=`ping -c 1 $T_ATM_IP |grep loss |awk '{ print $7; }'`

if [ "$STATUS1" = "100%" ]; then
   if [ "$STATUS2" = "100%" ]; then  # ALL line down
      if [ "$active" = "P" ]; then
         echo -e "n
         ALL ADSL DOWN!n
         Date: $(date)n
         Host: $(hostname)n
         " | /usr/bin/mail -s "$(date) ALL ADSL DOWN!" root
         active="S"
       else
         echo -e "ALL ADSL DOWN!"
       fi
   else  # Hinet down, TFN up
       if [ "$active" = "P" ]; then
          echo -e "n
          ADSL $H_ATM_IP DOWN!n
          Date: $(date)n
          Host: $(hostname)n
          " | /usr/bin/mail -s "$(date) ADSL Hinet DOWN!" root
          route delete -net 0.0.0.0
          route add -net 0.0.0.0 -gateway $T_GW2_IP
          pfctl -f /etc/pf2.conf
          active="S"
        else
          echo -e "Hinet ADSL DOWN!"
       fi
   fi
else
    if [ "$STATUS2" = "100%" ]; then   # Hinet up, TFN down
       if [ "$active" = "P" ]; then
          echo -e "n
          ADSL $T_ATM_IP DOWN!n
          Date: $(date)n
          Host: $(hostname)n
          " | /usr/bin/mail -s "$(date) ADSL TFN DOWN!" root
          route delete -net 0.0.0.0
          route add -net 0.0.0.0 -gateway $H_GW1_IP
          pfctl -f /etc/pf2.conf
          active="S"
        else
          echo -e "TFN ADSL DOWN!"
        fi
    else   # All line up
        if [ "$active" = "S" ]; then
           echo -e "n
           ALL ADSL UP!n
           Date: $(date)n
           Host: $(hostname)n
           " | /usr/bin/mail -s "$(date) ALL ADSL UP!" root
           pfctl -f /etc/pf.conf
           active="P"
        else
          echo -e "ALL ADSL UP!"
        fi
     fi
fi
sleep 5
done

#chmod 755 /usr/local/sbin/loadsharing.sh      #   改變權限更改為可執行


Setp 2.

#vi /etc/pf.conf      
#  PF 設定檔,讓兩片對外的網卡流量負載平衡

lan_net="10.77.77.0/24"
ext_if1="xl0"
ext_if2="vr0"
int_if="de0"
ext_gw1="210.xx.xx.254"
ext_gw2="61.xx.xx.254"
tcp_services= "{ 22, 113 }"
#
#  nat outgoing connections on each internet interface
nat on $ext_if1 from $lan_net to any -> ($ext_if1)
nat on $ext_if2 from $lan_net to any -> ($ext_if2)
#  default deny
block in  from any to any
block out from any to any

#  pass all outgoing packets on internal interface
pass out on $int_if from any to $lan_net
#  pass in quick any packets destined for the gateway itself
pass in quick on $int_if from $lan_net to $int_if
#  load balance outgoing tcp traffic from internal network.
pass in on $int_if route-to
    { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin
    proto tcp from $lan_net to any flags S/SA modulate state
#  load balance outgoing udp and icmp traffic from internal network
pass in on $int_if route-to
    { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin
    proto { udp, icmp } from $lan_net to any keep state

#  general "pass out" rules for external interfaces
pass out on $ext_if1 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if1 proto { udp, icmp } from any to any keep state
pass out on $ext_if2 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if2 proto { udp, icmp } from any to any keep state

#  route packets from any IPs on $ext_if1 to $ext_gw1 and the same for
#  $ext_if2 and $ext_gw2
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 to any
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 to any
#
pass in on $ext_if1 inet proto tcp from any to ($ext_if1)
   port $tcp_services flags S/SA keep state
pass in on $ext_if2 inet proto tcp from any to ($ext_if2)
   port $tcp_services flags S/SA keep state

#vi /etc/pf2.conf       #  PF 的一般設定,這邊是做為有斷線時所切換採用的 rule

ext_if1="xl0"
ext_if2="vr0"
int_if="de0"
#
nat on $ext_if1 from $int_if:network to any -> ($ext_if1)
nat on $ext_if2 from $int_if:network to any -> ($ext_if2)
rdr on $int_if proto tcp from any to any port ftp -> 127.0.0.1 port 8021

#
pass in all
pass out all



Setp 3.


#sh -x /usr/local/sbin/loadsharing.sh       #   可測試 debug 程式
#sh /usr/local/sbin/loadsharing.sh &       #   讓程式在背景跑

#vi /usr/local/etc/rc.d/boot_loadsharing.sh        #  簡易的開機自動啟動讓程式跑在背景

sh /usr/local/sbin/loadsharing.sh &

相簿設定
標籤設定
相簿狀態