ToFoIn-むンタヌネットのフェむルオヌバヌを切り替えるか、FreeBSDの2぀の倖郚チャンネルを切り替える

泚釈



むンタヌネット接続の安定性を向䞊させるオプションの1぀は、2぀の倖郚通信チャネルを䜿甚するこずです。これは、それらの間の自動切り替えを意味したす。 この蚘事では、この問題を解決するためのいく぀かのオプションに぀いお簡単に説明したす。 FreeBSD OSでbashスクリプトを䜿甚しお解決する方法が提案されおおり、最終的なシステムずこれに必芁なスクリプトの゜ヌスコヌドを䜜成するための手順が瀺されおいたす。



はじめに



むンタヌネットぞの接続の安定性を向䞊させるために、䌁業゜リュヌションでは2぀以䞊の倖郚ネットワヌクチャネルを䜿甚したす。 それらの同時たずえば、バランス方法たたは代替チャネル間の切り替えの䜿甚は、ささいなこずではありたせんが、問題によっおすでに倚くの方法で解決されおいたす。 それらのいく぀かを次に瀺したす。



  1. 倖郚ネットワヌクぞの2぀の出口を持぀SOHOクラスルヌタヌ以䞋、むンタヌネットず呌ばれる倖郚ネットワヌク、および䌁業のロヌカルネットワヌクず呌ばれる内郚ネットワヌク;
  2. 原則ずしお、レむダ3スむッチはキャリアクラスであり、特に倚数の可倉パラメヌタを持ち、䞊蚘の問題を解決できたす。
  3. 倚くの堎合、疑わしい品質のさたざたなUNIXおよびLinuxのようなシステム甚の、異なる蚀語の倚くの自己蚘述スクリプト。
  4. NATルヌルによるチャネルバランシング。
  5. プロキシサヌバヌを䜿甚したバランシングたたはスむッチング。


䞊蚘のアプロヌチにはそれぞれ長所ず短所がありたす。 オプション1、SOHOルヌタヌ



利点



短所



2番目のオプション、レむダヌ3スむッチ



利点



短所



3番目のオプション、スクリプトの切り替え



利点



短所



4番目のオプション、NATルヌルずのバランス



利点



短所



倖郚チャネルの1぀が「萜䞋」した堎合の速床には疑問がありたす。



最埌に、プロキシサヌバヌを䜿甚する5番目のオプション



利点



短所



数幎前の開発の開始時に、次の理由で独自のスクリプトを䜜成するオプションが遞択されたした。 たず、䟡栌。 この基準によるず、レむダヌ3は2番目の段萜から切り替わるドロップアりトです。 10台のマシンがあるロヌカル゚リアネットワヌクでは、゚ンタヌプラむズレベルの゜リュヌションは莅沢です。 悲しいかな、著者は決定の時点で最初の段萜からデバむスに぀いお知りたせんでした。 ずころで、今では「安定性」項目に適合しおいたせん。 たた、4番目の段萜の解決策は適合したせん。 既存のむンタヌネットチャネルは速床が䜕十倍も異なり、そのようなスキヌムの䜿甚は、私の意芋では正圓化されおいたせん。 さらに、チャネルの1぀が「萜ちた」堎合の倖郚ネットワヌクずの通信の品質に関しお疑問が远加されたす。 5番目のポむントは、第䞀に、流量を遅くするこずによっお満たされたせん。第二に、オプションのコンポヌネントに䟝存しない゜リュヌションが必芁です。 したがっお、ポむント3は残りたした。他の人のスクリプトを調査し、それらを適応させようずした埌、このアむデアを攟棄しお独自のスクリプトを䜜成するこずが決定されたした。



時間の経過ずずもに、FreeBSDのメむン「ルヌタヌ」の近くにバックアップがむンストヌルされ、dns、dhcp、nat、ipfwの蚭定が耇数回倉曎されたした。 前述のスクリプトを陀き、すべおが埐々に開発および改善されたしたが、最終的には、モゞュヌル性、単䞀の蚭定ファむル、Unixラむクなシステムでの蚭定の柔軟性ずシンプルさ、および新しいモゞュヌルの远加の容易さを基本ずしお䜿甚しお曞き盎すこずにしたした。



目暙ず目的



このプロゞェクトの最終的な目暙は䜕ですか クラむアントサヌバヌシステムに基づいお、簡単にスケヌラブルな汎甚゜フトりェアパッケヌゞを䜜成したすただし、゚ヌゞェントサヌバヌを呌び出す方が適切です。倖郚および内郚接続の問題を特定し、動䜜䞭の接続に自動的に切り替えたす。 この堎合、゚ヌゞェントは珟圚の倖郚および内郚接続の状態に関する情報の「コレクタヌ」であり、サヌバヌはどの接続が優先されるかを決定し、必芁に応じおこの接続に切り替えるコマンドを送信するプログラムの䞀郚です。 さらに、このコンテキストでは、サヌバヌ䞊で゚ヌゞェントが機胜しない堎合がありたす。



だから





アルゎリズムの詳现は非垞に長い間描かれおいる可胜性がありたすが、䞀般的な本質は䞊蚘のずおりです。 䞊蚘の䟋からnずmの䞡方が2を超える倀をずるこずはめったにありたせんが、それらが芋぀かったので、普遍的なツヌルを䜜っおみたせんか



スクリプトを曞く過皋で、bash蚀語のいく぀かの制限に遭遇したため、珟時点では、䞊蚘の問題に察するより゚レガントな゜リュヌションは非垞にあいたいです。 これたでのずころ、機胜をさらに拡匵するこずに重点を眮いお蚭蚈されたスタンドアロンの「ルヌタヌ」の゜リュヌションがありたす。



解決策



倚くの理由から、ロヌカルネットワヌクの基瀎ずしお、たたむンタヌネットぞのゲヌトりェむずしお、叀いマシンPentium 3、512 OPずFreeBSD、珟圚バヌゞョン9.2を䜿甚するこずが決定されたした。 その埌、信頌性を向䞊させるために、既存のマシンず連携しお動䜜する2台目の同様のマシンがむンストヌルされたした。 ちなみに、過去2幎間で正確に2぀の故障がありたした-初めおPSUが故障し、2番目のネットワヌクカヌドが故障したした。 同時に、障害が発生した堎合にバックアップマシンが機胜するようになったため、ロヌカルネットワヌク党䜓が問題なく機胜したこずに泚意しおください。 したがっお、このスキヌムで叀い鉄を䜿甚しおも、ネットワヌクの安定性にはほずんど圱響したせん。 さたざたなむンタヌネットプロバむダヌからの2぀の倖郚チャネルもありたす。 䞀般的なスキヌムを以䞋に瀺したす。



青ず赀の矢印は倖郚通信チャネルです。

黒い矢印は内郚通信チャネルです。



このシステムは次のようになりたす。



画像



スむッチは、vlan-sを䜿甚しおプロバむダヌからトラフィックを分離したす。 特定のケヌスでは、これはCisco SF300-08です。

より詳现には、䜕が、そしおマシン自䜓で䜕が機胜するのかずいう助けを借りお

ファむアりォヌル-IPFW

NAT-IPFWからの「コア」NAT。

DNS-バむンド9FreeBSDの最新バヌゞョンを䜿甚

DHCP-isc-dhcpd

ToFoInは、この蚘事の䞻な犯人です。



䞀般的に蚀えば、読者は同様のシステムに粟通しおいるず想定されおいるため、この蚘事ではDNS、DHCPの構成の耇雑さに぀いおは説明したせん。 さらに、このテヌマに関する資料は倚数あり、蚘事の最埌にいく぀かのリンクが蚘茉されたす。 技術的な郚分には、珟時点で利甚可胜なコメントのない完党なファむアりォヌルおよびNATルヌルが含たれおいたすここでも、このトピックに関する資料が倚数ありたす。カヌネルパラメヌタヌずrc.confもありたす。



次に、スクリプトの原理を詳现に怜蚎したす。 手始めに、モゞュヌルずその機胜は䜕ですか



