Python / JUNOS環境で、NETCONF動作を試してみる
SDN時代のインフラ構築には、APIベースの設定作業が標準になりつつあります。
通常、仮想VMであれば、OpenStackなどが活用されるところでしょう。
SDNインフラ環境でも既存ネットワークとの相互運用は必須になりますが、NW機器での諸設定が従来通りの手作業によるコンフィグ設定が行なわれている事例がまだ多いと思います。
昨今のSDN技術の台頭により、作業効率の向上、および、オペミス防止の観点から、従来のNW機器もSDNオーケストレーション的なアプローチでAPIベースで制御してしまおうという風潮が高まりつつあります。
そこで、 NETCONFというプロトコルが注目されるわけですね。
◼️ NETCONF確認用のSRXトポロジ環境
今回は、NETCONFを活用したSRX実機でのBGP設定にチャレンジしたいと思います。
なお、BGP構成は、以前の記事と全く同じ構成にします。
なお、NETCONFサーバ動作環境の構築方法は、以前のブログ記事「vSRXを活用した、JUNOSのお勉強まとめ【JUNOS初期設定 + BGP基本編】」と同じです。
SRX実機も、vSRXも同じJUNOSなので、環境構築上の違いはないです。詳しくは、こちらの参照ください。
ttsubo.hatenablog.com
今回は、さらに、NETCONF動作環境を追加しているイメージです。
+----------+ | -MacOS X-| | NETCONF | | (Client) | +----------+ + | | 192.168.100.0/24 | + .101 +----------+ +----------+ .1 | -SRX100- | .1 i-BGP .2 | -BHR4GRV-| .1 ... -------------+ | NETCONF | +----------------------+ | OpenWRT | +------------- ... 172.16.0.0/24 | (Server) | 192.168.0.0/30 | (Quagga) | 172.16.1.0/24 +----------+ +----------+ < AS65000 > < AS65000 >
SRXトポロジj構成として、SRX実機に加えて、対向BGPルータを用意する必要があります。
ただ、環境構築になるべくお金を掛けたくなかったので、対向BGPには、Buffalo"BHR-4GRV"に、OpenWRT環境をセットアップした上で、Quaggaをインストールして代用しました。
ttsubo.hatenablog.com
◼️ NETCONF環境を設定する
1. NETCONFクライアント側の環境設定
SDNオーケストレーションなどの自動制御を担う動作環境で、NETCONFを動作させるには、
オープンソースの"ncclient: Python library for NETCONF clients"が活用されることが多いようです。
github.com
ncclientは、次のような多種多様なNETCONF装置に対応しているようです。
Supported device handlers
ncclient/README.rst at master · ncclient/ncclient · GitHub
(1) 事前準備
まず、ncclientをインストールします。
$ pip install ncclient
(2) BGP設定サンプルアプリ[create-bgp.py]の配置
NETCONFを活用して、BGPコンフィグ設定を行うサンプルアプリを配置します。
from ncclient import manager from ncclient.xml_ import * import time def connect(host, port, user, password, config): conn = manager.connect(host=host, port=port, username=user, password=password, timeout=30, device_params = {'name':'junos'}, hostkey_verify=False) print "------------" print "1. conn.lock" print "------------" try: lock = conn.lock('candidate') print lock.tostring except Exception as e: print ("Error in 'conn.lock': type=[%s], message=[%s]"%(type(e), e.message)) raise print "--------------------------" print "2. conn.load_configuration" print "--------------------------" try: load_conf = conn.load_configuration(target="candidate", config=config["routing_options"], format='xml') print load_conf.tostring load_conf = conn.load_configuration(target="candidate", config=config["protocols"], format='xml') print load_conf.tostring except Exception as e: print ("Error in 'conn.load_configuration': type=[%s], message=[%s]"%(type(e), e.message)) raise print "----------------" print "3. conn.validate" print "----------------" try: validate = conn.validate() print validate.tostring except Exception as e: print ("Error in 'conn.validate': type=[%s], message=[%s]"%(type(e), e.message)) raise print "-----------------------------" print "4. conn.compare_configuration" print "-----------------------------" try: compare = conn.compare_configuration() print compare.tostring except Exception as e: print ("Error in 'conn.compare_configuration': type=[%s], message=[%s]"%(type(e), e.message)) raise print "---------------" print "5. conn.commit" print "---------------" try: commit = conn.commit() print commit.tostring except Exception as e: print ("Error in 'conn.commit': type=[%s], message=[%s]"%(type(e), e.message)) raise print "---------------" print "6. conn.unlock" print "---------------" try: unlock = conn.unlock() print unlock.tostring except Exception as e: print ("Error in 'conn.unlock': type=[%s], message=[%s]"%(type(e), e.message)) raise if __name__ == '__main__': protocols = new_ele('protocols') bgp = sub_ele(protocols, 'bgp') group = sub_ele(bgp, 'group') group_name = sub_ele(group, 'name').text = 'INTERNAL' sub_ele(group, 'type').text = 'internal' sub_ele(group, 'export').text = 'export-bgp' sub_ele(group, 'neighbor').text = '192.168.0.2' routing_options = new_ele('routing-options') sub_ele(routing_options, 'router-id').text = '10.0.0.1' sub_ele(routing_options, 'autonomous-system').text = '65000' config = {} config["routing_options"] = routing_options config["protocols"] = protocols connect('192.168.100.101', 830, 'tsubo', 'xxxxxxx', config)
(3) BGP確認サンプルアプリ[show-bgp.py]の配置
NETCONFを活用して、BGP動作確認を行うサンプルアプリを配置します。
from ncclient import manager from ncclient.xml_ import * import time def connect(host, port, user, password): conn = manager.connect(host=host, port=port, username=user, password=password, timeout=30, device_params = {'name':'junos'}, hostkey_verify=False) print "-------------------------------------" print "1. conn.get_configuration 'protocols'" print "-------------------------------------" config_filter = new_ele('configuration') sub_ele(config_filter, 'routing-options') sub_ele(config_filter, 'protocols') get_conf = conn.get_configuration(format='text', filter=config_filter) print get_conf.tostring print "----------------------------------" print "2. conn.command 'show bgp summary'" print "----------------------------------" time.sleep(10) print "root@SRX> show bgp summary" result = conn.command(command='show bgp summary', format='text') print result.xpath('output')[0].text print "-------------------------------------------------------------" print "3. conn.command 'show route receive-protocol bgp 192.168.0.2'" print "-------------------------------------------------------------" print "root@SRX> show route receive-protocol bgp 192.168.0.2" result = conn.command(command='show route receive-protocol bgp 192.168.0.2', format='text') print result.xpath('output')[0].text if __name__ == '__main__': connect('192.168.100.101', 830, 'tsubo', 'xxxxxxx')
2. NETCONFサーバ側の環境設定
NETCONFサーバ環境として、JUNOS搭載のNW機器が活用されることが多いと思います、
そこで、今回は、JUNOS搭載のNETCONFサーバ環境として、SRX実機を採用しました。
(1) 事前準備
NETCONFクライアント環境からの制御を受信できるように準備しておきます。
具体的には、NETCONFプロトコル(830ポート)を有効にしておきます。
root@SRX> configure Entering configuration mode [edit] root@SRX# set system services netconf ssh port 830
(2) その他、事前に行っておくコンフィグ設定
今回のNETCONF動作として、"protocols"と"routing-options "を設定することにします。
従って、それ以外の各種コンフィグ設定は、事前に設定しておきます。
root@SRX> show configuration |display set set version 12.1X44-D35.5 set system host-name SRX set system time-zone Asia/Tokyo set system root-authentication encrypted-password "$1$kAd32lTR$F7o4dwAbW9vY1CIV.a9kt." set system login user tsubo uid 2000 set system login user tsubo class super-user set system login user tsubo authentication encrypted-password "$1$eT7nqVkt$uCwT9W8WuBhrEhBcyKoQ5/" set system services ssh root-login allow set system services netconf ssh port 830 set system syslog archive size 100k set system syslog archive files 3 set system syslog user * any emergency set system syslog file messages any any set system syslog file messages authorization info set system syslog file interactive-commands interactive-commands any set system max-configurations-on-flash 5 set system max-configuration-rollbacks 5 set system license autoupdate url https://ae1.juniper.net/junos/key_retrieval set system ntp set interfaces fe-0/0/0 unit 0 family inet address 192.168.100.101/24 set interfaces fe-0/0/1 unit 0 family inet address 192.168.0.1/24 set interfaces fe-0/0/2 unit 0 family inet address 172.16.0.1/24 set interfaces lo0 unit 0 family inet address 10.0.0.1/32 set policy-options policy-statement export-bgp term 1 from route-filter 172.16.0.0/24 exact set policy-options policy-statement export-bgp term 1 then accept set security forwarding-options family inet6 mode packet-based set security forwarding-options family mpls mode packet-based
◼️ いよいよ、NETCONF動作を試してみる
1. BGP設定を行う
まずは、NETCONFを活用して、"routing-options"と"protocols"のコンフィグ設定を行います。
$ python create-bgp.py ------------ 1. conn.lock ------------ <rpc-reply message-id="urn:uuid:06ced48c-03d4-11e6-81aa-a45e60ba8c55"> <ok/> </rpc-reply> -------------------------- 2. conn.load_configuration -------------------------- <rpc-reply message-id="urn:uuid:06e4c133-03d4-11e6-ab26-a45e60ba8c55"> <load-configuration-results> <ok/> </load-configuration-results> </rpc-reply> <rpc-reply message-id="urn:uuid:06f798fd-03d4-11e6-afa3-a45e60ba8c55"> <load-configuration-results> <ok/> </load-configuration-results> </rpc-reply> ---------------- 3. conn.validate ---------------- <rpc-reply message-id="urn:uuid:070b022b-03d4-11e6-bca1-a45e60ba8c55"> <commit-results> </commit-results> <ok/> </rpc-reply> ----------------------------- 4. conn.compare_configuration ----------------------------- <rpc-reply message-id="urn:uuid:0a753c47-03d4-11e6-8b4f-a45e60ba8c55"> <configuration-information> <configuration-output> [edit] + routing-options { + router-id 10.0.0.1; + autonomous-system 65000; + } + protocols { + bgp { + group INTERNAL { + type internal; + export export-bgp; + neighbor 192.168.0.2; + } + } + } </configuration-output> </configuration-information> </rpc-reply> --------------- 5. conn.commit --------------- <rpc-reply message-id="urn:uuid:0b0273cc-03d4-11e6-a844-a45e60ba8c55"> <ok/> </rpc-reply> --------------- 6. conn.unlock --------------- <rpc-reply message-id="urn:uuid:1663174f-03d4-11e6-bf75-a45e60ba8c55"> <ok/> </rpc-reply>
特に、エラーも発生せずに、BGP設定を行うことができたようです。
2. BGP動作を確認してみる
それでは、NETCONFを活用して、"routing-options"と"protocols"のコンフィグ設定が正しく行われたことを確認してみます。
$ python show-bgp.py ------------------------------------- 1. conn.get_configuration 'protocols' ------------------------------------- <rpc-reply message-id="urn:uuid:2119510a-03d4-11e6-9a47-a45e60ba8c55"> <configuration-text> ## Last changed: 2016-04-16 22:06:42 JST routing-options { router-id 10.0.0.1; autonomous-system 65000; } ## Last changed: 2016-04-16 22:06:42 JST protocols { bgp { group INTERNAL { type internal; export export-bgp; neighbor 192.168.0.2; } } } </configuration-text> </rpc-reply> ---------------------------------- 2. conn.command 'show bgp summary' ---------------------------------- root@SRX> show bgp summary Groups: 1 Peers: 1 Down peers: 0 Table Tot Paths Act Paths Suppressed History Damp State Pending inet.0 1 1 0 0 0 0 Peer AS InPkt OutPkt OutQ Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped... 192.168.0.2 65000 3 4 0 0 18 1/1/1/0 0/0/0/0 ------------------------------------------------------------- 3. conn.command 'show route receive-protocol bgp 192.168.0.2' ------------------------------------------------------------- root@SRX> show route receive-protocol bgp 192.168.0.2 inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 172.16.1.0/24 192.168.0.2 0 100 I
さらに、対向BGPルータにて、SRXから配布されたBGP経路が受信できたことを確認してみます。
Quagga-3# show ip bgp BGP table version is 0, local router ID is 10.0.1.3 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *>i172.16.0.0/24 192.168.0.1 100 0 i *> 172.16.1.0/24 0.0.0.0 0 32768 i Total number of prefixes 2
以上より、NETCONFを活用することにより、NW機器への各種コンフィグ設定/確認が自動的に実施できるよう、Pythonスクリプト化することができました。
◼️ NETCONFエラー判定動作を確認する
ncclient側でのAPI制御結果として、エラー判定された時のNETCONF動作を確認しておきます。
事例1「他ユーザが、コンフィグ処理中のとき」
例えば、lo0インタフェースのDescriptionの設定に関わるコンフィグ設定が完了しないときに、NETCONFを活用して、BGP設定を行ってみます。
(1) 他ユーザによるDescriptionの設定
Description設定後、commitを行わず、放置しておきます。
root@SRX# set interfaces lo0 description lo0_description [edit] root@SRX# show |compare [edit interfaces lo0] + description lo0_description; [edit]
(2) NETCONFによるBGP設定
このとき、NETCONFのlock処理がエラー判定となるので、BGP設定サンプルアプリ[create-bgp.py]が異常終了することを確認します。
$ python create-bgp.py ------------ 1. conn.lock ------------ Error in 'conn.lock': type=[<class 'ncclient.operations.rpc.RPCError'>], message=[ configuration database modified ] Traceback (most recent call last): File "create-bgp.py", line 99, in <module> connect('192.168.100.101', 830, 'tsubo', 'xxxxxxxx', config) File "create-bgp.py", line 18, in connect lock = conn.lock('candidate') File "/usr/local/lib/python2.7/site-packages/ncclient/manager.py", line 158, in wrapper return self.execute(op_cls, *args, **kwds) File "/usr/local/lib/python2.7/site-packages/ncclient/manager.py", line 228, in execute raise_mode=self._raise_mode).request(*args, **kwds) File "/usr/local/lib/python2.7/site-packages/ncclient/operations/lock.py", line 35, in request return self._request(node) File "/usr/local/lib/python2.7/site-packages/ncclient/operations/rpc.py", line 336, in _request raise self._reply.error ncclient.operations.rpc.RPCError: configuration database modified
期待どおりに、ncclient側でのNETCONF処理でエラー判定された場合には、Python処理がException終了してくれました。
事例2「事前設定のコンフィグ不備のとき」
BGP設定サンプルアプリ[create-bgp.py]では、事前にpolicy-statement "export-bgp"を設定しておく必要があります。
ここでは、あえて、事前に、policy-statementを削除してみます。
(1) policy-statement "export-bgp"のコンフィグ設定不備
policy-statementを削除しておきます。
root@SRX# delete policy-options [edit] root@SRX# show |compare [edit] - policy-options { - policy-statement export-bgp { - term 1 { - from { - route-filter 172.16.0.0/24 exact; - } - then accept; - } - } - } [edit] root@SRX# commit commit complete [edit]
(2) NETCONFによるBGP設定
このとき、NETCONFのvalidate処理がエラー判定となるので、BGP設定サンプルアプリ[create-bgp.py]が異常終了することを確認します。
$ python create-bgp.py ------------ 1. conn.lock ------------ <rpc-reply message-id="urn:uuid:8853948f-0454-11e6-975b-a45e60ba8c55"> <ok/> </rpc-reply> -------------------------- 2. conn.load_configuration -------------------------- <rpc-reply message-id="urn:uuid:88685466-0454-11e6-a6e1-a45e60ba8c55"> <load-configuration-results> <ok/> </load-configuration-results> </rpc-reply> <rpc-reply message-id="urn:uuid:887ab21c-0454-11e6-bdd1-a45e60ba8c55"> <load-configuration-results> <ok/> </load-configuration-results> </rpc-reply> ---------------- 3. conn.validate ---------------- Error in 'conn.validate': type=[<class 'ncclient.operations.rpc.RPCError'>], message=[error: Policy error: Policy export-bgp referenced but not defined error: BGP: export list not applied error: configuration check-out failed] Traceback (most recent call last): File "create-bgp.py", line 99, in <module> connect('192.168.100.101', 830, 'tsubo', 'xxxxxxxx', config) File "create-bgp.py", line 44, in connect validate = conn.validate() File "/usr/local/lib/python2.7/site-packages/ncclient/manager.py", line 158, in wrapper return self.execute(op_cls, *args, **kwds) File "/usr/local/lib/python2.7/site-packages/ncclient/manager.py", line 228, in execute raise_mode=self._raise_mode).request(*args, **kwds) File "/usr/local/lib/python2.7/site-packages/ncclient/operations/edit.py", line 123, in request return self._request(node) File "/usr/local/lib/python2.7/site-packages/ncclient/operations/rpc.py", line 334, in _request raise RPCError(to_ele(self._reply._raw), errs=errors) ncclient.operations.rpc.RPCError: error: Policy error: Policy export-bgp referenced but not defined error: BGP: export list not applied error: configuration check-out failed
期待どおりに、ncclient側でのNETCONF処理でエラー判定された場合には、Python処理がException終了してくれました。
◼️ 最後に、
SDNインフラと相互接続しているNW機器を、SDNオーケストレーション層から順序制御できる仕組みとして、NETCONFの活用は、とても有効であると思います。
今後も、クラウド基盤として、OpenStackが活用される事例は、ますます増えていくと思います。OpenStackとNETCONFの動作連携を担う仕組みとして、heat プロジェクトの役割りの重要性が、どんどん増していくのでしょう。
vSRXを活用した、JUNOSのお勉強まとめ【mpBGP / MPLS-VPN 続編】
今回も、引き続き、JUNOSのお勉強メモです。
ttsubo.hatenablog.com
前回は、PE - CE間は、Staticルーティングを前提としておりました。
今回は、PE - CE間で、eBGPによるダイナミックルーティングの設定に変更します。
◼︎ vSRXトポロジ構成
だんだんと、トポロジ図が複雑になってしまったので、今回は、OSPF / LDP面の記載を割愛しました。
あと、前回からの差分は、
・pc1の箇所に、VyOS-1を配備
・VyOS-1とvSRX-1間をeBGPに変更
vSRX-1 vSRX-3 +---------+ +---------+ | | | | | 10.0.0.1| vSRX-2 | 10.0.0.3| | +-----+ | +----+ | +-----+ | | | GRT +-------------------+ GRT | | | +--+--+ | +----+ | +--+--+ | | | | | | | 20.0.0.1/24 +--------+ 172.16.0.0/30 | +--+--+ | | +--+--+ | 172.16.1.0/30 +-----+ 10.0.0.1/24 20.0.1.1/24 | VyOS-1 +-----------------+ VRF | | | | VRF +-----------------+ pc2 | 10.0.1.1/24 +--------+ .1 .2 | +-----+ | | +-----+ | .1 .2 +-----+ 10.0.2.1/24 AS: 65001 +---------+ +---------+ AS: 65000 AS: 65000 : : : : : : : < --------- > : : < --------- > : : < --------- > : eBGP mp-iBGP static
◼︎ JUNOSルーティング設定
(0) 事前準備
前回の記事で設定したダイレクト接続経路"172.16.0.0/30"を再配布するコンフィグ設定を、削除しておきます。
それ以外のコンフィグ設定は、前回のまま活用することとします。
root@vSRX-1# delete routing-instances VPN-A vrf-table-label root@vSRX-1# commit
(1) VRFルーティングインスタンス基本設定
vSRX-1側でのコンフィグは、概ね、前回を設定を踏襲します。唯一、VRF内部で、eBGP Peerを動作させる設定のみ追加します。
なお、vSRX-3側でのコンフィグは、全く変更の必要がありません。
1. routing-instancesを設定する
root@vSRX-1# set routing-instances VPN-A protocols bgp group VPN-A-BGP type external root@vSRX-1# set routing-instances VPN-A protocols bgp group VPN-A-BGP peer-as 65001 root@vSRX-1# set routing-instances VPN-A protocols bgp group VPN-A-BGP neighbor 172.16.0.1 [edit] root@vSRX-1# show | compare [edit routing-instances VPN-A] + protocols { + bgp { + group VPN-A-BGP { + type external; + peer-as 65001; + neighbor 172.16.0.1; + } + } + } root@vSRX-1# commit
2. BGP Peerの状態を確認しておく
root@vSRX-1> show bgp neighbor 172.16.0.1 Peer: 172.16.0.1+35346 AS 65001 Local: 172.16.0.2+179 AS 65000 Type: External State: Established Flags: <Sync> Last State: OpenConfirm Last Event: RecvKeepAlive Last Error: None Options: <Preference PeerAS Refresh> Holdtime: 90 Preference: 170 Number of flaps: 0 Peer ID: 172.16.0.1 Local ID: 172.16.0.2 Active Holdtime: 90 Keepalive Interval: 30 Group index: 1 Peer index: 0 BFD: disabled, down Local Interface: ge-0/0/0.0 NLRI for restart configured on peer: inet-unicast NLRI advertised by peer: inet-unicast NLRI for this session: inet-unicast Peer supports Refresh capability (2) Stale routes from peer are kept for: 300 Peer does not support Restarter functionality Peer does not support Receiver functionality Peer supports 4 byte AS extension (peer-as 65001) Peer does not support Addpath Table VPN-A.inet.0 Bit: 20001 RIB State: BGP restart is complete RIB State: VPN restart is complete Send state: in sync Active prefixes: 2 Received prefixes: 2 Accepted prefixes: 2 Suppressed due to damping: 0 Advertised prefixes: 4 Last traffic (seconds): Received 21 Sent 5 Checked 51 Input messages: Total 10 Updates 2 Refreshes 0 Octets 268 Output messages: Total 11 Updates 1 Refreshes 0 Octets 301 Output Queue[1]: 0 (VPN-A.inet.0, inet-unicast)
3. VPN-Aのアドバタイズ経路を確認しておく
対向側(VyOS-1)からアドバタイズされた経路を受信できるようになりました。
root@vSRX-1> show route receive-protocol bgp 172.16.0.1 table VPN-A.inet.0 VPN-A.inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 20.0.0.0/24 172.16.0.1 1 65001 I * 20.0.1.0/24 172.16.0.1 1 65001 I
つづいて、対向側(VyOS-1)へのアドバイズを確認してみました。
通常のBGP設定と異なり、mpBGP/MPLS-VPN設定の場合は、Export policy適用せずとも、アドバタイズされるようです。
root@vSRX-1> show route advertising-protocol bgp 172.16.0.1 VPN-A.inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 10.0.0.0/24 Self I * 10.0.1.0/24 Self I * 10.0.2.0/24 Self I * 172.16.1.0/30 Self I
vSRX-1でのVRFテーブルの保持状態を確認してみます。
root@vSRX-1> show route table VPN-A.inet.0 VPN-A.inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.0/24 *[BGP/170] 03:13:11, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299856, Push 299792(top) 10.0.1.0/24 *[BGP/170] 03:13:11, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299856, Push 299792(top) 10.0.2.0/24 *[BGP/170] 03:13:11, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299856, Push 299792(top) 20.0.0.0/24 *[BGP/170] 00:13:36, MED 1, localpref 100 AS path: 65001 I, validation-state: unverified > to 172.16.0.1 via ge-0/0/0.0 20.0.1.0/24 *[BGP/170] 00:13:36, MED 1, localpref 100 AS path: 65001 I, validation-state: unverified > to 172.16.0.1 via ge-0/0/0.0 172.16.0.0/30 *[Direct/0] 06:00:41 > via ge-0/0/0.0 172.16.0.2/32 *[Local/0] 06:00:41 Local via ge-0/0/0.0 172.16.1.0/30 *[BGP/170] 03:13:11, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299856, Push 299792(top)
(2) エンド端末間での疎通確認
まず、VyOS-1側でのBGPテーブルを確認しておきます。
vyos# show ip bgp BGP table version is 0, local router ID is 172.16.0.1 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *> 10.0.0.0/24 172.16.0.2 0 65000 i *> 10.0.1.0/24 172.16.0.2 0 65000 i *> 10.0.2.0/24 172.16.0.2 0 65000 i *> 20.0.0.0/24 0.0.0.0 1 32768 i *> 20.0.1.0/24 0.0.0.0 1 32768 i *> 172.16.1.0/30 172.16.0.2 0 65000 i Total number of prefixes 6
エンドエンド端末間でpingをうってみましょう。
1. "172.16.1.2"宛にpingをうってみる
vyos# ping 172.16.1.2 PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data. 64 bytes from 172.16.1.2: icmp_req=1 ttl=61 time=0.624 ms 64 bytes from 172.16.1.2: icmp_req=2 ttl=61 time=1.69 ms 64 bytes from 172.16.1.2: icmp_req=3 ttl=61 time=0.810 ms 64 bytes from 172.16.1.2: icmp_req=4 ttl=61 time=0.700 ms 64 bytes from 172.16.1.2: icmp_req=5 ttl=61 time=0.747 ms ^C --- 172.16.1.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 3999ms rtt min/avg/max/mdev = 0.624/0.914/1.690/0.393 ms
pingが成功しました!
2. "10.0.0.1"宛にpingをうってみる
vyos# ping 10.0.0.1 PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data. 64 bytes from 10.0.0.1: icmp_req=1 ttl=61 time=0.735 ms 64 bytes from 10.0.0.1: icmp_req=2 ttl=61 time=0.826 ms 64 bytes from 10.0.0.1: icmp_req=3 ttl=61 time=0.834 ms 64 bytes from 10.0.0.1: icmp_req=4 ttl=61 time=0.716 ms 64 bytes from 10.0.0.1: icmp_req=5 ttl=61 time=0.921 ms ^C --- 10.0.0.1 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 3996ms rtt min/avg/max/mdev = 0.716/0.806/0.921/0.078 ms
こちらも、pingが成功しました!
◼︎ 最終的なコンフィグ内容の確認
1. vSRX-1側コンフィグ内容
root@vSRX-1> show configuration ... (snip) routing-options { router-id 10.0.0.1; autonomous-system 65000; } protocols { mpls { interface ge-0/0/1.0; } bgp { group L3VPN { type internal; local-address 10.0.0.1; family inet-vpn { unicast; } neighbor 10.0.0.3; } } ospf { area 0.0.0.0 { interface ge-0/0/1.0; interface lo0.0 { passive; } } } ldp { interface ge-0/0/1.0; } } routing-instances { VPN-A { instance-type vrf; interface ge-0/0/0.0; route-distinguisher 65000:101; vrf-target target:65000:101; protocols { bgp { group VPN-A-BGP { type external; peer-as 65001; neighbor 172.16.0.1; } } } } }
2. VyOS-1側コンフィグ内容
vyos# show running-config Building configuration... Current configuration: ! log syslog log facility local7 ! debug ospf6 lsa unknown ! interface eth0 ipv6 nd suppress-ra link-detect ! interface eth1 ip address 172.16.0.1/30 ipv6 nd suppress-ra link-detect ! interface eth2 ip address 20.0.0.1/24 ipv6 nd suppress-ra link-detect ! interface eth3 ip address 20.0.1.1/24 ipv6 nd suppress-ra link-detect ! interface lo ! router bgp 65001 bgp router-id 172.16.0.1 bgp network import-check network 20.0.0.0/24 network 20.0.1.0/24 neighbor 172.16.0.2 remote-as 65000 ! ip forwarding ipv6 forwarding ! line vty ! end
◼︎ 最後に
mpBGP /MPLS-VPN構成における"GRT"、"VRF"の関係と、おのおので動作するBGP動作がイメージできれば、JUNOSコンフィグの階層構造は、とても理解しやすいものであると感じました。
以上です。
vSRXを活用した、JUNOSのお勉強まとめ【mpBGP / MPLS-VPN編】
今回も、引き続き、JUNOSのお勉強メモです。
ttsubo.hatenablog.com
◼︎ 前回の記事での技術課題
エンド端末間での疎通確認において、エンド端末"pc1"から、エンド端末"pc2"側"10.0.0.1"に対して、pingをうってみたところ、
pingは成功した。この時、pc2側でパケットキャプチャを行ったところ、ICMP Echo Request / Replyが観測されなかった。
「誰がICMP Echo Replyを送信したのだろうか?」というものでした。
まず、こちらのトポロジ構成をご覧ください。
BGP運用経験の豊富な方は、すでに発生事象の原因にお気づきだと思います。
[ AS: 65000 ] [ AS: 65000 ] 10.0.0.1 10.0.0.2 10.0.0.3 +---------+ +--------+ +---------+ | | | | | | | vSRX-1 | | vSRX-2 | | vSRX-3 | +-----+ 172.16.0.0/30 | +-----+ | 192.168.0.0/30 | | 192.168.1.0/30 | +-----+ | 172.16.1.0/30 +-----+ 10.0.0.1/24 | pc1 +-----------------+ GRT +----------------+ | | +----------------+ GRT +-----------------+ pc2 | 10.0.1.1/24 +-----+ .1 .2 | +-----+ | .1 .2 | | .1 .2 | +-----+ | .1 .2 +-----+ 10.0.2.1/24 | | | | | | +---------+ +--------+ +---------+ : : : : : : : : : < --------- > : : < ---------- > : : < ---------- > : : < --------- > : static : LDP(ospf) LDP(ospf) : static : : : : : < ------------------------------------ > : iBGP
vSRX-1側での追跡調査
まず、vSRX-1で保持しているルーティング情報を確認してみましょう。
root@vSRX-1> show route table inet.0 inet.0: 13 destinations, 13 routes (13 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.0/24 *[BGP/170] 03:08:48, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299792 10.0.0.1/32 *[Direct/0] 07:51:02 > via lo0.0 10.0.0.2/32 *[OSPF/10] 04:12:50, metric 1 > to 192.168.0.2 via ge-0/0/1.0 10.0.0.3/32 *[OSPF/10] 04:12:50, metric 2 > to 192.168.0.2 via ge-0/0/1.0 10.0.1.0/24 *[BGP/170] 03:08:48, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299792 10.0.2.0/24 *[BGP/170] 03:08:48, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299792 172.16.0.0/30 *[Direct/0] 06:30:00 > via ge-0/0/0.0 172.16.0.2/32 *[Local/0] 06:30:00 Local via ge-0/0/0.0 172.16.1.0/30 *[BGP/170] 03:25:48, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299792 192.168.0.0/30 *[Direct/0] 06:32:29 > via ge-0/0/1.0 192.168.0.1/32 *[Local/0] 06:32:29 Local via ge-0/0/1.0 192.168.1.0/30 *[OSPF/10] 04:12:50, metric 2 > to 192.168.0.2 via ge-0/0/1.0 224.0.0.5/32 *[OSPF/10] 04:13:05, metric 1 MultiRecv
はい、お察しの通りでしたね。
vSRXでのルーティング情報は、グローバルルーティングテーブル(GRT)で全て保持することになります。
このGRTでは、OSPF, BGPなどのルーティングプロトコルで学習したルーティング情報に加えて、スタティック経路や、ダイレクト接続された経路も保持することになります。
そして、vSRX-1では、pc1から10.0.0.1”宛のIPパケットを受信した際には、このGRTをルックアップして、次の転送先が決定されますが、この場合だと、ループバックインタフェースが選定されます。
最終的に、vSRX-1のルップバックインタフェースが、ICMP Echo Replyを送信することになります。
これが、前回記事での技術課題の発生原因です。
課題解決を目指して ... mpBGP/ MPLS-VPM化
そもそも、エンド端末を使う人の立場から述べると、
「エンド端末"pc1", "pc2"間で通信できればよくて、vSRX側で構成されるバックボーンネットワークと通信したいわけではない。」
と主張されるのでしょう。
この技術課題を解決する手段として、mpBGP / MPLS-VPN適用が有望だと思います。
そこで、今回のJUNOSのお勉強の素材として、mpBGP / MPLS-VPN対応に着手してみます。
◼︎ vSRXトポロジ構成
前回と同様のトポロジ構成になっています。このトポロジ構成の特徴は、mpBGP / MPLS-VPN対応です。
従って、GRT / VRFの関係がわかりやすいよう記載しました。
[ AS: 65000 ] [ AS: 65000 ] 10.0.0.1 10.0.0.2 10.0.0.3 +---------+ +--------+ +---------+ | | | | | | | vSRX-1 | | vSRX-2 | | vSRX-3 | | +-----+ | 192.168.0.0/30 | | 192.168.1.0/30 | +-----+ | | | GRT +----------------+ | | +----------------+ GRT | | | +--+--+ | .1 .2 | | .1 .2 | +--+--+ | | | | | | | | | +-----+ 172.16.0.0/30 | +--+--+ | | | | +--+--+ | 172.16.1.0/30 +-----+ 10.0.0.1/24 | pc1 +-----------------+ VRF | | | | | | VRF +-----------------+ pc2 | 10.0.1.1/24 +-----+ .1 .2 | +-----+ | | | | +-----+ | .1 .2 +-----+ 10.0.2.1/24 +---------+ +--------+ +---------+ : : : : : : : : : < --------- > : : < ---------- > : : < ---------- > : : < --------- > : static : LDP(ospf) LDP(ospf) : static : : : : : < ------------------------------------ > : mp-iBGP
ここでのポイントは、エンド端末を収容するvSRXルータは、ProviderEdge(PE)ルータの役割を担うということです。
なお、PEルータでは、GRT, VRFテーブルをおのおの保持しており、エンド端末との間で共有すべきルーティング情報は、VRFテーブルで保持することになります。
PEルータ間でのエンド端末に関わるBGP経路情報を共有する際には、GRTテーブルを介してmp-BGP UPDATEメッセージでやりとりが行われます。そして、最終的にVRFテーブルに保持されます。
◼︎ JUNOSルーティング設定
mpBGP / MPLS-VPNに関わる各種ルーティング設定を行います。
(0) 事前準備
前回の記事で設定したBGP関連のコンフィグ設定を、全て削除しておきます。
ただし、OSPF, LDPのコンフィグ設定は、前回のまま活用することとします。
root@vSRX-1# delete protocols bgp root@vSRX-1# delete policy-options [edit] root@vSRX-1# show | compare [edit protocols] - bgp { - group INTERNAL { - type internal; - local-address 10.0.0.1; - export export-bgp; - neighbor 10.0.0.3; - } - } [edit] - policy-options { - policy-statement export-bgp { - term 1 { - from { - route-filter 172.16.0.0/30 exact; - } - then accept; - } - } - } root@vSRX-1# commit
vSRX-3では、スタティック経路の設定も削除しておきます。
root@vSRX-3# delete routing-options static
(1) mpBGP / MPLS-VPN基本設定
1. routing-instancesを設定する
root@vSRX-1# set routing-instances VPN-A instance-type vrf root@vSRX-1# set routing-instances VPN-A interface ge-0/0/0.0 root@vSRX-1# set routing-instances VPN-A route-distinguisher 65000:101 root@vSRX-1# set routing-instances VPN-A vrf-target target:65000:101 root@vSRX-1# show | compare [edit] + routing-instances { + VPN-A { + instance-type vrf; + interface ge-0/0/0.0; + route-distinguisher 65000:101; + vrf-target target:65000:101; + } + } root@vSRX-1# commit
2. protocolsを設定する
root@vSRX-1# set protocols bgp group L3VPN type internal root@vSRX-1# set protocols bgp group L3VPN local-address 10.0.0.1 root@vSRX-1# set protocols bgp group L3VPN neighbor 10.0.0.3 root@vSRX-1# set protocols bgp group L3VPN family inet-vpn unicast root@vSRX-1# show | compare [edit protocols] + bgp { + group L3VPN { + type internal; + local-address 10.0.0.1; + family inet-vpn { + unicast; + } + neighbor 10.0.0.3; + } + } root@vSRX-1# commit
3. static routeを設定する
vSRX-3側では、pc2配下のスタティック経路をエントリしておく必要があります。
set routing-instances VPN-A routing-options static route 10.0.0.0/24 next-hop 172.16.1.2 set routing-instances VPN-A routing-options static route 10.0.1.0/24 next-hop 172.16.1.2 set routing-instances VPN-A routing-options static route 10.0.2.0/24 next-hop 172.16.1.2 root@vSRX-3# show | compare [edit routing-instances VPN-A routing-options static] + route 10.0.0.0/24 next-hop 172.16.1.2; + route 10.0.1.0/24 next-hop 172.16.1.2; + route 10.0.2.0/24 next-hop 172.16.1.2; root@vSRX-3# commit
4. BGP Peerの状態を確認しておく
root@vSRX-1> show bgp neighbor Peer: 10.0.0.3+50824 AS 65000 Local: 10.0.0.1+179 AS 65000 Type: Internal State: Established Flags: <Sync> Last State: OpenConfirm Last Event: RecvKeepAlive Last Error: None Options: <Preference LocalAddress AddressFamily Rib-group Refresh> Address families configured: inet-vpn-unicast Local Address: 10.0.0.1 Holdtime: 90 Preference: 170 Number of flaps: 0 Peer ID: 10.0.0.3 Local ID: 10.0.0.1 Active Holdtime: 90 Keepalive Interval: 30 Group index: 0 Peer index: 0 BFD: disabled, down NLRI for restart configured on peer: inet-vpn-unicast NLRI advertised by peer: inet-vpn-unicast NLRI for this session: inet-vpn-unicast Peer supports Refresh capability (2) Stale routes from peer are kept for: 300 Peer does not support Restarter functionality NLRI that restart is negotiated for: inet-vpn-unicast NLRI of received end-of-rib markers: inet-vpn-unicast NLRI of all end-of-rib markers sent: inet-vpn-unicast Peer supports 4 byte AS extension (peer-as 65000) Peer does not support Addpath Table bgp.l3vpn.0 RIB State: BGP restart is complete RIB State: VPN restart is complete Send state: not advertising Active prefixes: 4 Received prefixes: 4 Accepted prefixes: 4 Suppressed due to damping: 0 Table VPN-A.inet.0 Bit: 20000 RIB State: BGP restart is complete RIB State: VPN restart is complete Send state: in sync Active prefixes: 4 Received prefixes: 4 Accepted prefixes: 4 Suppressed due to damping: 0 Advertised prefixes: 1 Last traffic (seconds): Received 16 Sent 22 Checked 32 Input messages: Total 137 Updates 8 Refreshes 0 Octets 2973 Output messages: Total 136 Updates 7 Refreshes 0 Octets 2913 Output Queue[1]: 0 (VPN-A.inet.0, inet-vpn-unicast)
5. VPN-Aのアドバタイズ経路を確認しておく
通常のBGP設定と異なり、mpBGP/MPLS-VPN設定の場合は、vSRX-3ルータ側でExport policy適用せずとも、アドバタイズされるようです。
対向側(vSRX-3ルータ)からアドバタイズされた経路を受信できるようになりました。
root@vSRX-1> show route receive-protocol bgp 10.0.0.3 table bgp.l3vpn.0 bgp.l3vpn.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path 65000:101:10.0.0.0/24 * 10.0.0.3 100 I 65000:101:10.0.1.0/24 * 10.0.0.3 100 I 65000:101:10.0.2.0/24 * 10.0.0.3 100 I 65000:101:172.16.1.0/30 * 10.0.0.3 100 I
つづいて、対向側(vSRX-3ルータ)へのアドバイズを確認してみました。
しかしながら、"172.16.0.0/30"は、アドバタイズされていないようです。
root@vSRX-1> show route advertising-protocol bgp 10.0.0.3 VPN-A.inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 172.16.0.0/30 Not advertised 100 I
ここでのトラブル解析として、各々のvSRXルータでのVRFテーブルの保持状態を確認してみます。
まずは、vSRX-1側から確認します。
root@vSRX-1> show route table VPN-A.inet.0 VPN-A.inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.0/24 *[BGP/170] 00:43:58, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299808, Push 299792(top) 10.0.1.0/24 *[BGP/170] 00:17:30, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299808, Push 299792(top) 10.0.2.0/24 *[BGP/170] 00:17:30, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299808, Push 299792(top) 172.16.0.0/30 *[Direct/0] 01:21:51 > via ge-0/0/0.0 172.16.0.2/32 *[Local/0] 01:21:51 Local via ge-0/0/0.0 172.16.1.0/30 *[BGP/170] 00:43:58, localpref 100, from 10.0.0.3 AS path: I, validation-state: unverified > to 192.168.0.2 via ge-0/0/1.0, Push 299808, Push 299792(top)
問題なく、VRFテーブルは構築できているようです。
つづいて、vSRX-3側でも確認してみます。
root@vSRX-3> show route table VPN-A.inet.0 VPN-A.inet.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.0/24 *[Static/5] 00:46:45 > to 172.16.1.2 via ge-0/0/1.0 10.0.1.0/24 *[Static/5] 00:20:17 > to 172.16.1.2 via ge-0/0/1.0 10.0.2.0/24 *[Static/5] 00:20:17 > to 172.16.1.2 via ge-0/0/1.0 172.16.1.0/30 *[Direct/0] 01:12:49 > via ge-0/0/1.0 172.16.1.1/32 *[Local/0] 01:12:49 Local via ge-0/0/1.0
やはり、vSRX-1側でのダイレクト接続経路"172.16.0.0/30"が、VRFテーブルに保持されておりませんね。
どうやら、pc1側では、スタティック経路が存在しないので、next-hopに該当するダイレクト接続経路"172.16.0.0/30"を、敢えて、BGP経路としてアドバタイズしていないようです。
6. ダイレクト接続経路"172.16.0.0/30"を再配布するには、
CiscoのIOSの"redistribute connected"コマンドのように、BGP経路に再配布する方法をいろいろ試行錯誤してみましたが、うまく行きません。そこで、不本意ながら、default-routeを再配布する方法で、問題回避を試みました。
root@vSRX-1# set routing-instances VPN-A routing-options static route 0.0.0.0/0 next-hop 172.16.0.1 [edit] root@vSRX-1# show | compare [edit routing-instances VPN-A] + routing-options { + static { + route 0.0.0.0/0 next-hop 172.16.0.1; + } + } root@vSRX-1# commit
とりあえず、vSRX-1側で、ダイレクト接続経路"172.16.0.0/30"をアドバタイズするようになりました。
root@vSRX-1> show route advertising-protocol bgp 10.0.0.3 VPN-A.inet.0: 7 destinations, 7 routes (7 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 0.0.0.0/0 Self 100 I * 172.16.0.0/30 Self 100 I
改めて、vSRX-3側でのVRFテーブルの保持状態を確認してみます。
root@vSRX-3> show route table VPN-A.inet.0 VPN-A.inet.0: 7 destinations, 7 routes (7 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 0.0.0.0/0 *[BGP/170] 00:03:03, localpref 100, from 10.0.0.1 AS path: I, validation-state: unverified > to 192.168.1.1 via ge-0/0/0.0, Push 299824, Push 299776(top) 10.0.0.0/24 *[Static/5] 00:57:51 > to 172.16.1.2 via ge-0/0/1.0 10.0.1.0/24 *[Static/5] 00:31:23 > to 172.16.1.2 via ge-0/0/1.0 10.0.2.0/24 *[Static/5] 00:31:23 > to 172.16.1.2 via ge-0/0/1.0 172.16.0.0/30 *[BGP/170] 00:03:03, localpref 100, from 10.0.0.1 AS path: I, validation-state: unverified > to 192.168.1.1 via ge-0/0/0.0, Push 299824, Push 299776(top) 172.16.1.0/30 *[Direct/0] 01:23:55 > via ge-0/0/1.0 172.16.1.1/32 *[Local/0] 01:23:55 Local via ge-0/0/1.0
今回は、問題なく、VRFテーブルは構築できているようです。
(2) エンド端末間での疎通確認
エンドエンド端末間でpingをうってみましょう。
1. "172.16.1.2"宛にpingをうってみる
tsubo@pc1:~$ ping 172.16.1.2 PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data. 64 bytes from 172.16.1.2: icmp_seq=1 ttl=61 time=0.849 ms 64 bytes from 172.16.1.2: icmp_seq=2 ttl=61 time=0.905 ms 64 bytes from 172.16.1.2: icmp_seq=3 ttl=61 time=0.829 ms 64 bytes from 172.16.1.2: icmp_seq=4 ttl=61 time=0.759 ms 64 bytes from 172.16.1.2: icmp_seq=5 ttl=61 time=0.960 ms ^C --- 172.16.1.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4001ms rtt min/avg/max/mdev = 0.759/0.860/0.960/0.073 ms
pingが成功しました!
この時、pc2側でtcpdumpを動作させて、パケットモニタリングしておきます。
root@pc2:~# tcpdump -i eth1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes 23:04:48.390124 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2594, seq 1, length 64 23:04:48.390160 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2594, seq 1, length 64 23:04:49.390956 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2594, seq 2, length 64 23:04:49.390985 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2594, seq 2, length 64 23:04:50.390871 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2594, seq 3, length 64 23:04:50.390901 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2594, seq 3, length 64 23:04:51.390847 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2594, seq 4, length 64 23:04:51.390876 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2594, seq 4, length 64 23:04:52.391451 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2594, seq 5, length 64 23:04:52.391480 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2594, seq 5, length 64 23:04:53.393256 ARP, Request who-has 172.16.1.1 tell 172.16.1.2, length 28 23:04:53.394175 ARP, Reply 172.16.1.1 is-at 00:0c:29:70:81:a6 (oui Unknown), length 46 ^C 12 packets captured 12 packets received by filter 0 packets dropped by kernel
期待通り、ICMP Echo Request / Replyが観測できました。
2. "10.0.0.1"宛にpingをうってみる
tsubo@pc1:~$ ping 10.0.0.1 PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data. 64 bytes from 10.0.0.1: icmp_seq=1 ttl=61 time=1.68 ms 64 bytes from 10.0.0.1: icmp_seq=2 ttl=61 time=1.10 ms 64 bytes from 10.0.0.1: icmp_seq=3 ttl=61 time=0.794 ms 64 bytes from 10.0.0.1: icmp_seq=4 ttl=61 time=0.975 ms 64 bytes from 10.0.0.1: icmp_seq=5 ttl=61 time=0.763 ms ^C --- 10.0.0.1 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4005ms rtt min/avg/max/mdev = 0.763/1.064/1.685/0.334 ms
こちらも、pingが成功しましたね!
この時、pc2側でtcpdumpを動作させて、パケットモニタリングしておきます。
root@pc2:~# tcpdump -i eth1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes 23:07:52.149141 IP 172.16.0.1 > 10.0.0.1: ICMP echo request, id 2595, seq 1, length 64 23:07:52.149182 IP 10.0.0.1 > 172.16.0.1: ICMP echo reply, id 2595, seq 1, length 64 23:07:53.150952 IP 172.16.0.1 > 10.0.0.1: ICMP echo request, id 2595, seq 2, length 64 23:07:53.150983 IP 10.0.0.1 > 172.16.0.1: ICMP echo reply, id 2595, seq 2, length 64 23:07:54.152578 IP 172.16.0.1 > 10.0.0.1: ICMP echo request, id 2595, seq 3, length 64 23:07:54.152607 IP 10.0.0.1 > 172.16.0.1: ICMP echo reply, id 2595, seq 3, length 64 23:07:55.151633 IP 172.16.0.1 > 10.0.0.1: ICMP echo request, id 2595, seq 4, length 64 23:07:55.151664 IP 10.0.0.1 > 172.16.0.1: ICMP echo reply, id 2595, seq 4, length 64 23:07:56.153395 IP 172.16.0.1 > 10.0.0.1: ICMP echo request, id 2595, seq 5, length 64 23:07:56.153424 IP 10.0.0.1 > 172.16.0.1: ICMP echo reply, id 2595, seq 5, length 64 23:07:57.152492 ARP, Request who-has 172.16.1.1 tell 172.16.1.2, length 28 23:07:57.153588 ARP, Reply 172.16.1.1 is-at 00:0c:29:70:81:a6 (oui Unknown), length 46 ^C 12 packets captured 12 packets received by filter 0 packets dropped by kernel
こちらも、期待通り、ICMP Echo Request / Replyが観測できましたね!
ただし、pc1拠点相当を、さらに追加する場合には、default-routeを再配布する方法は採用できません。
CiscoのIOSの"redistribute connected"コマンド相当をサルベージする必要があるのかもしれません。
◼︎ 3/27追記「@kazubuさんから、回避策を教えてもらいました」
こちらが、Direct経路がBGPアドバタイズ経路に乗らない件の回避策になります。
では、早速、試してみましょう。
1. 暫定的に設定しておいたdefault-routeの再配布の設定を削除する
root@vSRX-1# delete routing-instances VPN-A routing-options static root@vSRX-1# commit
2. routing-instanceにvrf-table-labelを設定する
root@vSRX-1# set routing-instances VPN-A vrf-table-label root@vSRX-1# show | compare [edit routing-instances VPN-A] + vrf-table-label; root@vSRX-1# commit
vSRX-1側で、ダイレクト接続経路"172.16.0.0/30"をアドバタイズされるようになりました。
root@vSRX-1> show route advertising-protocol bgp 10.0.0.3 VPN-A.inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 172.16.0.0/30 Self 100 I
対向側(vSRX-3)でも、ダイレクト接続経路"172.16.0.0/30"が、受信できたことも確認できました。
root@vSRX-3> show route receive-protocol bgp 10.0.0.1 table bgp.l3vpn.0 bgp.l3vpn.0: 1 destinations, 1 routes (1 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path 65000:101:172.16.0.0/30 * 10.0.0.1 100 I
以下、個人的な所感です。
今まで、「VRFにて保持されるルーティング情報は、一律、BGP Peerにアドバタイズされる。」と理解しておりました。
ところが、通常のMPLSルータでは、「VRFにて保持されるルーティング情報は、next-hopが検出されるタイミングでVPNラベルが付与されるので、BGP Peerへのアドバタイズも可能になる」という仕様なんですね。
ダイレクト接続経路の場合だと、このままでは、next-hopが検出されないので、BGP Peerへのアドバタイズは行われない。
そこで、ダイレクト接続経路に対して、明示的にVPNラベルを付与する必要がある。
その方法は、JUNOSの場合だと、"vhf-table-label"を設定し、CiscoのIOSの場合だと、"redistribute connected"を設定する。
ちょっとだけ、賢くなりました。これにて、一件落着という感じです。
◼︎ 最終的なコンフィグ内容の確認
1. vSRX-1側コンフィグ内容
root@vSRX-1> show configuration ... (snip) routing-options { router-id 10.0.0.1; autonomous-system 65000; } protocols { mpls { interface ge-0/0/1.0; } bgp { group L3VPN { type internal; local-address 10.0.0.1; family inet-vpn { unicast; } neighbor 10.0.0.3; } } ospf { area 0.0.0.0 { interface ge-0/0/1.0; interface lo0.0 { passive; } } } ldp { interface ge-0/0/1.0; } } routing-instances { VPN-A { instance-type vrf; interface ge-0/0/0.0; route-distinguisher 65000:101; vrf-target target:65000:101; vrf-table-label; } }
2. vSRX-3側コンフィグ内容
root@vSRX-3> show configuration ... (snip) routing-options { router-id 10.0.0.3; autonomous-system 65000; } protocols { mpls { interface ge-0/0/0.0; } bgp { group L3VPN { type internal; local-address 10.0.0.3; family inet-vpn { unicast; } neighbor 10.0.0.1; } } ospf { area 0.0.0.0 { interface ge-0/0/0.0; interface lo0.0 { passive; } } } ldp { interface ge-0/0/0.0; } } routing-instances { VPN-A { instance-type vrf; interface ge-0/0/1.0; route-distinguisher 65000:101; vrf-target target:65000:101; routing-options { static { route 10.0.0.0/24 next-hop 172.16.1.2; route 10.0.1.0/24 next-hop 172.16.1.2; route 10.0.2.0/24 next-hop 172.16.1.2; } } } }
◼︎ 最後に
今回は、JUNOSによる、mpBGP / MPLS-VPNの基本動作を確認しました。
基本的なJUNOSコマンド操作感は、とてもわかりやすいと感じました。
以上です。
vSRXを活用した、JUNOSのお勉強まとめ【OSPF + MPLS編】
今回も、引き続き、JUNOSのお勉強メモです。
ttsubo.hatenablog.com
◼︎ vSRXトポロジ構成
今回は、vSRX3台構成としました。
[ AS: 65000 ] [ AS: 65000 ] 10.0.0.1 10.0.0.2 10.0.0.3 +-----+ +--------+ +--------+ +--------+ +-----+ | | 172.16.0.0/30 | | 192.168.0.0/30 | | 192.168.1.0/30 | | 172.16.1.0/30 | | 10.0.0.1/24 | pc1 | +-----------+ | vSRX-1 | +------------+ | vSRX-2 | +------------+ | vSRX-3 | +-----------+ | pc2 | 10.0.1.1/24 | | .1 .2 | | .1 .2 | | .1 .2 | | .1 .2 | | 10.0.2.1/24 +-----+ +--------+ +--------+ +--------+ +-----+ : : : : : : : : : < --------- > : : < ---------- > : : < ---------- > : : < --------- > : static : ospf ospf : static : : : : : < ------------------------------------ > : i-BGP
◼︎ JUNOSルーティング設定
複数台のvSRX間でIP通信が可能なように、各種ルーティング設定を行います。
(1) OSPF基本設定
今回は、すべてのvSRXルータをエリア0に収容する形態としました。
1. protocolsを設定する
まずは、vSRX-1の場合、ge-0/0/1.0 のインタフェースをOSPFエリア0に収容するには、次のようにコンフィグ設定します。
なお、ループバックでOSPFを有効にする場合には、パッシブインタフェースとして設定するのが一般的だそうです。
root@vSRX-1# set protocols ospf area 0.0.0.0 interface ge-0/0/1.0 root@vSRX-1# set protocols ospf area 0.0.0.0 interface lo0.0 passive root@vSRX-1# show | compare [edit] + protocols { + ospf { + area 0.0.0.0 { + interface ge-0/0/1.0; + interface lo0.0 { + passive; + } + } + } + } root@vSRX-1# commit
2. OSPF隣接関係の状態を確認しておく
すべてのvSRXルータでも同様に、OSPFエリア0に収容するインタフェースを有効にします。
vSRX-1で、OSPF隣接状態を確認してみます。
あと、ループバックインタフェースでもOSPFが有効になっていることを確認しておきます。
root@vSRX-1> show ospf neighbor Address Interface State ID Pri Dead 192.168.0.2 ge-0/0/1.0 Full 10.0.0.2 128 33 root@vSRX-1> show ospf interface Interface State Area DR ID BDR ID Nbrs ge-0/0/1.0 BDR 0.0.0.0 10.0.0.2 10.0.0.1 1 lo0.0 DRother 0.0.0.0 0.0.0.0 0.0.0.0 0
そして、vSRX-2でも、OSPF隣接状態を確認してみます。
root@vSRX-2> show ospf neighbor Address Interface State ID Pri Dead 192.168.0.1 ge-0/0/0.0 Full 10.0.0.1 128 35 192.168.1.2 ge-0/0/1.0 Full 10.0.0.3 128 39 root@vSRX-2> show ospf interface Interface State Area DR ID BDR ID Nbrs ge-0/0/0.0 DR 0.0.0.0 10.0.0.2 10.0.0.1 1 ge-0/0/1.0 BDR 0.0.0.0 10.0.0.3 10.0.0.2 1 lo0.0 DRother 0.0.0.0 0.0.0.0 0.0.0.0 0
さらに、vSRX-3でも、OSPF隣接状態を確認しておきます。
root@vSRX-3> show ospf neighbor Address Interface State ID Pri Dead 192.168.1.1 ge-0/0/0.0 Full 10.0.0.2 128 32 root@vSRX-3> show ospf interface Interface State Area DR ID BDR ID Nbrs ge-0/0/0.0 DR 0.0.0.0 10.0.0.3 10.0.0.2 1 lo0.0 DRother 0.0.0.0 0.0.0.0 0.0.0.0 0
最後に、OSPFプロトコルによって学習したルーティング情報を確認しておきます。
root@vSRX-1> show route protocol ospf inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.2/32 *[OSPF/10] 00:21:26, metric 1 > to 192.168.0.2 via ge-0/0/1.0 10.0.0.3/32 *[OSPF/10] 00:21:26, metric 2 > to 192.168.0.2 via ge-0/0/1.0 192.168.1.0/30 *[OSPF/10] 00:21:26, metric 2 > to 192.168.0.2 via ge-0/0/1.0 224.0.0.5/32 *[OSPF/10] 00:21:41, metric 1 MultiRecv
(2) BGP基本設定
1. BGP Peer相手となる対向vSRXとの疎通性を確認しておく
まず、vSRX-1とvSRX-3の間で、ループバックインタフェース間での疎通性を確認しておきます。
root@vSRX-1> ping 10.0.0.3 source 10.0.0.1 count 5 PING 10.0.0.3 (10.0.0.3): 56 data bytes 64 bytes from 10.0.0.3: icmp_seq=0 ttl=63 time=3.796 ms 64 bytes from 10.0.0.3: icmp_seq=1 ttl=63 time=1.610 ms 64 bytes from 10.0.0.3: icmp_seq=2 ttl=63 time=1.324 ms 64 bytes from 10.0.0.3: icmp_seq=3 ttl=63 time=1.154 ms 64 bytes from 10.0.0.3: icmp_seq=4 ttl=63 time=1.340 ms --- 10.0.0.3 ping statistics --- 5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max/stddev = 1.154/1.845/3.796/0.986 ms
問題なく、ping動作しております。
2. routing-optionを設定する
ここからは、ほぼ前回の記事と同じ作業になります。
BGP Peerアドレスとして、ループバックインタフェースを指定する点が異なります。
root@vSRX-1# set routing-options router-id 10.0.0.1 autonomous-system 65000 root@vSRX-1# show | compare [edit] + routing-options { + router-id 10.0.0.1; + autonomous-system 65000; + } root@vSRX-1# commit
3. protocolsを設定する
root@vSRX-1# set protocols bgp group INTERNAL type internal local-address 10.0.0.1 neighbor 10.0.0.3 root@vSRX-1# show | compare [edit protocols] + bgp { + group INTERNAL { + type internal; + local-address 10.0.0.1; + neighbor 10.0.0.3; + } + } root@vSRX-1# commit
4. BGP Peerの状態を確認しておく
root@vSRX-1> show bgp neighbor Peer: 10.0.0.3+57167 AS 65000 Local: 10.0.0.1+179 AS 65000 Type: Internal State: Established Flags: <Sync> Last State: OpenConfirm Last Event: RecvKeepAlive Last Error: None Options: <Preference LocalAddress Refresh> Local Address: 10.0.0.1 Holdtime: 90 Preference: 170 Number of flaps: 0 Peer ID: 10.0.0.3 Local ID: 10.0.0.1 Active Holdtime: 90 Keepalive Interval: 30 Group index: 0 Peer index: 0 BFD: disabled, down NLRI for restart configured on peer: inet-unicast NLRI advertised by peer: inet-unicast NLRI for this session: inet-unicast Peer supports Refresh capability (2) Stale routes from peer are kept for: 300 Peer does not support Restarter functionality NLRI that restart is negotiated for: inet-unicast NLRI of received end-of-rib markers: inet-unicast NLRI of all end-of-rib markers sent: inet-unicast Peer supports 4 byte AS extension (peer-as 65000) Peer does not support Addpath Table inet.0 Bit: 10000 RIB State: BGP restart is complete Send state: in sync Active prefixes: 0 Received prefixes: 0 Accepted prefixes: 0 Suppressed due to damping: 0 Advertised prefixes: 0 Last traffic (seconds): Received 21 Sent 21 Checked 21 Input messages: Total 3 Updates 1 Refreshes 0 Octets 101 Output messages: Total 3 Updates 0 Refreshes 0 Octets 120 Output Queue[0]: 0 (inet.0, init-unicast)
5. Export policy適用
こちらも、前回と同様に、Export policy作成して、適用します。
自分が保持している経路を、BGP Peerに対して、アドバタイズするには、Export policyを作成して、BGPピアのGroupに適用する必要があるようです。
root@vSRX-1# set policy-options policy-statement export-bgp term 1 from route-filter 172.16.0.0/30 exact root@vSRX-1# set policy-options policy-statement export-bgp term 1 then accept root@vSRX-1# set protocols bgp group INTERNAL export export-bgp root@vSRX-1# show | compare [edit protocols bgp group INTERNAL] + export export-bgp; [edit] + policy-options { + policy-statement export-bgp { + term 1 { + from { + route-filter 172.16.0.0/30 exact; + } + then accept; + } + } + } root@vSRX-1# commit
すると、想定どおりに、自分が保持している経路をアドバタイズするようになりました。
root@vSRX-1> show route advertising-protocol bgp 10.0.0.3 inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 172.16.0.0/30 Self 100 I
さらに、対向側(vSRX-3ルータ)でも、Export policy適用してみると、アドバタイズされた経路を受信できるようになりました。
root@vSRX-1> show route receive-protocol bgp 10.0.0.3 inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 172.16.1.0/30 10.0.0.3 100 I
今回は、さらに、vSRX-3側でスタティック経路も追加しておきます。
root@vSRX-3# set routing-options static route 10.0.0.0/24 next-hop 172.16.1.2 root@vSRX-3# set routing-options static route 10.0.1.0/24 next-hop 172.16.1.2 root@vSRX-3# set routing-options static route 10.0.2.0/24 next-hop 172.16.1.2 root@vSRX-3# show | compare [edit routing-options] + static { + route 10.0.0.0/24 next-hop 172.16.1.2; + route 10.0.1.0/24 next-hop 172.16.1.2; + route 10.0.2.0/24 next-hop 172.16.1.2; + } root@vSRX-3# commit
ただし、このままでは、vSRX-1側では、スタティック経路を受信しておりません。
vSRX-3側で保持しているスタティック経路を、BGP再配布するには、Export policyを作成して、BGPピアのGroupに適用する必要があるようです。
root@vSRX-1> show route receive-protocol bgp 10.0.0.3 inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 172.16.1.0/30 10.0.0.3 100 I
6. Export policy再適用
スタティック経路のBGP再配布に関わるExport policy作成して、適用します。
root@vSRX-3# set policy-options prefix-list PREFIX 10.0.0.0/24 root@vSRX-3# set policy-options prefix-list PREFIX 10.0.1.0/24 root@vSRX-3# set policy-options prefix-list PREFIX 10.0.2.0/24 root@vSRX-3# set policy-options policy-statement export-bgp term 1 from prefix-list PREFIX root@vSRX-3# set policy-options policy-statement export-bgp term 1 then accept root@vSRX-3# show | compare [edit policy-options] + prefix-list PREFIX { + 10.0.0.0/24; + 10.0.1.0/24; + 10.0.2.0/24; + } [edit policy-options policy-statement export-bgp term 1 from] + prefix-list PREFIX; root@vSRX-3# commit
この状態でのpolicy-options設定内容は、こんな感じになっています。
policy-options { prefix-list PREFIX { 10.0.0.0/24; 10.0.1.0/24; 10.0.2.0/24; } policy-statement export-bgp { term 1 { from { route-filter 172.16.1.0/30 exact; prefix-list PREFIX; } then accept; } } }
すると、vSRX-1ルータ側では、アドバタイズされたスタティック経路も受信できるようになりました。
root@vSRX-1> show route receive-protocol bgp 10.0.0.3 inet.0: 13 destinations, 13 routes (13 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 10.0.0.0/24 172.16.1.2 100 I * 10.0.1.0/24 172.16.1.2 100 I * 10.0.2.0/24 172.16.1.2 100 I * 172.16.1.0/30 10.0.0.3 100 I
ここまでは、順調ですね。
(3) エンド端末間での疎通確認
それでは、OSPF, BGPの基本設定も完了したので、最後に、エンドエンド端末間でpingをうってみましょう。
tsubo@pc1:~$ ping 172.16.1.2 PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data. ^C --- 172.16.1.2 ping statistics --- 15 packets transmitted, 0 received, 100% packet loss, time 13999ms
残念ながら、pingが成功しません!
ここでの課題は、vSRX-2では、"172.16.1.0/30"のルーティング情報を保持しておりません。
よって、ICMP Echo Requestのパケットを受信しても、vSRX-3に転送せずに、ドロップしてしまった!
こちらのSlideShareが参考になると思います。
(4) MPLS / LDP基本設定
早速、先ほどの課題解決のために、MPLS / LDPを設定します。
1. interfacesを設定する
root@vSRX-1# set interfaces ge-0/0/1 unit 0 family mpls root@vSRX-1# show | compare [edit interfaces ge-0/0/1 unit 0] + family mpls; root@vSRX-1# commit
2. protocolsを設定する
MPLSも有効にします。
root@vSRX-1# set protocols mpls interface ge-0/0/1.0 root@vSRX-1# show | compare [edit protocols] + mpls { + interface ge-0/0/1.0; + } root@vSRX-1# commit
LDPも有効にします。
root@vSRX-1# set protocols ldp interface ge-0/0/1.0 [edit] root@vSRX-1# show | compare [edit protocols] + ldp { + interface ge-0/0/1.0; + } [edit] root@vSRX-1# commit commit complete
3. LDP隣接関係の状態を確認しておく
すべてのvSRXルータでも同様に、MPLS / LDPを設定します。
そして、vSRX-1で、LDP隣接状態を確認してみます。
root@vSRX-1> show ldp neighbor Address Interface Label space ID Hold time 192.168.0.2 ge-0/0/1.0 10.0.0.2:0 12 root@vSRX-1> show ldp interface Interface Label space ID Nbr count Next hello ge-0/0/1.0 10.0.0.1:0 1 4
さらに、vSRX-2でも、LDP隣接状態を確認してみます。
root@vSRX-2> show ldp neighbor Address Interface Label space ID Hold time 192.168.0.1 ge-0/0/0.0 10.0.0.1:0 12 192.168.1.2 ge-0/0/1.0 10.0.0.3:0 14 root@vSRX-2> show ldp interface Interface Label space ID Nbr count Next hello ge-0/0/0.0 10.0.0.2:0 1 1 ge-0/0/1.0 10.0.0.2:0 1 2
vSRX-3でも、OSPF隣接状態を確認しておきます。
root@vSRX-3> show ldp neighbor Address Interface Label space ID Hold time 192.168.1.1 ge-0/0/0.0 10.0.0.2:0 10 root@vSRX-3> show ldp interface Interface Label space ID Nbr count Next hello ge-0/0/0.0 10.0.0.3:0 1 3
LDPプロトコルによって学習したルーティング情報を確認しておきます。
root@vSRX-1> show route protocol ldp inet.0: 13 destinations, 13 routes (13 active, 0 holddown, 0 hidden) inet.3: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 10.0.0.2/32 *[LDP/9] 00:14:15, metric 1 > to 192.168.0.2 via ge-0/0/1.0 10.0.0.3/32 *[LDP/9] 00:13:31, metric 1 > to 192.168.0.2 via ge-0/0/1.0, Push 299792 mpls.0: 7 destinations, 7 routes (7 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 299776 *[LDP/9] 00:14:15, metric 1 > to 192.168.0.2 via ge-0/0/1.0, Pop 299776(S=0) *[LDP/9] 00:14:15, metric 1 > to 192.168.0.2 via ge-0/0/1.0, Pop 299792 *[LDP/9] 00:13:31, metric 1 > to 192.168.0.2 via ge-0/0/1.0, Swap 299792
(5) エンド端末間での疎通確認
それでは、LDPの基本設定も完了したので、もう一度、エンドエンド端末間でpingをうってみましょう。
tsubo@pc1:~$ ping 172.16.1.2 PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data. 64 bytes from 172.16.1.2: icmp_seq=1 ttl=61 time=0.758 ms 64 bytes from 172.16.1.2: icmp_seq=2 ttl=61 time=0.728 ms 64 bytes from 172.16.1.2: icmp_seq=3 ttl=61 time=0.758 ms 64 bytes from 172.16.1.2: icmp_seq=4 ttl=61 time=0.828 ms 64 bytes from 172.16.1.2: icmp_seq=5 ttl=61 time=55.9 ms ^C --- 172.16.1.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 3999ms rtt min/avg/max/mdev = 0.728/11.812/55.992/22.090 ms||<
今回は、pingが成功しましたね!
この時、pc2側でtcpdumpを動作させて、パケットモニタリングしておきます。
root@pc2:~# tcpdump -i eth1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes 17:29:11.583949 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2198, seq 1, length 64 17:29:11.583983 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2198, seq 1, length 64 17:29:12.586912 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2198, seq 2, length 64 17:29:12.586940 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2198, seq 2, length 64 17:29:13.588175 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2198, seq 3, length 64 17:29:13.588204 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2198, seq 3, length 64 17:29:14.588207 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2198, seq 4, length 64 17:29:14.588240 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2198, seq 4, length 64 17:29:14.974839 IP 192.168.105.1.17500 > 192.168.105.255.17500: UDP, length 131 17:29:15.590265 IP 172.16.0.1 > 172.16.1.2: ICMP echo request, id 2198, seq 5, length 64 17:29:15.590293 IP 172.16.1.2 > 172.16.0.1: ICMP echo reply, id 2198, seq 5, length 64
こちらも期待通り、ICMP Echo Request / Replyが観測できました。
さらに、pc2側の"10.0.0.1"に対して、pingをうってみましょう。
tsubo@pc1:~$ ping 10.0.0.1 PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data. 64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.273 ms 64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.353 ms 64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.328 ms 64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.312 ms 64 bytes from 10.0.0.1: icmp_seq=5 ttl=64 time=0.264 ms ^C --- 10.0.0.1 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 3999ms rtt min/avg/max/mdev = 0.264/0.306/0.353/0.033 ms
こちらも、pingは、成功しました。
この時、pc2側でtcpdumpを動作させて、パケットモニタリングしておきます。
root@pc2:~# tcpdump -i eth1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes ^C 0 packets captured 0 packets received by filter 0 packets dropped by kernel
あれっ?
こちらは、期待に反して、ICMP Echo Request / Replyが観測できません。
pc2には、ICMP Echo Requestパケットが届いていないのに、pc1では、ICMP Echo Replyを受信してしまっている。
という、奇妙に現象が発生してしまいました。
◼︎ 最終的なコンフィグ内容の確認
root@vSRX-1> show configuration | display set set version 15.1X49-D15.4 set system host-name vSRX-1 set system time-zone Asia/Tokyo set system root-authentication encrypted-password "$1$XvI2vVPR$7lnJdb5gNeg4zql8lZ/1Q1" set system login user tsubo uid 2000 set system login user tsubo class super-user set system login user tsubo authentication encrypted-password "$1$THS.KlMg$SvjUk8SUxyDY3rDRGT3hK/" set system services ssh root-login allow set system services web-management http interface fxp0.0 set system syslog user * any emergency set system syslog file messages any any set system syslog file messages authorization info set system syslog file interactive-commands interactive-commands any set system license autoupdate url https://ae1.juniper.net/junos/key_retrieval set security forwarding-options family inet6 mode packet-based set security forwarding-options family mpls mode packet-based set interfaces ge-0/0/0 unit 0 family inet address 172.16.0.2/30 set interfaces ge-0/0/1 unit 0 family inet address 192.168.0.1/30 set interfaces ge-0/0/1 unit 0 family mpls set interfaces fxp0 unit 0 set interfaces lo0 unit 0 family inet address 10.0.0.1/32 set routing-options router-id 10.0.0.1 set routing-options autonomous-system 65000 set protocols mpls interface ge-0/0/1.0 set protocols bgp group INTERNAL type internal set protocols bgp group INTERNAL local-address 10.0.0.1 set protocols bgp group INTERNAL export export-bgp set protocols bgp group INTERNAL neighbor 10.0.0.3 set protocols ospf area 0.0.0.0 interface ge-0/0/1.0 set protocols ospf area 0.0.0.0 interface lo0.0 passive set protocols ldp interface ge-0/0/1.0 set policy-options policy-statement export-bgp term 1 from route-filter 172.16.0.0/30 exact set policy-options policy-statement export-bgp term 1 then accept
◼︎ 最後に
先ほどの課題は、次回、考察したいと思います。
以上です。
vSRXを活用した、JUNOSのお勉強まとめ【JUNOS初期設定 + BGP基本編】
これから、しばらく、ネットワーク技術のお勉強に時間を費やしたいと思います。
ネットワークのお勉強の素材としては、「Junos設定&管理完全Bible」を選びました。
ただ、こちらの書籍なんですが、すでに、在庫が存在しておらず、中古品をゲットすることになりました。
◼︎ vSRX環境構築
以前のブログ記事「Mac OS X環境のVMware Fusion上で、vSRXを動かす」をそのまま活用します。
本来、vSRXは、Flowベースの仮想ファイアウォールなのですが、ルーティングの勉強用には、Packetベースに動作モードを変更しております。ご注意ください。
ttsubo.hatenablog.com
◼︎ vSRXトポロジ構成
Mac OS X環境で、複数台のvSRXを動作させたいところですが、今回は、vSRX2台構成としました。
+---------+ i-BGP +--------+ ... -------------+ | vSRX-1 | +---------------------------------+ | vSRX-2 | +---- ... 172.16.0.1/24 | | 192.168.0.1/30 192.168.0.2/30 | | 172.16.1.1/24 +---------+ +--------+ < AS65000 > < AS65000 >
◼︎ JUNOS基本設定
ネットワークエンジニア界隈で、よく使用されているJUNOS操作の習熟を目指して、最初から環境設定に取り掛かります。
(1) vSRXの初期設定
1. rootパスワードを設定する
初期状態では、rootユーザのパスワードは設定されていないので、パスワードを設定する
root# set system root-authentication plain-text-password New password: Retype new password:
2. ホスト名を設定する
root# set system host-name vSRX-1 root# commit
3. タイムゾーンを設定する
root@vSRX-1# set system time-zone Asia/Tokyo root@vSRX-1# commit
4. 一般ユーザを作成する
root@vSRX-1# set system login user tsubo class super-user root@vSRX-1# set system login user tsubo authentication plain-text-password New password: Retype new password:
5. vSRXの動作モードを変更する
vSRXは、通常、Flow-based forwardingモードで動作しているので、packet-based forwardingモードに変更しておきます。
動作モードの変更を有効にするために、vSRXを再起動します。
root@vSRX-1# delete security root@vSRX-1# set security forwarding-options family mpls mode packet-based root@vSRX-1# set security forwarding-options family inet6 mode packet-based root@vSRX-1# commit root@vSRX-1# exit Exiting configuration mode root@vSRX-1> request system reboot Reboot the system ? [yes,no] (no) yes Shutdown NOW!
すると、packet basedに変更されたことが確認できるようになります。
root@vSRX-1> show security flow status Flow forwarding mode: Inet forwarding mode: packet based Inet6 forwarding mode: packet based MPLS forwarding mode: packet based ISO forwarding mode: drop Flow trace status Flow tracing status: off Flow session distribution Distribution mode: RR-based Flow ipsec performance acceleration: off Flow packet ordering Ordering mode: Hardware
6. rootユーザでのsshログインを許可する
root@vSRX-1# set system services ssh root-login allow
7. ge-0/0/0.0にアドレスを付与する
root@vSRX-1# set interfaces ge-0/0/0 unit 0 family inet address 192.168.0.1/24 root@vSRX-1# commit root@vSRX-1# run show interfaces ge-0/0/0.0 brief Logical interface ge-0/0/0.0 Flags: Up SNMP-Traps 0x4000 Encapsulation: ENET2 Security: Zone: Null inet 192.168.0.1/24
8. ループバックを設定する
root@vSRX-1# set interfaces lo0 unit 0 family inet address 10.0.0.1 root@vSRX-1# commit root@vSRX-1# run show interfaces lo0.0 brief Logical interface lo0.0 Flags: Down SNMP-Traps Encapsulation: Unspecified Security: Zone: Null inet 10.0.0.1 --> 0/0
(2) BGP基本設定
1. 対向vSRXとの疎通性を確認しておく
root@vSRX-1# run ping 192.168.0.2 count 5 PING 192.168.0.2 (192.168.0.2): 56 data bytes 64 bytes from 192.168.0.2: icmp_seq=0 ttl=64 time=3.993 ms 64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=1.605 ms 64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=1.101 ms 64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=3.063 ms 64 bytes from 192.168.0.2: icmp_seq=4 ttl=64 time=1.969 ms --- 192.168.0.2 ping statistics --- 5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max/stddev = 1.101/2.346/3.993/1.046 ms
2. routing-optionを設定する
root@vSRX-1# set routing-options router-id 10.0.0.1 autonomous-system 65000 root@vSRX-1# show | compare [edit] + routing-options { + router-id 10.0.0.1; + autonomous-system 65000; + } root@vSRX-1# commit
3. protocolsを設定する
root@vSRX-1# set protocols bgp group INTERNAL type internal neighbor 192.168.0.2 root@vSRX-1# show | compare [edit] + protocols { + bgp { + group INTERNAL { + type internal; + neighbor 192.168.0.2; + } + } + } root@vSRX-1# commit
4. BGP Peerの状態を確認しておく
root@vSRX-1> show bgp neighbor Peer: 192.168.0.2+55175 AS 65000 Local: 192.168.0.1+179 AS 65000 Type: Internal State: Established Flags: <Sync> Last State: OpenConfirm Last Event: RecvKeepAlive Last Error: Open Message Error Options: <Preference Refresh> Holdtime: 90 Preference: 170 Number of flaps: 0 Error: 'Open Message Error' Sent: 3 Recv: 0 Peer ID: 10.0.0.2 Local ID: 10.0.0.1 Active Holdtime: 90 Keepalive Interval: 30 Group index: 0 Peer index: 0 BFD: disabled, down NLRI for restart configured on peer: inet-unicast NLRI advertised by peer: inet-unicast NLRI for this session: inet-unicast Peer supports Refresh capability (2) Stale routes from peer are kept for: 300 Peer does not support Restarter functionality NLRI that restart is negotiated for: inet-unicast NLRI of received end-of-rib markers: inet-unicast NLRI of all end-of-rib markers sent: inet-unicast Peer supports 4 byte AS extension (peer-as 65000) Peer does not support Addpath Table inet.0 Bit: 10000 RIB State: BGP restart is complete Send state: in sync Active prefixes: 0 Received prefixes: 0 Accepted prefixes: 0 Suppressed due to damping: 0 Advertised prefixes: 0 Last traffic (seconds): Received 3 Sent 3 Checked 83 Input messages: Total 6 Updates 1 Refreshes 0 Octets 158 Output messages: Total 6 Updates 0 Refreshes 0 Octets 177 Output Queue[0]: 0 (inet.0, inet-unicast)
(3) down-link側の設定
1. ge-0/0/1.0にアドレスを付与する
root@vSRX-1# set interfaces ge-0/0/1 unit 0 family inet address 172.16.0.1/24 root@vSRX-1# show | compare [edit interfaces] + ge-0/0/1 { + unit 0 { + family inet { + address 172.16.0.1/24; + } + } + } root@vSRX-1# commit
2. Export policy作成と適用
自分が保持している経路を、BGP Peerに対して、アドバタイズするには、Export policyを作成して、BGPピアのGroupに適用する必要があるようです。
root@vSRX-1# set policy-options policy-statement export-bgp term 1 from route-filter 172.16.0.0/24 exact root@vSRX-1# set policy-options policy-statement export-bgp term 1 then accept root@vSRX-1# set protocols bgp group INTERNAL export export-bgp root@vSRX-1# show | compare [edit protocols bgp group INTERNAL] + export export-bgp; [edit] + policy-options { + policy-statement export-bgp { + term 1 { + from { + route-filter 172.16.0.0/24 exact; + } + then accept; + } + } + } root@vSRX-1# commit
すると、自分が保持している経路をアドバタイズするようになりました。
root@vSRX-1> show route advertising-protocol bgp 192.168.0.2 inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 172.16.0.0/24 Self 100 I
さらに、対向側でもExport policy作成と適用してみると、アドバタイズされた経路を受信できるようになりました。
root@vSRX-1> show route receive-protocol bgp 192.168.0.2 inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden) Prefix Nexthop MED Lclpref AS path * 172.16.1.0/24 192.168.0.2 100 I
(4) エンド端末間での疎通確認
tsubo@pc1:~$ ping 172.16.1.2 PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data. 64 bytes from 172.16.1.2: icmp_seq=1 ttl=62 time=83.3 ms 64 bytes from 172.16.1.2: icmp_seq=2 ttl=62 time=0.584 ms 64 bytes from 172.16.1.2: icmp_seq=3 ttl=62 time=0.701 ms 64 bytes from 172.16.1.2: icmp_seq=4 ttl=62 time=0.634 ms 64 bytes from 172.16.1.2: icmp_seq=5 ttl=62 time=0.678 ms ^C --- 172.16.1.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4001ms rtt min/avg/max/mdev = 0.584/17.194/83.377/33.091 ms
◼︎ 最終的なコンフィグ内容の確認
root@vSRX-1> show configuration | display set set version 15.1X49-D15.4 set system host-name vSRX-1 set system time-zone Asia/Tokyo set system root-authentication encrypted-password "$1$XvI2vVPR$7lnJdb5gNeg4zql8lZ/1Q1" set system login user tsubo uid 2000 set system login user tsubo class super-user set system login user tsubo authentication encrypted-password "$1$THS.KlMg$SvjUk8SUxyDY3rDRGT3hK/" set system services ssh root-login allow set system services web-management http interface fxp0.0 set system syslog user * any emergency set system syslog file messages any any set system syslog file messages authorization info set system syslog file interactive-commands interactive-commands any set system license autoupdate url https://ae1.juniper.net/junos/key_retrieval set security forwarding-options family inet6 mode packet-based set security forwarding-options family mpls mode packet-based set interfaces ge-0/0/0 unit 0 family inet address 192.168.0.1/24 set interfaces ge-0/0/1 unit 0 family inet address 172.16.0.1/24 set interfaces fxp0 unit 0 set interfaces lo0 unit 0 family inet address 10.0.0.1/32 set routing-options router-id 10.0.0.1 set routing-options autonomous-system 65000 set protocols bgp group INTERNAL type internal set protocols bgp group INTERNAL export export-bgp set protocols bgp group INTERNAL neighbor 192.168.0.2 set policy-options policy-statement export-bgp term 1 from route-filter 172.16.0.0/24 exact set policy-options policy-statement export-bgp term 1 then accept
◼︎ 最後に
まぁ、今回は、単に、BGPを動かしただけなので、これといったコメントはありません。
以上です。
etcdの分散Key-Valuesストアを試してみる
CoreOSが提供するetcdの動作をお手軽に試してみました。
なお、etcdとは、分散Key-Valuesストアを使い,各種設定をノード間で共有するメカニズムだそうです。
etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines.
It’s open-source and available on GitHub. etcd gracefully handles master elections during network partitions
and will tolerate machine failure, including the master.
◼️ まずは、環境準備から ...
まずは、golang環境を準備しておきます。
Getting Started - The Go Programming Language
そして、Mac OS X環境で、etcdを動作させる場合、こちらのGetting Startedに従って作業します。
github.com
$ curl -L https://github.com/coreos/etcd/releases/download/v2.2.2/etcd-v2.2.2-darwin-amd64.zip -o etcd-v2.2.2-darwin-amd64.zip $ unzip etcd-v2.2.2-darwin-amd64.zip $ cd etcd-v2.2.2-darwin-amd64 $ ./etcd 2015-12-27 15:42:15.142251 I | etcdmain: etcd Version: 2.2.2 2015-12-27 15:42:15.142330 I | etcdmain: Git SHA: b4bddf6 2015-12-27 15:42:15.142346 I | etcdmain: Go Version: go1.5.1 2015-12-27 15:42:15.142349 I | etcdmain: Go OS/Arch: darwin/amd64 2015-12-27 15:42:15.142360 I | etcdmain: setting maximum number of CPUs to 8, total number of available CPUs is 8 2015-12-27 15:42:15.142364 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd 2015-12-27 15:42:15.142982 I | etcdmain: listening for peers on http://localhost:2380 2015-12-27 15:42:15.143166 I | etcdmain: listening for peers on http://localhost:7001 2015-12-27 15:42:15.143335 I | etcdmain: listening for client requests on http://localhost:2379 2015-12-27 15:42:15.143499 I | etcdmain: listening for client requests on http://localhost:4001 2015-12-27 15:42:15.144404 I | etcdserver: name = default 2015-12-27 15:42:15.144433 I | etcdserver: data dir = default.etcd 2015-12-27 15:42:15.144447 I | etcdserver: member dir = default.etcd/member 2015-12-27 15:42:15.144451 I | etcdserver: heartbeat = 100ms 2015-12-27 15:42:15.144453 I | etcdserver: election = 1000ms 2015-12-27 15:42:15.144467 I | etcdserver: snapshot count = 10000 2015-12-27 15:42:15.144474 I | etcdserver: advertise client URLs = http://localhost:2379,http://localhost:4001 2015-12-27 15:42:15.144478 I | etcdserver: initial advertise peer URLs = http://localhost:2380,http://localhost:7001 2015-12-27 15:42:15.144487 I | etcdserver: initial cluster = default=http://localhost:2380,default=http://localhost:7001 2015-12-27 15:42:15.145942 I | etcdserver: starting member ce2a822cea30bfca in cluster 7e27652122e8b2ae 2015-12-27 15:42:15.146367 I | raft: ce2a822cea30bfca became follower at term 0 2015-12-27 15:42:15.146404 I | raft: newRaft ce2a822cea30bfca [peers: [], term: 0, commit: 0, applied: 0, lastindex: 0, lastterm: 0] 2015-12-27 15:42:15.146415 I | raft: ce2a822cea30bfca became follower at term 1 2015-12-27 15:42:15.146776 I | etcdserver: starting server... [version: 2.2.2, cluster version: to_be_decided] 2015-12-27 15:42:15.147874 N | etcdserver: added local member ce2a822cea30bfca [http://localhost:2380 http://localhost:7001] to cluster 7e27652122e8b2ae 2015-12-27 15:42:15.147934 E | etcdserver: cannot monitor file descriptor usage (cannot get FDUsage on darwin) 2015-12-27 15:42:15.548221 I | raft: ce2a822cea30bfca is starting a new election at term 1 2015-12-27 15:42:15.548284 I | raft: ce2a822cea30bfca became candidate at term 2 2015-12-27 15:42:15.548299 I | raft: ce2a822cea30bfca received vote from ce2a822cea30bfca at term 2 2015-12-27 15:42:15.548316 I | raft: ce2a822cea30bfca became leader at term 2 2015-12-27 15:42:15.548330 I | raft: raft.node: ce2a822cea30bfca elected leader ce2a822cea30bfca at term 2 2015-12-27 15:42:15.548736 I | etcdserver: published {Name:default ClientURLs:[http://localhost:2379 http://localhost:4001]} to cluster 7e27652122e8b2ae 2015-12-27 15:42:15.548760 I | etcdserver: setting up the initial cluster version to 2.2 2015-12-27 15:42:15.550378 N | etcdserver: set the initial cluster version to 2.2
◼️ オープンソース"go-etcd"を活用して、etcdの分散Key-Valuesストアを試してみる
それでは、オープンソース"go-etcd"を活用して、golangから、etcdを試してみます。
0. etcdのKey-Valuesストアを確認する
別ターミナルから、etcdctlコマンドで、etcdのストアデータを確認してみます。
まだ、etcdを起動したばかりなので、何も表示されないですけど。
$ ./etcdctl --peers "http://127.0.0.1:4001" ls
1. etcdにサンプルデータをセットしてみる
オープンソース"go-etcd"を活用して、手軽にKey-Valuesストアをセットできるサンプルコードを準備しておきます。
package main import ( "github.com/coreos/go-etcd/etcd" "log" ) var etcdServers = []string{ "http://127.0.0.1:4001", } func SetStatus_for_server(client *etcd.Client, status string){ // Set "active" to path of "/state/server" _, err := client.Set("/state/server", status, 0) if err != nil { log.Fatal(err) } } func SetStatus_for_network(client *etcd.Client, status string){ // Set "active" to path of "/state/network" _, err := client.Set("/state/network", status, 0) if err != nil { log.Fatal(err) } } func main() { // Create etcd client client := etcd.NewClient(etcdServers) SetStatus_for_server(client, "active") SetStatus_for_network(client, "down") }
サンプルコードを実行して、etcdにサンプルデータをセットしてみます。
エラーが表示されなければOKです。
$ go run go-etcd-set.go
2. etcdctlコマンドで、再度、Key-Valuesストアを確認する
今度は、"/state"という結果が表示されました。
$ ./etcdctl --peers "http://127.0.0.1:4001" ls /state
ちなみに、etcdのKey-Valuesストアデータは、ディレクトリ構造(=パス)で管理されております。
/state配下のパスを確認する場合は、"--recursive"を指定します。
$ ./etcdctl --peers "http://127.0.0.1:4001" ls --recursive /state /state/server /state/network
続いて、Key-ValuesストアのValuesを確認してみます。
まずは、"server"が"active"の状態であることを確認します。
$ ./etcdctl --peers "http://127.0.0.1:4001" get /state/server active
つぎに、"network"が"down"の状態であることを確認します。
$ ./etcdctl --peers "http://127.0.0.1:4001" get /state/network down
3. もっと、お手軽にKey-ValuesストアのValuesを確認してみる
オープンソース"go-etcd"を活用して、手軽にKey-Valuesストアを確認できるサンプルコードを準備しておきます。
package main import ( "github.com/coreos/go-etcd/etcd" "log" "fmt" ) var etcdServers = []string{ "http://127.0.0.1:4001", } func main() { client := etcd.NewClient(etcdServers) resp, err := client.Get("/state", false, true) if err != nil { log.Fatal(err) } for _, n := range resp.Node.Nodes { fmt.Printf("%s: %s\n", n.Key, n.Value) } }
サンプルコードを実行して、Key-ValuesストアのValuesを確認してみます。
$ go run go-etcd-get.go /state/server: active /state/network: down
4. etcdのKey-ValuesストアのValuesを監視してみる
ここからは、応用編です。
Key-ValuesストアのValuesが外部要因によって変更された場合、そのValuesをモニタ監視するサンプルコードを準備しておきます。
12/28追記:パス情報が複数変更された場合でも、モニタ監視できるようサンプルコードを修正しました。
package main import ( "os" "os/signal" "github.com/coreos/go-etcd/etcd" "log" ) var etcdServers = []string{ "http://127.0.0.1:4001", } func main() { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) etcdResponseChan := make(chan *etcd.Response) client := etcd.NewClient(etcdServers) go func(){ _, err := client.Watch("/state", 0, true, etcdResponseChan, nil) if err != nil { log.Fatal(err) } }() log.Println("Waiting for an update...") go func(){ for { response := <-etcdResponseChan log.Printf("Got updated state : path=[%s], value=[%s]\n", response.Node.Key, response.Node.Value) } }() <-c }
サンプルコードを実行して、Valuesをモニタ監視できるよう準備しておきます。
$ go run ./go-etcd-watch.go 2015/12/27 16:46:16 Waiting for an update...
続いて、別ターミナルから、"network"を"active"の状態に更新します。
更新方法は、なんでも良いのですが、curlコマンドで更新してみます。
$ curl -L http://127.0.0.1:4001/v2/keys/state/network -XPUT -d value='active' {"action":"set","node":{"key":"/state/network","value":"active","modifiedIndex":6,"createdIndex":6},"prevNode":{"key":"/state/network","value":"down","modifiedIndex":5,"createdIndex":5}}
すると、先ほどモニタ監視として実行しておいたサンプルコードの起動画面にて、"network"が"active"の状態に更新されたことが検出できました。
$ go run ./go-etcd-watch.go 2015/12/27 16:46:16 Waiting for an update... 2015/12/27 16:47:07 Got updated state : path=[/state/network], value=[active]
事後確認として、Key-ValuesストアのValuesを確認してみます。
$ go run go-etcd-get.go /state/server: active /state/network: active
SDNアプローチによるBGP経路監視を試してみる
「ネットワーク運用の自動化」として、BGP経路監視を考察してみたいと思います。
NetOpsCoding Advent Calendar 2015 12/12分のエントリーです
qiita.com
◾️ ”BGP運用”という言葉から想定されるイメージ
BGP運用というと、なんとなく「BGP職人さん」という言葉を連想してしまうのは、私だけでしょうか?
BGP職人さんは、事前に策定されたBGP運用ポリシーに従って、ポリシー・ルーティングに関わるルートマップ等コンフィグを投入することができる存在であり、想定どおり、ポリシー・ルーティングが動作されているかを確認するため、ベンダ固有のCLIコマンドを駆使して細かなBGP制御を確認することを日々の業務として実施する。
そんなイメージを、「BGP運用」からは、連想してしまいます。
さらに、不測な事態としてNWトポロジが安定動作していないことが判明した際には、BGP等プロトコル動作の振る舞いから、障害箇所を推測して、長年の運用経験から導き出された障害対策案の中からベストな方法で障害復旧を施すことができるネットワーク達人こそが、大規模ネットワーク運用を担っていることでしょう。
◾️ ”BGP職人の世界”に運用自動化のメスを入れるためには?
BGP職人の運用経験を踏まえた、運用の自動化を実現するには、
- 課題1「BGPコンフィグ設定通りに、BGP動作していることを、検証する仕組み」
- 課題2「実ネットワークでのBGP動作履歴を、オペレーション観点で、ログ管理できる仕組み」
- 課題3「BGP障害解析として、過去のBGP障害履歴から障害箇所を推定する仕組み」
が備わっているBGPシミュレーション機能を有する運用システムが必要になるのでしょう。
まずは、課題1「BGPコンフィグ設定通りに、BGP動作していることを、検証する仕組み」の解決方法と一つとして、End-End開通監視に着目した過去のSlideshareを共有しておきます。
www.slideshare.net
ここでのポイントは、従来のCLI, SNMPでのBGP監視では、リアルタイムな監視の実現が困難なので、BMPに着目してEnd-End開通監視のプロトタイプを実現しましたというネタになります。
◾️ SDNアプローチによるBGP経路監視を試してみる
前置きが長くなりましたが、ここからが本題です。
BGP経路監視ツール"bgpSimulator"の作成して、BGP経路監視の有効性を確認しました。
ちなみに、BGP経路監視には、BGPルータ側でのBMP機能が動作することを前提としております。
そこで、CSR1000v(IOS XE)を検証構成に配備しました。
(1) BGP経路監視ツール"bgpSimulator"
BGP経路監視ツール"bgpSimulator"は、”BMP処理部"と"BGPパス計算部"から構成されております。
前者は、Ryu BMP Serverを活用した実装コードになっております。また、後者は、Ryu BGPコードを改造して実現しております。
なお、動作としては、以下のような処理の流れによって実現しております。
1. まず、BGP経路監視ツール"bgpSimulator"の起動時に、CSR1000vのBGP構成をシミュレーション面として構築する
2. CSR1000vで、adj-RIB-inが変化したタイミングで、BGP UpdateメッセージをBMP情報として通知する
3. bgpSimulatorは、受信したBMP情報からBGP Updateメッセージを抽出する
4. bgpSimulatorは、"BGP1"のBGPシミュレーション面のadj-RIB-inに、BGP Ipdateメッセージを注入する
5. bgpSimulatorは、BGPシミュレーション面のadj-RIB-inの更新を契機に、BGPパス計算を行い、RIB-localに保持する
6. オペレータは、bgpSimulatorのコマンド上から、RIB-local情報を参照する
(2) BGP検証環境
全体のNWトポロジは、こんな感じです。CSR1000vは、BGP1の箇所に配備しております。
ちなみに、bgpSimulatorツールを起動した後に、"BGP6"ルータで、プレフィックス"172.16.0.0/24"を追加した上で、BGP経路監視の様子を確認しております。
(3) 動作結果の確認
まずは、bgpSimulatorツール起動後に、BMP情報を受信した様子を確認しておきます。
$ sudo ryu-manager bgpSimulator.py loading app bgpSimulator.py creating context wsgi instantiating app None of SimpleBGPSpeaker creating context bgps instantiating app bgpSimulator.py of BgpSimulator (3684) wsgi starting up on http://0.0.0.0:8080/ (3684) accepted ('127.0.0.1', 50301) ... (snip) BMP client connected, ip=192.168.100.1, port=14855 Start BMP session!! [192.168.100.1] Received BMPPeerUpNotification, peer=[10.0.0.1] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.0.1] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.0.1] Received BMPPeerUpNotification, peer=[10.0.1.2] Received BMPRouteMonitoring=[{'path_attributes': {'ORIGIN': '?', 'EXTENDED_COMMUNITIES': ['65010:101'], 'AS_PATH': [[65010]], 'MP_REACH_NLRI': {'nexthop': '192.168.101.101', 'nlri': [{'prefix': '192.168.2.0/24', 'label_list': [20], 'route_dist': '65010:101'}, {'prefix': '172.16.0.0/24', 'label_list': [22], 'route_dist': '65010:101'}]}}, 'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_Update'}], peer=[10.0.0.1] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.0.1] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.0.1] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.1.2] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.1.2] Received BMPPeerUpNotification, peer=[10.0.1.3] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.1.2] Received BMPRouteMonitoring=[{'path_attributes': {'ORIGIN': '?', 'MP_REACH_NLRI': {'nexthop': '192.168.104.102', 'nlri': [{'prefix': '192.168.2.0/24', 'label_list': [20], 'route_dist': '65010:101'}, {'prefix': '172.16.0.0/24', 'label_list': [22], 'route_dist': '65010:101'}]}, 'AS_PATH': [[65010]], 'MULTI_EXIT_DISC': 0, 'LOCAL_PREF': 100, 'EXTENDED_COMMUNITIES': ['65010:101']}, 'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_Update'}], peer=[10.0.1.2] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.1.2] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.1.3] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.1.3] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.1.3] Received BMPRouteMonitoring=[{'path_attributes': {'ORIGIN': '?', 'MP_REACH_NLRI': {'nexthop': '192.168.105.102', 'nlri': [{'prefix': '192.168.1.0/24', 'label_list': [18], 'route_dist': '65010:101'}]}, 'AS_PATH': [], 'MULTI_EXIT_DISC': 0, 'LOCAL_PREF': 100, 'EXTENDED_COMMUNITIES': ['65010:101']}, 'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_Update'}], peer=[10.0.1.3] Received BMPRouteMonitoring=[{'received_time': '2015/12/10 23:33:44', 'message_type': 'BGP_RouteRefresh'}], peer=[10.0.1.3]
さらに、CSR1000v上のBGPテーブルと、bgpSimulatorル上のBGPテーブルを比較してみます。
CSR1000v上のBGPテーブル
BGP1>show bgp vpnv4 unicast all BGP table version is 68, local router ID is 10.0.1.1 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, x best-external, a additional-path, c RIB-compressed, Origin codes: i - IGP, e - EGP, ? - incomplete RPKI validation codes: V valid, I invalid, N Not found Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 65010:101 *> 172.16.0.0/24 192.168.101.101 0 65010 ? * i 192.168.104.102 0 100 0 65010 ? *>i 192.168.1.0 192.168.105.102 0 100 0 ? *> 192.168.2.0 192.168.101.101 0 65010 ? * i 192.168.104.102 0 100 0 65010 ?
bgpSimulator上のBGPテーブル
$ ./get_rib.sh Status codes: * valid, > best Origin codes: i - IGP, e - EGP, ? - incomplete Network Labels Next Hop Reason Metric LocPrf Path *> 65010:101:192.168.2.0/24 [20] 192.168.101.101 ASN 65010 ? * [20] 192.168.104.102 0 100 65010 ? *> 65010:101:172.16.0.0/24 [22] 192.168.101.101 ASN 65010 ? * [22] 192.168.104.102 0 100 65010 ? *> 65010:101:192.168.1.0/24 [18] 192.168.105.102 Only Path 0 100 ?
CSR1000vのBGPテーブルと、bgpSimulatorのBGPテーブルは、同じBGPパス情報を保持しています。
(4) BGP Peerダウン時の動作結果の確認
今度は、BGP4〜1BGP1との間のBGP Peerがダウンさせてみます。
bgpSimulatorツールを起動したターミナル上には、BMPPeerDownNotificationを受信した旨が表示されます。
$ sudo rya-manager bgpSimulator.py ... (snip) Received BMPPeerDownNotification, peer=[10.0.0.1]
つづいて、CSR1000v上のBGPテーブルと、bgpSimulatorル上のBGPテーブルを比較してみます。
CSR1000v上のBGPテーブル
CSR1000vのBGPテーブルでは、BGP4〜1BGP1との間のBGP Peerがダウンに基づき、BGPパス再計算が行われたため、nexthopが変化している様子がわかります。
BGP1>show bgp vpnv4 unicast all BGP table version is 70, local router ID is 10.0.1.1 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, x best-external, a additional-path, c RIB-compressed, Origin codes: i - IGP, e - EGP, ? - incomplete RPKI validation codes: V valid, I invalid, N Not found Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 65010:101 *>i 172.16.0.0/24 192.168.104.102 0 100 0 65010 ? *>i 192.168.1.0 192.168.105.102 0 100 0 ? *>i 192.168.2.0 192.168.104.102 0 100 0 65010 ?
bgpSimulator上のBGPテーブル
一方、BGP経路監視ツール"bgpSimulator"では、”PeerDownNotification”を受信した場合ても、BGPパス再計算を実施するようには実装しておりません。
よって、 bgpSimulatorのBGPテーブルは、BGP4〜1BGP1との間のBGP Peerがダウン前のBGPパス情報からnexthopの変化は観測されません。
$ ./get_rib.sh Status codes: * valid, > best Origin codes: i - IGP, e - EGP, ? - incomplete Network Labels Next Hop Reason Metric LocPrf Path *> 65010:101:192.168.2.0/24 [20] 192.168.101.101 ASN 65010 ? * [20] 192.168.104.102 0 100 65010 ? *> 65010:101:172.16.0.0/24 [22] 192.168.101.101 ASN 65010 ? * [22] 192.168.104.102 0 100 65010 ? *> 65010:101:192.168.1.0/24 [18] 192.168.105.102 Only Path 0 100 ?
BGP Peerダウンが発生すると、CSR1000vのBGPテーブルと、bgpSimulatorのBGPテーブルは、同じBGPパス情報を保持しないという特徴をうまく活用してあげれば、BGP経路監視の観点で、早期にBGP障害を検知することが可能になるかもしれません。
以上より、BGP動作履歴を管理するには、BMPが有効であることが確認できました。
◾️ おまけ編:BGP経路監視ツール"bgpSimulator"をお手軽に試してみる
CSR1000vなどの実際のBGPルータを配備して、NWトポロジを構築するのは、なかなか手間がかかる話です。
RyuBGPには、BMP Client機能を有しているので、RyuBGPを活用して、BGP/MPLS-VPN面を構築した上で、もっと、手軽にBGP経路監視ツール"bgpSimulator"の動作を試してみることができるように、dockerコンテナでの実験環境を用意しました。
"README.md"通りに環境準備してもらえれば、BGP経路監視の動作イメージを体感してもらえると思います。
github.com