iBGP ネイバーの問題とフルメッシュの問題
iBGP ネイバー (同一 AS 内での BGP ネイバー) が多段となる場合、直接ネイバーのルータが生成したルートは学習できますが、2 段目以降のルータが生成したルートは学習できません。
例えば下図の上段の構成において、RT1 は RT2 と直接ネイバーになっているため、2.2.2.0/24 は学習しますが、直接ネイバーとなっていない RT3, RT4, RT5 の各ルート (3.3.3.0/24 , 4.4.4.0/24 , 5.5.5.0/24) については RT2 から学習することができません。
これは BGP がもともと AS 間での学習を想定しており、AS 内での学習については IGP など他の方法で対応することを想定したプロトコル設計になっているためです。(BGP synchronization もその話の 1 つです。)
この問題への対応方法としては、上図の下段にあるように『① 全ルータで iBGP ネイバーを確立する (フルメッシュ構成にする)』ことや『② 外部ルート (1.1.1.0/24 ~ 5.5.5.0/24) を IGP で学習させる』ことがあります。
① については設定が複雑になり、トラブル時の対応など運用面の負荷もありますし、② についても、外部ルートが大量にあるインターネットにおいてはルータへの負荷が大きいです。
これらとは別の対応方法として、Route Reflector (RR) という方法があります。
Route Reflector (RR) とは
Route Reflector (RR) とは、RFC4456 で規定された iBGP フルメッシュの代替手段です。
[RFC4456 のタイトル]
BGP Route Reflection: An Alternative to Full Mesh Internal BGP (IBGP)
RR を使うと、iBGP で学習したルートを他の iBGP ネイバーにも学習させることができます。
あるルータ上で、ネイバーを "RR クライアント" と指定すると、そのルータが RR となります。
例えば先程の図例と同じ構成で RT2 上の設定により RT1 と RT3 を "RR クライアント" として指定すると、RT2 が RR となります。そして RT1 と RT3 は全てのルートを学習することができます。
RT2 を RR とし、RT1 と RT3 を RR クライアントとする設定は、以下の通りです。
RT2(config)# router bgp 10 RT2(config-router)# neighbor 10.1.12.1 route-reflector-client RT2(config-router)# neighbor 10.1.23.3 route-reflector-client
理解のため、RT4 と RT5 をわざと "RR クライアント" から外していますが、RT4 と RT5 は (RT2 から見て) "Non-RR クライアント" となり、お互いのルートだけは学習できません。(RT4 は 5.5.5.0/24 を、RT5 は 4.4.4.0/24 を学習できません。)
また、注意点として、RR 設定をした場合は iBGP に対しての neighbor ~ next-hop-self が効きません。
そのため、OSPF 等の IGP で内部ルート (10.1.**.0/24) のルートを学習させるか、neighbor ~ route-map ChangeNH 等 route-map を使って NextHop を無理やり変更させる必要があります。
以下にルートマップでの設定変更例を示します。
RT2(config)# route-map ChangeNH RT2(config-route-map)# set ip next-hop 10.1.12.2 RT2(config)# router bgp 10 RT2(config-router)# neighbor 10.1.12.1 route-map ChangeNH
ルートリフレクタにより反射されたルートには、ORIGINATOR_ID 属性と CLUSTER_LIST 属性が付加されます。
これらの属性はルートのループ防止に使われます。次の章で詳細を見ていきます。
ルートリフレクタのループ回避
ルートリフレクタは見境なくルートを反射します。なので RR クライアントが RR にルートを投げると、そのルートが自分にも戻ってきます。このときにルートを破棄する仕組みが『ORIGINATOR_ID』属性です。
ORIGINATOR_ID 属性
RR がルートを反射する際は、そのルートに ORIGINATOR_ID 属性を付加し、提供元のルータの bgp router-id を格納します。そのルートに既に ORIGINATOR_ID が格納されている場合は変更しません。
例えば先程の図例で、RT1 で生成したルート 1.1.1.0/24 を RT2 が RR としてルート反射する様子を見てみます。
RT2 は 1.1.1.0/24 に対して『ORIGINATOR_ID=1.1.1.1』をセットします (RT1 の bgp router-id が 1.1.1.1 であるため)。そしてこのルートは RT3 にルート反射されますが、RT1 にもルート反射されます。
ですが RT1 は ORIGINATOR_ID を見て自分の bgp router-id と一致するため、1.1.1.0/24 のルートを無視します。
ルートリフレクタの冗長構成とループ回避
ルートリフレクタで冗長構成を組むと効率的です。以下の構成図では RT4 と RT5 がバックボーンルータとして冗長化されており、どちらかが故障してももう片方のルータで通信が継続できます。
ですが RR を複数設定すると、反射の反射のそのまた反射がループになる可能性があります。これを防止する仕組みが『CLUSTER_LIST』属性です。
CLUSTER_LIST 属性と CLUSTER_ID
CLUSTER_LIST 属性および CLUSTER_ID は RR 間でのルート反射を抑える仕組みです。
RR がルートを反射する際に自分の CLUSTER_ID を CLUSTER_LIST 属性にセットします。
そして別の RR がそれを受け取り、さらに反射する際にはそのルータも自分の CLUSTER_ID を CLUSTER_LIST 属性に追加します。
そして RR が受信したルートの CLUSTER_LIST の中に自分の CLUSTER_ID を検知した場合は、そのルートを破棄します。
デフォルトでは bgp router-id = CLUSTER_ID なので、(CLUSTER_ID が重複しないため) デフォルトではこの機能が動作することはありません。cluster-id の設定変更により、この機能を使うことができます。
例えば前述の構成図で、RT4 と RT5 を同じ cluster-id = 45.45.45.45 でセットすると、RT4 から RT5 へ反射されたルートは破棄され、同様に RT5 から RT4 へ反射されたルートは無視されます。
実はこの話、RT4 と RT5 の直結をしなければ発生しない問題です。RFC4456 でも、飽くまでも設定ミス (misconfiguration) によるループを識別する、とあります。
RFC4456 Section 8 より引用
When an RR reflects a route, it MUST prepend the local CLUSTER_ID to the CLUSTER_LIST. If the CLUSTER_LIST is empty, it MUST create a new one. Using this attribute an RR can identify if the routing information has looped back to the same cluster due to misconfiguration.
また、ほとんどのケースでは ORIGINATOR_ID でのループ回避で十分対応できるため、cluster-id の設定についてはそこまで神経質になる必要はありません。
cluster-id を設定するコマンドは以下の通りです。
RT4(config)# router bgp 10 RT4(config-router)# bgp cluster-id 45.45.45.45
コメント