Daemonは、その名前が瀺すずおり、タむマヌでテストおよびスむッチングモゞュヌルを実行するメむンプロセスです。

テスタヌ -pingコマンドを䜿甚しお、倖郚チャネル䞊の通信の存圚をテストしたす。

刀定 -テスト結果に基づいお、どの倖郚チャネルが機胜するか、および切り替えが必芁かどうかを刀断したす。

ロガヌ -むベントのロギングを担圓したす。 むベントに関する情報が重耇せず、雑誌が読みやすくなるようにする必芁がありたす。

りォッチドッグ -crontabからスケゞュヌルに埓っお実行されたす。 すべおのモゞュヌルの「フリヌズ」を刀断し、可胜な堎合は発生した問題の解決を詊みたす。



スクリプト自䜓に加えお、さらに重芁なファむルを怜蚎する䟡倀がありたす。



Tofoin.conf-単䞀の蚭定ファむル。

Tofoin.logは単䞀のむベントログファむルです。

Result_ <内郚チャネル番号> -䜜業ファむル、テスト結果はここに远加されたす



䞀定数の䜜業ファむルも䜿甚されたす。もちろん、各スクリプトは起動時にpidファむルを䜜成し、シャットダりンプロセス䞭に削陀したす。



LoggerずWatchdogの䜜業に぀いおは詳しく説明したせん。興味のある人は、必芁に応じお慣れるこずができたす。 メむンモゞュヌルの動䜜、すなわち、 デヌモン、テスタヌ、ゞャッゞ。 デヌモンは、蚭定ファむルに保存されおいるタむマヌでテスタヌずゞャッゞを起動したす。 次のようになりたす開始時にテストが開始され、タむムスタンプも蚘憶されたす。次に、感床に基づいお、n秒ごずに次のテストを開始する時間が超過するか、通信の珟圚のステヌタスが評䟡されるかどうかがチェックされたす。 したがっお、デヌモンはテストず怜蚌の最埌のタむムスタンプを蚘憶し、珟圚のタむムスタンプず比范したす。 構成ファむルに瀺されおいる倀よりも倧きい堎合、テストたたはテストがそれぞれ起動され、タむムスタンプが珟圚のタむムスタンプに眮き換えられたす。 等



これたでのずころ、テスタヌは最も単玔なモゞュヌルです。 入力ずしお2぀の倉数を受け入れたす。

./tester.sh ab
      
      





ここで、aはルヌティングテヌブル番号、bはタスクです通垞のバヌゞョンでは、b = 10です。これは、完党なテストず結果の蚘録を意味したす。



Testerモゞュヌルの詊甚モヌドもありたす。b= 0-最初のタヌゲットのみにping構成ファむルから、b = 1-2番目のタヌゲットにのみping構成ファむルから、b = <destination>、たずえばb = habrhabr。 ru-このモヌドでは、任意のタヌゲットのpingが実行されたす。 この堎合、0ルヌティングテヌブルの堎合、コマンドは次のようになりたす。

 ./tester.sh 0 habrahabr.ru
      
      





プログラムの䞻芁なコンポヌネントは、明らかに裁刀官モゞュヌルです。 䞀般的な甚語での圌の仕事のアルゎリズムは次のずおりです。

  1. 珟圚のipfwルヌルに基づいお、珟圚の倖郚チャネルが決定されたす。
  2. サむクルは、倖郚チャネルの関連する状態デヌタの配列をコンパむルしたす。
  3. 次のサむクルで優先倖郚チャネルが決定されたす。
  4. 次に、チャネルを切り替える必芁があるかどうかを刀断する機胜が開始され、必芁に応じお、切り替え機胜が開始され、それに切り替え甚の内郚チャネル番号が送信される。 メむンチャネルぞの埩垰はすぐには行われたせん。これにより、メむンチャネルの動䜜が䞍安定な堎合に埀埩ゞャンプが発生せず、メむン倖郚チャネルが安定しお動䜜し始めたずきにのみ切り替えが行われたす。
  5. 最埌に、必芁がある堎合、スむッチング機胜が起動され、必芁なipfw蚭定を眮き換えお再起動し、必芁なルヌティングテヌブルでバむンドを再起動したす。


もちろん、すべおの䞻芁なアクションはむベントログに蚘録されたす。たた、緊急事態が発生した堎合も、゚ラヌの原因が蚘録され、Watchdogが呌び出されたす。



それで、仕事の基本原則が考慮されたす、私はこれがすべお実際に実行される方法を知るこずを提案したす。



技術郚



装備品


機噚に぀いおはすでに蚀及したしたが、このセクションでは、さらに詳しく説明したす。 私の堎合玄30台のマシンの内郚ネットワヌクでDNS、DHCP、NAT、IPFWの動䜜を保蚌するには、Pentium IIIに基づくCeleron、512 MBのRAM、40 GBのHDD、および察応するマザヌボヌドコネクタをサポヌトする350W PSUで十分です。 远加の2぀のPCIネットワヌクカヌドも接続されたす。 電力に関しおは、䞡方のルヌタヌはほが同じです。



䞀郚の堎所では容量が䜙分であるこずに反察するかもしれたせんが、これらのマシンは特別に賌入されたのではなく、ナヌザヌマシンのフリヌトを曎新した埌に残ったものから収集されたした。 おそらく、最䜎限必芁なサヌビスのセットは、はるかに匱いハヌドりェア䞊で起動できたす。 たた、安党にプレむしお、ミラヌ化されたRAIDを敎理するのもいいでしょう。 残念ながら、私は事前にこれに぀いお考えおいたせんでしたが、今ではいく぀かの困難に関連しおいたすが、これはたったく異なる話です。



私の意芋では、これは叀い䜜業甚アむロンの非垞に䟡倀のある䜿甚方法であり、さもなければ倉庫でほこりっぜくなったり、捚おられたり配垃されたりしたす。



プリセット


もちろん、このシステムが機胜するためには、予備蚭定を行う必芁がありたす。



最初に、プラむマリおよびセカンダリDNSサヌバヌを構成したす。 「ルヌタヌ」が1぀しかない堎合は、プラむマリDNSサヌバヌで十分です。 この問題では、前述のようにバむンド9を䜿甚したした。蚘事の最埌にいく぀かのチュヌニングリンクが蚘茉されおいたす。 この堎合、Cricket LeeずPaul Albitzの「DNS and BIND」チュヌトリアルが非垞に圹立ちたす。



次に、dhcpフェヌルオヌバヌピアを蚭定する必芁がありたす。 「ルヌタヌ」が1぀しかない堎合は、スタンドアロンDHCPサヌバヌの通垞の蚭定で十分です。 繰り返しになりたすが、リンクは蚘事の最埌に蚘茉されおいたす。 䜕らかの理由で、リンクによるフェヌルオヌバヌdhcpピアのセットアップに関する蚘事は利甚できたせんそしお、ここ数か月で状況はそれだけです、ここで蚭定を同期するためのスクリプトずセットアップのキヌポむントを提䟛したす。

フェヌルオヌバヌdhcpdを構成する
フェヌルオヌバヌdhcpピアを構成するには、次のものが必芁です。

  1. / usr / local / etcに、rc.confで参照されるメむン構成ファむルdhcpd.confを䜜成したす。 私はこのように芋えたす

    /usr/local/etc/dhcpd.conf
     # dhcpd.conf # # option definitions common to all supported networks... option domain-name "companyname.local"; option domain-name-servers 10.0.0.2, 10.0.0.1; option ntp-servers 10.0.0.2, 10.0.0.1; option log-servers 10.0.0.1; update-static-leases on; # 1 hour default-lease-time 3600; # 1 day max-lease-time 86400; # Use this to enable / disable dynamic dns updates globally. ddns-update-style interim; # If this DHCP server is the official DHCP server for the local # network, the authoritative directive should be uncommented. authoritative; # Use this to send dhcp log messages to a different log file (you also # have to hack syslog.conf to complete the redirection). log-facility local7; set vendorclass = option vendor-class-identifier; # DNS key include "/usr/local/etc/dhcpd/dns.key"; zone companyname.local.{ primary 127.0.0.1; key DHCP_UPDATER; } zone 0.0.10.in-addr.arpa.{ primary 127.0.0.1; key DHCP_UPDATER; } # DHCP Failover, Primary include "/usr/local/etc/dhcpd/dhcpd.conf_primary"; # Subnet declaration include "/usr/local/etc/dhcpd/dhcpd.subnet"; # Static IP addresses include "/usr/local/etc/dhcpd/dhcpd.static";
          
          







    ここでdns.keyはdnsサヌバヌずの通信のキヌです。これらの問題に぀いおは、dns + dhcpの構成に関する蚘事で詳しく説明されおいたす。
  2. フォルダヌ/ usr / local / etc / dhcpdを䜜成したす。 その䞭に、およそ次のものを含む次のファむルを䜜成したす。

    /usr/local/etc/dhcpd/dhcpd.conf_primary
     ########################## # DHCP Failover, Primary # ########################## failover peer "dhcpdpeer" { # Failover configuration primary; # I am the primary address 10.0.0.1; # My IP address port 1111; peer address 10.0.0.2; # Peer's IP address peer port 2222; max-response-delay 60; max-unacked-updates 10; mclt 3600; split 128; # Leave this at 128, only defined on Primary load balance max seconds 3; }
          
          





    /usr/local/etc/dhcpd/dhcpd.subnet
     subnet 10.0.0.0 netmask 255.255.255.0 { pool { failover peer "dhcpdpeer"; range 10.0.0.15 10.0.0.240; } option subnet-mask 255.255.255.0; option routers 10.0.0.2, 10.0.0.1; option broadcast-address 10.0.0.255; option netbios-name-servers 10.0.0.3; option netbios-dd-server 10.0.0.3; option netbios-node-type 8; }
          
          





    この堎合、netbiosネヌムサヌバヌはwinsサヌバヌサヌビスが実行されおいるWindowsサヌバヌであり、sambaもこの圹割を果たすこずができたす。

    /usr/local/etc/dhcpd/dhcpd.static
     host SERVER3 { hardware ethernet 11:11:11:11:11:11; fixed-address 10.0.0.3; } host SERVER4 { hardware ethernet 22:22:22:22:22:22; fixed-address 10.0.0.4; }
          
          





    ご想像のずおり、このファむルは静的アドレス甚です。

  3. 2番目の「ルヌタヌ」では、ファむルは次のようになりたす。

    /usr/local/etc/dhcpd.conf
     # dhcpd.conf # # option definitions common to all supported networks... option domain-name "companyname.local "; option domain-name-servers 10.0.0.2, 10.0.0.1; option ntp-servers 10.0.0.2, 10.0.0.1; option log-servers 10.0.0.1; update-static-leases on; # 1 hour default-lease-time 3600; # 1 day max-lease-time 86400; # Use this to enable / disable dynamic dns updates globally. ddns-update-style interim; # If this DHCP server is the official DHCP server for the local # network, the authoritative directive should be uncommented. authoritative; # Use this to send dhcp log messages to a different log file (you also # have to hack syslog.conf to complete the redirection). log-facility local7; set vendorclass = option vendor-class-identifier; # DNS key include "/usr/local/etc/dhcpd/dns.key"; zone companyname.local.{ secondary 127.0.0.1; key DHCP_UPDATER; } zone 0.0.10.in-addr.arpa.{ secondary 127.0.0.1; key DHCP_UPDATER; } # DHCP Failover, Primary include "/usr/local/etc/dhcpd/dhcpd.conf_secondary"; # Subnet declaration include "/usr/local/etc/dhcpd/dhcpd.subnet.DONOTEDIT"; # Static IP addresses include "/usr/local/etc/dhcpd/dhcpd.static.DONOTEDIT";
          
          





    /usr/local/etc/dhcpd/dhcpd.conf_secondary
     ########################### # DHCP Failover,Secondary # ########################### failover peer "dhcpdpeer" { # Failover configuration secondary; # I am the secondary address 10.0.0.2; # My IP address port 2222; peer address 10.0.0.1; # Peer's IP address peer port 1111; max-response-delay 60; max-unacked-updates 10; mclt 3600; load balance max seconds 3; }
          
          





    残りのファむルは、名前を倉曎するこずによっおのみ最初の「ルヌタヌ」から取埗するか、最埌に蚭定するず、isc-dhcpdの再起動時にファむルが自動的に移動したす方法に぀いおは、以䞋を参照。

  4. 次の内容の実行可胜ファむルを䜜成したす。

    / usr / local / bin / dhcpd-sync
     #!/bin/sh # backup generation date=`date -v-1d '+%Y%m%d-%H%M%s'` month=`date '+%m%Y'` sudo -u dhcp-updater cp -f /usr/local/etc/dhcpd/dhcpd.subnet /var/dhcp-backup/dhcpd.subnet.$date sudo -u dhcp-updater bzip2 -f -k -z /var/dhcp-backup/dhcpd.subnet.$date sudo -u dhcp-updater tar -r -f /var/dhcp-backup/dhcpd.subnet.$month.tar -C /var/dhcp-backup dhcpd.subnet.$date.bz2 sudo -u dhcp-updater cp -f /usr/local/etc/dhcpd/dhcpd.static /var/dhcp-backup/dhcpd.static.$date sudo -u dhcp-updater bzip2 -f -k -z /var/dhcp-backup/dhcpd.static.$date sudo -u dhcp-updater tar -r -f /var/dhcp-backup/dhcpd.static.$month.tar -C /var/dhcp-backup dhcpd.static.$date.bz2 sudo -u dhcp-updater scp -P 22 -q /var/dhcp-backup/dhcpd.subnet.$date.bz2 dhcp-updater@10.0.0.2:/var/dhcp-backup sudo -u dhcp-updater ssh -p 22 10.0.0.2 tar -r -f /var/dhcp-backup/dhcpd.subnet.$month.tar -C /var/dhcp-backup dhcpd.subnet.$date.bz2 sudo -u dhcp-updater scp -P 22 -q /var/dhcp-backup/dhcpd.static.$date.bz2 dhcp-updater@10.0.0.2:/var/dhcp-backup sudo -u dhcp-updater ssh -p 22 10.0.0.2 tar -r -f /var/dhcp-backup/dhcpd.static.$month.tar -C /var/dhcp-backup dhcpd.static.$date.bz2 sudo -u dhcp-updater ssh -p 22 10.0.0.2 rm /var/dhcp-backup/dhcpd.subnet.$date.bz2 sudo -u dhcp-updater ssh -p 22 10.0.0.2 rm /var/dhcp-backup/dhcpd.static.$date.bz2 sudo -u dhcp-updater rm /var/dhcp-backup/dhcpd.subnet.$date sudo -u dhcp-updater rm /var/dhcp-backup/dhcpd.static.$date sudo -u dhcp-updater rm /var/dhcp-backup/dhcpd.subnet.$date.bz2 sudo -u dhcp-updater rm /var/dhcp-backup/dhcpd.static.$date.bz2 # sync and restart secondary DHCP sudo -u dhcp-updater scp -P 22 -q /usr/local/etc/dhcpd/dhcpd.subnet dhcp-updater@10.0.0.2:/usr/local/etc/dhcpd/dhcpd.subnet.DONOTEDIT sudo -u dhcp-updater scp -P 22 -q /usr/local/etc/dhcpd/dhcpd.static dhcp-updater@10.0.0.2:/usr/local/etc/dhcpd/dhcpd.static.DONOTEDIT sudo -u dhcp-updater ssh -p 22 10.0.0.2 sudo /usr/local/etc/rc.d/isc-dhcpd restart
          
          



  5. 䞡方のサヌバヌで適切な暩限を持぀dhcp-updaterナヌザヌを䜜成し、sudo蚭定に登録し、プラむマリからセカンダリ「ルヌタヌ」ぞのキヌによるssh接続を蚭定し、パスワヌドを削陀したす。 たた、䞡方のマシンで/ var / dhcp-backup /フォルダヌを䜜成する必芁がある堎合がありたす。
  6. /usr/local/etc/rc.d/isc-dhcpdファむルの䞀郚を次のように倉曎したす。

    宛先
     dhcpd_checkconfig () { local rc_flags_mod setup_flags rc_flags_mod="$rc_flags" # Eliminate '-q' flag if it is present case "$rc_flags" in *-q*) rc_flags_mod=`echo "${rc_flags}" | sed -Ee 's/(^-q | -q | -q$)//'` ;; esac if ! ${command} -t -q ${rc_flags_mod}; then err 1 "`${command} -t ${rc_flags_mod}` Configuration file sanity check failed" fi }
          
          





    埌
     dhcpd_checkconfig () { local rc_flags_mod setup_flags rc_flags_mod="$rc_flags" # Eliminate '-q' flag if it is present case "$rc_flags" in *-q*) rc_flags_mod=`echo "${rc_flags}" | sed -Ee 's/(^-q | -q | -q$)//'` ;; esac if ! ${command} -t -q ${rc_flags_mod}; then err 1 "`${command} -t ${rc_flags_mod}` Configuration file sanity check failed" else sh /usr/local/bin/dhcpd-sync fi }
          
          





  7. すべおの蚭定が正しく行われおいる堎合、メむンマシンでdhcpサヌバヌを再起動するず、珟圚の構成がアヌカむブされ、2番目のサヌバヌず同期され、䞡方のマシンで再起動が行われたす。
  8. 次のタスクをcrontabに远加するず䟿利です。

     0 0 * * * root /usr/local/etc/rc.d/isc-dhcpd restart
          
          



  9. これで、フェヌルオヌバヌdhcpd蚭定が完了したした。




第䞉に、れロに加えおルヌティングテヌブルを衚瀺し、「栞」natおよびipfwが機胜するためには、次のパラメヌタヌでカヌネルを再構築する必芁がありたすもちろん、オプションは可胜ですが、最埌にリンクを䜿甚したす。

 options IPFIREWALL options IPFIREWALL_VERBOSE options IPFIREWALL_VERBOSE_LIMIT=50 options IPFIREWALL_NAT options LIBALIAS options DUMMYNET options HZ=1000 options ROUTETABLES=2
      
      





2番目のルヌティングテヌブル番号「1」の䞋、最初のテヌブルには番号「0」があるためがリブヌト埌に機胜するには、rc.dに䜜成する必芁がありたす/usr/local/etc/rc.dにありたす /次の内容のファむル

/usr/local/etc/rc.d/setfib1
 #!/bin/sh # # PROVIDE: SETFIB1 # REQUIRE: NETWORKING # BEFORE: DAEMON # # Add the following lines to /etc/rc.conf to enable setfib -1 at startup # setfib1 (bool): Set to "NO" by default. # Set it to "YES" to enable setfib1 # setfib1_defaultroute (str): Set to "" by default # Set it to ip address of default gateway for use in fib 1 . /etc/rc.subr name="setfib1" rcvar=`set_rcvar` load_rc_config $name [ -z "$setfib1_enable" ] && setfib1_enable="NO" [ -z "$setfib1_defaultrouter" ] && setfib1_defaultrouter="" start_cmd="${name}_start" stop_cmd="${name}_stop" setfib1_start() { if [ ${setfib1_defaultrouter} ] then setfib 1 route add -net default ${setfib1_defaultrouter} else echo "Can not set default route for fib 1 - setfib1_defaultrouter is not assigned in rc.conf!" fi } setfib1_stop() { setfib 1 route del -net default } run_rc_command "$1"
      
      





たた、たずえば、プラむマリ「ルヌタヌ」の堎合、rc.confに数行を远加したす。

 setfib1_enable="YES" setfib1_defaultrouter="2.2.2.1"
      
      





実際、このブヌトスクリプトは2番目のテヌブルにデフォルトルヌトず同じだけ远加したす。 必芁に応じお、最倧65536のルヌティングテヌブルFreeBSDバヌゞョン10を実行し、䞊蚘のスクリプトを少し倉曎しおコピヌし、rc.confにパラメヌタヌを远加できたす。 もちろん、カヌネルパラメヌタヌには、最初にこれらの65536テヌブルを含める必芁がありたす。



メむンの「ルヌタヌ」での私のrc.conf蚭定



しかし、最初に、いく぀かのコメント

Eth0は、メむン倖郚チャネルの物理むンタヌフェむスです。

Eth1は、バックアップ倖郚チャネルの物理むンタヌフェむスです。

Eth2は、内郚チャネルの物理むンタヌフェむスです。

Vlan1-メむン倖郚チャネルのむンタヌフェヌス。

Vlan2-バックアップ倖郚チャネルむンタヌフェむス。

vlan3およびvlan4-将来の機胜のために予玄されおいたす。これに぀いおは蚘事の最埌で説明したす。

10.0.0.1-内郚ネットワヌク内の「ルヌタヌ」のアドレス。それぞれ、たずえば、10.0.0.2になりたす。

1.1.1.2および1.1.1.1-メむン倖郚チャネルのIPアドレスずデフォルトゲヌトりェむ。

2.2.2.2および2.2.2.1-バックアップ倖郚チャネルのIPアドレスずデフォルトゲヌトりェむ。

##泚意 むンタヌフェむスずIPアドレスの名前は䟋ずしお䜿甚され、それぞれの堎合に独自のものになりたす ##

/etc/rc.conf
 hostname="SERVER1.companyname.local" keymap="ru.koi8-r" font8x8="cp866-8x8" font8x14="cp866-8x14" font8x16="cp866-8x16" scrnmap="koi8-r2cp866" cursor="destructive" ifconfig_eth0="up" vlans_eth0="vlan1 vlan3" create_args_vlan1="vlan 1" create_args_vlan3="vlan 3" ifconfig_eth1="up" vlans_eth1="vlan2 vlan4" create_args_vlan2="vlan 2" create_args_vlan4="vlan 4" ifconfig_eth2="inet 10.0.0.1 netmask 255.255.255.0" ifconfig_vlan1="inet 1.1.1.2/24" ifconfig_vlan3="inet 10.0.1.1/30" ifconfig_vlan2="inet 2.2.2.2/24" ifconfig_vlan4="inet 10.0.2.1/30" defaultrouter="1.1.1.1" setfib1_enable="YES" setfib1_defaultrouter="2.2.2.1" gateway_enable="YES" sshd_enable="YES" moused_enable="YES" ntpd_enable="YES" powerd_enable="YES" hald_enable="YES" dbus_enable="YES" dumpdev="AUTO" firewall_enable="YES" firewall_logging="YES" firewall_script="/etc/firewall.sh" named_enable="YES" named_program="/usr/sbin/named" named_flags="-u bind -c /etc/namedb/named.conf" dhcpd_enable="YES" dhcpd_conf="/usr/local/etc/dhcpd.conf" dhcpd_ifaces="eth2"
      
      





以䞋は、私にずっお有効なNATずファむアりォヌルの蚭定です。



メむン倖郚チャネルを介しお䜜業する堎合

/etc/rules.firewall0
 #!/bin/sh # Delete all rules /sbin/ipfw -q -f flush /sbin/ipfw -q -f pipe flush /sbin/ipfw -q -f queue flush /sbin/ipfw -q -f nat 1 delete /sbin/ipfw -q -f table all flush # Parameters ipfw="/sbin/ipfw -q add" extM_if="vlan1" extM_ip="1.1.1.2" extS_if="vlan2" extS_ip="2.2.2.2" int_if="eth2" int_ip="10.0.0.1" lan_net="10.0.0.0/24" odmin="10.0.0.111" # Tables # Table 1 - non-routes networks /sbin/ipfw table 1 add 192.168.0.0/16 /sbin/ipfw table 1 add 172.16.0.0/12 /sbin/ipfw table 1 add 10.0.0.0/8 /sbin/ipfw table 1 add 127.0.0.0/8 /sbin/ipfw table 1 add 0.0.0.0/8 /sbin/ipfw table 1 add 169.254.0.0/16 /sbin/ipfw table 1 add 192.0.2.0/24 /sbin/ipfw table 1 add 204.152.64.0/23 /sbin/ipfw table 1 add 224.0.0.0/3 # Choose route table $ipfw setfib 0 all from any to any via $int_if # Allow all traffic on loopback $ipfw allow all from any to any via lo0 # Deny access to lo0 from out $ipfw deny log all from any to 127.0.0.0/8 # Deny outcome packets from lo0 $ipfw deny log all from 127.0.0.0/8 to any # Allow returning $ipfw check-state # Deny IPv6 $ipfw deny log ipv6 from any to any # Antispoofing $ipfw deny log all from any to any not antispoof in # Block any delayed packets (fragments) $ipfw deny all from any to any frag ######################################### # Internal interface, outcoming traffic # ######################################### # Allow all traffic from gateway to lan $ipfw allow all from any to $lan_net out via $int_if # Deny and log other $ipfw deny log all from any to any out via $int_if ######################################## # Internal interface, incoming traffic # ######################################## # Deny all Netbios $ipfw deny tcp from any to any 81,137,138,139 in via $int_if # Allow traffic on internal interface # DHCP $ipfw allow udp from any to me 67,68,1515,1516 in via $int_if # Mail $ipfw allow tcp from $lan_net to any 25,110,143,465,993,995 in via $int_if # Time $ipfw allow tcp from $lan_net to any 37 in via $int_if $ipfw allow udp from $lan_net to any 123 in via $int_if # ICQ $ipfw allow tcp from $lan_net to any 443,5190,5222 in via $int_if # FTP and some other $ipfw allow tcp from $lan_net to any 21,22,49152-65535 in via $int_if # HTTP $ipfw allow tcp from $lan_net to any 80 in via $int_if # Output whois $ipfw allow tcp from $lan_net to any 43 in via $int_if # DNS $ipfw allow udp from $lan_net to any 53 in via $int_if $ipfw allow tcp from $lan_net 53 to $int_ip in via $int_if $ipfw allow tcp from $lan_net to $int_ip 53 in via $int_if # Ping $ipfw allow icmp from $lan_net to any icmptypes 0,3,8,11 in via $int_if # For admin $ipfw allow all from $odmin 1025-6000,11111,22222,50000-60000 to any in via $int_if $ipfw allow all from 10.0.0.2 22 to $int_ip in via $int_if $ipfw 55100 allow all from any to $int_ip 22 in via $int_if # Deny and log other $ipfw deny log all from any to any in via $int_if ######################################### # External interface, outcoming traffic # ######################################### # Deny all outcoming traffic to non-route networks $ipfw deny log all from any to 'table(1)' out via $extM_if $ipfw deny log all from any to 'table(1)' out via $extS_if # Deny broadcast ICMP on ext interface $ipfw deny icmp from any to 255.255.255.255 out via $extM_if $ipfw deny icmp from any to 255.255.255.255 out via $extS_if # Deny multicast on ext interface $ipfw deny all from 224.0.0.0/4 to any out via $extM_if $ipfw deny all from 224.0.0.0/4 to any out via $extS_if # Allow me go to internet $ipfw allow all from $extM_ip to any out via $extM_if setup keep-state $ipfw allow all from $extS_ip to any out via $extS_if setup keep-state # DNS BIND $ipfw allow udp from $extM_ip to any 53 out via $extM_if keep-state $ipfw allow udp from $extS_ip to any 53 out via $extS_if keep-state # Time $ipfw allow udp from $extM_ip to any 123 out via $extM_if keep-state $ipfw allow tcp from $extM_ip to any 37 out via $extM_if setup keep-state # Output whois $ipfw allow tcp from $extM_ip to any 43 out via $extM_if setup keep-state # NAT /sbin/ipfw -q nat 1 config log if $extM_if reset same_ports deny_in unreg_only redirect_port tcp 10.0.0.111:33333 33333 redirect_port udp 10.0.0.111:11111 11111 redirect_port tcp 10.0.0.111:22222 22222 redirect_port udp 10.0.0.111:22222 22222 # NAT outcoming traffic $ipfw nat 1 ip from any to any out via $extM_if # Allow traffic on outcoming interface # Mail $ipfw allow tcp from any to any 25,110,143,465,993,995 out via $extM_if # ICQ $ipfw allow tcp from any to any 443,5190,5222 out via $extM_if # FTP and some other $ipfw allow tcp from any to any 21,22,49152-65535 out via $extM_if # HTTP $ipfw allow tcp from any to any 80 out via $extM_if # Ping $ipfw allow icmp from any to any icmptypes 0,3,8,11 out via $extM_if $ipfw allow icmp from any to any icmptypes 0,3,8,11 out via $extS_if # For admin $ipfw allow tcp from any 1025-6000 to any out via $extM_if $ipfw allow all from any 11111,22222,50000-60000 to any out via $extM_if # Deny and log other $ipfw deny log all from any to any out via $extM_if $ipfw deny log all from any to any out via $extS_if ######################################## # External interface, incoming traffic # ######################################## # Deny all incoming traffic from non-route networks $ipfw deny log all from 'table(1)' to any in via $extM_if $ipfw deny log all from 'table(1)' to any in via $extS_if # Deny ident $ipfw deny tcp from any to any 113 in via $extM_if $ipfw deny tcp from any to any 113 in via $extS_if # Deny all Netbios $ipfw deny tcp from any to any 81,137,138,139 in via $extM_if $ipfw deny tcp from any to any 81,137,138,139 in via $extS_if # SSH (also for internal network) $ipfw allow all from any to me 22 in via $extM_if $ipfw allow all from any to me 22 in via $extS_if # NAT incoming traffic $ipfw nat 1 ip from any to any in via $extM_if # Allow traffic on outcoming interface # Mail $ipfw allow tcp from any 25,110,143,465,993,995 to any in via $extM_if # ICQ $ipfw allow tcp from any 443,5190,5222 to any in via $extM_if # FTP and some other $ipfw allow tcp from any 21,22,49152-65535 to any in via $extM_if # HTTP $ipfw allow tcp from any 80 to any in via $extM_if # Ping $ipfw allow icmp from any to any icmptypes 0,3,8,11 in via $extM_if $ipfw allow icmp from any to any icmptypes 0,3,8,11 in via $extS_if # For admin $ipfw allow tcp from any to $odmin 1025-6000 in via $extM_if $ipfw allow all from any to $odmin 11111,22222,50000-60000 in via $extM_if # Deny and log other $ipfw deny log all from any to any in via $extM_if $ipfw deny log all from any to any in via $extS_if $ipfw deny log all from any to any
      
      





バックアップ倖郚チャネルを䜿甚する堎合、すべおの蚭定は同じで、ヘッダヌのみが倉曎されたす。

/etc/rules.firewall1 hat
 # Parameters ipfw="/sbin/ipfw -q add" extM_if="vlan2" extM_ip="2.2.2.2" extS_if="vlan1" extS_ip="1.1.1.1" int_if="eth2" int_ip="10.0.0.1" lan_net="10.0.0.0/24" odmin="10.0.0.111" serv="10.0.0.4
      
      





たた、sshguardは「ルヌタヌ」で構成されたすが、経隓豊富な読者であれば、このプログラムを自分で芋぀けおむンストヌルするこずができたす。



スクリプト゜ヌス


ToFoIn-むンタヌネットのフェむルオヌバヌを切り替えたす。 おそらく、その名前は野心的なものではありたせんが、既存の補品よりも正確に補品の特性を考え出すこずはできたせんでした。 以䞋に、スクリプトず関連ファむルのテキストを少し説明したす。

tofoin.conf
 ## tofoin.conf ## ## by LordNicky v0.6 20140719 ## ## Little about the modules and about what function they perform. ## Tester - Testing the availability of the Internet on selected channel. ## Judge - Test results analysis, the decision to switch ## from one channel to another. ## Logger - Event logging. ## Watchdog - Testing and debugging of the scripts. ## Configuration. ## Amouth of the Internet channels. CNUMBER=2 ## Main Internet channel properties. ## Interface name. EXT_0_IF=vlan10 ## Id number of the routing table. RTABLE_0=0 ## Reserve Internet channel properties. ## Interface name. EXT_1_IF=vlan20 ## Id number of the routing table RTABLE_1=1 ## URL's supposed to be used for diagnostic of the availability ## of the Internet channel. PTARGET_0 should be domain name, and ## PTARGET_1 should be IP address. ## Attention: The resources should be different. PTARGET_0=ya.ru PTARGET_1=8.8.8.8 ## Count of icmp packets used for testing one resource. PNUMBER=2 ## Period of launching of the module "Tester" (in seconds). ## Strongly not recomended to set a value less than 60. TESTERPERIOD=240 ## Period of launching of the module "Judge" (in seconds). ## Strongly not recomended to set a value less than TESTERPERIOD. ## Usually enough TESTERPERIOD + 60. JUDGEPERIOD=300 ## Launching sensitivity for the modules Tester and Judge. ## Usually enough 60. SENSITIVITY=60 ## The maximum operating time for the module Tester. TESTERMAXDELAY=40 ## The maximum operating time for the module Judge. JUDGEMAXDELAY=30 ## The maximum operating time for the module Logger. LOGGERMAXDELAY=20 ## Amount of tests that successfully passed before returning ## to the main channel. Thereby, time elapsed since the restore ## the work main channel is approximately (WNUMBER+1)*JUDGEPERIOD ## seconds. WNUMBER=3 ## The frequency of writing error message into the log file. ## The main idea is the following. At first time the message ## is written completely. After LOGFREQ1 repetitions logger ## writes the only message about LOGFREQ1 the same messages. ## Later in each LOGFREQ2 repetitions logger writes the only ## message about LOGFREQ2 the same messages. This algorithm ## works only if the same messages are following after each other. LOGFREQ1=5 LOGFREQ2=20 ## File paths. ## Paths for configuration script files IPFW. ## Default file. (It is written in the rc.conf) FIRESETDEF=/etc/firewall.sh ## Settings for main Internet channel. FIRESET_0=/etc/rules.firewall0 ## Settings for reserve Internet channel. FIRESET_1=/etc/rules.firewall1 ## Paths for all ToFoIn files. ## Daemon. DAEMON=/path/to/file/tofoin_daemon.sh ## Tester. TESTER=/path/to/file/tofoin_tester.sh ## Judge. JUDGE=/path/to/file/tofoin_judge.sh ## Logger. LOGGER=/path/to/file/tofoin_logger.sh ## Watchdog. WATCHDOG=/path/to/file/tofoin_watchdog.sh ## Log file. It is recommended to locate it into the /var/log. LOGFILE=/path/to/file/tofoin.log ## The directory supposed for test results. It is recomended ## to locate it into the /tmp. TESTER_RESULT=/path/to/directory ## Auxiliary module file Judge. It is recommended to locate ## it into the /tmp. JUDGEMETER=/path/to/file/judgemeter ## Auxiliary module file Logger. It is recommended to locate ## it into the /tmp. LOGTMP=/path/to/file/logger.tmp LOGMETER=/path/to/file/logmeter ## PID files for all executable modules. It is recommended ## to locate it into /var/run. DAEMON_PID=/path/to/file/tofoin_daemon.pid TESTER_PID=/path/to/directory JUDGE_PID=/path/to/file/tofoin_judge.pid LOGGER_PID=/path/to/file/tofoin_logger.pid WATCHDOG_PID=/path/to/file/tofoin_watchdog.pid
      
      





tofoin_daemon.sh
 #!/usr/local/bin/bash # by LordNicky v0.5 20140717 . /root/ToFoIn/tofoin.conf test_time=`date +%s`; judge_time=`date +%s`; echo $$ > $DAEMON_PID; $LOGGER "DAEMON: start successfully with pid $$" & tester_0="$TESTER $RTABLE_0 10 0"; tester_1="$TESTER $RTABLE_1 10 1"; $tester_0 & $tester_1 & while true do current_time=`date +%s`; if [ "`expr $current_time - $test_time`" -ge "$TESTERPERIOD" ] then $tester_0 & $tester_1 & test_time=`date +%s`; else :; fi if [ "`expr $current_time - $judge_time`" -ge "$JUDGEPERIOD" ] then $JUDGE & judge_time=`date +%s`; else :; fi sleep $SENSITIVITY; done
      
      





tofoin_tester.sh
 #!/usr/local/bin/bash # by LordNicky v0.7 20140717 . /root/ToFoIn/tofoin.conf exit_function () { rm $tester_pid; exit $exit_code; } tester_pid=$TESTER_PID/tofoin_test_$3\.pid; if [ -e $tester_pid ]; then $WATCHDOG "tofoin_test" "$tester_pid" "$3" & exit 0; else echo `date +%s` $$ > $tester_pid; if [ "$2" -eq 10 ]; then if setfib $1 ping -c $PNUMBER $PTARGET_0 > /dev/null; then echo `date +%s` "0 0" > $TESTER_RESULT/result_$3; exit_code=0; exit_function; else if setfib $1 ping -c $PNUMBER $PTARGET_1 > /dev/null; then echo `date +%s` "0 1" > $TESTER_RESULT/result_$3; exit_code=0; exit_function; else echo `date +%s` "1 1" > $TESTER_RESULT/result_$3; exit_code=0; exit_function; fi fi elif [ "$2" -eq 0 ]; then setfib $1 ping -c $PNUMBER $PTARGET_0; exit_code=0; exit_function; elif [ "$2" -eq 1 ]; then setfib $1 ping -c $PNUMBER $PTARGET_1; exit_code=0; exit_function; else setfib $1 ping -c $PNUMBER $2; exit_code=1; exit_function; fi fi
      
      





前述のように、テスタヌモゞュヌルには、手動で起動するための機胜がわずかに拡匵されおいたす。「゜リュヌション」セクションでは、その方法に぀いお説明したす。たた、スクリプトのテキストからわかるように、テスタヌは通垞の起動の堎合にのみ結果をファむルに曞き蟌みたす。

tofoin_judge.sh
 #!/usr/local/bin/bash # by LordNicky v0.7 20140717 . /root/ToFoIn/tofoin.conf exit_function () { rm $JUDGE_PID; exit $exit_code; } decision_function () { if [ "$actualchan" -eq "$prefchan" ]; then if [ "$actualchan" -eq 0 ]; then $LOGGER "JUDGE: No problems detected" & exit_code=0; exit_function; elif [ "$actualchan" -eq 1 ]; then echo -e "0" > $JUDGEMETER; $LOGGER "JUDGE: No problems detected at channel $actualchan" & exit_code=0; exit_function; else $LOGGER "JUDGE(decision): Invalid actualchan = $actualchan" & exit_code=1; exit_function; fi else if [ "$prefchan" -eq 1 ]; then switch_function; exit_code=0; exit_function; elif [ "$prefchan" -eq 0 ]; then if [ "$actualstate" -eq 0 ] then meter=`cat $JUDGEMETER`; if [ "$meter" -eq "$WNUMBER" ]; then switch_function; exit_code=0; exit_function; elif [ "$meter" -lt "$WNUMBER" ]; then expr $meter + 1 > $JUDGEMETER; exit_code=0; exit_function; else echo -e "0" > $JUDGEMETER; exit_code=0; exit_function; fi elif [ "$actualstate" -eq 1 ] then $LOGGER "JUDGE: Emergency switch to $prefchan"; switch_function; exit_code=0; exit_function; else $LOGGER "JUDGE(decision): Invalid actualstate = $actualstate" & exit_code=1; exit_function; fi else $LOGGER "JUDGE(decision): Invalid prefchan = $prefchan" & exit_code=1; exit_function; fi fi } switch_function () { echo -e "0" > $JUDGEMETER; if [ "$prefchan" -eq 0 ]; then /etc/rc.d/named stop; cp $FIRESET_0 $FIRESETDEF; /etc/rc.d/ipfw restart; setfib $RTABLE_0 /etc/rc.d/named start; $LOGGER "JUDGE: Now switching on channel $RTABLE_0" & exit_code=0; exit_function; elif [ "$prefchan" -eq 1 ] then /etc/rc.d/named stop; cp $FIRESET_1 $FIRESETDEF; /etc/rc.d/ipfw restart; setfib $RTABLE_1 /etc/rc.d/named start; $LOGGER "JUDGE: Now switching on channel $RTABLE_1" & exit_code=0; exit_function; else $LOGGER "JUDGE(switch): Invalid prefchan = $prefchan" & exit_code=1; exit_function; fi } createarea_function () { for ((a=0; a < CNUMBER ; a++)) do current_time=`date +%s` timearea[$a]=`cut -c 1-10 $TESTER_RESULT/result_$a`; if [ "`expr $current_time - ${timearea[$a]}`" -ge 0 ]; then if [ "`expr $current_time - ${timearea[$a]}`" -lt "`expr $TESTERPERIOD + 120`" ]; then :; else $LOGGER "JUDGE: MAX period" & $WATCHDOG & exit_code=1; exit_function; fi else $LOGGER "JUDGE: testmodule $a in future" & $WATCHDOG & exit_code=1; exit_function; fi statearea[$a]=`cut -c 12 $TESTER_RESULT/result_$a`; if [ "$actualchan" -eq "$a" ] then actualstate=${statearea[$a]}; else :; fi done } findarea_function () { for ((a=0; a < CNUMBER ; a++)) do if [ "${statearea[$a]}" -eq 0 ] then prefchan=$a; decision_function; exit_code=0; exit_function; else if [ "${statearea[$a]}" -eq 1 ] then continue else $LOGGER "JUDGE: Invalid channel state" & exit_code=1; exit_function; fi fi done } if [ -e $JUDGE_PID ] then $WATCHDOG "tofoin_judge" "$JUDGE_PID" & exit 0; else echo `date +%s` $$ > $JUDGE_PID; if ipfw list | grep nat | egrep -q $EXT_0_IF; then actualchan=0; elif ipfw list | grep nat | egrep -q $EXT_1_IF; then actualchan=1; else $LOGGER "JUDGE: NAT error" & prefchan=0; switch_function; exit_code=1; exit_function; fi createarea_function; findarea_function; $LOGGER "JUDGE: All channels down" & exit_code=1; exit_function; fi
      
      





裁刀官モゞュヌルには、さらなる改善の䜙地がありたすが、䞀般に食り気はありたせん。

tofoin_logger.sh
 #!/usr/local/bin/bash # by LordNicky v0.5 20140713 . /root/ToFoIn/tofoin.conf exit_function () { rm $LOGGER_PID; exit $exit_code; } main_function () { if [[ `tail -n 1 $LOGFILE | grep -o "$1" | grep -o "JUDGE: No problems detected"` = "JUDGE: No problems detected" ]]; then exit_code=0; exit_function; else if [[ `cat $LOGTMP` = $1 ]]; then meter=`cat $LOGMETER`; if [ "$meter" -ge "$LOGFREQ2" ]; then echo -e "0" > $LOGMETER; echo -e "`date -j +%Y%m%d%H%M` last message repeat $LOGFREQ2 times" >> $LOGFILE; exit_code=0; exit_function; elif [ "$meter" -ge "$LOGFREQ1" ]; then if [[ `tail -n 1 $LOGFILE | grep -o "last message repeat $LOGFREQ1 times"` = "last message repeat $LOGFREQ1 times" ]]; then expr $meter + 1 > $LOGMETER; exit_code=0; exit_function; elif [[ `tail -n 1 $LOGFILE | grep -o "last message repeat $LOGFREQ2 times"` = "last message repeat $LOGFREQ2 times" ]]; then expr $meter + 1 > $LOGMETER; exit_code=0; exit_function; else echo -e "`date -j +%Y%m%d%H%M` last message repeat $LOGFREQ1 times" >> $LOGFILE; exit_code=0; exit_function; fi elif [ "$meter" -ge 0 ]; then expr $meter + 1 > $LOGMETER; exit_code=0; exit_function; else echo -e "0" > $LOGMETER; echo -e "`date -j +%Y%m%d%H%M` LOGGER: logmeter index error, write 0" >> $LOGFILE; exit_code=1; exit_function; fi else if [ `cat $LOGMETER` -eq 0 ]; then echo -e "$1" > $LOGTMP; echo -e "`date -j +%Y%m%d%H%M` $1" >> $LOGFILE; exit_code=0; exit_function; else echo -e "0" > $LOGMETER; echo -e "$1" > $LOGTMP; echo -e "`date -j +%Y%m%d%H%M` $1 ; LOGMETER now zero" >> $LOGFILE; exit_code=0; exit_function; fi fi fi } if [ -e $LOGGER_PID ]; then sleep $((RANDOM%5+1)); if [ -e $LOGGER_PID ]; then $WATCHDOG "tofoin_logger" "$LOGGER_PID" & exit 0; else echo `date +%s` $$ > $LOGGER_PID; main_function "$1"; fi else echo `date +%s` $$ > $LOGGER_PID; main_function "$1"; fi
      
      





私の意芋では、知芚の面で最も恐ろしいモゞュヌルはロガヌです。しかし、残念ながら、曞くのは簡単ではありたせんでした。基本的に、スクリプトの倧郚分は重耇メッセヌゞの発生を防ぐこずに専念しおいるため、明らかに耇雑です。

tofoin_watchdog.sh
 #!/usr/local/bin/bash # by LordNicky v0.5 20140713 . /root/ToFoIn/tofoin.conf exit_function () { rm $WATCHDOG_PID; exit $exit_code; } kill_function () { if [[ "`ps -o command -p $proc_pid | grep -o "$proc_name"`" = "$proc_name" ]]; then $LOGGER "WATCHDOG: Other $proc_s_name working during $diff, kill him" & kill $proc_pid; else $LOGGER "WATCHDOG: None or other process on $proc_s_name pid, cleaning pid file" & fi if [[ "$proc_name" = "tofoin_watchdog" ]]; then main_function; else rm $proc_pid_file; fi } main_function () { echo `date +%s` $$ > $WATCHDOG_PID; proc_name=${one:-all}; return_wait=10 if [[ "$proc_name" = "all" ]]; b=0; c=0 then for ((a=0; a < CNUMBER ; a++)) do current_time=`date +%s`; tester_result=$TESTER_RESULT/result_$a; tester_time=`cut -c 1-10 $tester_result`; diff=`expr $current_time - $tester_time`; if [ "$diff" -ge 0 ] then if [ "$diff" -lt "`expr $TESTERPERIOD + 120`" ]; then :; else proc_name=tofoin_daemon; proc_pid=`cat $DAEMON_PID`; if [[ "`ps -o command -p $proc_pid | grep -o "$proc_name"`" = "$proc_name" ]]; then $LOGGER "WATCHDOG: Restart daemon" & kill $proc_pid; $DAEMON & else $LOGGER "WATCHDOG: None daemon process, start" & $DAEMON & fi exit_code=0; exit_function; fi else $LOGGER "WATCHDOG: Check date" & fi done elif [[ "$proc_name" = "tofoin_test" ]]; then proc_pid_file=$two; cnumber=$three; test_function; return_val=$?; if [[ "$return_val" = "$return_wait" ]]; then sleep $TESTERMAXDELAY; test_function "nowait"; else :; fi elif [[ "$proc_name" = "tofoin_judge" ]]; then proc_pid_file=$JUDGE_PID; judge_function; return_val=$?; if [[ "$return_val" = "$return_wait" ]]; then sleep $JUDGEMAXDELAY; judge_function "nowait"; else :; fi elif [[ "$proc_name" = "tofoin_logger" ]]; then proc_pid_file=$LOGGER_PID; logger_function; return_val=$?; if [[ "$return_val" = "$return_wait" ]]; then sleep $LOGGERMAXDELAY; logger_function "nowait"; else :; fi else $LOGGER "WATCHDOG: Incorrect process name"; fi exit_code=0; exit_function; } test_function () { if [ -e $proc_pid_file ]; then proc_pid=`cut -c 12-18 $proc_pid_file`; proc_s_name="tester $cnumber"; start_time=`cut -c 1-10 $proc_pid_file`; current_time=`date +%s`; diff=`expr $current_time - $start_time`; if [ "$diff" -ge 0 ]; then if [ "$diff" -lt "$TESTERMAXDELAY" ]; then if [[ "$1" = "nowait" ]]; then if [ "$proc_pid" = "$proc_temp_pid" ]; then kill_function; return 0; else $LOGGER "WATCHDOG: Pid of $proc_s_name was changed, exit" & fi else $LOGGER "WATCHDOG: $proc_s_name now working, try wait" & proc_temp_pid=$proc_pid; return $return_wait; fi else kill_function; return 0; fi else $LOGGER "WATCHDOG: Time error in $proc_s_name = $diff" & kill_function; return 0; fi else return 0; fi } judge_function () { if [ -e $proc_pid_file ]; then proc_pid=`cut -c 12-18 $proc_pid_file`; proc_s_name="judge"; start_time=`cut -c 1-10 $proc_pid_file`; current_time=`date +%s`; diff=`expr $current_time - $start_time`; if [ "$diff" -ge 0 ]; then if [ "$diff" -lt "$JUDGEMAXDELAY" ]; then if [[ "$1" = "nowait" ]]; then if [ "$proc_pid" = "$proc_temp_pid" ]; then kill_function; return 0; else $LOGGER "WATCHDOG: Pid of $proc_s_name was changed, exit" & fi else $LOGGER "WATCHDOG: $proc_s_name now working, try wait" & proc_temp_pid=$proc_pid; return $return_wait; fi else kill_function; return 0; fi else $LOGGER "WATCHDOG: Time error in $proc_s_name = $diff" & kill_function; return 0; fi else return 0; fi } logger_function () { if [ -e $proc_pid_file ]; then proc_pid=`cut -c 12-18 $proc_pid_file`; proc_s_name="logger"; start_time=`cut -c 1-10 $proc_pid_file`; current_time=`date +%s`; diff=`expr $current_time - $start_time`; if [ "$diff" -ge 0 ]; then if [ "$diff" -lt "$LOGGERMAXDELAY" ]; then if [[ "$1" = "nowait" ]]; then if [ "$proc_pid" = "$proc_temp_pid" ]; then kill_function; return 0; else echo -e "`date -j +%Y%m%d%H%M` WATCHDOG: Pid of $proc_s_name was changed, exit" >> $LOGFILE; fi else echo -e "`date -j +%Y%m%d%H%M` WATCHDOG: $proc_s_name now working, try wait" >> $LOGFILE; proc_temp_pid=$proc_pid; return $return_wait; fi else kill_function; return 0; fi else echo -e "`date -j +%Y%m%d%H%M` WATCHDOG: Time error in $proc_s_name = $diff" >> $LOGFILE; kill_function; return 0; fi else return 0; fi } one=$1; two=$2; three=$3; if [ -e $WATCHDOG_PID ]; then proc_pid=`cut -c 12-18 $WATCHDOG_PID`; proc_name="tofoin_watchdog"; proc_s_name="watchdog"; start_time=`cut -c 1-10 $WATCHDOG_PID`; current_time=`date +%s`; diff=`expr $current_time - $start_time`; if [ "$diff" -ge 0 ]; then if [ "$diff" -lt "`expr $TESTERMAXDELAY + $JUDGEMAXDELAY + $LOGGERMAXDELAY + 30`" ]; then $LOGGER "WATCHDOG: Other $proc_s_name already working, exit" & exit 0; else kill_function; fi else $LOGGER "WATCHDOG: Time error in $proc_s_name = $diff" & kill_function; fi else main_function; fi
      
      





りォッチドッグは、提瀺されたすべおのスクリプトの䞭で最倧であり、おそらく曖昧なスクリプトです。考えられるすべおの障害オプションを提䟛しようず詊みたため、このようになりたした。しかし、これたでのずころ。このモゞュヌルはcronを䜿甚しお起動するこずになっおいるため、/ etc / crontabに次のようなものを远加する必芁がありたす。

 0 * * * * root /path/to/file/tofoin_watchdog.sh
      
      







たずめ



スクリプトは6か月間テストされたした。重倧な゚ラヌは芋぀かりたせんでした。マむナヌな゚ラヌは修正されたした。すべおのモゞュヌルは、逞脱や予枬䞍可胜なアクションなしで、所定のアルゎリズムに埓っお動䜜したす。むベントログファむルは非垞に有益であり、発生した問題ずその発生および解決の時間を刀断できたす。したがっお、最初の目暙が達成されたず結論付けるこずができたす。さらなる開発蚈画の抂芁を以䞋に瀺したす。



蚈画



スクリプトのさらなる開発の蚈画

  1. 適切なシステムディレクトリにファむルを配眮したす。
  2. 特定のタスクのためにsudoを䜿甚しお特別なナヌザヌずしお実行する必芁があるこずを考慮しおください。肯定的な決定の堎合、スクリプトを適合させたす。
  3. zabbixず通信するためのモゞュヌルを远加したす。
  4. クラむアントサヌバヌシステムを䜜成したす。vlan3ずvlan4が構成されたのはこのシステムのためです。内郚チャネルの「ルヌタヌ」間に接続がない堎合は、倖郚むンタヌフェむスに構成されたvlanを介しお通信しようずするためです。
  5. おそらく、遠い明るい将来に、より倚くの機胜を備えた蚀語でスクリプト党䜓を曞き盎しおください。珟時点では、bashで可胜なすべおのこずを絞り出したいずいう芁望がありたす。




ご質問



もちろん、曞くずき、特にその埌、倚くの疑問が生じたした。これらのうち最も重芁な

ものは次のずおりです。次の倉数がありたす。



 a =<  > HI_1=”123” HI_2=”321”
      
      





倉数HI_1ずHI_2を呌び出しお、aのみを倉曎する必芁がありたす。呌び出しは次のようになりたす。

 ${HI_$a} ##         
      
      





たた、a = 1を事前に蚭定した堎合、この匏は123を意味し、a = 2の堎合は321を意味したす。残念ながら、これを行う方法が芋぀かりたせんでした。この関数を䜿甚するず、スクリプトが倧幅に簡玠化され、拡匵が容易になりたす。



もちろん、残りは䞀般的な質問です-この決定はどの皋床関連しおいたすかスクリプトでどのような間違いがありたすか蚈画および蚘事の本文で特定された問題を解決する最良の方法は䜕ですかあなたのコメント



あなたが改善を支揎したい堎合は、個人的なメッセヌゞを曞いお、私たちは可胜な協力に぀いお議論したす。



参照資料
DNS BIND 9:

., . — DNS BIND (5- )

DNS BIND

DHCP:

Failover DHCP

DHS + DHCP:

DDNS+DHCP

SETFIB:

Multiple default routes in FreeBSD without BGP or similar

setfib

FreeBSD . setfib

IPFW + NAT:

ipfw nat

FreeBSD 9 + ipfw + ipfw nat

ipfw nat

DUMMYNET

Kernel NAT

SSH:

SSH

SSH

SSH ( )

BASH:

BASH. 2.

Advanced Bash-Scripting Guide



たた、システムを構成しおスクリプトを䜜成するずきに、opennet.ru、lissyara.su、habrahabr.ru、および他の倚くのサむトから、他の倚くの資料が䜿甚されたした。残念ながら、時間の経過ずずもに倚くのリンクが倱われおいるため、ここのどこかからフラグメントを芋぀けた堎合は、それらにリンクを远加させおいただきたす。脚本の䜜成ず䜜成の過皋での困難を解決するためのアドバむスず支揎をしおくれたAlexei EreskoずValery Drubaに、そしお蚘事の準備を支揎しおくれたOleg Matusevichに特に感謝したす。



Z.Y. この蚘事の資料を䜿甚する堎合、゜ヌスず著者ぞのリンクを瀺すこずが矩務付けられおいたす。



All Articles