TECH PLAY

NTTドコモビジネス

NTTドコモビジネス の技術ブログ

616

はじめに こんにちは、イノベーションセンターの鈴ヶ嶺です。 普段はクラウドサービスをオンプレミス環境でも同様のUI/UXで使用できるハイブリッドクラウド製品の技術検証をしています。 我々は以下のように過去にAWSのサーバ型ハイブリッドクラウドの解説や実施検証などを行ってきました。 engineers.ntt.com engineers.ntt.com このたび、新たにAWS Graviton2搭載のOutposts Serverを導入しさまざまな検証を進めています。 本記事では、AWS Graviton2搭載のOutposts ServerとIntel Xeon搭載のOutposts Serverとの性能差や電力効率を比較した結果を共有します。 まずこれまでのAWS Graviton2, Intel Xeonの比較検証記事の調査結果を共有します。 次に、実際にインテリジェントPDUに接続したOutposts Server上で複数のベンチマークを用いて性能、電力量を計測して電力効率(電力量あたりの性能値)を検証します。 結果として、AWS Graviton2搭載Outposts Serverは一部アプリケーションの大規模グラフ処理ベンチマークGraph500においては2.89倍、Linux Kernelのbuild時間で3.48倍、圧縮ツール7zにおいて3.81倍高い電力効率の結果が得られました。 目次 はじめに 目次 AWS Gravitonについて AWS Gravitonの歴史 最適化・移行方法 AWS Graviton2, Intel Xeon比較記事サーベイ ベンチマーク 計測方法 結果 まとめ 付録 検証環境 ベンチマークコマンド一覧 AWS Gravitonについて AWS GravitonはAWSが独自開発しているARMベースのプロセッサです。 Intelプロセッサ搭載のコンピューティングに比べて高いコストパフォーマンス、高いエネルギー効率が大きな特徴です。 同等のインスタンスサイズで、Intelと比べて最大60%少ないエネルギーで利用することが可能とされています。 1 AWS Gravitonの歴史 2018年 Graviton A1 2 最大45%の大幅なコスト削減 2020年 Graviton2 M6g 3 , C6g, R6g 4 前世代Gravitonと比較して、性能が7倍、コンピューティングコア数が4倍、キャッシュの大きさが2倍、メモリの高速化が5倍 x86ベースのM5インスタンスよりも40%優れたコストパフォーマンス 2021年 Graviton3 C7g 5 前世代Graviton2と比較して最大25%優れたコンピューティングパフォーマンス、最大2倍高い浮動小数点パフォーマンス、および最大2倍速い暗号化ワークロードパフォーマンス 前世代Graviton2 C6gと比較して20%高いネットワーク帯域幅 DDR5メモリ搭載によるDDR4と比較して50%広い帯域幅 2023年 Graviton3E Hpc7g 6 HPCワークロードでは、同等の前世代のインスタンスよりもパフォーマンスが最大60%向上 Elastic Fabric Adapter (EFA)による200Gbpsの低レイテンシーのノード間通信 最適化・移行方法 AWS Gravitonに最適化されたアプリケーション実装には、 aws-graviton-getting-started が参考になります。 SIMDの利用方法、言語別の最適化方法の詳細などが記載されています。 例えばC/C++では、次の表のように最適化するためのコンパイルフラグなどが記載されています。 CPU Flag GCC version LLVM verison Graviton2 -mcpu=neoverse-n1 * GCC-9^ Clang/LLVM 10+ Graviton3(E) -mcpu=neoverse-512tvb % GCC 11+ Clang/LLVM 14+ https://github.com/aws/aws-graviton-getting-started/blob/main/c-c++.md また、AWS Gravitonへの移行を支援するソースコード分析ツール Porting Advisor for Graviton などがあります。2023年9月時点では次の言語が分析対象としてサポートされています。 Python 3+ Java 8+ Go 1.11+ C, C++, Fortran AWS Graviton2, Intel Xeon比較記事サーベイ ここでは、AWS Graviton2とIntel Xeonを比較した過去の発表や記事を共有します。 比較記事 Deep dive on new Arm-based AWS Graviton2 processor-powered Amazon EC2 instances 2019年 AWS re:Inventにおいて発表されたIntel Xeonの M5 とAWS Gravion2の M6g のEC2の比較になります。 https://d1.awsstatic.com/events/reinvent/2019/REPEAT_1_Deep_dive_on_Arm-based_EC2_instances_powered_by_AWS_Graviton_CMP322-R1.pdf M6gのパフォーマンスがSPECcpu2017, Nginx, Memcached, x264のメディアエンコード, TVM (FP16利用)のBERTで優れた性能を発揮しています。 Benchmarking the AWS Graviton2 with KeyDB – M6g up to 65% faster 2020年 KeyDBのブログにおいて、M5とM6g上でインメモリデータベースのKeyDBを動作させた比較になります。 https://docs.keydb.dev/blog/2020/03/02/blog-post/ m6g.largeはm5.largeより1.65倍、m6g.xlargeはm5.xlargeより1.45倍の性能を示しています。さらにM6gはM5よりも20%安いコストで利用できるため高いコストパフォーマンスが達成可能であることを示しています。 Accelerate .NET 6 performance with Arm64 on AWS Graviton2 2020年 AWS Compute Blogにおいて公開されたIntel Xeonのm5.xlargeとAWS Gravion2のm6g.xlarge上で.NET 5を動作させた比較結果です。ベンチマークはASP.NET Coreを用いて作成したWeb APIのリクエスト処理性能を比較しています。 https://aws.amazon.com/jp/blogs/compute/powering-net-5-with-aws-graviton2-benchmark-results/ 左図は1秒あたりのリクエスト数を示しており、Graviton2のm6g.xlargeが全てのテストで多くのリクエストを処理していることが分かります。特に2MBデータをJSONにシリアライズする MvcJsonOutput2M ではm5.xlargeよりも31.6%優れた性能を示しています。 右図はコストあたりのリクエスト数を示しています。ここでもGraviton2のm6g.xlargeは全ての項目で優れており、MvcJsonOutput2M では64%コストあたりのパフォーマンスが優れている結果を示しています。 Performance Analysis for Arm vs x86 CPUs in the Cloud 2021年 InfoQのブログにおいて、Intel Xeonの t3.small とAWS Graviton2の t4g.small を比較した結果になります。 次のようなベンチマーク環境で測定しています。 Docker + Node.js Docker + Native Docker上でC/C++のネイティブアプリケーションを実行 SSVM RustでWebAssemblyにコンパイルして Second State WebAssembly VM (SSVM) で実行 ベンチマークとしては、 Computer Languages Benchmarks Game から4つのベンチマークプログラム nbody , fannkuch-redux , mandelbrot , binary-trees を用いて測定しています。 https://www.infoq.com/articles/arm-vs-x86-cloud-performance/ 左図は実行時間を示しており、小さいほど良い結果と判断します。ネイティブアプリケーションの実行ではGraviton2はIntelよりも性能が高いです。一方でNode.jsとSSVMでは甲乙つけられない結果となっています。 右図はコストあたりの性能を示しています。全体的にGraviton2はIntelに比べて優れたコストパフォーマンスを示しています。 AWS Graviton2: Arm Brings Better Price-Performance than Intel 2021年 ScyllaDBのブログにおいて、Intel Xeonのm5d.8xlargeとGraviton2のm6gd.8xlarge上で分散データベースのScyllaDBを動作させたスループットを比較した結果になります。 https://www.scylladb.com/2021/09/16/aws-graviton2-arm-brings-better-price-performance-than-intel/ 上図はスループットを比較したものになります。基本的にはほぼ互角のパフォーマンスを示しています。 下図は、コストあたりのスループットを示しています。m6gdの方がコスト面で20%ほど有利なためこちらの結果ではGraviton2が15%-25%ほど高いコストパフォマンスを示す結果となりました。 Run Your Databricks Queries in Up to 71% Less Time and Reduce Costs: Select Amazon® R5d Instances Featuring 2nd Gen Intel® Xeon® Scalable Processors 2021年 Intelから発表された記事です。 Databricks レイクハウスプラットフォームの次世代エンジン Photon 対応の第2世代Intel Xeonのr5d.2xlargeと非対応のAWS Graviton2のr6gd.2xlarge上でDatabricks Runtime 9.0のクエリを実行させた結果になります。 https://www.intel.co.jp/content/www/jp/ja/partner/workload/amazon/databricks-on-aws-r5d-vs-r6gd-benchmark.html 図のように、Photon対応の第2世代Intel Xeonは最大で71%処理時間を削減しています。また、性能あたりのコストを比較しても第2世代Intel Xeonが33%低いコストで実行可能な結果を示しています。 Achieve up to 4.96 Times the BERT-Large Inference Work by Selecting AWS M6i Instances Featuring 3rd Gen Intel® Xeon® Scalable Processors 2021年 Intelから発表された第3世代Intel Xeonのm6i.8xlarge, m6i.16xlargeとAWS Graviton2のm6g.8xlarge, m6g.16xlarge上でBERT-Largeを実行させた結果です。 https://www.intel.com/content/www/us/en/partner/workload/amazon/bert-large-aws-m6i-m6g-benchmark.html 8xlargeのインスタンサイズにおいて図のように、INT8精度の第3世代Intel XeonはFP32精度のGraviton2に対して4.96倍の性能を発揮しました。さらに、同条件で16xlargeのインスタンスサイズの場合でも3.07倍の優れた性能を示しています。 Improved performance with AWS Graviton2 instances on Amazon OpenSearch Service 2022年 AWS Big Data Blogにて、Amazon OpenSearch Serviceのパフォーマンスを比較しています。 Intelベースのc5.xlarge, r5.xlargeとGraviton2ベースのc6g.xlarge, r6g.xlargeでElasticsearch 7.10を実行しています。 https://aws.amazon.com/jp/blogs/big-data/improved-performance-with-aws-graviton2-instances-on-amazon-opensearch-service/ 同じスループットでドキュメントをインジェストした結果、Graviton2はIntelに比べて低いレイテンシを示しました。 Achieve up to 27% better price-performance for Spark workloads with AWS Graviton2 on Amazon EMR Serverless 2023年 AWS Big Data Blogにて、Amazon EMR Serverlessにおける比較になります。 https://aws.amazon.com/jp/blogs/big-data/achieve-up-to-27-better-price-performance-for-spark-workloads-with-aws-graviton2-on-amazon-emr-serverless/ 図のようにSparkワークロードにおいて10%のパフォーマンス改善を達成しています。またGraviton2はx86よりも20%低いコスト 7 で実行可能なため価格性能は最終的に27%向上する結果となりました。 Get Higher Cassandra Database Throughput with AWS C6id Instances Compared to C6gd Instances 2023年 Intelから発表された第3世代Intel XeonのC6idとAWS Graviton2のC6gd上でCassandra Databaseを実行させた比較結果になります。 https://www.intel.com/content/www/us/en/content-details/780542/get-higher-cassandra-database-throughput-with-aws-c6id-instances-compared-to-c6gd-instances.html 図のように、さまざまなインスタンスサイズにおいてIntel Xeon搭載のC6idが高いスループットを示し、Graviton2に対して最大で1.36倍のパフォマンスを示しました。 64-vCPU AWS EC2 M5 Instances Achieved Up to 1.67 Times the Work of AWS EC2 M6G Instances Intelから発表された第2世代Intel Xeonのm5.16xlargeとAWS Graviton2のm6g.16xlarge上でそれぞれASP.NET, MySQL, Java server benchmarkについて比較した結果です。 https://www.intel.com/content/www/us/en/partner/workload/amazon/64-vcpu-aws-ec2-165-of-aws-m6g-benchmark.html ASP.NETフレームワークを用いたwebサイトの性能比較では、第2世代Intel Xeonが1.67倍優れている結果となりました。また、図のようにMySQLにおいても1.65倍、Java server benchmarkでは1.2倍程度Graviton2より優れた性能を示していることが分かります。 比較記事の総評 上記の調査結果から実行するベンチマークやアプリケーションによって異なる性能を示すことが分かりました。 また、Graviton2は同等インスタンスサイズにおいて、低価格で利用できるためIntel Xeonに対してコストあたりの性能に着目すると非常に高いコストパフォーマンスを示すケースが多々ありました。 しかし、Gravitonのもう1つの特徴であるエネルギー効率面に関してはクラウド上で実行するので計測の困難さもあり、定量的に比較した記事があまり見受けられませんでした。 そこで我々はAWS Graviton2, Intel Xeon搭載のOutposts ServerにインテリジェントPDUを接続してベンチマーク実行時の電力量を測定し電力効率を測定・検証しました。 ベンチマーク 計測方法 計測したOutposts Serverのフォームファクタは次の2つになります。 Outpost リソース ID ラックユニットの高さ EC2 容量 プロセッサ/アーキテクチャ vCPU メモリ ローカル NVMe SSD ストレージ ネットワークアップリンク 消費電力 重量 電源タイプ OR-STBKRBE 1U c6gd.16xlarge Graviton2 / Arm 64 128 GiB 3.8 TB 10 Gbps 0.8 kVA 13 kg AC OR-KOSKFSF 2U c6id.32xlarge Xeon Ice Lake / x86 128 256 GiB 7.6 TB 10 Gbps 1.5 kVA 16 kg AC これらのサーバにインテリジェントPDUを設置し電力量を計測しました。 インスタンスがない場合のサーバの待機電力はAWS Graviton2 176W, Intel Xeon 323Wでした。 また、ベンチマーク実行中の最大電力はAWS Graviton2 393W, Intel Xeon 1099Wでした。 それぞれ同等のインスタンスサイズである AWS Graviton2 (c6gd.16xlarge), Intel Xeon (c6id.16xlarge)上で計測しています。 検証環境の詳細は こちら の付録を参照してください。 結果 ベンチマークにはベンチマークスイートツールであるphoronix-test-suiteや、個別にOpenSSL, Unixbench, 7zip, TorchBench, Renaissanceなどを用いています。 合計24のベンチマークで計測し、可能な限り偏らないようにしました。 詳細なコマンドは こちら を参照してください。 次の図は、Intel Xeonのベンチマーク値(Score)を1として正規化した性能の結果になります。値が大きいほど良い結果を表しています。 この性能結果からは、アプリケーションによって異なりGraviton2とIntelでは全体的に大きな差はないように見られます。 次の図は、Intel Xeonのベンチマーク値(Score) / 積算電力量(kwh)を1として正規化した電力効率の結果になります。値が大きいほど電力効率が高いことを表しています。 こちらの結果では性能結果と同様にsvt-avt, ffmpeg(libx265)のようなメディアエンコードやpytorchなどの機械学習ベンチマークでIntel Xeonと比べてGraviton2は低い電力効率を示しました。 しかし、一方でIntel Xeonに比べてGraviton2が特に大規模グラフ処理ベンチマークGraph500においては2.89倍、Linux Kernelのbuild時間で3.48倍、圧縮ツール7zにおいて3.81倍高い電力効率の結果が得られました。また、性能結果では劣っていたベンチマーク openssl(aes-128-ctr), nginx, srsran(Throughput Total) john the ripper(Blowfish, bcrypt) も電力効率の面では優れた結果となっていることが分かります。 まとめ 本記事では、AWS Graviton2, Intel Xeon搭載のOutposts Serverの電力効率検証の結果を共有しました。その結果、Graviton2は特定のアプリケーションでは最大3.81倍の高い電力効率を示すことが分かりました。また、性能では劣るものも電力量あたりの性能はIntel Xeonを逆転するベンチマークが多々あるということも分かりました。 以上の検証から電力規制が厳しい環境やサステナブルな社会に、AWS Graviton2搭載のOutposts Serverは貢献に寄与すると思われます。 付録 検証環境 AWS Graviton2 (c6gd.16xlarge) OS: Amazon Linux 2023 AMI ID: ami-037f40c2ea5b01508 $ uname -a Linux ip-10-0-0-126.ap-northeast-1.compute.internal 6.1.41-63.114.amzn2023.aarch64 #1 SMP Tue Aug 1 20:47:07 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux $ openssl version OpenSSL 3.0.8 7 Feb 2023 (Library: OpenSSL 3.0.8 7 Feb 2023) $ cat byte-unixbench/UnixBench/README | grep Version Version 5.1.3 -- 2011-01-13 $ 7z 7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21 p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,64 CPUs LE) $ gcc --version gcc (GCC) 11.3.1 20221121 (Red Hat 11.3.1-4) Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ java --version openjdk 17.0.8 2023-07-18 LTS OpenJDK Runtime Environment Corretto-17.0.8.7.1 (build 17.0.8+7-LTS) OpenJDK 64-Bit Server VM Corretto-17.0.8.7.1 (build 17.0.8+7-LTS, mixed mode, sharing) $ lscpu Architecture: aarch64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 64 On-line CPU(s) list: 0-63 Vendor ID: ARM Model name: Neoverse-N1 Model: 1 Thread(s) per core: 1 Core(s) per socket: 64 Socket(s): 1 Stepping: r3p1 BogoMIPS: 243.75 Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs Caches (sum of all): L1d: 4 MiB (64 instances) L1i: 4 MiB (64 instances) L2: 64 MiB (64 instances) L3: 32 MiB (1 instance) NUMA: NUMA node(s): 1 NUMA node0 CPU(s): 0-63 Vulnerabilities: Gather data sampling: Not affected Itlb multihit: Not affected L1tf: Not affected Mds: Not affected Meltdown: Not affected Mmio stale data: Not affected Retbleed: Not affected Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl Spectre v1: Mitigation; __user pointer sanitization Spectre v2: Mitigation; CSV2, BHB Srbds: Not affected Tsx async abort: Not affected Intel Xeon (c6id.16xlarge) OS: Amazon Linux 2023 AMI ID: ami-0310b105770df9334 $ uname -a Linux ip-10-0-1-175.ap-northeast-1.compute.internal 6.1.41-63.114.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Aug 1 20:47:25 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux $ openssl version OpenSSL 3.0.8 7 Feb 2023 (Library: OpenSSL 3.0.8 7 Feb 2023) $ cat byte-unixbench/UnixBench/README | grep Version Version 5.1.3 -- 2011-01-13 $ 7z 7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21 p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,64 bits,64 CPUs Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz (606A6),ASM,AES-NI) $ gcc --version gcc (GCC) 11.3.1 20221121 (Red Hat 11.3.1-4) Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ java --version openjdk 17.0.8 2023-07-18 LTS OpenJDK Runtime Environment Corretto-17.0.8.7.1 (build 17.0.8+7-LTS) OpenJDK 64-Bit Server VM Corretto-17.0.8.7.1 (build 17.0.8+7-LTS, mixed mode, sharing) $ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 46 bits physical, 48 bits virtual Byte Order: Little Endian CPU(s): 64 On-line CPU(s) list: 0-63 Vendor ID: GenuineIntel Model name: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz CPU family: 6 Model: 106 Thread(s) per core: 2 Core(s) per socket: 32 Socket(s): 1 Stepping: 6 BogoMIPS: 5799.98 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscal l nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_know n_freq pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsav e avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsb ase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb av x512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves wbnoinvd ida arat avx512vbmi pku ospke avx512_v bmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg tme avx512_vpopcntdq rdpid md_clear flush_l1d arch_capabil ities Virtualization features: Hypervisor vendor: KVM Virtualization type: full Caches (sum of all): L1d: 1.5 MiB (32 instances) L1i: 1 MiB (32 instances) L2: 40 MiB (32 instances) L3: 54 MiB (1 instance) NUMA: NUMA node(s): 1 NUMA node0 CPU(s): 0-63 Vulnerabilities: Gather data sampling: Vulnerable: Microcode update required Itlb multihit: Not affected L1tf: Not affected Mds: Not affected Meltdown: Not affected Mmio stale data: Mitigation; Clear CPU buffers; SMT Host state unknown Retbleed: Not affected Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization Spectre v2: Mitigation; Enhanced IBRS, IBPB conditional, RSB filling, PBRSB-eIBRS SW sequence Srbds: Not affected Tsx async abort: Not affected ベンチマークコマンド一覧 hpl 8 phoronix-test-suite benchmark pts/hpl-1.0.0 hpcg phoronix-test-suite benchmark pts/hpcg-1.3.0 # [X Y Z: 104 104 104 - RT: 1800] graph500 phoronix-test-suite benchmark pts/graph500-1.0.1 # [Scale: 26] openssl(aes-128-ctr) openssl speed -multi 64 -bytes 16384 -seconds 300 -evp aes-128-ctr openssl(aes-128-gcm) openssl speed -multi 64 -bytes 16384 -seconds 300 -evp aes-128-gcm openssl(chacha20-poly1305) openssl speed -multi 64 -bytes 16384 -seconds 300 -evp chacha20-poly1305 Unixbench 9 # Version 5.1.3 Run -c 64 7zip 10 7z b 30 nginx phoronix-test-suite benchmark pts/nginx-3.0.1 # [Connections: 4000] build linux kernel phoronix-test-suite benchmark pts/build-linux-kernel-1.15.0 build llvm phoronix-test-suite benchmark pts/build-llvm-1.5.0 Renaissance akka-uct 11 java -jar renaissance-gpl-0.14.2.jar akka-uct srsran(Throughput Total) phoronix-test-suite benchmark pts/srsran-2.1.0 # [Test: PUSCH Processor Benchmark, Throughput Total] srsran(Throughput Thread) phoronix-test-suite benchmark pts/srsran-2.1.0 # [Test: PUSCH Processor Benchmark, Throughput Thread] srsran(Downlink) phoronix-test-suite benchmark pts/srsran-2.1.0 # [Test: Downlink Processor Benchmark] svt-av1 phoronix-test-suite benchmark pts/svt-av1-2.10.0 # [Encoder Mode: Preset 4 - Input: Bosphorus 4K] ffmpeg(libx265) phoronix-test-suite benchmark pts/ffmpeg-6.0.0 # [Encoder: libx265 - Scenario: Video On Demand] pytorch(resnet50) 12 python run.py resnet50 -d cpu -t eval --use_cosine_similarity --bs 32 pytorch(BERT) python run.py BERT_pytorch -d cpu -t eval --use_cosine_similarity --bs 32 john the ripper(md5) phoronix-test-suite benchmark pts/john-the-ripper-1.8.0 # [Test: MD5] john the ripper(Blowfish) phoronix-test-suite benchmark pts/john-the-ripper-1.8.0 # [Test: Blowfish] john the ripper(HMAC-SHA512) phoronix-test-suite benchmark pts/john-the-ripper-1.8.0 # [Test: HMAC-SHA512] john the ripper(bcrypt) phoronix-test-suite benchmark pts/john-the-ripper-1.8.0 # [Test: bcrypt] john the ripper(WPA_PSK) phoronix-test-suite benchmark pts/john-the-ripper-1.8.0 # [Test: WPA PSK] https://aws.amazon.com/jp/ec2/graviton/ ↩ https://aws.amazon.com/jp/about-aws/whats-new/2018/11/introducing-amazon-ec2-a1-instances/ ↩ https://aws.amazon.com/jp/about-aws/whats-new/2020/05/amazon-ec2-m6g-instances-powered-by-aws-graviton2-processors-generally-available/ ↩ https://aws.amazon.com/jp/about-aws/whats-new/2020/06/amazon-ec2-c6g-r6g-instances-amazon-graviton2-processors-generally-available/ ↩ https://aws.amazon.com/jp/about-aws/whats-new/2021/11/amazon-ec2-c7g-instances-aws-graviton3-processors/ ↩ https://aws.amazon.com/jp/about-aws/whats-new/2023/06/amazon-ec2-hpc7g-instances/ ↩ https://aws.amazon.com/jp/emr/pricing/#Amazon_EMR_Serverless ↩ https://www.phoronix-test-suite.com/ ↩ https://github.com/kdlucas/byte-unixbench ↩ https://www.7-zip.org/ ↩ https://renaissance.dev/ ↩ https://github.com/pytorch/benchmark ↩
サマリ 概要 Multi-vendor Flex-Algorithm 動作確認検証 1. リンクに対するメトリックの定義 2. リンクに対する color の定義 3. FAD の設定 4. Algorithm に参加するための設定 5. FAD の確認 6. BGP Import ポリシーの設定と確認 7. traceroute による VPN の通信経路確認 まとめ サマリ Flexible Algorithm による VPN 経路の TE を SR OS で実現 IOS XR + Junos + SR OS の Multi-vendor 環境で TE と Delay metric を含めた Algorithm の定義と動作検証に成功 この記事は Multi-AS SR 検証連載の第 15 回です。目次は こちら 概要 イノベーションセンターの吉田 晴信です。 普段の業務では Multi-AS Segment Routing に関する技術検証をしています。 第 6 回 の記事で IOS XR + Junos の2つのベンダー機器で構成される Flexible Algorithm (以降 Flex-Algorithm と呼びます) についてご紹介しました。 今回新たに Nokia SR OS (Service Router Operating System) を加えた3つのベンダー機器での Flex-Algorithm 相互動作確認をご紹介します。 さらに第 6 回は IGP metric の検証のみでしたが、今回は TE と Delay metric を用いた Flex-Algorithm の作成と動作確認を行いましたので、そちらもご紹介します。 なお、Flex-Algorithm の説明は、第 6 回記事の概要章にてご紹介しましたので、そちらをご参照ください。 Multi-vendor Flex-Algorithm 動作確認検証 本記事では、Nokia SR OS を加えた3つのベンダー機器での Flex-Algorithm 相互動作確認を行います。 その際に、IGP 、TE 、 Delay の 3 つのメトリックを使用します。 次の図で Flex-Algorithm に使用するリンクの color も含めて全体を示します。 各 Algorithm の制約ごとにトポロジーを示します。 Algorithm 128: リンク RED を除いた、IGP metric に従ったトポロジー cust-a は Algorithm 128 のトポロジーを用いて転送するため、以下のような経路を通ります。 Algorithm 129: リンク BLUE のみで、TE metric に従ったトポロジー cust-b は Algorithm 129 のトポロジーを用いて転送するため、以下のような経路を通ります。 Algorithm 130: リンク GREEN を除いた、Delay metric に従ったトポロジー cust-c は Algorithm 130 のトポロジーを用いて転送するため、以下のような経路を通ります。 検証に用いた各ルーターのバージョンは下記の通りです。 PE1、PE2: Nokia SR OS 22.7.R1 P1: Cisco IOS XR 7.4.1 P2: Junos OS 23.1R1.8 事前準備として VPRN (VRF) cust-a、cust-b、cust-c の 3 つの L3VPN を作成します。 詳しくは 第 12 回 に設定例があるので、そちらをご参照ください。 Flex-Algorithm の検証は次のステップで行います。 リンクに対するメトリックの定義 リンクに対する color の定義 FAD の設定 Algorithm に参加するための設定 FAD の確認 BGP Import ポリシーの設定と確認 traceroute による VPN の通信経路確認 1. リンクに対するメトリックの定義 各ルーターのインタフェースに対し IGP、 TE、 Delay のメトリックを指定します。 下記では、 SR OS における 3 種のメトリック、 IOS XR と Junos OS における TE metric と Delay metric の設定方法を示します。 IOS XR と Junos OS における IGP metric の設定方法については、 第 6 回 の記事で説明していますので、ご参照ください。 SR OS (PE1) SR OS における IGP、 TE、 Delay metric の設定方法を示します。 各メトリックは以下の階層にあります。 IGP metric は router isis TE metric は router mpls Delay metric は router interface 例では、PE1 の P1 向けインタフェースに IGP metric 10、TE metric 10、Delay metric 10 を設定しています。 他のインタフェースや PE2 も同様の方法で設定します。 [gl:/configure] A:user@PE1# info router isis interface "to_P1" level 2 { metric 10 } [gl:/configure] A:user@PE1# info router mpls interface "to_P1" te-metric 10 [gl:/configure] A:user@PE1# info router interface "to_P1" if-attribute { delay { static 10 } } IOS XR (P1) IOS XR における TE metric は segment-routing 階層の下にあります。 また、 Delay metric は performance-measurement 階層の下にあります。 例では、PE1 向けインタフェース Gi 0/0/0/0 に TE metric 10 と Delay metric 10、P2 向けインタフェース Gi 0/0/0/1 に TE metric 10 と Delay metric 10、PE2 向けインタフェース Gi 0/0/0/2 に TE metric 100 と Delay metric 10 を設定しています。 RP/0/RP0/CPU0:P1#show running-config segment-routing Thu Jul 20 14:55:00.724 JST segment-routing traffic-eng interface GigabitEthernet0/0/0/0 metric 10 ! interface GigabitEthernet0/0/0/1 metric 10 ! interface GigabitEthernet0/0/0/2 metric 100 ! ! ! RP/0/RP0/CPU0:P1#show running-config performance-measurement Thu Jul 20 18:42:33.471 JST performance-measurement interface GigabitEthernet0/0/0/0 delay-measurement advertise-delay 10 ! ! interface GigabitEthernet0/0/0/1 delay-measurement advertise-delay 10 ! ! interface GigabitEthernet0/0/0/2 delay-measurement advertise-delay 10 ! ! ! Junos OS (P2) Junos OS における TE metric と Delay metric は protocol isis 階層の下にあります。 例では、PE1 向けインタフェース ge-0/0/0 に TE metric 10 と Delay metric 100、P1 向けインタフェース ge-0/0/1 に TE metric 10 と Delay metric 10、PE2 向けインタフェース ge-0/0/2 に TE metric 10 と Delay metric 10 を設定しています。 set protocols isis interface ge-0/0/0.0 level 2 te-metric 10 set protocols isis interface ge-0/0/0.0 level 2 application-specific attribute-group Flex-Algo advertise-delay-metric set protocols isis interface ge-0/0/0.0 level 2 application-specific attribute-group Flex-Algo te-metric 10 set protocols isis interface ge-0/0/0.0 delay-metric 100 set protocols isis interface ge-0/0/1.0 level 2 te-metric 10 set protocols isis interface ge-0/0/1.0 level 2 application-specific attribute-group Flex-Algo advertise-delay-metric set protocols isis interface ge-0/0/1.0 level 2 application-specific attribute-group Flex-Algo te-metric 10 set protocols isis interface ge-0/0/1.0 delay-metric 10 set protocols isis interface ge-0/0/2.0 level 2 te-metric 10 set protocols isis interface ge-0/0/2.0 level 2 application-specific attribute-group Flex-Algo advertise-delay-metric set protocols isis interface ge-0/0/2.0 level 2 application-specific attribute-group Flex-Algo te-metric 10 set protocols isis interface ge-0/0/2.0 delay-metric 10 2. リンクに対する color の定義 各ルーターにてインタフェースに対し Flex-Algorithm の color を指定します。 本記事では、SR OS におけるリンクに対する color の設定方法を示します。 IOS XR と Junos OS における color の設定方法については 第 6 回 の記事で説明していますので、ご参照ください。 SR OS (PE1) SR OS における color は router interface 階層の下にあります。 また、color と Administrative Group の紐付けは routing-options if-attribute の階層で行います。 例として、PE1 の P1 向けインタフェースに対して以下のように設定します。 他のインタフェース、PE も同様の方法で設定します。 [gl:/configure] A:user@PE1# info router interface "to_P1" if-attribute { admin-group ["BLUE"] } [gl:/configure] A:user@PE1# info routing-options if-attribute admin-group "BLUE" { value 2 } admin-group "GREEN" { value 3 } admin-group "RED" { value 1 } 3. FAD の設定 各ルーターでメトリックやリンクの color の制約を含む Flexible Algorithm Definition (FAD) を設定し広告します。 また、FAD の設定では Flex-Algorithm を識別する数値 (Algorithm) 128、 129、 130 も定義します。 本検証では、IOS XR、Junos OS、SR OS 間で FAD を広告できるか確認するため、3 種類の FAD をそれぞれ別のルーターで定義します。 組み合わせは以下の通りです。 Algorithm 128: P1 (IOS XR) Algorithm 129: P2 (Junos OS) Algorithm 130: PE2 (SR OS) IOS XR (P1) P1 ではリンク RED を除いて、IGP metric に従ったトポロジーを算出する Algorithm 128 を定義し広告します。 router isis 1 flex-algo 128 advertise-definition affinity exclude-any RED ! ! Junos OS (P2) P2 ではリンク BLUE のみで、TE metric に従ったトポロジーを算出する Algorithm 129 を定義し広告します。 set routing-options flex-algorithm 129 definition metric-type te-metric set routing-options flex-algorithm 129 definition spf set routing-options flex-algorithm 129 definition admin-group include-any BLUE SR OS (PE2) PE2 ではリンク GREEN を除いて、Delay metric に従ったトポロジーを算出する Algorithm 130 を定義し広告します。 [gl:/configure] A:user@PE2# info router "Base" isis 0 flexible-algorithms { flex-algo 130 { participate true advertise "FAD-130-DELAY" } } [gl:/configure] A:user@PE2# info routing-options flexible-algorithm-definitions { flex-algo "FAD-130-DELAY" { admin-state enable metric-type delay priority 100 exclude { admin-group "GREEN" { } } } } 4. Algorithm に参加するための設定 各ルーターで広告している Algorithm へ参加するための設定をします。 SR OS (PE1) PE1 では Algorithm 128、 129、 130 に参加する設定と各 Algorithm で利用する Node SID を定義します。 PE2 でも同様の設定をします。 [gl:/configure] A:user@PE1# info router "Base" isis 0 flexible-algorithms admin-state enable flex-algo 128 { participate true } flex-algo 129 { participate true } flex-algo 130 { participate true } [gl:/configure] A:user@PE1# info router "Base" isis 0 interface "system" flex-algo 128 { ipv4-node-sid { index 1001 } } flex-algo 129 { ipv4-node-sid { index 2001 } } flex-algo 130 { ipv4-node-sid { index 3001 } } IOS XR (P1) P1 では Algorithm 128、 129、 130 で利用する Node SID を定義します。 router isis 1 ! flex-algo 129 ! flex-algo 130 ! interface Loopback0 address-family ipv4 unicast prefix-sid algorithm 128 index 1002 prefix-sid algorithm 129 index 2002 prefix-sid algorithm 130 index 3002 ! ! ! Junos OS (P2) P2 では Algorithm 128、 129、 130 で利用する Node SID を定義します。 set policy-options policy-statement Flex-Algo-SID term ALGO-SID from route-filter 10.255.0.3/32 exact set policy-options policy-statement Flex-Algo-SID term ALGO-SID then prefix-segment algorithm 128 index 1003 set policy-options policy-statement Flex-Algo-SID term ALGO-SID then prefix-segment algorithm 128 node-segment set policy-options policy-statement Flex-Algo-SID term ALGO-SID then prefix-segment algorithm 129 index 2003 set policy-options policy-statement Flex-Algo-SID term ALGO-SID then prefix-segment algorithm 129 node-segment set policy-options policy-statement Flex-Algo-SID term ALGO-SID then prefix-segment algorithm 130 index 3003 set policy-options policy-statement Flex-Algo-SID term ALGO-SID then prefix-segment algorithm 130 node-segment set protocols isis source-packet-routing flex-algorithm 128 set protocols isis source-packet-routing flex-algorithm 129 set protocols isis source-packet-routing flex-algorithm 130 set protocols isis source-packet-routing strict-asla-based-flex-algorithm set protocols isis traffic-engineering advertisement always set protocols isis export Flex-Algo-SID 5. FAD の確認 各ルーターで設定された FAD が学習されているかを確認します。 はじめに、SR OS (PE1) で IOS XR、 Junos OS、 SR OS の FAD を確認した後、IOS XR (P1) で SR OS の FAD を確認します。 SR OS (PE1) SR OS では以下のコマンドで学習している FAD を確認できます。 PE1 で IOS XR(P1) で定義された Algorithm 128、Junos OS(P2) で定義された Algorithm 129、SR OS(PE2) で定義された Algorithm 130 を確認できます。 [/] A:user@PE1# show router isis flex-algo detail =============================================================================== Rtr Base ISIS Instance 0 Flex-Algos (detail) =============================================================================== ------------------------------------------------------------------------------- Flex-Algo : 128 ------------------------------------------------------------------------------- Advertising FAD : None Participating : Yes Micro-Loop-Avoidance : Disabled Loop-Free-Alternate : Disabled L2 Oper state : UP Displaying Level 2 FAD Info ------------------------------------------------------------------------------- FADs-count : 1 Selected FAD Fad-Owner : 0000.0AFF.0002 Supported : Yes Priority : 128 Metric Type : igp Calculation Type : spf(0) Exclude : 0x2 Include Any : 0x0 Include All : 0x0 Fad Flags : 0x0 Level : L2 ------------------------------------------------------------------------------- Flex-Algo : 129 ------------------------------------------------------------------------------- Advertising FAD : None Participating : Yes Micro-Loop-Avoidance : Disabled Loop-Free-Alternate : Disabled L2 Oper state : UP Displaying Level 2 FAD Info ------------------------------------------------------------------------------- FADs-count : 1 Selected FAD Fad-Owner : 0000.0AFF.0003 Supported : Yes Priority : 0 Metric Type : te-metric Calculation Type : spf(0) Exclude : 0x0 Include Any : 0x4 Include All : 0x0 Fad Flags : 0x0 Level : L2 ------------------------------------------------------------------------------- Flex-Algo : 130 ------------------------------------------------------------------------------- Advertising FAD : None Participating : Yes Micro-Loop-Avoidance : Disabled Loop-Free-Alternate : Disabled L2 Oper state : UP Displaying Level 2 FAD Info ------------------------------------------------------------------------------- FADs-count : 1 Selected FAD Fad-Owner : 0102.5500.0004 Supported : Yes Priority : 100 Metric Type : delay Calculation Type : spf(0) Exclude : 0x8 Include Any : 0x0 Include All : 0x0 Fad Flags : M Level : L2 ------------------------------------------------------------------------------- FAD: Flexible Algorithm Definition Fad Flags: M = Prefix Metric =============================================================================== IOS XR (P1) IOS XR では以下のコマンドで学習している FAD を確認できます。 P1 で Junos OS(P2) で定義された Flex-Algo 129 と SR OS(PE2) で定義された Flex-Algo 130 を確認できます。 RP/0/RP0/CPU0:P1#show isis flex-algo 129 Wed Jul 19 13:44:09.974 JST IS-IS 1 Flex-Algo Database Flex-Algo 129: Level-2: Definition Priority: 0 Definition Source: P2.00 Definition Equal to Local: No Definition Metric Type: TE Definition Flex-Algo Prefix Metric: No Disabled: No Local Priority: 128 FRR Disabled: No Microloop Avoidance Disabled: No RP/0/RP0/CPU0:P1#show isis flex-algo 130 Wed Jul 19 13:44:12.627 JST IS-IS 1 Flex-Algo Database Flex-Algo 130: Level-2: Definition Priority: 100 Definition Source: PE2.00 Definition Equal to Local: No Definition Metric Type: Delay Definition Flex-Algo Prefix Metric: Yes Disabled: No Local Priority: 128 FRR Disabled: No Microloop Avoidance Disabled: No 6. BGP Import ポリシーの設定と確認 上記の情報を確認した後に、事前に構築した L3VPN と定義した Algorithm を紐付けるための設定をします。 SR OS (PE1) SR OS では BGP Import ポリシー にて、特定の Route Target (RT) に対する action として Algorithm を指定できます。 そういったポリシーを L3VPN に適用し、それぞれの VPN 経路と Algorithm が紐付けられます。 以下の例では、RT target-100 に Algorithm 128 を付与しています。 これにより、VPRN cust-a で使用する RT target-100 が付与された経路と Algorithm 128 が紐付けられます。 Algorithm 129、130 にも同様の方法で設定します。 [gl:/configure] A:user@PE1# info policy-options policy-statement "vrf-import-100" entry 10 { from { community { name "target-100" } } action { action-type accept flex-algo 128 } } [gl:/configure] A:user@PE1# info service vprn "cust-a" bgp-ipvpn mpls admin-state enable route-distinguisher "65000:100" vrf-import { policy ["vrf-import-100"] } vrf-export { policy ["vrf-export-100"] } auto-bind-tunnel { resolution filter resolution-filter { sr-isis true sr-policy true } } 次に、PE1 で Algorithm 128 と VPRN cust-a で使用する経路が紐付けられているか確認します。 まず、PE1 が認識している Tunnel ID を確認すると、 Algorithm 128 では Node SID 17003 に対応した Tunnel ID 524310 と、 Node SID 17004 に対応した Tunnel ID 524311 があります。 [/] A:user@PE1# show router fp-tunnel-table 1 =============================================================================== IPv4 Tunnel Table Display Legend: label stack is ordered from bottom-most to top-most B - FRR Backup =============================================================================== Destination Protocol Tunnel-ID Lbl/SID NextHop Intf/Tunnel Lbl/SID (backup) NextHop (backup) ------------------------------------------------------------------------------- (snip) 10.255.0.3/32 SR-ISIS-0 524310 17003 10.1.2.2 1/1/c1/1:0 10.255.0.4/32 SR-ISIS-0 524293 16004 10.1.2.2 1/1/c1/1:0 10.255.0.4/32 SR-ISIS-0 524308 18004 10.1.3.2 1/1/c2/1:0 10.255.0.4/32 SR-ISIS-0 524309 19004 10.1.2.2 1/1/c1/1:0 10.255.0.4/32 SR-ISIS-0 524311 17004 10.1.2.2 1/1/c1/1:0 ------------------------------------------------------------------------------- Total Entries : 14 ------------------------------------------------------------------------------- =============================================================================== 次に、VPRN cust-a のルーティングテーブルを確認すると、Nexthop の Tunnel ID が 524311 となっています。 これにより、VPRN cust-a で使用する経路が Algorithm 128 に紐付いていることがわかります。 [/] A:user@PE1# show router "100" route-table =============================================================================== Route Table (Service: 100) =============================================================================== Dest Prefix[Flags] Type Proto Age Pref Next Hop[Interface Name] Metric ------------------------------------------------------------------------------- 192.168.0.0/24 Local Local 13d23h57m 0 to_cust-a 0 192.168.10.0/24 Remote BGP VPN 09d21h53m 170 10.255.0.4 (tunneled:SR-ISIS:524311) 30 192.168.10.254/32 Remote BGP VPN 09d21h53m 170 10.255.0.4 (tunneled:SR-ISIS:524311) 30 ------------------------------------------------------------------------------- No. of Routes: 3 Flags: n = Number of times nexthop is repeated B = BGP backup route available L = LFA nexthop available S = Sticky ECMP requested =============================================================================== 7. traceroute による VPN の通信経路確認 最後に、3 つの L3VPN の経路が定義した Algorithm の制約通りになっているかを確認します。 PE1 -> PE2 VPRN cust-a Algorthm 128 で定義した制約の通り、RED のリンクを避け、IGP metric が最小になるよう、PE1 -> P1 -> P2 -> PE2 と通過していることがわかります。 [/] A:user@PE1# traceroute 192.168.10.254 router-instance "cust-a" traceroute to 192.168.10.254, 30 hops max, 40 byte packets 1 10.1.2.2 (10.1.2.2) 5.00 ms 3.56 ms 13.1 ms 2 10.2.3.2 (10.2.3.2) 3.28 ms 7.75 ms 10.5 ms 3 192.168.10.254 (192.168.10.254) 3.11 ms 9.96 ms 3.37 ms PE1 -> PE2 VPRN cust-b Algorthm 129 で定義した制約の通り、BLUE のリンクのみを利用し、TE metric が最小になるよう、PE1 -> P2 -> PE2 と通過していることがわかります。 [/] A:user@PE1# traceroute 192.168.11.254 router-instance "cust-b" traceroute to 192.168.11.254, 30 hops max, 40 byte packets 1 10.1.3.2 (10.1.3.2) 2.84 ms 3.10 ms 2.87 ms 2 192.168.11.254 (192.168.11.254) 3.10 ms 2.94 ms 3.07 ms PE1 -> PE2 VPRN cust-c Algorthm 130 で定義した制約の通り、GREEN のリンクを避け、Delay metric が最小になるよう、PE1 -> P1 -> P2 -> PE2 と通過していることがわかります。 [/] A:user@PE1# traceroute 192.168.12.254 router-instance "cust-c" traceroute to 192.168.12.254, 30 hops max, 40 byte packets 1 10.1.2.2 (10.1.2.2) 17.2 ms 6.56 ms 3.51 ms 2 10.2.3.2 (10.2.3.2) 3.34 ms 3.34 ms 9.39 ms 3 192.168.12.254 (192.168.12.254) 3.10 ms 7.79 ms 3.16 ms まとめ 本記事では、IOS XR、 Junos OS、 Nokia SR OS の 3 ベンダー間の Flex-Algorithm の相互動作を確認しました。 IGP 、 TE と Delay metric の Algorithm を定義し、動作検証を行いました。 次回の記事では、Delay Measurement について紹介予定です。 (2023/10/02 追記) 公開しました: [Multi-AS Segment Routing 検証連載 #16] Delay Measurement using IOS XR, Junos and SR OS
目次 目次 はじめに NeRFの概要と最近の課題 モデル軽量化に関する論文 PlenVDB: Memory Efficient VDB-Based Radiance Fields for Fast Training and Rendering Masked Wavelet Representation for Compact Neural Radiance Fields MobileNeRF: Exploiting the Polygon Rasterization Pipeline for Efficient Neural Field Rendering on Mobile Architectures 表現力の拡張に関する論文 K-Planes: Explicit Radiance Fields in Space, Time, and Appearance ABLE-NeRF: Attention-Based Rendering With Learnable Embeddings for Neural Radiance Field カメラ姿勢のずれの解決に焦点を当てた論文 Local-to-Global Registration for Bundle-Adjusting Neural Radiance Fields 最後に はじめに こんにちは、イノベーションセンターのメディアAIチームです。普段はコンピュータビジョンの技術開発やAI/機械学習(ML)システムの検証に取り組んでいます。6月18日から22日にかけて、コンピュータービジョン分野におけるトップカンファレンスのひとつであるCVPR2023が開催され、NTT Comからは現地とオンラインで参加しました。本記事ではCVPRで登場したNeRFに関する論文をいくつかご紹介します。 NeRFの概要と最近の課題 NeRF 1 はニューラルネットワークベースの微分可能な3次元レンダリング手法で、3次元位置と視線方向の入力に対して色と密度を返すNNモデルを使いボリュームレンダリングを行います。物体のさまざまな方向からの写真をデータセットとしてこのモデルを学習することで、未知の視点からのレンダリング(novel view synthesis)が可能になります。 2020年にNeRFが提案されてから非常に多くの改善や拡張が提案されており、CVPR2023では約40本のNeRF関連論文が採択されました。これらの論文で提案されている内容は以下のように分類されます。 計算時間やメモリ使用量を軽減する 学習したモデルを改変したり、複数のモデルを統合する 屋外のように距離制限がないシーンを撮影する 透過や反射などの表現力の向上 時間方向への拡張 悪い撮影環境(光源変化や他物体の写り込み、不正確なカメラ姿勢など)に強くする この中で特にモデル軽量化と表現力向上、そして不正確なカメラ姿勢への対策の3つのテーマについて、私たちが面白いと思った論文をピックアップしてご紹介します。 モデル軽量化に関する論文 オリジナルのNeRFモデルは9つの全結合層を含んだ多層パーセプトロン(MLP)であり、レイトレーシングの際に何度もこのモデルのforward関数を計算するので、レンダリングに時間がかかるという問題がありました。 公式の実装 によると、モデルサイズは5MBと小さいものの、GPU推論で画像を1枚レンダリングするのに最大30秒、学習には1日かかるとあり、実際の活用には困難が伴います。このレンダリングや学習の計算時間を短縮するために提案された手法をいくつかご紹介します。 PlenVDB: Memory Efficient VDB-Based Radiance Fields for Fast Training and Rendering 2 MLPの計算時間を削減するために、高次元の特徴量を3次元グリッド状に保持し、レンダリング時は入力座標を元に特徴量を参照して残りの計算を軽量なMLPで計算するという手法が提案されています。これはグリッドベース手法と言われ、さまざまな手法が提案されています。 グリッドベースNeRFモデルの特徴として、グリッド全体に対して意味のあるデータが含まれている部分が少ないというものがあり、このスパース性を計算速度の改善に繋げたのがこの論文です。VDBと呼ばれるデータ構造を採用しており、効率的に3次元データを格納できる一般的なデータ構造であるoctreeよりも高速な要素アクセスが可能です。 また、VDBのGPU実装である NanoVDB を活用することで、iPhone12のようなモバイル環境で720pのレンダリングを30FPSで実行できるとしています。 こちらは 公式実装 をA100 GPUx1で実験した結果です。NanoVDBを使わなくてもかなり高速にレンダリング可能であることがわかります。 model filesize train time rendering time PSNR↑ mic 59.6MB 33min 2.7s 33.18 drums 100MB 34min 2.98s 25.39 materials 175MB 37min 2.05s 29.59 Masked Wavelet Representation for Compact Neural Radiance Fields 3 スパースなデータを取り扱う手法として、データ構造を工夫する以外にデータを圧縮するという方法があります。ECCV2022で発表されたTensoRF 4 はテンソル分解と呼ばれる次元削減手法を用いて、3次元データを2次元行列と1次元ベクトルとの外積の和に分解しています。この手法はデータ構造を工夫する手法とは異なり、メモリ使用量や学習済みモデルのファイルサイズを軽減できます。 本手法はこのTensoRFをさらに軽量化するために、TensoRFモデル内の2次元行列をウェーブレット基底で表現しデータを圧縮することを提案しています。また、非ゼロ部分を示すマスクを学習させることで、95%以上の値が0であるスパースなパラメータを学習できたとしています。 こちらは 公式実装 をA100 GPUx1で実験した結果です。 model filesize(圧縮前) filesize(圧縮後) train time rendering time PSNR↑ mic 63MB 551KB 85min 17s 33.30 drums 67MB 989KB 62min 17s 25.46 materials 78MB 1013KB 96min 13s 29.57 この実験で示されているように、学習済みモデルには非常に強力な圧縮をかけることができており、スパースなパラメータを学習できていることがうかがえます。 MobileNeRF: Exploiting the Polygon Rasterization Pipeline for Efficient Neural Field Rendering on Mobile Architectures 5 本手法ではボリュームレンダリングを行わず、テクスチャ付き三角メッシュを学習するため、一般的なレンダリングエンジンの最適化の恩恵を受けることができます。学習は既存のNeRFと同様に日単位の時間がかかってしまうものの、レンダリング時はモバイル環境でもリアルタイムに動作します。また、モデルがメッシュで表現されているため、モデルの変形や合成、削除などを一般的な3DCGにおける頂点操作で行うことも筆者は示唆しています。 以下の節で論文の画像を用いながら学習とレンダリングの概要を説明します。 Rendering 原論文 Figure 2 から引用 学習済みモデルは三角メッシュと特徴量空間におけるテクスチャマップ、そして軽量なMLPからなります。 まずGPUのレンダリングバッファを用いて特徴量空間におけるレンダリング画像を生成します(図c)。そして各ピクセルに対してMLPを適用することでRGB空間における画像を生成します(図d)。この一連の処理はWebGLで実装でき、プロジェクトページではモデルを表示するHTMLが公開されています。 Training 原論文 Figure 3 から引用 学習開始時に、まずグリッド状に組まれた初期メッシュを用意します。そしてそのメッシュの頂点位置と、特徴量と透明度を予測するMLP、特徴量から色を予測する軽量なMLPをNeRFの手法で最適化します。ここで特徴量と透明度については光線の位置のみを入力とし、軽量なMLPは特徴量と光線方向を入力としています。そのため光線方向に依存しない特徴量と透明度は、学習が済んだ後テクスチャマップにベイク(bake)できるため、PNG画像として保存されます(Rendering図のb)。 Limitation この手法には半透明な物体を表現するのが難しいという欠点があります。 デモページ でドラムのモデルを表示した結果が次の画像です。膜の部分がうまくレンダリングできていないというのが見てわかると思います。 表現力の拡張に関する論文 K-Planes: Explicit Radiance Fields in Space, Time, and Appearance 6 グリッドベースのNeRFモデルの軽量化手法であるTensoRFでは3次元空間を平面とベクトルに分解したのに対し、本手法では 平面、 平面、 平面の3つの平面の組に分解することを提案しています。これは高次元の空間を扱うNeRFモデルにも適用でき、例えば時間経過で物体が変形するシーンにおいても、空間 の3軸と時間 の1軸から選んだ6組の平面( )で学習できるのが特長です。学習時間も比較的短く、既存手法のDyNeRF (CVPR2022)が8GPUで1週間かけていたサンプルを、1GPUで4時間に短縮できています。 原論文 Figure 1 から引用 ABLE-NeRF: Attention-Based Rendering With Learnable Embeddings for Neural Radiance Field 7 NeRFで表現が不得意な物体として光沢のある表面、透明な面が挙げられます。NeRFのボリューメトリックレンダリングで輝度は各点の密度σと点のサンプリング間隔δに影響されますが、NeRFで各点のσは視線方向によらず固定されています。これによって、NeRFは異なる角度で透過特性と反射特性の両方を示す表面点の色を予測することが困難であり、その結果「濁った」外見になってしまうという課題があります。ABLE-NeRFではAttentionベースのネットワークを利用し、Learnable Embeddingsの導入によって間接照明効果を捉えることで解決しています。 Attention-based Volumetric Rendering ボリューメトリックレンダリングにおいて点の重みは自身の重みと、光線上に存在する前の点の重みに依存します。NeRFでは光線上の点の重みをσとδに基づいて割り当てていましたが、ABLE-NeRFではTransformerモデルのAttention計算によって個々の点の重みを決定します。 ここでは与えられた光線に対して、mip-NeRF 8 で説明されているIPE(Integrated Positional Encoding)でエンコードされた、光線に沿ったボリュームの円錐台を N 個サンプリングします。各円錐ボリュームは、Embeddingブロックを通過して、ボリューム埋め込み を生成します。( i はカメラからの光線に沿った位置)また、ViT 9 のclassトークンと同様に、同じ次元のRayトークン(R)をシーケンスに付加してTransformerで処理します。 Attentionの際はMaskを利用し、ボリューム埋め込みが注目する対象を自分自身とRayトークン、光線に沿って前方にあるボリュームだけに限定します。 Learnable Embeddings ABLE-NeRFでは、他の光源から放射される間接照明効果を捉えるため、光線に沿ったボリュームを超える外部光源に対する問い合わせプロセスとしてLearnable Embeddings(LE)を組み込んでいました。 LEはViTのclassトークンと同様に静的な照明情報を保存するために使用される学習可能なネットワーク・パラメータ(メモリ・トークン)です。学習プロセスにより、シーンの照明情報がメモリとして符号化されます。推論の際、ボリューム埋め込みはLEとのCross Attentionを介して潜在空間にマッピングされ、その後、視線方向トークン(Viewトークン)でデコードされます。視線方向トークンはカメラポーズを16バンドでフーリエ符号化し、線形層でLEと同じ次元にマッピングしたものとなっています。 ABLE-NeRFの構成は下図のようになっています。AB Transformerは光線に沿ったボリュームの直接照明を出力し、LE Transformerはボリュームの視線依存の照明を出力します。2つに分離することでオーバーフィッティングを防ぐことができるようです。2つの出力を組み合わせるため、sRGBに変換する固定マッピング関数を適用して最終的な出力を得ています。 原論文 Figure 2 から引用 結果 こちらは 公式実装 をA100 GPUx8で実験した結果(レンダリング時はA100 GPUx1)です。 model train time rendering time PSNR↑ mic 25h 59s 36.84 drums 25h 59s 26.87 materials 25h 59s 35.46 この実験で示されているように、PSNRでは上の圧縮モデルの精度を上回っており、特に光沢表現が多いmaterialsで優れた精度を示しました。しかし、学習に非常に時間がかかっています。これは光線に対してAB Transformer、LE TransformerでAttention計算を繰り返し行うので計算量が膨大であるためだと考えられます。 カメラ姿勢のずれの解決に焦点を当てた論文 Local-to-Global Registration for Bundle-Adjusting Neural Radiance Fields 10 カメラ位置と姿勢が正確でない場合、レンダリングの際に歪みが生じてしまいます。そのため、bundle adjustmentsにより、カメラの位置と姿勢を正確に推論し、レンダリングの改善をします。 L2G-NeRFでは、2つの手法を組み合わせたアプローチの提案をしています。まず、異なる画像間で対応するピクセルを合わせる処理をDNNの学習により最適化され、ピクセルごとに最適なアライメントを見つけることができます。次に、グローバルアライメントではピクセルごとの対応関係に基づいて、異なる視点からの画像を重ね合わせるために画像の剛体変換のパラメータを推定しています。これにより、異なる視点からの画像を正確に重ね合わせることができレンダリングの際に生じる歪みを改善できます。下の図を見るとL2G-NeRFが他の手法と比較し、カメラ姿勢の最適化が適切にされていることがわかります。 原論文 Figure 8 から引用 最後に 本ブログでは、私たちが興味を持ったCVPR2023の論文についてご紹介しました。NTT Comでは、今回ご紹介した分野に限らず、画像や映像、さらには音声言語も含めたさまざまなメディアAI技術の論文調査や研究開発に今後も積極的に取り組んでいきます。 Ben Mildenhall, Pratul P. Srinivasan, Matthew Tancik, Jonathan T. Barron, Ravi Ramamoorthi, Ren Ng. NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis. In ECCV2020 ↩ Han Yan, Celong Liu, Chao Ma, Xing Mei. PlenVDB: Memory Efficient VDB-Based Radiance Fields for Fast Training and Rendering. In CVPR2023 ↩ Daniel Rho, Byeonghyeon Lee, Seungtae Nam, Joo Chan Lee, Jong Hwan Ko, Eunbyung Park. Masked Wavelet Representation for Compact Neural Radiance Fields. In CVPR2023 ↩ Anpei Chen, Zexiang Xu, Andreas Geiger, Jingyi Yu, Hao Su. TensoRF: Tensorial Radiance Fields. In ECCV2022 ↩ Zhiqin Chen, Thomas Funkhouser, Peter Hedman, Andrea Tagliasacchi. MobileNeRF: Exploiting the Polygon Rasterization Pipeline for Efficient Neural Field Rendering on Mobile Architectures. In CVPR2023 ↩ Sara Fridovich-Keil, Giacomo Meanti, Frederik Warburg, Benjamin Recht, Angjoo Kanazawa. K-Planes: Explicit Radiance Fields in Space, Time, and Appearance. In CVPR2023 ↩ Zhe Jun Tang, Tat-Jen Cham, Haiyu Zhao. ABLE-NeRF: Attention-Based Rendering with Learnable Embeddings for Neural Radiance Field. In CVPR2023 ↩ Jonathan T. Barron, Ben Mildenhall, Matthew Tancik, Peter Hedman, Ricardo Martin-Brualla, Pratul P. Srinivasan. Mip-NeRF: A Multiscale Representation for Anti-Aliasing Neural Radiance Fields. In ICCV2021 ↩ Alexey Dosovitskiy, Lucas Beyer, Alexander Kolesnikov, Dirk Weissenborn, Xiaohua Zhai, Thomas Unterthiner, Mostafa Dehghani, Matthias Minderer, Georg Heigold, Sylvain Gelly, Jakob Uszkoreit, Neil Houlsby. An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale. In ICLR2021 ↩ Yue Chen, Xingyu Chen, Xuan Wang, Qi Zhang, Yu Guo, Ying Shan, Fei Wang. Local-to-Global Registration for Bundle-Adjusting Neural Radiance Fields. In CVPR2023 ↩
サマリ 概要 検証 1. Color 200 用 SR Policy の作成 SR Policy の確認 2. Color の付与と広告 経路の確認 動作確認 まとめ サマリ SR-MPLS + VPNv4 + explicit path による BGP Color を用いた Traffic Engineering (TE) を実現 IOS XR + Junos + SR OS の Multi-vendor 環境での動作検証に成功 この記事は Multi-AS Segment Routing 検証連載の第 14 回です。過去の記事一覧は こちら にあります。 概要 イノベーションセンターの田島です。本連載のような Segment Routing 関連の技術検証の指揮を執ったり、自動化による高度な運用を開発したりしています。 本記事では IOS XR + Junos + SR OS の Multi-vendor における Traffic Engineering (TE) についてご紹介します。 Segment Routing では ingress PE において転送するパスを決定し、適切な SID をパケットに付与することで TE を実現します。 本記事では TE の対象となる VPN 経路に対して BGP Color Extended Community (以下単に Color) を付与することで転送するパスを切り替える様子を示します。 第 4 回の記事 でもご紹介した通り、すでに IOS XR + Junos の Multi-vendor 環境での検証は実施済みで、 今回はそれらに Nokia SR OS を加えて検証します。 VPNv4 による L3VPN の相互接続は 第 12 回の記事 にて紹介済みですので、そちらも併せてご参照ください。 検証 本記事での検証は、L3VPN の prefix ごとに Color をつけて広告し、その Color によって転送する経路を変えるものです。 Color そのものや SR Policy に関する説明は 第 4 回の記事 を、 L3VPN に関する説明や設定は 第 12 回の記事 をご覧ください。 検証トポロジーは次のようなシンプルなものを用意します。 各 PE には VRF 100と VRF 200 が設定され、それぞれの経路に Color 100 と Color 200 を付与して広告します。 Color 100 の方は直通の最短経路で、Color 200 の方は迂回する経路での転送を実現します。 本記事では L3VPN はすでに開通しているとし、その後の設定を SR OS を中心に紹介します。 Color による TE は次の 2 ステップで設定します。 Color 200 用 SR Policy の作成 Color の付与と広告 なお本記事では下記のバージョンで検証しました。 rt01: IOS XR 7.4.1 rt02: Junos 21.3R1.9 rt03: SR OS 22.7.R1 1. Color 200 用 SR Policy の作成 Endpoint と Color を指定して SR Policy を作成します。 SR OS では SR Policy 用のラベルブロック (LB) を指定し、 BSID をそのブロックの中から手動で採番する必要があります。 rt01 向けの Segment List は、トポロジー図にあるように rt02 16002 を経由するものです。 router "Base" { mpls-labels { reserved-label-block "SR-Policy-LB" { start-label 52400 end-label 52499 } } segment-routing { sr-policies { admin-state enable reserved-label-block "SR-Policy-LB" static-policy "rt01-color200-policy" { admin-state enable color 200 endpoint 10.255.0.1 head-end local binding-sid 52410 segment-list 1 { admin-state enable segment 1 { mpls-label 16002 } segment 2 { mpls-label 16001 } } } } } } SR Policy の確認 設定した SR Policy が有効になっているかを表示して確認します。 Active になっていることが表示されます。 rt03 (SR OS) A:user@rt03# /show router segment-routing sr-policies static end-point 10.255.0.1 color 200 =============================================================================== SR-Policies Path =============================================================================== ------------------------------------------------------------------------------- Type : srMpls Active : Yes Owner : static Color : 200 Head : 0.0.0.0 Endpoint Addr : 10.255.0.1 RD : 0 Preference : 100 BSID : 52410 TunnelId : 917506 Age : 231 Origin ASN : 0 Origin : 0.0.0.0 NumReEval : 0 ReEvalReason : none NumActPathChange: 0 Last Change : 06/27/2023 05:09:21 Maintenance Policy: N/A Path Segment Lists: Segment-List : 1 Weight : 1 S-BFD State : Down S-BFD Transitio*: 0 Num Segments : 2 Last Change : 06/27/2023 01:41:02 Seg 1 Label : 16002 State : resolved-up Seg 2 Label : 16001 State : N/A =============================================================================== 2. Color の付与と広告 MP-BGP で VPN 経路を広告するときに Color を付与します。 VRF の export policy に設定することにより実現します。 なお、 SR OS では Color を示す color:00:<10進数> という書き方と、 BGP Extended Community 一般の記法で Color を指定する ext:030b:<16進数> という書き方ができます。 今回は見やすい前者で設定します。 policy-options { community "color-100" { member "color:00:100" { } } community "target-100" { member "target:65000:100" { } } policy-statement "vrf-export-100" { entry 10 { action { action-type accept community { add ["target-100" "color-100"] } } } } } service { vprn "100" { bgp-ipvpn { mpls { vrf-export { policy ["vrf-export-100"] } } } } } 経路の確認 rt03 で設定した Color は他のルーターで参照できます。 対向の rt01 では次のように Color 100 の経路と Color 200 の経路がそれぞれ認識されます。 rt01 (IOS XR) RP/0/RP0/CPU0:rt01#show bgp vpnv4 unicast rd 65000:100 192.168.103.0/24 detail Tue Jun 27 14:56:46.266 JST BGP routing table entry for 192.168.103.0/24, Route Distinguisher: 65000:100 Versions: Process bRIB/RIB SendTblVer Speaker 22 22 Flags: 0x00041001+0x00000000; Last Modified: Jun 27 14:56:00.872 for 00:00:45 Paths: (1 available, best #1) Not advertised to any peer Path #1: Received by speaker 0 Flags: 0x2000000085060005, import: 0x9f Not advertised to any peer Local 10.255.0.3 (metric 10) from 10.255.0.3 (10.255.0.3), if-handle 0x00000000 Received Label 524284 Origin IGP, localpref 100, valid, internal, best, group-best, import-candidate, imported Received Path ID 0, Local Path ID 1, version 22 Extended community: Color:100 RT:65000:100 Source AFI: VPNv4 Unicast, Source VRF: 100, Source Route Distinguisher: 65000:100 RP/0/RP0/CPU0:rt01#show bgp vpnv4 unicast rd 65000:200 192.168.203.0/24 detail Tue Jun 27 15:38:56.569 JST BGP routing table entry for 192.168.203.0/24, Route Distinguisher: 65000:200 Versions: Process bRIB/RIB SendTblVer Speaker 31 31 Flags: 0x00363001+0x00000000; Last Modified: Jun 27 15:38:49.872 for 00:00:06 Paths: (1 available, best #1) Not advertised to any peer Path #1: Received by speaker 0 Flags: 0x2000000085060005, import: 0x9f Not advertised to any peer Local 10.255.0.3 (metric 10) from 10.255.0.3 (10.255.0.3), if-handle 0x00000000 Received Label 524283 Origin IGP, localpref 100, valid, internal, best, group-best, import-candidate, imported Received Path ID 0, Local Path ID 1, version 27 Extended community: Color:200 RT:65000:200 Source AFI: VPNv4 Unicast, Source VRF: 200, Source Route Distinguisher: 65000:200 一方で逆向きの、対向ルーターが広告する Color を rt03 で確認します。 それぞれの経路に Color 100 と Color 200 が付与されています。 rt03 (SR OS) A:user@rt03# /show router bgp routes vpn-ipv4 rd 65000:100 detail (snip) Network : 192.168.101.0/24 Nexthop : 10.255.0.1 Route Dist. : 65000:100 VPN Label : 24004 Path Id : None From : 10.255.0.1 Res. Nexthop : n/a Local Pref. : 100 Interface Name : to_rt01 Aggregator AS : None Aggregator : None Atomic Aggr. : Not Atomic MED : 0 AIGP Metric : None IGP Cost : 20 Connector : None Community : color:00:100 target:65000:100 Cluster : No Cluster Members Originator Id : None Peer Router Id : 10.255.0.1 Fwd Class : None Priority : None Flags : Used Valid Best Incomplete Route Source : Internal AS-Path : No As-Path Route Tag : 0 Neighbor-AS : n/a Orig Validation: N/A Source Class : 0 Dest Class : 0 Add Paths Send : Default Last Modified : 00h13m13s VPRN Imported : 100 A:user@rt03# /show router bgp routes vpn-ipv4 rd 65000:200 detail (snip) Network : 192.168.201.0/24 Nexthop : 10.255.0.1 Route Dist. : 65000:200 VPN Label : 24005 Path Id : None From : 10.255.0.1 Res. Nexthop : n/a Local Pref. : 100 Interface Name : to_rt01 Aggregator AS : None Aggregator : None Atomic Aggr. : Not Atomic MED : 0 AIGP Metric : None IGP Cost : 20 Connector : None Community : color:00:200 target:65000:200 Cluster : No Cluster Members Originator Id : None Peer Router Id : 10.255.0.1 Fwd Class : None Priority : None Flags : Used Valid Best Incomplete Route Source : Internal AS-Path : No As-Path Route Tag : 0 Neighbor-AS : n/a Orig Validation: N/A Source Class : 0 Dest Class : 0 Add Paths Send : Default Last Modified : 00h13m46s VPRN Imported : 200 動作確認 Color 100 と Color 200 が付いたそれぞれの宛先に対して traceroute をすることで、直通か迂回路かを使い分けられていることが転送ホップ数から確認できます。 rt03 (SR OS) A:user@rt03# /traceroute 192.168.101.254 router-instance 100 probe-count 1 traceroute to 192.168.101.254, 30 hops max, 40 byte packets 1 10.0.2.1 (10.0.2.1) 3.99 ms A:user@rt03# /traceroute 192.168.201.254 router-instance 200 probe-count 1 traceroute to 192.168.201.254, 30 hops max, 40 byte packets 1 10.0.3.1 (10.0.3.1) 2.62 ms 2 10.0.1.1 (10.0.1.1) 8.97 ms 経路表でも直接 IS-IS で転送先が解決される Color 100 と、 SR Policy によって転送される Color 200 が確認できます。 この tunnel-id 917506 は「SR Policy の確認」節での show 結果に出ている Policy が使用されていることを示します。 [/] A:user@rt03# /show router service-name 100 route-table 192.168.101.0/24 =============================================================================== Route Table (Service: 100) =============================================================================== Dest Prefix[Flags] Type Proto Age Pref Next Hop[Interface Name] Metric ------------------------------------------------------------------------------- 192.168.101.0/24 Remote BGP VPN 00h21m21s 170 10.255.0.1 (tunneled:SR-ISIS:524298) 20 ------------------------------------------------------------------------------- No. of Routes: 1 Flags: n = Number of times nexthop is repeated B = BGP backup route available L = LFA nexthop available S = Sticky ECMP requested =============================================================================== [/] A:user@rt03# /show router service-name 200 route-table 192.168.201.0/24 =============================================================================== Route Table (Service: 200) =============================================================================== Dest Prefix[Flags] Type Proto Age Pref Next Hop[Interface Name] Metric ------------------------------------------------------------------------------- 192.168.201.0/24 Remote BGP VPN 00h15m31s 170 10.255.0.1 (tunneled:SR-Policy:917506) 0 ------------------------------------------------------------------------------- No. of Routes: 1 Flags: n = Number of times nexthop is repeated B = BGP backup route available L = LFA nexthop available S = Sticky ECMP requested =============================================================================== 逆向きの rt01 から rt03 宛ての経路についても同様に、直通経路と、途中に 1 ホップする経路が使い分けられています。 rt01 (IOS XR) RP/0/RP0/CPU0:rt01#traceroute 192.168.103.254 vrf 100 probe 1 Tue Jun 27 15:32:02.036 JST Type escape sequence to abort. Tracing the route to 192.168.103.254 1 192.168.103.254 2 msec RP/0/RP0/CPU0:rt01#traceroute 192.168.203.254 vrf 200 probe 1 Tue Jun 27 15:32:03.991 JST Type escape sequence to abort. Tracing the route to 192.168.203.254 1 10.0.1.2 [MPLS: Labels 16003/524283 Exp 0] 3 msec 2 192.168.203.254 4 msec まとめ 本記事では、SR OS を含めた Multi-vendor 環境における Color-Based TE の検証結果を紹介しました。 (2023/9/19 編集・追記) 次のエントリは予定を変更して Flex-Algo の相互運用性の記事を公開しました: [Multi-AS Segment Routing 検証連載 #15] IGP Flexible Algorithm Interoperability Updates
はじめに こんにちは、イノベーションセンターの黒木(GitHub: krk09 )と鍔木(GitHub: takuma0121 )です。 今回はOT(Operational Technology)ネットワークのセキュリティリスク可視化サービスである OsecT(オーセクト) のリニューアル提供を開始したので、サービス運用で得られた知見をもとに、どのような機能改善をしたのか紹介します。 OsecTとは OsecTとは工場などのOTシステムのセキュリティリスクを可視化・検知するサービスです。 多様化する工場システムのセキュリティ脅威に対して、パケット解析するセンサー機器を設置するだけで、OTシステムへの影響なく、ネットワークの可視化と脅威・脆弱性検知ができます。 早期にリスク感知できる状態を作り、工場停止による損失を未然に防ぐことができます。 詳しくは過去のブログ記事に書いているので、興味がある人はぜひ見てください。 ( OsecTリリース ・ OsecT前編 ・ OsecT後編 ) サービス運用から得た知見 2022年4月にサービスリリースしてから1年ほど経過して、実証実験では得られなかった知見を得ることができました。 その1つが OTネットワークがITネットワークと分離されていない環境が多くある です。この記事ではそのような環境をIT/OT非分離環境と呼びます。 このような環境でOsecTを利用すると、性能不足や過検知が課題になることがわかりました。 その他にもOsecTの利用ユーザーが増えていくにつれて、「可視化画面やアラートが見にくい」「自分で設定したい、またはしたくない」「OTプロトコルの可視化・検知を充実させてほしい」などの声もいただきました。 リニューアル提供での主な改善点 本章ではサービス運用から得られた知見をもとにした改善点を、可視化・検知機能を有するクラウド上にあるOsecTコアと、パケット解析機能を有するOsecTセンサーに分けてご紹介します。 OsecTコア OsecTを利用できる環境を広げるためにIT/OT非分離環境への対応や、脅威検知機能の刷新やサービス名の編集をはじめとしてより使いやすく、分かりやすくするための改善を行いました。 IT/OT非分離環境への対応 これまでITネットワークとOTネットワークが分離されていない環境にOsecTを置いた場合、IT機器によるインターネットへのアクセスが含まれることによって、管理していないインターネット上のIPアドレス等もOsecT上で端末として可視化/検知されてしまうことがありました。その結果、端末(IPアドレス)数が多くなりすぎて処理に影響がでたり過検知によってアラートが大量に出てしまったりするという問題がありました。 これらの問題に対して、グローバルIPアドレスやインターネットドメインを集約する機能を追加することで、IT/OT非分離環境においてもOsecTを利用できるようにしました。 集約されたグローバルIPアドレスは以下の internet_address(v4) などのように1つにまとめて可視化されます。 OTネットワークがITネットワークと分離された環境向けに、従来通り集約せずに可視化することもできます(システム設定からインターネットアドレス可視化の設定をONにする)。 また、一部のグローバルIPアドレスやインターネットドメインのみを集約対象から除外して可視化したい場合のための設定項目も用意しています。 IT/OT非分離環境において、誤ってグローバルIPアドレスを可視化する設定にすると、管理対象外のIPアドレス(グローバルIPアドレス)もLAN内の端末と同じように扱われ、OsecT上にサービス仕様を超えた端末(1,000端末)数が表示されることがあります。 そのような場合に、お客さまへ注意喚起して設定の見直しを促すためにメールで通知する機能も併せて追加しました。 この通知を受け取ったお客さまには、管理対象外のIPアドレスまで可視化対象になっていないかご確認、及び適切な設定をお願いできればと思います。 学習ベース脅威検知の追加 元々OsecTに備わっているホワイトリスト方式の異常検知は、自動化されたシステムのように、端末が機械的な通信を繰り返し、通信先があまり変わらないような厳格なOT環境においては有効です。しかしそうではない環境、例えば人手による端末操作などにより通信先が頻繁に変動する環境では過検知を引き起こしてしまいます。 通信先などが変動するような環境においても適用できる学習ベースの検知機能として、今回新しくIP統計検知を追加しました。 IP統計検知は、IPアドレス単位で宛先IPアドレス数や送受信パケット数などといったIP通信の傾向を表す数値を元に異常を検知する機能です。 具体的には、一定時間毎にIPアドレス単位で宛先IPアドレス数や送信/受信パケット数などの分析に使う値を算出し、信頼区間分析/主成分分析をそれぞれ行います。 信頼区間分析は、学習時に各値で99.9%信頼区間を求めて算出した閾値を元に検知します。 主成分分析では、学習時に各値をまとめた主成分分析によって得られた主成分毎の最小値/最大値を閾値として検知します。 信頼区間分析では各値を個別に分析して検知し、主成分分析では各値を相関的に分析して検知するイメージです。 端末情報表示の整理 「端末」の「IP別接続サービス」タブの名称を「詳細」に変更し、それに伴って表示する情報を拡充しました。 元々MACアドレスやベンダー名など接続サービス以外の情報も表示していたため、実態に合った名称となり、「一覧」タブに表示されているホスト名やOSなどの情報も表示されるようになりました。 また、検知アラート画面において、IPアドレスがリンクになっていたりホバーで端末の情報が表示されたりと挙動が統一されていなかったものを、ホバー表示に統一した上で表示内容を統一・整理しました。 脅威検知アラートのわかりやすさ向上 各検知アラートがどんなアラートなのか(何故発生したのか)分かりやすくするために、検知アラートの一覧ページに各アラートの概要を説明する項目を追加しました。 具体例として新規端末アラートの場合「新規端末192.168.0.xが出現」、脆弱端末アラートの場合「サポート切れOS Windows 7の端末192.168.0.xが出現」といった説明が表示されます。 ポート番号に対する名称変更機能の追加 これまではポート番号やパケットの内容から自動で判定できたプロトコルのみサービス名を表示していましたが、特定のポート番号に対してユーザーがサービス名を編集できる機能を今回追加しました。 TCP/IP上で独自プロトコルを使っている場合などに、この機能を使ってサービス名を設定することによって、自動で判定できないプロトコルでも端末一覧などの可視化のページでユーザーの設定したサービス名が表示されるようになります。 脅威検知の使い勝手向上 より簡単な操作で脅威検知機能を利用できるよう、学習期間・検知期間を細かく設定しなくても学習状況から自動的に検知へ移行する機能を追加しました。 また、どのようなOT環境でも共通的に使っていただきたいおすすめの検知種別については、事前設定不要で利用できるようなりました。 従来の機能はアドバンスモードとして残しているため、学習と検知の期間をそれぞれ設定したい場合はアドバンスモードをONにすることで従来通りの設定が可能です。 OsecTセンサー センサーでは、IT/OT非分離環境でのトラフィック量増加に対応するための性能向上や、ニーズの多いOTプロトコル(CC-Linkファミリー)への対応を行いました。 性能向上 これまでトラフィック量が比較的少ないOTネットワークを想定していたため、tcpdumpでPcapを生成後、 Zeek やSuricataなどのパケット解析ツールでログ化する処理をしていました。 しかしながら、この方式では数十Mbpsが性能の限界(サービス仕様上は10Mbps)だったため、インターフェースから直接ログ化する方式に変更しました。 従来の方式から新しい方式に変更することで、Pcapの生成→ログ化といった2段階の処理が解消されたことや、Pcapのパケット解析だとシングルコアでしか動作しなかったツールがマルチコアで動作できるようになり、数百Mbpsまでのトラフィックを処理できるようになりました(サービス仕様上は100Mbps)。 OTプロトコル(CC-Linkファミリー)への対応 今回のリリースでは、日本国内で開発され、広く普及しているOTプロトコルである CC-Linkファミリー のプロトコルに対応しました。 市販のOTセキュリティ製品のプロトコル対応状況は、製品毎プロトコル毎に異なり、プロトコル名を表示するだけのものからペイロードにある変数を使って異常を検知するものまでありますが、OsecTではCC-Linkのコマンドレベルでの可視化・検知まで実現できるようにしました。 OTプロトコルの対応にはZeekおよびSpicyを利用しており、具体的な実装方法は 【日本初紹介】Zeek・Spicyの使い方まとめ を参照していただければと思います。 OTプロトコルは業界・業種・機器メーカー毎ごとに存在するため、すべてのOTプロトコルに対応することは難しいです。一方で、今回のリニューアルを通じてOTプロトコルに対応するためのフレームワークや具体的な実装方法が確立できつつあります。 今後もユーザーのニーズを汲み取って、リリースごとに優先度の高いOTプロトコルに対応していきたいと考えています。 おわりに 今回はサービス運用を通じて得られた知見をもとに、どのような機能改善をしたのかご紹介しました。 実証実験だけでは明らかにならない課題もあり、サービスリリース後も素早く課題を見つけて改善を続けていくことがより良いサービスの実現につながると感じました。 OsecTは低価格でOTネットワークの可視化や脅威検知ができるので、セキュリティ対策に手が出ていない・不十分と感じている企業さまにはぜひご利用いただきたいです。 ご興味がある企業さまは、 WideAngle (OsecT) ご紹介ページ からお問い合わせいただければ幸いです。
わかること IoTプラットフォームにおける独自のイベント処理ロジックの構築について Things Cloud のノーコードツール「Analytics Builder」でできること ※本記事は、Things Cloud バージョン10.14 (8月以降リリース予定)の利用を想定しています。 はじめに こんにちは、Things Cloud のカスタマーサクセスチーム 井上です。 私たちは、5G&IoTサービス部で IoTプラットフォーム「Things Cloud」のサービス開発やお客さまへの技術支援を担当しています。 早速ですが、皆さんは「IoT化」という言葉を聞いて何を思い浮かべるでしょうか。データの収集から可視化、分析、異常検知、通知、自動制御などIoTで実現できることは幅広く、適用可能なビジネス領域や業界も多様です。特に最近では、専門的なスキルを必要とせず手軽にIoT化を実現できるIoTサービスが多く登場しています。 本記事では、IoTプラットフォームThings Cloudに搭載されているデータ処理機能の1つである「Analytics Builder」を利用して、ノーコードで独自の分析処理を構築する方法ご紹介します。 Analytics Builderとは Things Cloudの紹介 Analytics Builderを紹介する前に、 Things Cloud のサービスについて、概要をご紹介します。 Things Cloudは、NTT CommunicationsのSmart Data Platform(略称SDPF)の中で、データ収集機能を提供するプラットフォームの1つです。 製品やセンサーなどのIoTデバイスからデータを収集し蓄積できるクラウドサービスで、簡単な操作でデータの可視化やアラート通知を実現でき、デバイス接続/ユーザー管理/デバイス管理などIoT導入に必要な機能一式が揃ったIoTプラットフォームです。 Things Cloudには、データをリアルタイムで処理し、データに基づいて通知や制御などのアクションを実行するためのデータ処理機能がいくつか搭載されています。 Things Cloudのデータ処理では、リアルタイムに流れているイベント(データ)をトリガーとして処理を行い、処理結果としてデータベースへの書き込みやメール送信、通知、制御を行います。 データ処理機能の1つとして、今回紹介するAnalytics Builder 1 があります。 Analytics Builderを活用することで、テンプレートベースの標準機能だけでは実現できない独自のデータ処理機能をノーコードで簡単に構築できます。 Analytics Builderの概要 Analytics Builderは、ブラウザ上でグラフィカルに、データ処理モデルを構築できる機能です。 下図のように、事前定義された処理ブロックを線でつなぐことで処理モデルを構築できます。 ブロックは処理内容、ブロック間をつなぐ矢印はデータの入出力を表しています。 Analytics Builderの技術的観点や利用方法などの詳細を知りたい方は、 開発者ドキュメント 〜 Analytics Builder をはじめる〜 をご参照下さい。 ノーコードとは アプリケーションやシステムの開発において、昨今新たな手法として広まっているのが 「ノーコード」 や「ローコード」と呼ばれる開発手法です。 「ノーコード」は、一般的なプログラミングにおいて必要となるソースコードの記述が不要なため、特別なスキルが不要で手軽にアプリケーションを構築できます。 Things Cloudでは、IoTデバイスからのデータを処理するための処理ロジックをノーコードで構築できる「Analytics Builder」をプラットフォーム内に備えています。 参考サイト: DXを加速する「ノーコード ローコード」による開発とは? Analytics Builderの特徴 Analytics Builderには、以下のような特徴があります。 ユースケースに応じた独自処理の実現が可能 Analytics Builderは、テンプレートベースの標準機能では実現できない独自の処理を、ノーコードで簡単に実現できます。 グラフィカルなUIでわかりやすい Analytics Builderは、Things Cloud上のアプリケーションの一部であり、直感的に操作できるグラフィカルなUIを備えています。また、実装時は必要なブロックを選択しUI上で線を使ってつなげていくだけなので、すぐに分析モデルを構築できます。 すぐに始められる Analytics Builderでは、カテゴリ分けされたブロック群から必要なブロック(機能)を選択し、あらかじめ定義されたパラメータ設定するだけで必要な処理を実現できます。一般的なプログラミングのようにさまざまな文法や関数を学習する必要がなく、短時間で手軽に分析モデルを構築できます。 適用ユースケース/処理の例 ここまで、Analytics Builderの強みを説明してきました。 これまでに述べたように、Analytics Builderでは用意された複数の処理ブロックを簡単に組み合わせることができ、それによって個別の要件に応じたさまざまな処理モデルの構築が可能です。 ここでは、代表的な適用例を一部ご紹介します。 温度センサ等を利用したユースケースの場合 温度が3分継続して40℃以上になった時、アラームを生成 デバイスごとの計測値の10分平均を算出し、計測値として登録 特定のデバイスグループ全体の計測値の10分平均を算出 電力使用量を計測するユースケースの場合 日次の総電力使用量の集計 拠点ごとに総電力使用量を集計 その他 デバイスからの通信が途絶した後、復旧した際に通知メールを送信 イベントやアラームをトリガーとしたデバイスデータの更新 (例:機器の動作開始/終了イベントから、デバイス情報の"動作ステータス値"を更新) より簡単な標準機能 「スマートルール」 Things Cloudのデータ処理機能には、より簡単に設定/利用が可能な「スマートルール」が標準搭載されています。 スマートルールは、あらかじめ定義されているテンプレートからUI上でデータにもとづくアクションを簡単に設定できる機能です。 スマートルールのテンプレートでは「しきい値超過時にアラームを発生させる」「アラーム発生時に通知メールを送る」など頻繁に利用される機能が定義されており、操作も非常にわかりやすいため、Things Cloudのデータ処理ではまずスマートルールの利用を考えます。 スマートルールで定義されていないような独自の処理を行いたい場合には、Analytics Builderの活用が有効です。 ※スマートルールの詳細については、 開発者ドキュメント をご参照ください。 Analytics Builder 実装例 ここでは、温度値の集計を題材として、実際にAnalytics Builderを利用して1つの処理モデルを構築した例をご紹介します。 処理内容 入力する計測値: 温度センサで計測した温度値 (20秒おきに送信) 出力する結果: 5分間の平均値がしきい値を上回った場合に、アラームを発生させる 処理内容 : デバイスの温度値を取得 5分間の平均値を算出 平均値がしきい値を超過しているか判定 アラーム通知用の文章を作成 アラームを送信 実装/動作例 Analytics Builderで作成したモデルの例 ブロックの設定例(平均値ブロック) しきい値超過時のアラーム発生画面 他の実装例や具体的な実装方法について知りたい方は、 開発者ドキュメントの例題 をご覧下さい。 応用例:Slackに通知内容を送信 Analytics Builder には、入力/出力/集約など便利で豊富なブロックが標準で搭載されていますが、入出力/パラメータ/処理内容を自身で設定/構築するカスタムブロック 2 というものを作成することも可能です。 以下は、Slackに通知するカスタムブロックを開発し、先ほど紹介したモデルに対して追加した例になります。 ※Slackの Incoming Webhook機能 を利用しています。 Slack通知のカスタムブロック(開発例) Slackに通知される様子 おわりに いかがでしたか? 今回は、Things Cloudのノーコードツール「Analytics Builder」についてご紹介しました。 Things Cloudでは、スマートルールやAnalytics Builderを活用することで、さまざまなユースケースに対応したデータ処理をコーディング不要で簡単に実現可能です。また、より高度で複雑な処理を実現したい場合やプログラミングに慣れている方向けには、コーディングによってデータ処理を構築するApama EPL機能 3 も備えています。 Things Cloud カスタマーサクセスチームでは、ますます広がっていくIoTユースケースにおいて、より便利な使い方を開拓すべく機能検証や内製開発をしています。今後もIoTに関連する開発ネタを発信していきたいと思います! Things Cloud 関連ブログ: IoTデバイス接続の難しさを解決するNTT Comのお手軽IoT Observable を活用した IoT データの可視化探索ガイド 問い合わせ先 お手数ですが@を半角文字に置き換えてください。 Things Cloud サービスについて:iot-info@ntt.com Things Cloud カスタマーサクセスチーム:iot-app@ntt.com Analytics Builderの利用には「カスタムストリーミング処理機能」のオプション申し込みが必要です。 ↩ カスタムブロックの作成には、開発環境の準備および専用の言語によるコーディングが必要です。 ↩ Apama EPL機能の利用には「カスタムストリーミング処理機能」のオプション申し込みが必要です。Apama EPL機能について詳しく知りたい方は、 開発者ドキュメント 〜Apama EPLをはじめる〜 をご覧下さい。 ↩
みなさんこんにちは、イノベーションセンターの @Mahito です。普段は社内のエンジニアが働きやすくなることを目標に、コーポレートエンジニアとしての活動やエンジニア向けイベントの企画・運営をしています。 今回は、本 NTT Communications Engineers' Blog を2年間運営してきたノウハウについて共有できればと思います。先日 はてなブログ DevBlog Meetup #1 に登壇させていただく機会があり、ブログ運営に関していくつかお話しさせていただいたのですが、イベント当日に言えなかったことや言ったことの補足などをできればと思います。 目次 目次 開発者ブログのこれまでと目的 運用のノウハウ・意識していること 執筆者の確保・継続・インセンティブ設計 1. 定期的にブログの取り組みを社内に紹介することで取り組みに興味を持ってもらう 2. ニュースリリースを見て、技術的に面白そうな取り組みをしているところに声をかける 3. 執筆のハードルを下げる 運用 レビュー 記事公開 KPI や指標 その他 長く続けるために個人的に意識していること まとめ 開発者ブログのこれまでと目的 開発者ブログの運用ノウハウをお伝えする前に、少しだけ本ブログについてのお話をさせていただきます。 こちら「 開発者ブログをリニューアルしました! 」でも書いたのですが、NTT Com では元々2015年に6月頃から開発者ブログを開始しました。当時はCMSを自分たちで運用していくスタイルでしたが、CMSの使い勝手やレビューのしづらさなどもあり、リニューアルという形ではてなブログへと引っ越しをする形になりました。 エンジニアブログをリニューアルする際には、開発者ブログに以下のような目的を定めました。 NTT Comのエンジニアの取り組みを広く知ってもらう 社外のユーザーやエンジニアとコミュニケーションをとれるきっかけの場とする NTT Comのエンジニアが自己発信できる場を提供する NTT Comにはさまざまなエンジニアがそれぞれの仕事をしていますが、その多くは外部には見えません。例えば、NTT Comのニュースリリースを見ても、技術の詳細などは書かれていません。そのため、リクルーター活動などをしていると、NTT Comのエンジニアが何をしているのか社外に知られていないと感じることが多くありました。 一方で、エンジニアの中には自分たちの取り組みを知ってもらうことで、社外のエンジニアやユーザーと繋がり、そこから採用や新規ユーザーの獲得に繋げたいと考えている人もいます。しかし、社外のエンジニアやユーザーとの交流のきっかけや、自分たちで発信する場があまりないという問題がありました。そこで、開発者ブログを通じて、これらの問題を解決できるようにしていこうとなりました。 運用のノウハウ・意識していること 執筆者の確保・継続・インセンティブ設計 NTT Comでは、ブログは書きたい人が書くというスタイルを取っています。これは、持ち回りで定期的に記事を出すということよりも、書きたい人のやる気を優先することでいい記事が生まれ、いい結果につながるのではというような話だったと思います。(運営の中で全然議論にならなかったのでうろ覚えです) おかげで1ヶ月近く新しい記事がでないこともありますが、タイミング的にまだ公開できない未公開記事や、「書きたい!」と言って準備してくれている人が常にいる状態のため、運営スタッフは「今週もでなかったね〜」ぐいらいのノリで焦りは特にありません。 新規の執筆者をどう確保するのかという点では、以下の3点を意識しています。 定期的にブログの取り組みを社内に紹介することで取り組みに興味を持ってもらう ニュースリリース を見て、技術的に面白そうな取り組みをしているところに声をかける 執筆のハードルを下げる 1. 定期的にブログの取り組みを社内に紹介することで取り組みに興味を持ってもらう 社内でもまだまだ開発者ブログに取り組んでいることを知らない人もいるため、社内での開発者ブログの認知を上げることや、そのタイミングではブログのネタがなく興味を持たなかった人に再度知ってもらうことで書くきっかけにつながればと思っています。社内に紹介する方法としては、社内ポータルの周知に「今月どんな記事が出たかのまとめ」を掲載したり、新しい記事がでたら Slack や Microsoft Viva Engage(旧称 Yammer) に自動投稿したり、社内のイベントでブログの活動を紹介したりとさまざまです。 2. ニュースリリースを見て、技術的に面白そうな取り組みをしているところに声をかける 我々運営スタッフも社内のすべてを知っているわけではないので、運営の定例などで NTT Com のニュースリリースをチェックし、技術的に面白そうな取り組みをしているところに連絡をしています。こちらの「 駆け出し開発チームでも45万回利用されるシステムを2カ月で作れた話 」 はニュースリリースを見て、運営から声をかけさせてもらった記事です。個人的にはプロジェクトのはじまるきっかけなど、ニュースリリースに書かれていない部分も知ることができとてもいい記事でした。 3. 執筆のハードルを下げる 執筆者のハードルを下げる取り組みは、「執筆したいけどできない」とか「こんなこと書いていいのかな」という問題を解決することです。 前者は、稼働の問題や周囲の理解、技術的な問題など、さまざまな理由がありますが、副社長や幹部に開発者ブログの活動にお墨付きをいただいています。 何か問題があれば「偉い人の承認を得ている取り組みですよ」ということができます(使ったことはないけど)。 また、後者に関しては、運営スタッフが色々サポートできます。 例えば、NTT Comの開発者ブログでは、記事はMarkdownで記載され、GitHubを利用して記事の管理やレビューをしています。 執筆者の中には、これらに慣れていない方もいますが、運営スタッフがサポートして記事が書けるようにお手伝いしています。 「こんなこと書いていいのかな」という疑問に対しては、運営スタッフが相談に乗ることもあります。エンジニアは、自分たちのやっていることがたいしたことではないと思いがちですが、「自分たちならではの部分や工夫」があることも多いため、そういった部分を記事に取り入れることを提案します。 また、開発者ブログを継続することで記事の専門性が深くなったり、難しい課題を解決した話がでることもありますが、それによって新しい執筆者が「自分はそんな記事をかけない」とハードルを感じることもあります。そのため、時々「 知ってるようで知らない YAML のご紹介 」のような比較的軽い記事を投稿して、執筆者のハードルが上がりすぎないように意識しています。 運用 NTT Com 開発者ブログの運用は有志の運営スタッフで行われています。 運営スタッフに参加している理由は面白そう、社内の取り組みが知りたい、社内の人と知り合いたいなど人それぞれですが、業務時間内の仕事の合間を縫って活動をしています。 運営スタッフのやることは主に以下のとおりです。 記事のレビュー 執筆者のサポート 記事のネタ・執筆者探し 運営上の課題解決 運営スタッフは毎週定例を設けており、上記の進捗状況などについて共有したり議論をしています。 レビュー 記事のレビューは GitHub 上で行っており、執筆者の Pull Request(以下、PR) が来るとランダムで運営スタッフからレビュー担当が1名つきます。 また、レビューの前に GitHub Actions が動作し、はてなブログへ下書き状態での記事投稿や、 textlint を用いて表現や文章のチェックがなされます。 レビューでは執筆者が伝えたいことや文章の個性をそのまま読者へ届けられるようにしつつも、より読みやすい形で出すために以下のような点を確認しています。 読者が読んでいて疑問に思うところがないか 読者が読みやすい文章表現になっているか 数字の正確性確認 ブログに使われている画像に問題がないか 記事によってはレビュー担当のカバーする技術分野から離れた専門領域の内容をレビューすることもあります。 そうした場合はその領域をカバーできるスタッフに代わってもらいますが、代わってもらう人がいない場合は自分で調べながらレビューすることもあります。 私自身専門外の記事レビューを何度か経験しましたが、レビューは難しくも普段と違う技術領域を知るきっかけになり楽しんでいました。 textlint では社名(正式略称は「NTT Com」)や商品名、日本語の表現などがチェックされ、問題があれば PR にコメントとして残されます。 これは、読者の方が読みやすい文章になるだけでなく、レビュー担当の負担を減らすことや、レビューの見逃しをなくすことに繋がっています。 記事公開 記事の公開はレビューが終わり次第可能となり、PR の Merge ボタンを押すと GitHub Actions が下書き状態だった記事を公開状態に変更します。 執筆者の希望公開日があればその日にデプロイをしますが、希望がなければ、運営スタッフが Page View(以下、PV) が稼げそうなタイミングでリリースをします。 この2年間でどういうタイミングに公開すると PV が伸びやすいかなど仮説を持って検証してきており、そうしたノウハウを活用しています。 記事公開にはレビューや textlint などのチェックを行っていますが、公開後に見つかるタイポや表現の問題があります。 その場合、修正の PR を作成し、レビュー、マージの手順を踏んで記事を更新しています。 ボタン1つで公開や修正をできる Continuous Delivery のしくみにすることで、記事の公開・修正のハードルを下げることに繋がっています。 KPI や指標 「ブログの KPI をどうしているか」という質問がイベントでもありましたが、NTT Com の開発者ブログにも KPI はあります。 PV 数や記事の投稿数など、定量的な指標を KPI にしていますが、あくまで、「NTT Com の開発者ブログがこういう状態になっていたら嬉しい」ぐらいの目標設定として数字は置かれています。 KPI の管理は毎週のスタッフ定例で進捗確認をしながら KPI の達成に向けた施策の検討や実施をしており、 毎年12月の アドベントカレンダー 企画や、社内の執筆者向けた情報公開、イベントなども行っています。 先日もブログリニューアル2周年を記念した運営スタッフと執筆者の Meetup が行われ、この2年間の活動の振り返りや、今後についての話し合いなどが行われました。 その他 長く続けるために個人的に意識していること ブログ運営を2年間続けている中で私個人として意識していることがあります。 それは、 「ゆるく」 運営をしていくことです。 「8年続く社内勉強会を続けていくために行っていること」 というタイトルの記事でも書かせてもらったのですが、運営を頑張ることはとても大事な一方で、頑張りすぎてしまうと燃え尽きてしまいあとが続かないこともあります。 先述したとおり、運営スタッフはそれぞれが開発者ブログに対して何らかの目的や思いを持って活動をしています。 一方で、運営スタッフは本業の合間を縫ってエンジニアブログの運営をしているため、運営を頑張るほどに運営スタッフの負担が上がり燃え尽きる可能性もあります。 社内の取り組みをより多くの人に知ってもらうための開発者ブログの活動を、運営スタッフが思いを持って運営し続けていけるしくみとして、「ゆるさ」が大事だと考えています。 その運営をゆるくするためにしくみのひとつとして、定例の簡素化があります。 運営スタッフの定例は時間と議題だけを決め、そのとき集まれるメンバが Slack ハドルミーティングに集まります。 議事録などは毎回残しているので参加できなかった運営スタッフは後から読むことができます。 また、Slack ハドルミーティングは普段から開発者ブログに関して運営や執筆者たちがやり取りをするチャンネルを用いているため、 定例には運営スタッフ以外にも開発者ブログの運営や執筆に興味がある人も参加できるオープンな形で開催しています。 この他にも GitHub の PR によるレビューや、GitHub Actions を使った textlint、記事の下書き投稿・公開の自動化などのしくみも、 我々運営スタッフの負担を減らし、ゆるくやっていくためのしくみの1つとして用意したものです。 今後も開発者ブログの運営が長続きするように、我々運営が頑張りすぎず、ゆるく運営を続けていければと思っています。 まとめ 今回は2年間の開発者ブログ運営のノウハウや意識していることなどを紹介しました。 企業の文化やルールによっては使えるノウハウ、使えないノウハウなどあるかもしれませんが、この記事がどこかの開発者ブログの運営のお役に立てれば幸いです。
TOC サマリ 概要 検証 EVI と CE 向けポート設定 EVI と CE 向けポートの状態確認 BGP の設定 Local Preference(LP) の設定 IOS XR ASBR 間 SR OS ASBR 間 経路の確認 EVI 3600 EVI 3700 疎通試験 制約事項 まとめ サマリ Multi-AS で構成されるネットワークにおいて、SR-MPLS + EVPN による L2VPN を実現 IOS XR + Junos + SR OS の Multi-vendor 環境での動作検証に、特定の組み合わせ以外は成功 この記事は Multi-AS SR 検証連載の第 13 回です。過去の記事は こちら 概要 イノベーションセンターの竹中です。普段の業務では Multi-AS Segment Routing に関する技術検証や、ネットワーク運用効率化のためのコントローラー開発などを行なっています。 第3回 の記事で IOS XR + Junos の 2 つのベンダー機器で構成される Single-AS/Multi-AS L2VPN についてご紹介しましたが、今回新たに Nokia SR OS(Service Router Operating System)を PE・P・ASBR に加えた 3 つのベンダー機器での Multi-AS L2VPN 動作検証をご紹介します。 EVPN による L2VPN に関する説明は、 第3回 記事の概要にて紹介しているので、そちらをご参照ください。 検証 EVPN L2VPN の検証例を実際の設定例を添えつつ紹介します。 IOS XR、Junos の設定例は 第3回 の記事で紹介したため本記事では割愛し、SR OS の設定例を中心に紹介します。 本記事の検証は Inter-AS Option B の L2VPN について、SR OS と各ベンダー間の互換性確認を目的とします。 つまり下記を検証します。 SR OS を PE として L2VPN が構築できるかどうかを確認する SR OS と IOS XR/Junos の間で L2VPN 経路を交換できるかどうかを確認する Inter-AS Option B 構成を構築する際に SR OS を ASBR として利用できるかを確認する 下記のトポロジーを利用し L2VPN の検証例を紹介します。 なお、検証は運用中の実機環境を利用しているため、一部トポロジーが雑然としていることはご了承ください。 また、各 EVI で扱う組み合わせを表に示します。 EVI AS65001 PE → → ASBR-ASBR → → AS65002 PE 3600 Juniper Cisco Nokia 3700 Cisco Nokia Juniper 使用する機器は以下の通りです。 IOS XR rt01: Cisco ASR9901 (IOS XR 7.6.1) rt03: Cisco 8201 (IOS XR 7.5.1) rt06、rt08: Cisco ASR9902 (IOS XR 7.5.1) rt10: Cisco NCS55A2 (IOS XR 7.5.1) Junos rt02、rt12: Juniper MX204 (JUNOS 22.1R1.10) rt04: Juniper PTX10001-36MR (JUNOS 21.4R1.15-EVO) SR OS rt05、rt07、rt09、rt11、rt13: Nokia 7750 SR-1 (SR OS 23.3.R1) SR OS の IGP や SR の設定は 第12回 の記事で紹介したため割愛します。下記の設定および確認を順に行います。 EVI と CE 向けポート設定と状態確認 BGP の設定 LP の設定 経路の確認 疎通試験 EVI と CE 向けポート設定 まず、PE で EVI と CE 向けポートを設定します。各 EVI は MP-BGP EVPN にて 64999:<EVI 番号> の RT を用いて経路交換します。 PE (例: rt13) [gl:/configure policy-options] A:user@rt13# info community "comm-3600" { member "target:64999:3600" { } } policy-statement "vsi-export-3600" { entry 10 { action { action-type accept community { add ["comm-3600"] } } } } policy-statement "vsi-import-3600" { entry 10 { from { community { name "comm-3600" } } action { action-type accept } } } [gl:/configure service] A:user@rt13# info customer "3600" { } system { bgp { evpn { ethernet-segment "esi-26-1/2/c16/1" { admin-state enable esi 0x02000000010000002616 multi-homing-mode single-active association { port 1/2/c16/1 { } } } } } } vpls "3600" { admin-state enable customer "3600" bgp 1 { route-distinguisher "10.255.2.26:3600" vsi-import ["vsi-import-3600"] vsi-export ["vsi-export-3600"] } bgp-evpn { evi 3600 mpls 1 { admin-state enable auto-bind-tunnel { resolution any } } } sap 1/2/c16/1:3600 { admin-state enable } } EVI と CE 向けポートの状態確認 EVI と CE 向けポートが紐づき、また Admin/Operation 共に up していることが確認できます。 [/] A:user@rt13# show service id 3600 sap =============================================================================== SAP(Summary), Service 3600 =============================================================================== PortId SvcId Ing. Ing. Egr. Egr. Adm Opr QoS Fltr QoS Fltr ------------------------------------------------------------------------------- 1/2/c16/1:3600 3600 1 none 1 none Up Up ------------------------------------------------------------------------------- Number of SAPs : 1 ------------------------------------------------------------------------------- =============================================================================== BGP の設定 L2VPN 経路を広告するため PE と ASBR で MP-BGP EVPN を設定します。 PE (例: rt13) [gl:/configure router "Base" bgp] A:user@rt13# info rapid-withdrawal true family { evpn true } rapid-update { evpn true } group "iBGP" { peer-as 65002 local-address 10.255.2.2 family { evpn true } } neighbor "10.255.2.6" { admin-state enable group "iBGP" } neighbor "10.255.2.7" { admin-state enable group "iBGP" } ASBR (例: rt07) [gl:/configure router "Base" bgp] A:user@rt07# info inter-as-vpn true rapid-withdrawal true family { evpn true } ebgp-default-reject-policy { import false export false } rapid-update { evpn true } next-hop-resolution { labeled-routes { transport-tunnel { family vpn { resolution any } } } } group "65002" { vpn-apply-import true peer-as 65002 bfd-liveness true family { evpn true } } group "iBGP" { peer-as 65001 local-address 10.255.1.7 family { evpn true } } neighbor "10.100.3.2" { group "65002" } neighbor "10.255.1.1" { group "iBGP" } neighbor "10.255.1.2" { group "iBGP" } Local Preference(LP) の設定 EVI ごとに通過する ASBR を制御するため、ASBR で LP を設定します。 本検証では RT ごとに通過させたい ASBR への経路には LP 300 を、通過させたくない ASBR への経路には LP 50 を明示的に設定します。 IOS XR ASBR 間 rt06 route-policy lp-for-evpn if extcommunity rt matches-any (64999:3600) then set local-preference 300 elseif extcommunity rt matches-any (64999:3700) then set local-preference 50 else pass endif end-policy router bgp 65001 neighbor 10.100.1.2 address-family l2vpn evpn route-policy lp-for-evpn in ! ! rt08 route-policy lp-for-evpn if extcommunity rt matches-any (64999:3600) then set local-preference 300 elseif extcommunity rt matches-any (64999:3700) then set local-preference 50 else pass endif end-policy router bgp 65002 neighbor 10.100.1.1 address-family l2vpn evpn route-policy lp-for-evpn in ! ! SR OS ASBR 間 rt07 [gl:/configure policy-options] A:user@rt07# info community "lp-high-grp" { member "target:64999:3700" { } } community "lp-low-grp" { member "target:64999:3600" { } } policy-statement "lp-for-evpn" { entry 1 { from { community { name "lp-high-grp" } } action { action-type accept local-preference 300 } } entry 2 { from { community { name "lp-low-grp" } } action { action-type accept local-preference 50 } } } [gl:/configure router "Base" bgp] A:user@rt07# info vpn-apply-export true vpn-apply-import true group "65002" { import { policy ["lp-for-evpn"] } } rt09 [gl:/configure policy-options] A:user@rt09# info community "lp-high-grp" { member "target:64999:3700" { } } community "lp-low-grp" { member "target:64999:3600" { } } policy-statement "lp-for-evpn" { entry 1 { from { community { name "lp-high-grp" } } action { action-type accept local-preference 300 } } entry 2 { from { community { name "lp-low-grp" } } action { action-type accept local-preference 50 } } } [gl:/configure router "Base" bgp] A:user@rt09# info vpn-apply-export true vpn-apply-import true group "65001" { import { policy ["lp-for-evpn"] } } 経路の確認 各 PE で構成に従った経路を学習しているかを確認します。 type1 経路、type3 経路が交換されていること、また EVI ごとにそれぞれ nexthop が適切な ASBR となっていることが確認できます。 EVI 3600 AS65001 側 PE (rt02) user@rt02> show route table evpn-3600.evpn.0 evpn-3600.evpn.0: 9 destinations, 17 routes (9 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 1:10.255.1.2:3600::0207::0/192 AD/EVI *[EVPN/170] 15w4d 20:10:12 Indirect 1:10.255.2.26:3600::02000000010000002616::0/192 AD/EVI *[BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.3 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.4 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.20 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 1:10.255.2.26:3600::02000000010000002616::FFFF:FFFF/192 AD/ESI *[BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.3 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.4 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.20 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 2:10.255.1.2:3600::0::00:0c:29:f0:5a:09/304 MAC/IP *[EVPN/170] 14w5d 01:18:41 Indirect 2:10.255.2.26:3600::0::00:0c:29:1f:dd:dc/304 MAC/IP *[BGP/170] 00:00:26, localpref 300, from 10.255.1.3 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 00:00:26, localpref 300, from 10.255.1.4 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 00:00:26, localpref 300, from 10.255.1.20 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 2:10.255.1.2:3600::0::00:0c:29:f0:5a:09::192.168.32.1/304 MAC/IP *[EVPN/170] 14w5d 01:18:36 Indirect 2:10.255.1.2:3600::0::00:0c:29:f0:5a:09::192.168.33.1/304 MAC/IP *[EVPN/170] 1w3d 19:40:14 Indirect 3:10.255.1.2:3600::0::10.255.1.2/248 IM *[EVPN/170] 17w3d 18:54:21 Indirect 3:10.255.2.26:3600::0::10.255.2.26/248 IM *[BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.3 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.4 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.20 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 AS65002 側 PE (rt13) [/] A:user@rt13# show router bgp routes evpn auto-disc detail =============================================================================== BGP Router ID:10.255.2.26 AS:65002 Local AS:65002 =============================================================================== Legend - Status codes : u - used, s - suppressed, h - history, d - decayed, * - valid l - leaked, x - stale, > - best, b - backup, p - purge Origin codes : i - IGP, e - EGP, ? - incomplete =============================================================================== BGP EVPN Auto-Disc Routes =============================================================================== Original Attributes Network : n/a Nexthop : 10.255.2.1 Path Id : None From : 10.255.2.1 Res. Nexthop : 10.2.17.1 Local Pref. : 300 Interface Name : to_ar-rt10 Aggregator AS : None Aggregator : None Atomic Aggr. : Not Atomic MED : None AIGP Metric : None IGP Cost : 30 Connector : None Community : target:64999:3600 Cluster : 0.0.0.1 Originator Id : 10.255.2.1 Peer Router Id : 10.255.2.25 Flags : Valid IGP TieBreakReason : PeerIP MP Exc. Reason : NotNextHopDiverse Route Source : Internal AS-Path : 65001 EVPN type : AUTO-DISC ESI : 00:00:00:00:00:00:00:00:02:07 Tag : 0 Route Dist. : 10.255.1.2:3600 MPLS Label : LABEL 60946 Route Tag : 0 Neighbor-AS : 65001 DB Orig Val : N/A Final Orig Val : N/A Source Class : 0 Dest Class : 0 Add Paths Send : Default Last Modified : 52d23h37m Modified Attributes Network : n/a Nexthop : 10.255.2.1 Path Id : None From : 10.255.2.1 Res. Nexthop : 10.2.17.1 Local Pref. : 300 Interface Name : to_ar-rt10 Aggregator AS : None Aggregator : None Atomic Aggr. : Not Atomic MED : None AIGP Metric : None IGP Cost : 30 Connector : None Community : target:64999:3600 Cluster : 0.0.0.1 Originator Id : 10.255.2.1 Peer Router Id : 10.255.2.25 Flags : Valid IGP TieBreakReason : PeerIP MP Exc. Reason : NotNextHopDiverse Route Source : Internal AS-Path : 65001 EVPN type : AUTO-DISC ESI : 00:00:00:00:00:00:00:00:02:07 Tag : 0 Route Dist. : 10.255.1.2:3600 MPLS Label : LABEL 60946 Route Tag : 0 Neighbor-AS : 65001 DB Orig Val : N/A Final Orig Val : N/A Source Class : 0 Dest Class : 0 Add Paths Send : Default Last Modified : 52d23h37m (snip) ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Routes : 8 =============================================================================== [/] A:user@rt26# show router bgp routes evpn incl-mcast =============================================================================== BGP Router ID:10.255.2.26 AS:65002 Local AS:65002 =============================================================================== Legend - Status codes : u - used, s - suppressed, h - history, d - decayed, * - valid l - leaked, x - stale, > - best, b - backup, p - purge Origin codes : i - IGP, e - EGP, ? - incomplete =============================================================================== BGP EVPN Inclusive-Mcast Routes =============================================================================== Flag Route Dist. OrigAddr Tag NextHop ------------------------------------------------------------------------------- u*>i 10.255.1.2:3600 10.255.1.2 0 10.255.2.1 *i 10.255.1.2:3600 10.255.1.2 0 10.255.2.1 i 10.255.2.26:3600 10.255.2.26 0 10.255.2.26 i 10.255.2.26:3600 10.255.2.26 0 10.255.2.26 ------------------------------------------------------------------------------- Routes : 4 =============================================================================== EVI 3700 AS65001 側 PE (rt01) ※ type3 経路の nexthop が rt07 となっていませんが、こちらは後述の制約事項で扱います。 RP/0/RSP0/CPU0:rt01#show evpn evi vpn-id 3700 ead Mon Jun 19 11:49:14.279 JST VPN-ID Encap Ethernet Segment Id EtherTag Nexthop Label SID ---------- ------ ------------------------ ---------- --------------------------------------- -------- --------------------------------------- 3700 MPLS 0000.0000.0000.0000.0132 0x0 :: 24019 3700 MPLS 0000.0000.0000.0000.1607 0x0 10.255.1.22 507880 3700 MPLS 0000.0000.0000.0000.1607 0xffffffff 10.255.1.22 0 RP/0/RSP0/CPU0:rt01#show evpn evi vpn-id 3700 inclusive-multicast detail Mon Jun 19 11:48:06.327 JST VPN-ID Encap EtherTag Originating IP ---------- ------ ---------- ---------------------------------------- 3700 MPLS 0 10.255.1.1 TEPid : 0xffffffff PMSI Type: 6 Nexthop: :: Label : 26015 SR-TE Info: N/A Source : Local E-Tree : Root 3700 MPLS 0 10.255.2.8 TEPid : 0x02000002 PMSI Type: 6 Nexthop: 10.255.2.8 Label : 507882 SR-TE Info: N/A Source : Remote E-Tree : Root AS65002 側 PE (rt12) user@rt12> show route table evpn-3700.evpn.0 evpn-3700.evpn.0: 8 destinations, 12 routes (8 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 1:10.255.1.1:1::0132::FFFF:FFFF/192 AD/ESI *[BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.5 AS path: 65001 I, validation-state: unverified to 10.2.4.1 via et-0/0/1.0, Push 16009 > to 10.2.16.2 via et-0/0/2.0, Push 16009 [BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.25 AS path: 65001 I, validation-state: unverified to 10.2.4.1 via et-0/0/1.0, Push 16009 > to 10.2.16.2 via et-0/0/2.0, Push 16009 1:10.255.1.1:3700::0132::0/192 AD/EVI *[BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.5 AS path: 65001 I, validation-state: unverified > to 10.2.4.1 via et-0/0/1.0, Push 16009 to 10.2.16.2 via et-0/0/2.0, Push 16009 [BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.25 AS path: 65001 I, validation-state: unverified > to 10.2.4.1 via et-0/0/1.0, Push 16009 to 10.2.16.2 via et-0/0/2.0, Push 16009 1:10.255.2.8:3700::1607::0/192 AD/EVI *[EVPN/170] 14w1d 00:55:46 Indirect 2:10.255.1.1:3700::0::00:0c:29:f0:5a:13/304 MAC/IP *[BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.5 AS path: 65001 I, validation-state: unverified > to 10.2.4.1 via et-0/0/1.0, Push 16009 to 10.2.16.2 via et-0/0/2.0, Push 16009 [BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.25 AS path: 65001 I, validation-state: unverified > to 10.2.4.1 via et-0/0/1.0, Push 16009 to 10.2.16.2 via et-0/0/2.0, Push 16009 2:10.255.2.8:3700::0::00:0c:29:1f:dd:c8/304 MAC/IP *[EVPN/170] 00:11:41 Indirect 2:10.255.2.8:3700::0::00:0c:29:1f:dd:c8::192.168.33.3/304 MAC/IP *[EVPN/170] 00:06:33 Indirect 3:10.255.1.1:3700::0::10.255.1.1/248 IM *[BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.5 AS path: 65001 I, validation-state: unverified to 10.2.4.1 via et-0/0/1.0, Push 16009 > to 10.2.16.2 via et-0/0/2.0, Push 16009 [BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.25 AS path: 65001 I, validation-state: unverified to 10.2.4.1 via et-0/0/1.0, Push 16009 > to 10.2.16.2 via et-0/0/2.0, Push 16009 3:10.255.2.8:3700::0::10.255.2.8/248 IM *[EVPN/170] 15w6d 23:38:46 Indirect 疎通試験 各 EVI について、ce01 から ping で ce02 への疎通確認を行います。 EVI 3600 (192.168.32.0/24) user@ce01:~$ ping 192.168.32.2 -c 5 PING 192.168.32.2 (192.168.32.2) 56(84) bytes of data. 64 bytes from 192.168.32.2: icmp_seq=1 ttl=64 time=1.92 ms 64 bytes from 192.168.32.2: icmp_seq=2 ttl=64 time=2.02 ms 64 bytes from 192.168.32.2: icmp_seq=3 ttl=64 time=1.92 ms 64 bytes from 192.168.32.2: icmp_seq=4 ttl=64 time=1.96 ms 64 bytes from 192.168.32.2: icmp_seq=5 ttl=64 time=2.10 ms --- 192.168.32.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4006ms rtt min/avg/max/mdev = 1.919/1.984/2.096/0.067 ms EVI 3700 (192.168.33.0/24) user@ce01:~$ ping 192.168.33.2 -c 5 PING 192.168.33.2 (192.168.33.2) 56(84) bytes of data. 64 bytes from 192.168.33.2: icmp_seq=1 ttl=64 time=1.66 ms 64 bytes from 192.168.33.2: icmp_seq=2 ttl=64 time=1.50 ms 64 bytes from 192.168.33.2: icmp_seq=3 ttl=64 time=1.59 ms 64 bytes from 192.168.33.2: icmp_seq=4 ttl=64 time=1.49 ms 64 bytes from 192.168.33.2: icmp_seq=5 ttl=64 time=1.46 ms --- 192.168.33.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4007ms rtt min/avg/max/mdev = 1.461/1.541/1.660/0.073 ms パケットが転送でき、VPN が構築できていることが確認できました。 以上、2パターンの組み合わせで L2VPN が構築できている事が確認できました。 制約事項 2023/8/21 現在、L2VPN の Option-B シグナリングは IOS XR と SR OS で可能です。 しかし、相互接続において IOS XR と SR OS で Option-B によるシグナリング時の type3 経路 (IMET route) の解釈違いがありました。 解釈違いによって IOS XR を PE、SR OS を ASBR とする組み合わせの場合に AS を越えて BUM トラフィックが通らないことにご注意ください。 まとめ IOS XR 、Junos と SR OS の Multi-vendor 環境における Multi-AS L2VPN の検証結果を紹介しました。 次回の記事では、同様の Multi-vendor 環境における Color-Based TE について紹介予定です。 (2023/9/4 追記) 公開しました: [Multi-AS Segment Routing 検証連載 #14] Color-Based Steering using IOS XR, Junos and SR OS
TOC サマリ 概要 検証 検証項目とトポロジー 基本設定 IS-IS - 設定 IS-IS - 動作確認 VRF と MP-BGP VPNv4 - 機器設定 MP-BGP VPNv4 - 動作確認 LP の設定 cust-c の動作確認 cust-d の動作確認 cust-e の動作確認 まとめ サマリ Multi-AS で構成されるネットワークにおいて、SR-MPLS + VPNv4 による L3VPN を実現 IOS XR + Junos + SR OS の Multi-vendor 環境で動作検証に成功 この記事は Multi-AS SR 検証連載の第 12 回です。目次は こちら 概要 イノベーションセンターの岩田です。普段の業務では Multi-AS Segment Routing に関する技術検証や、ベンチャー企業への技術支援でスマートフォンアプリケーション開発業務などを行なっています。 第1回 、 第2回 の記事で IOS XR + Junos の 2 つのベンダー機器で構成される L3VPN についてご紹介しましたが、今回新たに Nokia SR OS(Service Router Operating System)を加えた 3 つのベンダー機器での L3VPN 相互動作確認をご紹介します。 L3VPN や Segment Routing など今回扱う技術の説明は、 第1回 、 第2回 記事の概要章にて紹介しているので、そちらをご参照ください。 検証 以降は L3VPN の検証例を実際の設定例を添えつつ紹介します。 IOS XR、Junos の設定例は 第1回 や 第2回 の記事で紹介したため本記事では割愛し、SR OS の設定例を中心に紹介します。 検証項目とトポロジー 本記事の検証では、Inter-AS Option B の L3VPN について、SR OS と 各ベンダー(SR OS 自身を含む)間の互換性確認を目的とします。 そのため、以下の検証項目を設定します。 項目1: SR OS(PE)と SR OS(PE)間で L3VPN が構築できるかを確認する 項目2: SR OS(PE)と IOS XR(PE)間で L3VPN が構築できるかを確認する 項目3: SR OS(PE)と Junos(PE)間で L3VPN が構築できるかを確認する 項目4: Inter-AS Option B 構成を構築する際に SR OS を ASBR として利用できるかを確認する 上記の確認のため、本記事では下図のようなトポロジーからなるネットワークを用いて検証します。 検証項目と、構築する L3VPN を構成する VRF と機器の組み合わせを以下の表に示します。 検証項目 VRF AS65001 PE → → ASBR-ASBR → → AS65002 PE 項目 2 cust-c IOS XR (rt01) Junos (rt05、 rt09) SR OS (rt13) 項目 3 cust-d Junos (rt02) IOS XR (rt04、 rt08) SR OS (rt13) 項目 1、 4 cust-e IOS XR (rt01) SR OS (rt06、 rt10) Junos (rt12) 使用する機器は以下の通りです。 rt01、rt04、rt07、rt08: Cisco IOS XR 7.4.1 rt02、rt05、rt09、rt12: Juniper Junos OS 21.3R1.9 rt06、rt10、rt13: Nokia SR OS 22.7.R1 この後は下記の流れに従って設定を紹介します。 IS-IS 設定と状態確認 VRF と MP-BGP 設定と状態確認 PE 間の ping 疎通試験 基本設定 IS-IS - 設定 IS-IS の SR 拡張を利用し、SR-MPLS の SID 情報を広告します。 SR OS(例: rt13) A:admin@rt13# /info router isis admin-state enable advertise-router-capability as level-capability 2 traffic-engineering true area-address [49.0000] segment-routing { admin-state enable prefix-sid-range { global } } interface "system" { } interface "to_rt08" { interface-type point-to-point level-capability 2 } interface "to_rt09" { interface-type point-to-point level-capability 2 } interface "to_rt10" { interface-type point-to-point level-capability 2 } level 2 { wide-metrics-only true } [ro:/configure] A:admin@rt13# /info router mpls-labels static-label-range 0 sr-labels { start 16000 end 23999 } [ro:/configure] A:admin@rt13# /info router segment-routing sr-mpls { prefix-sids "system" { ipv4-sid { index 13 } } } IS-IS - 動作確認 IS-IS ネイバーの状態と SID Table を確認します。 IS-IS ネイバーの状態の確認 [ro:/configure] A:admin@rt13# /show router isis adjacency =============================================================================== Rtr Base ISIS Instance 0 Adjacency =============================================================================== System ID Usage State Hold Interface MT-ID ------------------------------------------------------------------------------- rt08 L2 Up 25 to_rt08 0 rt09 L2 Up 25 to_rt09 0 rt10 L2 Up 20 to_rt10 0 ------------------------------------------------------------------------------- Adjacencies : 3 =============================================================================== SID Table の確認 [/] A:admin@rt13# /show router isis prefix-sids =============================================================================== Rtr Base ISIS Instance 0 Prefix/SID Table =============================================================================== Prefix SID Lvl/Typ SRMS AdvRtr Shared MT Flags ------------------------------------------------------------------------------- 10.255.2.2/32 12 2/Int. N rt12 N.A. 0 N 10.255.2.3/32 13 2/Int. N rt13 Yes 0 NnP 10.255.2.4/32 8 2/Int. N rt08 N.A. 0 N 10.255.2.5/32 9 2/Int. N rt09 N.A. 0 N 10.255.2.6/32 10 2/Int. N rt10 N.A. 0 NnP 10.255.2.7/32 14 2/Int. N rt14 N.A. 0 N ------------------------------------------------------------------------------- No. of Prefix/SIDs: 6 (6 unique) ------------------------------------------------------------------------------- SRMS: Y/N = prefix SID advertised by SR Mapping Server (Y) or not (N) S = SRMS prefix SID is selected to be programmed Flags: R = Re-advertisement N = Node-SID nP = no penultimate hop POP E = Explicit-Null V = Prefix-SID carries a value L = value/index has local significance Shared: Yes = local shared Node-SID No = not a local shared Node-SID N.A. = not applicable for Remote prefix-sid =============================================================================== VRF と MP-BGP VPNv4 - 機器設定 cust-c、d、e の VRF 設定と、経路を広告する MP-BGP L3VPN を設定します。 VPN の各パラメータは下記の通りです。 SR Domain 1 AS 番号: 65001 VRF 300(cust-c): RD/RT 65001:300 AS 間での VPN 経路広告用 RT: 64999:300 VRF 400(cust-d): RD/RT 65001:400 AS 間での VPN 経路広告用 RT: 64999:400 VRF 500(cust-e): RD/RT 65001:500 AS 間での VPN 経路広告用 RT: 64999:500 SR Domain 2 AS 番号: 65002 VRF 300(cust-c): RD/RT 65002:300 AS 間での VPN 経路広告用 RT: 64999:300 VRF 400(cust-d): RD/RT 65002:400 AS 間での VPN 経路広告用 RT: 64999:400 VRF 500(cust-e): RD/RT 65002:500 AS 間での VPN 経路広告用 RT: 64999:500 PE の設定(例: rt13、SR OS) A:admin@rt13# info policy-options community "shared-comm-cust-c" { member "target:64999:300" { } } community "shared-comm-cust-d" { member "target:64999:400" { } } policy-statement "vrf-export-cust-c" { entry 10 { action { action-type accept community { add ["shared-comm-cust-c"] } } } } policy-statement "vrf-export-cust-d" { entry 10 { action { action-type accept community { add ["shared-comm-cust-d"] } } } } policy-statement "vrf-import-cust-c" { entry 10 { from { community { name "shared-comm-cust-c" } } action { action-type accept } } } policy-statement "vrf-import-cust-d" { entry 10 { from { community { name "shared-comm-cust-d" } } action { action-type accept } } } A:admin@rt13# info service customer "cust-c" { customer-id 300 } customer "cust-d" { customer-id 400 } vprn "300" { admin-state enable customer "cust-c" bgp-ipvpn { mpls { admin-state enable route-distinguisher "65002:300" vrf-import { policy ["vrf-import-cust-c"] } vrf-export { policy ["vrf-export-cust-c"] } auto-bind-tunnel { resolution any } } } interface "to_cust-c" { admin-state enable ipv4 { primary { address 192.168.1.254 prefix-length 24 } } sap 1/1/c4/1:0 { admin-state enable } } } vprn "400" { admin-state enable customer "cust-d" bgp-ipvpn { mpls { admin-state enable route-distinguisher "65002:400" vrf-import { policy ["vrf-import-cust-d"] } vrf-export { policy ["vrf-export-cust-d"] } auto-bind-tunnel { resolution any } } } interface "to_cust-d" { admin-state enable ipv4 { primary { address 192.168.1.254 prefix-length 24 } } sap 1/1/c5/1:0 { admin-state enable } } } ASBR の設定(例: rt10、SR OS) A:admin@rt13# info router bgp vpn-apply-export true inter-as-vpn true rapid-withdrawal true family { vpn-ipv4 true } ebgp-default-reject-policy { import false export false } rapid-update { vpn-ipv4 true } next-hop-resolution { labeled-routes { transport-tunnel { family vpn { resolution any } } } } group "65001" { peer-as 65001 family { vpn-ipv4 true } } group "iBGP" { peer-as 65002 local-address 10.255.2.6 family { vpn-ipv4 true } } neighbor "10.100.3.1" { group "65001" local-address 10.100.3.2 } neighbor "10.255.2.7" { group "iBGP" } MP-BGP VPNv4 - 動作確認 下記 3 ステップで L3VPN の経路学習と転送動作を確認します。 今回は各ベンダーの ASBR の組で動作確認をするために ASBR へ LP を設定し、VRF ごとに ASBR を選択します。 動作確認したい ASBR の組が選択されるように LP を調整する PE で BGP から受信した経路を確認 ping による疎通確認 LP の設定 以下の設定で LP を調整し、cust-c、d、e に対応する ASBR を選択します。 cust-c(rt04、IOS XR) route-policy lp-high if extcommunity rt matches-any (64999:400) then set local-preference 300 endif end-policy ! router bgp 65001 neighbor-group ibgp address-family vpnv4 unicast route-policy lp-high out ! cust-d(rt05、Junos) set policy-options community CUST-C-SHARED members target:64999:300 set policy-options policy-statement lp-high term 1 from community CUST-C-SHARED set policy-options policy-statement lp-high term 1 then local-preference 300 set policy-options policy-statement lp-high term 1 then accept set protocols bgp group ibgp export lp-high cust-e(rt06、SR OS) A:admin@rt06# info policy-options community "CUST-E-SHARED" { member "target:64999:500" { } } policy-statement "lp-high" { entry 1 { from { community { name "CUST-E-SHARED" } } action { action-type accept local-preference 300 } } } A:admin@rt06# info router bgp vpn-apply-export true group "iBGP" { export { policy ["lp-high"] } } 動作確認 以下のように cust-c、d、e で適切な ASBR が選択されていることが確認できました。 RP/0/RP0/CPU0:rt07#show bgp vpnv4 unicast Fri Feb 3 15:50:04.866 JST BGP router identifier 10.255.1.7, local AS number 65001 BGP generic scan interval 60 secs Non-stop routing is enabled BGP table state: Active Table ID: 0x0 RD version: 0 BGP main routing table version 181 BGP NSR Initial initsync version 1 (Reached) BGP NSR/ISSU Sync-Group versions 0/0 BGP scan interval 60 secs Status codes: s suppressed, d damped, h history, * valid, > best i - internal, r RIB-failure, S stale, N Nexthop-discard Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 65001:300 *>i192.168.0.0/24 10.255.1.1 0 100 0 ? Route Distinguisher: 65001:400 *>i192.168.0.0/24 10.255.1.2 100 0 i Route Distinguisher: 65001:500 *>i192.168.0.0/24 10.255.1.1 0 100 0 ? Route Distinguisher: 65002:300 *>i192.168.1.0/24 10.255.1.5 300 0 65002 i *>i192.168.1.254/32 10.255.1.5 300 0 65002 i Route Distinguisher: 65002:400 *>i192.168.1.0/24 10.255.1.4 300 0 65002 i *>i192.168.1.254/32 10.255.1.4 300 0 65002 i Route Distinguisher: 65002:500 *>i192.168.1.0/24 10.255.1.6 300 0 65002 i cust-c の動作確認 rt01(PE)で対向 AS から広告された VRF 経路を受け取れていることを確認します。 RP/0/RP0/CPU0:rt01#show route vrf cust-c Fri Feb 3 14:03:42.980 JST Codes: C - connected, S - static, R - RIP, B - BGP, (>) - Diversion path D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2 E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP i - ISIS, L1 - IS-IS level-1, L2 - IS-IS level-2 ia - IS-IS inter area, su - IS-IS summary null, * - candidate default U - per-user static route, o - ODR, L - local, G - DAGR, l - LISP A - access/subscriber, a - Application route M - mobile route, r - RPL, t - Traffic Engineering, (!) - FRR Backup path Gateway of last resort is not set C 192.168.0.0/24 is directly connected, 6d20h, GigabitEthernet0/0/0/3 L 192.168.0.254/32 is directly connected, 6d20h, GigabitEthernet0/0/0/3 B 192.168.1.0/24 [200/0] via 10.255.1.5 (nexthop in vrf default), 1d23h B 192.168.1.254/32 [200/0] via 10.255.1.5 (nexthop in vrf default), 1d23h ping で疎通確認を行なってみます。 RP/0/RP0/CPU0:rt01#ping 192.168.1.254 vrf cust-c Fri Feb 3 16:07:13.844 JST Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 192.168.1.254, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 3/8/14 ms RP/0/RP0/CPU0:ar1018-rt01#traceroute 192.168.1.254 vrf cust-c Fri Feb 3 16:07:17.423 JST Type escape sequence to abort. Tracing the route to 192.168.1.254 1 10.1.2.2 [MPLS: Label 62 Exp 0] 14 msec 7 msec 14 msec 2 10.100.2.2 [MPLS: Label 31 Exp 0] 4 msec 11 msec 4 msec 3 192.168.1.254 8 msec 13 msec 3 msec パケットが転送でき、VPN が構築できていることが確認できました。 cust-d の動作確認 rt02(PE)で対向 AS から広告された VRF 経路を受け取れていることを確認します。 user@rt02> ping 192.168.1.254 routing-instance CUST-D PING 192.168.1.254 (192.168.1.254): 56 data bytes 64 bytes from 192.168.1.254: icmp_seq=0 ttl=62 time=2.849 ms 64 bytes from 192.168.1.254: icmp_seq=1 ttl=62 time=2.507 ms 64 bytes from 192.168.1.254: icmp_seq=2 ttl=62 time=3.050 ms ^C --- 192.168.1.254 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/stddev = 2.507/2.802/3.050/0.224 ms user@rt02> traceroute 192.168.1.254 routing-instance CUST-D no-resolve traceroute to 192.168.1.254 (192.168.1.254), 30 hops max, 52 byte packets 1 10.1.4.2 11.656 ms 2.224 ms 2.109 ms MPLS Label=24018 CoS=0 TTL=1 S=1 2 10.100.1.2 3.361 ms 10.787 ms 2.800 ms MPLS Label=24017 CoS=0 TTL=1 S=1 3 192.168.1.254 2.290 ms 1.691 ms 1.632 ms パケットが転送でき、VPN が構築できていることが確認できました。 cust-e の動作確認 rt01(PE)で対向 AS から広告された VRF 経路を受け取れていることを確認します。 RP/0/RP0/CPU0:rt01#show route vrf cust-e Fri Feb 3 14:03:54.438 JST Codes: C - connected, S - static, R - RIP, B - BGP, (>) - Diversion path D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2 E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP i - ISIS, L1 - IS-IS level-1, L2 - IS-IS level-2 ia - IS-IS inter area, su - IS-IS summary null, * - candidate default U - per-user static route, o - ODR, L - local, G - DAGR, l - LISP A - access/subscriber, a - Application route M - mobile route, r - RPL, t - Traffic Engineering, (!) - FRR Backup path Gateway of last resort is not set C 192.168.0.0/24 is directly connected, 6d19h, GigabitEthernet0/0/0/4 L 192.168.0.254/32 is directly connected, 6d19h, GigabitEthernet0/0/0/4 B 192.168.1.0/24 [200/0] via 10.255.1.6 (nexthop in vrf default), 00:37:18 ping で疎通確認を行なってみます。 RP/0/RP0/CPU0:rt01#ping 192.168.1.254 vrf cust-e Fri Feb 3 16:07:29.739 JST Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 192.168.1.254, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 3/7/13 ms RP/0/RP0/CPU0:ar1018-rt01#traceroute 192.168.1.254 vrf cust-e Fri Feb 3 16:07:33.584 JST Type escape sequence to abort. Tracing the route to 192.168.1.254 1 10.100.3.1 [MPLS: Labels 16006/524284 Exp 0] 11 msec 14 msec 5 msec 2 10.2.6.1 [MPLS: Label 524276 Exp 0] 12 msec 4 msec 7 msec 3 192.168.1.254 13 msec 6 msec 16 msec パケットが転送でき、VPN が構築できていることが確認できました。 以上で全ての組で VPN が構築できている事が確認できました。 まとめ IOS XR 、Junos と SR OS の Multi-vendor 環境における Multi-AS L3VPN の検証結果を紹介しました。 次回の記事では、これらの Multi-vendor 環境における Multi-AS L2VPN について紹介予定です。 (2023/8/21 追記) 公開しました: [Multi-AS Segment Routing 検証連載 #13] SR-MPLS L2VPN(EVPN) using IOS XR, Junos and SR OS
みなさんこんにちは、イノベーションセンターの @Mahito です。 普段は社内のエンジニアが働きやすくなることを目標に、コーポレートエンジニアとしての活動やエンジニア向けイベントの企画・運営をしています。 今回は NTT ComのSpeaker Deckアカウント ができましたというお知らせになります。 Speaker Deck 開設の背景 以前から、社内のエンジニアがイベントなどで外部発表をしたものの、 発表資料を置く場所がないという話がありました。 今まで会社として公式に発表資料を掲載する場所はなく、 部署単位での発表資料を公開する場所を用意していた時期もあります。 しかし、社内の組織変更や、利用していたサービスの仕様変更などもあり使われなくなったという過去があります。 結果として、外部発表をしたエンジニアは資料を公開しない、もしくは、個人のアカウントにアップロードをするという状況が続いていました。 特に前者は、せっかく発表する価値のある内容の資料が誰にも共有されることもなく仕舞われているという状況でした。 こうした状況の背景には、全社に関わるプロモーションは広報の仕事なので、 発表資料を公開する場所は広報が用意をするべきだという空気がありました。 しかしながら、なかなか整理等を実施して実現方法を含めて環境まで準備するには時間がかかりそうであったため、 本ブログのようにエンジニアが主体になって全社に関わるプロモーションの活動している実績もあり、 今回はエンジニアサイドから広報に外部発表の資料を置く場所を作らせてほしいという提案へ行くことにしました。 広報との話し合い 広報とは現状の課題として、会社のプレゼンス向上機会の損失という話をメインに進めました。 広報からは公式サイトに資料を置くこともできるという話もありましたが、 単純にPDFを置いて資料を見たい人がダウンロードするという流れを考えると、 不便さがあるという話をしました。 一方、Speaker Deckではブラウザ上で資料を見えることやページごとにURLが発行されており、 資料を見る側にとって便利なサービスであることを伝えました。 話し合いの結果、広報室から発表資料をSpeaker Deckに置くこと理解を得ることができ、 エンジニアブログの運用の実績から、Speaker Deckの運用もエンジニアサイドに一任して貰う形で終わりました。 Speaker Deck の運用 Speaker Deckへの資料掲載はハードルや手間を減らすために、 全社員が使えるマイクロソフトのサービスで簡易な掲載フローを組みました。 掲載までの流れは以下のようになっています。 掲載希望者はMS Formsから掲載のエントリー Power AutomateがMS Formsのエントリー情報をTeamsのSpeaker Deckの管理チームに通知 通知を元にSpeaker Deckへ記事を掲載 本当は3の部分もAPIを使って自動化しておきたいところですが、 あいにくSpeaker DeckにはAPIがないようなので手作業となっています。 今のところ依頼がまだそんなに多くないので人力でなんとかなっていますが、 依頼が増えてくるようならばヘッドレスブラウザなどを使うことも考えます。 おわりに 今まで社内のエンジニアたちが「外部で発表したけど資料を公開する場所がない!」というフラストレーションをためていましたが、 今回Speaker Deckを作ったことでこうした問題の解決になればと思っています。 また、「NTT Comがイベントで発表していたけどその資料が見つからない!」なんてご不便をおかけすることもあったかと思います。 これからはNTT Com社員が外部発表などをした際には、Speaker Deckに発表資料をアップロードすることもありますので、 興味のあるかたは是非 NTT ComのSpeaker Deckアカウント をフォローしてみてください。
目次 目次 はじめに L5GとICGWの相互接続構成 デモ内容 温湿度、Co2濃度の可視化 カメラ画像 各社L5Gのスループット計測値 設定・運用面の工夫 ゼロタッチプロビジョニング デバイスの遠隔保守 おわりに はじめに こんにちは、5G&IoTサービス部、IoTサービス部門の岩辻です。 NTTコミュニケーションズ株式会社 (以下、NTT Com) は、世界最大級のネットワーク展示会である 「Interop Tokyo 2023 (会場 : 幕張メッセ、会期 : 2023年6月14日〜16日、以下Interop) 」 において会場内に構築されたローカル5G (以下、L5G) と IoT Connect Gateway (以下、ICGW) の相互接続を実現しました。 また、L5G、ICGWを通じて収集したIoTデバイスのセンサデータ、L5Gネットワークのスループット計測などの可視化も実施しました。 本記事ではその構成や可視化方法、IoTデバイス運用面での工夫について解説します。 Interopでの取り組みを通じて、ICGWによって実現できること、 それをいかに効率よく構築・運用できるかを知っていただけると思います。 L5GとICGWの相互接続構成 現状、ICGWはNTT ComのMVMO回線であるIoT Connect Mobile Type S (以下 、ICMS) のみで利用できるサービスとなっていますが、今回はL5Gとの相互接続にチャレンジしました。 下図にあるように、Flexible Inter Connect (以下、FIC) を活用して、各社スライスを切ったL5G環境とICGWを容易に繋げることができました。 ICGWからThings Cloudへの接続はすでに商用提供されている機能となり、L5GとSDPF商材との組み合わせによって新たなソリューション展開が可能であるという技術的確認ができました。 ICGW以外にも様々なSDPFサービスの組み合わせにより、お客様環境を柔軟に構築することが可能になります。 L5Gの基地局や上流NWのトラブルによって、ICGWがデバイスを識別できなくなるという事象はありましたが、これについては暫定対処を実施しました。 デバイスに対して監視用のPingを定期的に飛ばし、疎通がなくなったら通知する仕組みを急遽用意し、異常検知を通知していました。 この通知によって問題解決をスピード感をもって実現できました。 デモ内容 Interop会場内にセンサー類を取り付けたデバイスを計8台配置し、会場内のL5G経由でICGWに接続 & クラウドへ転送して可視化しました。 クラウド上で可視化したデモ一覧は以下となります。 温湿度、Co2濃度の可視化 カメラ画像 各社様L5Gのスループット計測値 順次、実際の画面を交えて説明していきます。 温湿度、Co2濃度の可視化 センサーから送られてきたデータをICGWのクラウドサービス接続機能を使ってThings Cloudに送り、可視化をしています。 Things Cloudの標準ウィジェット機能を利用して温湿度のグラフ化を行っています。 また、Co2濃度に関してはカスタムウィジェット機能を使って、Interopの会場図上にヒートマップで可視化しました。 過去の類似例を参考に、Angularで開発してThings Cloud上にデプロイしています。 Things Cloudが受け取るデータのフォーマットは厳しく決められており、それに合わせるのはデバイスにとって負担となりますが、ICGWのフォーマット変換機能 (2023/09リリース予定) を使って解決しています。 予め作成した変換テンプレートに沿ってICGW内でデータの加工するため、デバイスからは計測値のみ送って、ICGW内でThings Cloudの形に統一する、ということが可能です。 デバイス側でのデータ加工の負担をなくし、送信するデータのサイズも小さくできるメリットがあります。 カメラ画像 M5Stack UnitV2 AI カメラをデバイスに取り付け、画像をThings Cloudで表示しています。 また、今回取り付けたカメラには物体認識の機能が備わっているため、撮影された画像の中のオブジェクト数と人数もデバイスから送信し、Things Cloud上でグラフ化しています。 実際のユースケースでは、イベント会場内の来客人数把握や人流検知に応用できるものだと考えています。 各社L5Gのスループット計測値 各社L5GのスループットをThings Cloudと、AWS EC2上に立てたGrafanaで可視化しました。 当初、Things Cloud上での可視化のみを予定していましたが、各社のLatency/Jitterの制御をよりきれいにグラフで表現したいという声があったため、急遽Grafanaでの可視化も行いました。 データはThings Cloudにのみアップロードし、Grafana側はThings Cloudに対してデータ取得のリクエストを発行して取得&利用しています。 今回は稼働が足りず断念しましたが、ICGWのミラーリング機能 (2023/09リリース予定) を利用すればThings Cloudに送りつつ、他クラウドにも同時に送ることが可能となり、複数のクラウドでの可視化がさらに容易になります。 (※ 各社帯域に制限をかけているため、Upload/Downloadについては差分が出ています) 設定・運用面の工夫 実際のお客様の環境では、IoT デバイスの数は多数になり、また設置場所もそれぞれバラバラになってしまうことが多いです。 設定の変更やトラブル対応時にはデバイスの元まで駆けつける必要がありますが、ICGWを利用すればその負担も軽減できます。 今回はInterop会場を実際のお客様環境に見立てて、我々が運用する上でチャレンジした内容を紹介させていただきます。 ゼロタッチプロビジョニング 今回のInteropで利用したデバイス数は8台程度で1台1台設定しても大きな負担にはなりませんが、実際のお客様環境ではもっと多数を利用することがほとんどです。 そのため、ICGWのコンフィグ配信、ストレージ機能を使って、下図のような構成でゼロタッチプロビジョニングを実現しています。 まずは以下の事前設定をします。 Node-REDでICGWにセンサーデータを送信するシナリオファイルを作成 シナリオファイルをクラウドストレージ (Wasabi) にアップロード ストレージ機能を使うための設定情報をコンフィグ配信機能に登録 設定ファイルの更新をICGWに問い合わせ、更新があればストレージ機能を使ってWasabiにシナリオファイルを取得するスクリプトを作成 4で作成したスクリプトをデバイス上で動作し続けるよう設定 事前設定を終えると、SIMをデバイスに差すだけで、シナリオファイルの取得&センサーデータの送信が始まり、ゼロタッチプロビジョニングが実現できます。 また、Node-REDのシナリオファイルを更新する際にも、1デバイス上でシナリオファイルを修正してWasabiにアップロードし、設定ファイルを更新するだけで8台全てにシナリオファイルの変更が完了します。 初期設定だけでなく、更新にも強い構成にでき、準備段階での稼働削減になりました。 デバイスの遠隔保守 ICGWのリモートアクセス機能を使って、IoTデバイスに遠隔から入れるようにしました。 リモートアクセス機能は、下図のようにICGW上で設定するだけで、外からオンデマンドにデバイスへアクセスできるエンドポイントを提供する機能です。 各デバイス毎のリモートアクセス設定を投入さえすれば、場所を選ばずデバイスの設定ができるため、まずはリモートアクセス設定を入れるところから始め、Interopの準備を進めていました。 会期中の運用では、デバイス上で動作するNode-REDに入ってシナリオの動作確認をしたり、必要であれば修正してました。 会場が広く、設置場所もバラバラであったため、一台一台デバイスの元まで行って確認する手間を省け、大きなメリットとなりました。 おわりに Interop会場に構築されたL5GとICGWの相互接続と環境データの可視化、運用負担の軽減などについて紹介させていただきました。 今回L5GとICGWの相互接続とのフィージビリティが検証できたので、今後はICMS以外の回線とも連携を進めていき、あらゆる回線からICGWを利用できて、よりお客様に利用していただきやすくなるよう努めていきたいと考えております。 9月以降にはインターネット回線からICGWを利用できる機能もリリース予定です。 ご興味のある方はぜひICGWのご利用を検討してみてください。 ICGWに関するお問い合わせ先 IoT Connect Gatewayサービス詳細 ICGWに関するお問い合わせ先 トライアル、サービス導入に関するお問い合わせ 資料請求・お問い合わせフォーム 開発チームへのお問い合わせ(お手数ですが@を半角文字に置き換えてください) メールを送る Interop Tokyo 2023 のその他関連記事 Engineer's Blog では本記事以外にもInterop Tokyo 2023 に関する記事が投稿されてます。 ご興味をお持ちの方は是非御覧ください。 Interop Tokyo 2023 〜 マルチベンダL5G x IoTサービス連携の取り組み〜 Interop Tokyo 2023 〜 L5G x AWS Outpostsサーバーの取り組み紹介 〜
概要 はじめまして。イノベーションセンター所属の鄭(GitHub: nbhgytzheng )です。2021年入社し、現在はテクノロジー部門のOsecT-Ops プロジェクトに所属して、 OsecT の開発・運用業務に取り組んでいます。 今回はOsecTで利用している Zeek (ネットワーク・セキュリティ・モニタリングツール)とZeekのプロトコル拡張ツールである Spicy (Zeekで利用するC++のパーサーをC++で記述することなく簡易に生成できるツール)の概要及び使い方・利用例を紹介します。探した限り日本語での使い方の紹介記事がないため、今回が日本初紹介です。本記事の目標は、ZeekとSpicyを使って任意のプロトコルを含むトラフィック解析ができるようになることです。 OsecTとは OsecTとは工場などの制御システム(OT; Operational Technology)のセキュリティリスクを可視化・検知するサービスです。 多様化する工場システムのセキュリティ脅威に対して、パケット解析するセンサー機器を設置するだけで、OTシステムへの影響なく、ネットワークの可視化と脅威・脆弱性検知ができます。早期にリスク感知できる状態を作り、工場停止による損失を未然に防ぐことができます。詳しくは過去のブログ記事に書いているので、興味がある人はぜひ見てください。( OsecTリリース ・ OsecT前編 ・ OsecT後編 ) Zeekとは Zeekとはネットワークを監視し、トラフィックを解析して、IPアドレス、MACアドレスやプロトコルなどの情報をログとして出力するOSSです。Zeekは下記のような基本ログ(conn.log, dns.log, dhcp.logなど)を出力します。また必要に応じて、プラグインを利用することで出力ログの追加ができます。 # 生成のログの例:dns.log #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path dns #open 2023-03-14-16-15-20 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id rtt query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected pkts #types time string addr port addr port enum count interval string count string count string count string bool bool bool bool count vector[string] vector[interval] bool int 1539457598.376546 CHTBxA4O2ypY1PxYPg fd00:f81d:f5f:6b92:fd0d:9399:3d28:3984 5353 ff02::fb 5353 udp 0 - _ipp._tcp.local 1 C_INTERNET 12 PTR - - F F F F 0 - - F - 1539459646.378861 COMnQY2JaJZ3TllMYb fd00:f81d:f5f:6b92:fd0d:9399:3d28:3984 5353 ff02::fb 5353 udp 0 - _ipp._tcp.local 1 C_INTERNET 12 PTR - - F F F F 0 - - F - 1539463246.380625 Cgu5Zw1ASoGNZ2UGok fd00:f81d:f5f:6b92:fd0d:9399:3d28:3984 5353 ff02::fb 5353 udp 0 - _ipp._tcp.local 1 C_INTERNET 12 PTR - - F F F F 0 - - F - 1539466846.382677 C5X9v4snqSDPMj3u7 fd00:f81d:f5f:6b92:fd0d:9399:3d28:3984 5353 ff02::fb 5353 udp 0 - _ipp._tcp.local 1 C_INTERNET 12 PTR - - F F F F 0 - - F - ... Spicyとは プラグインを利用することで、出力ログを増やせますが、必要なログを出力するプラグインがないこともあります。例えば、以下の要件を満たすプラグインは存在しません。 Zeekが対応しているプロトコルの出力ログ内に追加の情報を加えて出力したい場合 Zeekが対応していないプロトコルの情報をログに出するしたい場合 ここで登場するのがSpicyです。SpciyとはZeekで利用するC++のパーサーをC++で記述することなく簡易に生成するためのツールです。Spicyを利用すれば、ログ情報の追加やZeek及びプラグインで解析できないプロトコルの解析ができるようになります。 Zeek・Spicyによるプロトコル解析 ここまではZeek, Spicyの概要について紹介しました。本章ではZeek, Spicyの利用方法について、環境構築からコーディングまで紹介します。 1. ZeekとSpicyのインストール はじめに、Zeek, Spicyの実行環境を構築します。今回はUbuntu 22.04.1をベースに環境構築の方法を示します。その他のOSでのインストール方法は 公式サイト を参照してください。 1.まずはZeekのリソース(GitHub)を取得するため、gitコマンドをインストールします。 ~$ sudo apt install git 2.次にgitコマンドを利用して、Zeekのリソースをクローンします。 ~$ git clone --recursive https://github.com/zeek/zeek -b v5.0.0 3.Zeekのリソースはcmakeコマンドを利用して自動インストールできるので、cmakeコマンドと関連パッケージをインストールします。 ~$ sudo apt-get install cmake make gcc g++ flex libfl-dev bison libpcap-dev libssl-dev python3 python3-dev swig zlib1g-dev 4.最後にクローンしたZeekディレクトリへ移動し、以下のコマンドを実行すれば自動でインストールされます。makeは状況に応じて1時間以上かかる場合もあります。最後のmake installはスーパーユーザーで実行しないと、エラーになるため注意してください。 ~$ ./configure --build-type=Release ...一部省略... ================================================================ -- Configuring done -- Generating done -- Build files have been written to: /home/xxx/zeek/build ~$ make ...一部省略... Consolidate compiler generated dependencies of target zeek-archiver make[3]: Leaving directory '/home/xxx/zeek/build' [100%] Built target zeek-archiver ~$ sudo make install ...一部省略... make[1]: Leaving directory '/home/xxx/zeek/build' 5.以上でZeekのインストールは完了です。以下のコマンドでZeekが利用できることを確認します。 # パス追加 ~$ export PATH="$PATH:/usr/local/zeek/bin" # zeekコマンド確認 ~$ zeek -version zeek version 5.0.0 6.Spicyのインストールは 公式サイト でDEBファイルを取得し、以下のコマンドを順に実行すればインストールが完了です。 ~$ sudo dpkg --install xxx.deb (例:spicy-dev.deb) Selecting previously unselected package spicy. (Reading database ... 212653 files and directories currently installed.) Preparing to unpack spicy-dev.deb ... Unpacking spicy (2.4.8) ... Setting up spicy (2.4.8) ... 7.インストールが完了したら、以下のコマンドでSpicyが利用できることを確認します。 # パス追加 ~$ export PATH="$PATH:/opt/spicy/bin/spicyc" # spicyコマンド確認 ~$ spicyz -version 1.3.16 ~$ spicyc -version spicyc v1.5.0 (d0bc6053) 以上でZeekとSpicyの実行環境の構築は完了です。 2. プロトコル仕様の確認 SpicyではIPベースのプロトコルだけでなく、イーサネットベースのプロトコルのパーサーも作成できます。今回はIPベースのUDPプロトコルを例に説明します。IPベースのプロトコル構造は以下のようになっています。IPベースでSpicyを利用する場合、Spicyが自動的に青い部分(イーサネットヘッダー、IPヘッダー、TCP/UDPヘッダー)を除き、オレンジ色の部分を処理します。 まず、ログに出力する内容を決めるために、解析対象のプロトコル仕様を確認します。プロトコル仕様はGoogleなどで検索して見つけられるケースもありますが、プロトコルに関わる各種団体・協会経由で仕様書を取得するケースもあります。プロトコル仕様からポート番号(今回の例では1111)と以下のようなパケットフォーマット定義を用意して、Spicyでのパーサー実装に進みます。 項目名/フィールド名 サイズ(オクテット) 内容 header1 2 プロトコルヘッダー header2 1 プロトコルヘッダー command 2 リクエストのタイプを表す subCommand 2 実行する動作を表す … … … 次にパーサーで利用するSpicyファイル・evtファイル・Zeekファイルの作成方法について紹介します。 3. Spicyファイルを作成 本節では以下のテンプレートと前節で取得したプロトコル情報(ポート番号・パケットフォーマット定義)を利用したSpicyファイルの基本的な作成方法を紹介します。Spicyファイルでは、通信プロトコルのプロトコルフォーマットを定義します。 # spicyテンプレート module MYPROTOCOL; import zeek; import spicy; public type Message = unit { PROTOCOL_FIELD1: FIELD_TYPE &size=1; PROTOCOL_FIELD2: FIELD_TYPE &size=2; ... on %done { print self; zeek::confirm_protocol();} }; テンプレートの各部分を解説します。 module MYPROTOCOL; :任意のモジュール名を宣言 多くの場合、解析対象のプロトコル名を記述します。 import xxx :Spicy関数の取り込み 基本的には、Spicyの基本関数が入っている”spicy”とconn.logのservice列にプロトコル名を出力ための”zeek”が必要です。 public type Message = unit {} :プロトコルのデータ部分を格納する変数 データ部分はこの Message に渡されます。 PROTOCOL_FIELD1: FIELD_TYPE &size=1; :データ部分をブロックごとに分解 書き方はFIELD_TYPEによって異なるため 公式サイト を参照してください。 on %done { print self; zeek::confirm_protocol();} :Spicyが解析を終えたときに実行する関数 print self; :解析データの全てをprint(debug用) zeek::confirm_protocol(); :解析が終わったことをZeekに通知 そして、前節で取得したプロトコル情報を利用して、テンプレートを改造すると以下のようなSpicyファイルが作成できます。ここで、 subCommand までが必要なデータとした場合、最後に tmp という PROTOCOL_FIELD を追加で作成し、 subCommand 以降のデータをtmpに入れることができます。 module protocol_name; # Spicyを単独で実行する場合は下の import zeek をコメントアウトする import zeek; import spicy; public type Message = unit { header1: bytes &size=2; header2: bytes &size=1; command: bytes &size=2; subCommand: bytes &size=2; tmp: bytes &eod; # Spicyを単独で実行する場合は zeek::confirm_protocol(); 部分をコメントアウトする on %done { print self; zeek::confirm_protocol();} }; 実行すると、以下の出力が得られます。(Spicyのみ実行したい場合は上記のコードをコメントに従って変更する必要があります) # 実行結果 ~$ printf '\x00\x00\x01\x02\x02\x03\x03\x11\x11\x11\x11\x11\x11\x11' | spicy-driver test.spicy [$header1=b"\x00\x00", $header2=b"\x01", $command=b"\x02\x02", $subCommand=b"\x03\x03", $tmp=b"\x11\x11\x11\x11\x11\x11\x11"] 4. evtファイルを作成 本節では以下のテンプレートとプロトコル情報(ポート番号・パケットフォーマット定義)・Spicyファイルを利用して、evtファイルの作成方法を紹介します。evtファイルでは解析したいプロトコルを指定します。 protocol analyzer spicy::MYPROTOCOL over UDP: parse with MYPROTOCOL::Message, port PORT_NUMBER/udp; import MYPROTOCOL; on MYPROTOCOL::Message -> event MYPROTOCOL::message($conn, self.PROTOCOL_FIELD1, ...); 例えば、以下のようにプロトコルのポート番号(1111)、プロトコル名(protocol_name)、Zeekに渡したいプロトコルフィールド(header1、header2など)を記述します。 protocol analyzer spicy::protocol_name over UDP: parse with protocol_name::Message, port 1111/udp; import protocol_name; on protocol_name::Message -> event protocol_name::message($conn, self.header1, self.header2, ...); evtファイルを作成後、コンパイルしてオブジェクトファイルであるhtloファイルを生成します。 ~$ spicyz -o test.hlto test.spicy test.evt ~$ # test.hltoが生成される 5. Zeekファイルを作成 最後に、以下のテンプレートを利用して、Zeekファイルの作成方法を紹介します。Zeekファイルでは、Spicyの処理結果をログに出力します。 # Spicy側のパーサーを利用するための宣言 module MYPROTOCOL; # 実行開始前に必要な変数の宣言(global変数) export { redef enum Log::ID += { LOG }; # この変数の内容はlogに書き出す type Info: record { ts: time &log; uid: string &log; id: conn_id &log; ## MYPROTOCOL data. PROTOCOL_FIELD1: string &log; ## MYPROTOCOL data. PROTOCOL_FIELD2: string &log; ## MYPROTOCOL data. PROTOCOL_FIELD3: string &log; ... ... final_block: count &optional; done: bool &default=F; }; global log_myprotocol: event(rec: Info); } global expected_data_conns: table[addr, port, addr] of Info; redef record connection += { myprotocol: Info &optional; }; # $pathで出力ファイル名を指定する event zeek_init() &priority=5 { Log::create_stream(MYPROTOCOL::LOG, [$columns = Info, $ev = log_myprotocol, $path="myprotocol"]); } # logに書き出す時の動作を書く関数 event MYPROTOCOL::message(c: connection, PROTOCOL_FIELD1: string, PROTOCOL_FIELD2: string, PROTOCOL_FIELD3: string, ... ) { local info: Info; info$ts = network_time(); info$uid = c$uid; info$id = c$id; info$PROTOCOL_FIELD1 = PROTOCOL_FIELD1; info$PROTOCOL_FIELD2 = PROTOCOL_FIELD2; info$PROTOCOL_FIELD3 = PROTOCOL_FIELD3; ... ... c$myprotocol = info; # info内の変数を全部logに書き出す Log::write(MYPROTOCOL::LOG, info); } テンプレートの各部分を解説します。 module MYPROTOCOL; :Spciyで作成したパーサーをインポートするために宣言 export {…}; :Zeekで利用する変数の宣言 ログに出力したい項目はここで指定します。 event zeek_init() &priority=5 {…} :出力ログのパスを指定 event MYPROTOCOL::message(…) {…} :パーサーの処理結果をログに出力 ログに出力するタイミングで加工することもできます。 上記のテンプレートと今までの結果を利用し、プロトコル名(protocol_name)、出力したいフィールド(header1など)、出力したいログファイルの名前($path="protocol_name")を書き換えることで、以下のようなZeekファイルを作成できます。 # Spicy側のパーサーを利用するための宣言 module protocol_name; # 実行開始前に必要な変数の宣言(global変数) export { redef enum Log::ID += { LOG }; # この変数の内容はlogに書き出す type Info: record { ts: time &log; uid: string &log; id: conn_id &log; ## MYPROTOCOL data. header1: string &log; ## MYPROTOCOL data. header2: string &log; final_block: count &optional; done: bool &default=F; }; global log_protocol_name: event(rec: Info); } global expected_data_conns: table[addr, port, addr] of Info; redef record connection += { protocol_name: Info &optional; }; # $pathで出力ファイル名を指定する event zeek_init() &priority=5 { Log::create_stream(protocol_name::LOG, [$columns = Info, $ev = log_protocol_name, $path="protocol_name"]); } # logに書き出す時の動作を書く関数 event protocol_name::message(c: connection, header1: string, header2: string ) { local info: Info; info$ts = network_time(); info$uid = c$uid; info$id = c$id; info$header1 = header1; info$header2 = header2; c$protocol_name = info; # info内の変数を全部logに書き出す Log::write(protocol_name::LOG, info); } 6. テスト用Pcapで出力ログの確認 最後にテスト用Pcapを使って出力ログを確認します。 ~$ zeek -Cr cclink_ief_basic.pcap test.hlto test.zeek ~$ # protocol_name.logが生成される 生成されたログの中身を確認すると、以下のようになっています。最後の16進数の部分( P\x00 \x00 など)は今回出力したい部分です。今回は16進数のデータを出力しただけですが、Zeekファイルを作り込むことで人間が解釈できる文字列として出力もできます。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path protocol_name #open 2023-06-12-15-53-06 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p header1 header2 #types time string addr port addr port string string 1655284124.859924 C3KZkP3l8QTJaS2vg7 172.16.134.128 61450 172.16.134.255 61450 P\x00 \x00 1655284124.953994 CG3NWX3t9Qf1Xrezl5 172.16.134.129 61450 172.16.134.128 61450 \xd0\x00 \x00 1655284125.375608 C3KZkP3l8QTJaS2vg7 172.16.134.128 61450 172.16.134.255 61450 P\x00 \x00 1655284125.484180 CG3NWX3t9Qf1Xrezl5 172.16.134.129 61450 172.16.134.128 61450 \xd0\x00 \x00 1655284125.500485 C3KZkP3l8QTJaS2vg7 172.16.134.128 61450 172.16.134.255 61450 P\x00 \x00 1655284125.610011 CG3NWX3t9Qf1Xrezl5 172.16.134.129 61450 172.16.134.128 61450 \xd0\x00 \x00 ... ... Zeek・Spicyの活用例 ここまで、Zeek, Spicyの使い方まで紹介しました。本章ではイメージを深めるため、OsecTで実装したZeekが対応していないプロトコルの追加と、Zeekの基本ログへの情報追加の2つの例を紹介します。 CC-Linkファミリーへの対応 今回は市場ニーズを踏まえた上で、Zeekが対応していないOTプロトコル( CC-Linkファミリー )に対応しました。具体的なプロトコルはCC-Link IE FieldとCC-Link IE ControlとCC-Link IE Field Basicです。実装したコードは公開しているため、興味がある方は以下のリンクを参照ください。 zeek-parser-CCLinkFieldBasic zeek-parser-CCLinkField-CCLinkControl CC-Link IE Field Basicの出力ログは以下のようになっています。ペイロードの奥深くまで情報を取得することもできますが、今回はパケットの種類(cyclicDataRes、cyclicDataReq)と使っているコマンド(cyclic)をログに出力しました。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path cclink-ief-basic #open 2023-05-27-00-52-06 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p pdu cmd number ts_end #types time string addr port addr port string string int time 1655284124.953994 CIAp8bugKIZRVpAYk 172.16.134.129 61450 172.16.134.128 61450 cyclicDataRes - 222 1655284149.499713 1655284124.859924 Ckkc3929guO41BnpSa 172.16.134.128 61450 172.16.134.255 61450 cyclicDataReq cyclic 222 1655284149.392238 #close 2023-05-27-00-52-06 CC-Link IE FieldとCC-Link IE Controlの出力ログは以下のようになっています。ここではパケットの種類(select、scanなど)と種類別の情報(0x0001など)をログに出力しました。今回はテスト用Pcapを自作したため、全て 0x0001 になっています。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path cclink-ie #open 2023-03-15-16-56-36 #fields ts src_mac dst_mac service pdu_type cmd node_type node_id connection_info src_node_number number ts_end #types time string string string string string string int string string int time 1667903833.066101 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control select - - - - 0x0001 61 1667903833.134207 1667903833.065821 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control scan - - - - 0x0001 48 1667903833.129023 1667903833.064742 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control connectAck - - - - 0x0001 61 1667903833.133590 1667903833.065511 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control connect - - - - 0x0001 62 1667903833.134085 1667903833.067818 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control nTNTest - - - - 0x0001 53 1667903833.131018 1667903833.068939 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control dummy - - - - 0x0001 57 1667903833.133957 1667903833.065083 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control collect - - - - 0x0001 61 1667903833.133231 1667903833.064936 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control launch - - - - 0x0001 40 1667903833.132990 1667903833.066240 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control token - - - - 0x0001 57 1667903833.133351 #close 2023-03-15-16-56-36 Zeekの基本ログへの情報追加 DHCPv4はZeekが対応しているプロトコルですが、出力されるログの情報量に過不足がありました。そのため、Zeek, Spicyを利用して必要のない情報を削除・必要な情報を追加しました。実装したコードは公開しているため、興味がある方は MYDHCP を参照ください。 デフォルトの出力ログは以下のようになっています。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path dhcp #open 2023-06-16-18-23-59 #fields ts uids client_addr server_addr mac host_name client_fqdn domain requested_addr assigned_addr lease_time client_message server_message msg_types duration #types time set[string] addr addr string string string string addr addr interval string string vector[string] interval 1624301983.013489 Cah1vz3icJOQ3kUtk4,C6uWeo2ldOmwsjKUj7 10.0.2.15 10.0.2.2 00:00:20:b0:60:b0 kali - - 10.0.2.15 10.0.2.15 86400.000000 - - REQUEST,ACK 0.000309 #close 2023-06-16-18-23-59 そして、Zeek, Spicyによって改造後のログは以下のように変更しました。本来のログのMACアドレスとタイムスタンプをそのまま利用し、 SrcIP,Hostname,Parameter,ListClassId を追加しました。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path mydhcp #open 2023-06-16-18-23-59 #fields ts SrcIP SrcMAC Hostname ParameterList ClassId #types time addr string string vector[count] string 1624301983.013489 0.0.0.0 00:00:20:b0:60:b0 kali 1,2,6,12,15,26,28,121,3,33,40,41,42,119,249,252,17 - #close 2023-06-16-18-23-59 おわりに 今回はZeekとSpicyの概要及び使い方・利用例について紹介しました。この記事を参考に、プロトコルのパーサーを実装、ログ出力までできるようになれば幸いです。そして、Zeek, Spicyの活用例の章で紹介したスクリプトはすでにOsecTへ実装しリリース済です。OsecTもこれからZeek, Spicyを利用し、対応プロトコルの拡張などを続けていくので、興味を持たれた方はぜひご連絡ください。
はじめに こんにちは、イノベーションセンターの藤田、鈴ヶ嶺です。NTTコミュニケーションズ株式会社 (以下、NTT Com) は、世界最大級のネットワーク展示会である 「Interop Tokyo 2023(会場:幕張メッセ、会期:2023年6月14日〜16日)」 において構築されるShowNetに対し、コントリビューターとしてローカル5G(以下、L5G)システムを提供しました。その基盤としてAWS Outpostsサーバーを構築し提供しました。 本記事ではその構成や技術的な挑戦について解説します。 AWS Outpostsサーバーを用いたL5G基盤構築への挑戦 今回ShowNetにてL5G基盤をAWS Outposts サーバーを用いて構築するにあたり、2点の挑戦をしました。 Flexible InterConnectを利用したハイブリッドクラウドネットワーク EKS x EC2セルフマネージド型ノード on AWS Outpostsサーバー基盤 Flexible Inter Connectを利用したハイブリッドクラウドネットワーク 今回会場では、NTTドコモのキャリア 5G とNTT ComのL5G を組み合わせた環境で、ネットワークスライシング連携のデモンストレーションを構築・展示しています。その構築・展示に当たり、NTT Com内製のマイクロサービス開発フレームワーク Qmonus を活用しました。 このデモンストレーションを実現するためには、AWS Outposts サーバーをはじめとするオンプレミスと、Public Cloud (Public AWS) 間を安定して接続する必要があります。 本構築ではFlexible InterConnect、FIC-Connection AWSを利用することで、AWS OutpostsサーバーほかオンプレミスとPublic AWSに対して専用回線による安定した接続が可能なネットワークを実現しました。 EKS x EC2セルフマネージド型ノード on AWS Outpostsサーバー基盤 AWS OutpostsサーバーをL5G基盤として利用するにあたり、構築可能なEC2インスタンスタイプの制限があるため柔軟なリソース配分がしづらい問題がありました。 今回の構成ではより柔軟かつ可用性の高い基盤提供を目指し、Public AWSにてEKSクラスターを構築しAWS Outpostsサーバー上のEC2インスタンスをEKSのセルフマネージド型ノードとして動作する構成に挑戦をしています。 AWS Outpostsサーバー上のEC2インスタンスは同一VPC上に構築されたPublic AWS上のEC2インスタンスやEKSクラスターと疎通可能であるため、EKSの機能を利用しつつAWS Outpostsサーバーの機能であるLocal Network Interface(以下、LNI)を通じたpodレベルでのオンプレミスのネットワークとの接続を実現しています。 本構成によりAWSのマネージドなサービスをオンプレミスまで拡張することで、オンプレミスのネットワークと統合しつつ柔軟なリソース配分が可能となる可用性の高い基盤の提供に成功しています。 発見した課題 L5GのUPFをAWS Outpostsサーバー上に構築するにあたり、モバイル特有の処理を高速化する観点から1つのpodに対してLNI経由で複数のインターフェースをアタッチしDPDK経由で複数のVLANを接続をする挑戦も行いました。 しかしLNIはPromiscuous modeをサポートしていないため、macvlanによるNICの仮想化ができません。 1 またENA Poll Mode DriverはVLANをサポートしていないため、tagged vlanを利用できません。 2 以上から、本構成においてDPDK経由で複数のvlanを利用する高速化が困難であるといった課題が発見されました。 まとめ 本記事ではInterop Tokyo 2023のShowNetにおいて、L5G基盤に利用したAWS Outpostsサーバーの構成について紹介しました。本構成ではいくつか課題も見つかったため、それを踏まえてより柔軟性が高く可用性の高い基盤の提供を目指していくと共に、NTT Comのサービスへの応用について検討していきます。 https://docs.aws.amazon.com/outposts/latest/server-userguide/local-network-interface.html ↩ https://doc.dpdk.org/guides/nics/ena.html ↩
NTTコミュニケーションズ(以下、NTT Com)を含めたドコモグループではこの夏に3種類のインターンシップを開催します! ビジネス創造インターンシップ ドコモハッカソン 現場受け入れ型インターンシップ このうち、この記事ではNTT Comのリアルな業務を体験できる「現場受け入れ型インターンシップ」について紹介します。 現場受け入れ型インターンシップとは NTTドコモやNTT Comの社員と一緒に働きながら、実務を体験していただくインターンシップです。 セールスやビジネスデザイン、エンジニア、デザイナー、リーガルなど幅広い職種を取り揃えて、業務体験を通じて仕事の理解を深め、成長機会を提供する内容となっています。 今季は2023年8月28日(月)~9月8日(金)の土日祝を除く平日10日間(2weeks)で開催されます。開催場所は、出社+リモートワークのハイブリッド形式です(出社割合はポストにより異なります)。 募集ポスト 募集ポストについては下記のページの「受け入れポスト情報」をご覧ください。 information.nttdocomo-fresh.jp 記載されているポストのうち、受け入れ会社に NTTコミュニケーションズ株式会社 と記載されたポストがNTT Comでの業務です。 ポスト一覧表をこの記事の 末尾 にも掲載したので参考にしてください。 これまでのインターンシップの様子 これまで開催したインターンシップでNTT Comのエンジニア系ポストに参加してくれた学生の方々がこのEngineers' Blogに体験記を寄稿してくれています。 なお、NTT Comのデザイン系ポスト(KOEL)については KOEL公式note 、NTTドコモのエンジニア系ポストについては ドコモ開発者ブログ をご覧ください。 「インターンシップでどんなことに取り組むのだろう?」、「インターンシップを通して何が学べるのだろう?」といった疑問を解消する手助けになれば幸いです。 AI分野 engineers.ntt.com セキュリティ分野 engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com ネットワーク分野 engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com ソフトウェア/クラウド分野 engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com まとめ みなさんもこの夏、ドコモのインターンシップに参加して、興味分野で圧倒的成長をしてみませんか? 気になるポストの詳細やエントリーはこちらです(再掲)。 information.nttdocomo-fresh.jp エントリー締め切りは 6月30日(金)23:59 です。 みなさんのご応募をお待ちしています! 参考:ポスト一覧表 各ポストの詳細については、 現場受け入れ型インターンシップ をご覧ください。 カラムの説明 ポスト:ポスト名 受入:受け入れ会社( D =NTTドコモ、 C =NTT Com) 参考:参考情報 ビジネスデザイン(通信) ポスト 受入 参考 1.ドコモオンラインショップ/オンライン手続きの運用、 データ分析、販売促進施策企画、WEB広告運用業務 D 2.ahamoのモバイルサービスサイト・アプリのUI/UX戦略の企画/開発/運用/分析/改善 D ネットワークデザイン ポスト 受入 参考 3.ドコモビジネスを実現するNW装置の開発・検証を行うエンジニア D - ドコモビジネス - Arcstar Universal Oneイーサネット専用線 セールス(スマートライフ) ポスト 受入 参考 4.dポイント・d払い既存加盟店へのデジタルマーケティングを活用した販売促進支援 D ビジネスデザイン(スマートライフ) ポスト 受入 参考 5.自治体に向けた新たなヘルスケアサービスの企画とセールス統括を担うプロダクトマネージャー D - 健康マイレージ 6.クレジットカードサービス/dカードにおけるサービス戦略・企画 D - Theo+docomo×dカート積立投資 7.映像配信メディア「Lemino」向けオリジナルコンテンツの制作業務 D - 「Lemino」サービスサイト 8.dポイントクラブ会員基盤の拡大、及び新たな価値創出/サービスグロース検討 D - カボニューレコード プロダクト・サービスエンジニア ポスト 受入 参考 9.新デバイス・サービスの企画・開発 D セールス(法人) ポスト 受入 参考 10.法人のお客さまへの営業活動 C ビジネスデザイン(法人) ポスト 受入 参考 11.新サービスやビジネスの企画/プロモーション施策の立案 C - Smart Go / SmartGo Staple - OPEN HUB ソリューションエンジニア ポスト 受入 参考 12.法人のお客さま向けの新サービスの開発 C 13.法人向けのICTソリューション提供 C 14.次世代ネットワークサービスのソフトウェアエンジニア C - OCNにネットワークコントローラ入れてみたよ 15.次世代ネットワークサービスのセキュリティ機能開発 C 16.サイバー攻撃からお客さまを守るマネージドセキュリティサービスのサービス戦略/企画/マーケティング業務や、実際のお客さまへのセキュリティコンサルティング業務 C 17.オンライン英会話・オンライン医療などのビデオ通話を実現するプラットフォームサービス「SkyWay」の技術開発 C - SkyWay 先端研究開発(AI・データサイエンス) ポスト 受入 参考 18.機械翻訳/語学学習に関わる言語処理AIの研究開発 D 19.パブリッククラウドを活用した超大規模データ処理・分析環境開発 D 20.新しい画像認識技術の実用化開発および画像認識技術を活用したソリューション創出 D 21.FinTech領域における新規データ分析手法の検討業務 D 22.データ分析アプローチで全社・現場の課題を解決し、DXを推進(主にOSSを用いた分析システム) C 23.データ分析アプローチで全社・現場の課題を解決し、DXを推進(主にサービス開発組織の分析) C 24.データ分析アプローチで全社・現場の課題を解決し、DXを推進(主にセールス部門向け(大企業・中小企業担当)の分析) C 25.お客さまに具体的な価値を提供するAIテキスト分析プロダクトの開発 C 先端研究開発(ソフトウェア・セキュリティ) ポスト 受入 参考 26.大規模にクラウドを利用するドコモのCCoE(Cloud Center of Excellence)エンジニア D 27.エンタープライズ向け大規模クラウド/ネットワークサービスを支えるコントローラ開発 C - DSIGW - FRA - FIG - 2021 Cloud Meetup Egawa 「入社してから今までのお話」 - SDPFクラウド/サーバー ESIチームにおけるCI改善の取り組み - クラウドサービスのウラオモテ - Managed Load Balancer のつくりかた 28.エンタープライズ向け大規模クラウドサービス(仮想サーバー)のソフトウェア開発 C - Open TechLunch: 元ウェブ系エンジニアが語る IaaS(VM屋さん)の開発ってなにしてんの? - CODT2022: エンタープライズ向けクラウドサービス 仮想サーバー基盤開発のリリースサイクル改善 - CODT2021: エンタープライズ向けクラウドサービスにおける大規模・商用環境でのホストOSバージョンアップ - CODT2020: エンタープライズ向けクラウドサービスにおける大規模・商用環境でのOpenStackバージョンアップとVMHAの実運用 29.エンタープライズ向け大規模クラウド/ネットワークサービスを支える共通機能のソフトウェア開発 C 30.エンタープライズ向け大規模クラウドサービスのコントローラにおけるSRE推進のためのクラウドネイティブな共通基盤開発・運用 C - Blue-Green デプロイメントを採用したデプロイの仕組みを実装して共通基盤として導入した話 31.仮想アプライアンス専用基盤に関わる仮想サーバ技術開発 C 32.NTTグループ向けDevOps基盤「Qmonus」の内製開発および導入支援 C - OCNにネットワークコントローラ入れてみたよ - Cloud Native環境におけるエンタープライズシステムに対する高可用性実現への取り組み - DevOpsプラットフォームの取り組み, NTTコミュニケーションズ(NTTドコモの法人事業) エンジニアズブログ 33.CSIRTでのサイバー攻撃への対応実践と高度化 C 34.Webアプリケーションの脆弱性診断実践 C 35.テレプレゼンス(遠隔操作ロボット)の研究開発 C - テレプレゼンスPJ インターン参加レポート - 63. テレプレゼンス・ロボット・最後にRust w/ nakakura, kmat - みんなの夢を叶える「走るコタツ」を作ってみた - NTT Com、ロボットやカーボンクレジットなど先進ICTサービスを披露 36.データ分析基盤エンジニア C 38.サイバー攻撃の原理を理解し、攻撃インフラ(マルウェアインフラ)を解明するセキュリティアナリスト C - アクセスログ解析サービスVisionalistで利用していたドメイン(tracer[.]jp)の脅威分析と注意喚起 - 本当にあったドロップキャッチの怖い話 〜Visionalistの場合〜 (InternetWeek 2022) - サイバー脅威インテリジェンス(CTI)配信はじめました - インターンシップ体験記 〜Cobalt StrikeのC2サーバ追跡〜 41.Webアプリケーションソフトウェアエンジニアとして、コミュニケーションサービスの新機能開発 C - NeWork 先端研究開発(ネットワーク・デバイス) ポスト 受入 参考 42.5Gデバイス観点から5G NW運用を解明する無線通信スペシャリスト D 43.人間拡張技術を用いた体験共有に関する評価 D - 離れていても触れられる。「フィールテック™」が未来のコミュニケーションを変える。 - 6Gの時代に向けて挑む、「スキルをダウンロードする」技術とは。 44.6Gユースケース、要求条件、要素技術検討 D - ドコモの標準化への取組み 45.HAPS実用化に向けた技術検討 D - 世界初、成層圏下層から38GHz帯の電波伝搬実験に成功 - エアバス、NTT、ドコモ、スカパーJSATの4社がHAPSの早期実用化に向けた研究開発などの推進を検討する覚書を締結 - 未来を考える研究開発で、“世界のあたりまえ”を変える 46.携帯電話基地局などからの電波の測定技術検討 D - ドコモの電波の安全性に関する取組み - (お知らせ)国内初、マンホール型基地局の試作機を開発 - モバイル基地局環境における電波強度評価法 47.All Photonics Networkのための次世代光伝送ネットワークインフラおよびサービス開発エンジニア C 48.エンタープライズ向け大規模クラウドサービスを支えるネットワーク開発 C - OpenTech Lunch: クラウドの作り方(使い方じゃないよ) - EVPN Anycast Gateway を商用導入した話 - JANOG: エンタープライズ向けクラウドのSDN基盤の安定化への挑戦 - CNTOM: NFVサービスの 試験自動化とCI/CD 49.5G・IoTおよびIOWNを支えるNW基盤開発エンジニア C 50.ローカル5G無線(RAN), コア(5GC), トランスポートネットワーク(TN)の技術検証 C - Interop Tokyo 2022 〜400G-ZRを用いたイーサネット回線とローカル5G検証・展示のご紹介〜 リーガル ポスト 受入 参考 51.企業経営を支える法務業務 D/C
はじめに こんにちは、イノベーションセンターの内藤です。NTTコミュニケーションズ株式会社 (以下、NTT Com) は、世界最大級のネットワーク展示会である 「Interop Tokyo 2023(会場:幕張メッセ、会期:2023年6月14日〜16日)」 において構築されるShowNet 1 に対しコントリビューターとしてローカル5G(以下、L5G)システムを提供し、実機運用することに成功しました。 昨年 2 に引き続き、今年はより高度なマルチベンダーでの5Gコア/RAN端末の相互接続やネットワークスライシングにチャレンジ。実験試験局の免許も取得して無線区間をOTA 3 とし、End-to-Endでアプリケーションのトラフィック流通を実現しました。 本記事ではその構成やスライシング手法、技術的なチャレンジについて解説します。 マルチベンダーによるEnd to Endスライシング 私たちは、ユーザーの要求に応じてネットワークやエッジコンピューティング環境といったリソースを柔軟に提供することを目標としています。 それを達成するには、ユーザーやアプリケーション単位での細かい粒度で品質の異なるNW経路を提供する、ネットワークスライシング技術が必要になります。 ネットワークスライシングの説明は昨年の記事が参考になります。今回は詳細記載を省略します。 NTT ComではShowNetにて、昨年に引き続きマルチベンダーによる基地局(gNB)から5Gコアの先のData Network (N6) を含めたEnd to Endスライシングの実現にチャレンジしました。 下図が構成となります。順番に解説していきます。 スライシングに関する昨年からのアップデートは以下3点です。 1.マルチベンダーでのスライシングにチャレンジ Capgemini Engineering ViNGCは、Kubernetes/OpenShiftで動作する5GCであり、各Functionは1つ以上のPodとして構成されます。 C/U分離が可能であることから、UPFはKaloom UPFを使用します。Kaloom UPFはOpenShift上で動作するUPFであり、Edgecore Networks社のホワイトボックススイッチ上で動作します。 LeafとUPFからなる1つのクラスタで、複数の仮想UPFを動作させることが可能です。 ネットワークスライシングの手法は多数あり、昨年はS-NSSAIを用いた手法を実施しました。今回はマルチベンダーで相互接続をする観点から、インターオペラビリティの成熟度も探りつつ、仮想UPFを3台構成し、それぞれのN6に異なるDNN 4 を設定する方式を採用しました。DNNに紐ついたバックボーンネットワークは異なる品質設定がされており、UEではDNNを切り替えることで通過するネットワークの変更ができます。これをDNNスライスと定義しました。 2.5GCの設置場所としてMECを想定し、実サービスであるSDPF Edge 5 と連携 SDPF Edgeは任意のVM+アプリケーションをクラウド上の管理コンポーネントからZTPし、ユーザ拠点で起動できるサービスです。ViNGCの起動にはリソースが多く必要だったため、まだ商用ラインナップにはない高リソースMECをカスタマイズして作成し、Kubernetesを起動。5GCを構築しました。 3.自社開発のオーケストレーターであるQmonusを利用し設定自動化を実現 ViNGCに対して加入者データの投入やスライス作成/削除は、単体のAPI実行で完結するものではなく、複数のAPIを直列に、かつ5GC/UPF/バックボーン機器それぞれに対して操作が必要​となります。 NTT Com内製のマイクロサービス開発フレームワーク「Qmonus SDK」のトランザクション機能を用いて、システムを跨いだオーケストレーションスコープの一貫性を担保できます。トランザクションの状態と進行状況はフレームワークで管理されており、処理失敗時にはトランザクションの進捗状況に合わせて、各システムに対して最適な打ち消し処理を実行できます。 Qmonusを用いることでAPIによるデータ投入を実現しました。 なお、今回私たちはAWS Outposts ServerについてもShowNetにコントリビュートし、その上にNTTドコモの5GCを構築しました。この5GCについてもQmonusとの連携を実現しています。NTTドコモのコントリビューション部分については、NTTドコモのENGINEERING BLOG 6 をご覧ください。 実験試験局の運用 昨年のShowNetではUE – RU – CU/DUの無線区間はエミュレートしましたが、今年は免許申請を行い、電波を発波する実験試験局を運用しました。NTT Comには無線従事者免許を保有しているエンジニアが多数在籍しています。遵法し適切に電波を使用できるよう、輪番を組んで運用しました。 gNB装置は昨今登場した「RU/CU/DU一体型」を特徴とするものを採用。Airspan社のAirSpeed 1900を幕張メッセのhall6に設置しました。Interop準備期間中、遮蔽物が少なく、同時接続するUEの数も少ない好条件では期待以上の速度(DL790Mbps)が観測できたことも。 IoT Connect Gatewayとの接続 私たちはL5Gとその他サービスの組み合わせによる新しいユースケースの発掘にも日々挑戦しており、今回はN6に接続するサービスとしてIoT Connect Gateway(以下、ICGW)を選択しました。 ICGWは、IoTデバイスの通信をクラウド側でプロトコル変換(暗号化など)することでお客様の開発・運用コストを削減できるサービスです。 今回はCO2センサを会場に複数設置し、L5Gを介しICGWに接続。データの可視化を行いました。 ICGWはNTT Comが提供するSDP 7 サービスのひとつであり、今後も他のSDPサービスとL5Gとの連携を狙っていきます。 おわりに この記事ではInterop Tokyo 2023(会場:幕張メッセ、会期:2023年6月14日〜16日)において構築されたShowNetについて、L5GのマルチベンダーによるEnd to Endスライシングなどを紹介をしました。今後は、今回のフィールドテストの成果を踏まえより多種多様なユースケースに対応できるネットワークスライシングの方式や、UE/RU/CU/DU/5GC/UPE構成のベストプラクティスとなる提供方法を探り、NTT Comのネットワークサービスへの応用について検討していきます。 なお、私たちのチームはインターン 8 も募集しています。一緒にL5Gの高度化に取り組んでくれる仲間を募集しています。 ぜひご検討ください。 ShowNet: Interop Tokyoにおいて、様々な機器・サービスの相互接続性検証を実施するとともに、近未来のサービスアーキテクチャを実際に動かしている形で見ることができる世界最大規模のライブネットワークデモンストレーションです。Interop Tokyoへの出展社がインターネットへの接続性を利用して製品の動態展示のほか、来場者のインターネットへのアクセスとしても利用されるネットワーク。 https://www.interop.jp/2023/shownet/ ↩ 昨年: ShowNet2022でも我々はネットワークスライシングの取り組みを実施しました。 https://engineers.ntt.com/entry/2022/06/15/090043 ↩ OTA: Over The Airの略。データの送受信を無線通信で行う技術をさします。 ↩ DNN: Data Network Nameの略。5Gにおいて、UPFのN6以降のネットワークをさします。 ↩ SDPF Edge: NTT Comが提供中のMEC(Multi-access Edge Computing)サービスです。 https://www.ntt.com/business/sdpf/service/edge.html ↩ ENGINEERING BLOG: https://nttdocomo-developers.jp/ ↩ SDP: データ利活用に必要な機能をワンストップで提供するNTT Comのアーキテクチャです。 https://www.ntt.com/business/sdpf/about.html ↩ インターン: 「先端研究開発(ネットワーク・デバイス)」分野の「ローカル5G無線(RAN), コア(5GC), トランスポートネットワーク(TN)の技術検証」が私のチームです。 https://information.nttdocomo-fresh.jp/event/on-site-internship/ ↩
目次 はじめに 開発背景 機能紹介 実際に使ってみた ストレージ転送機能のセットアップ SSH一括実行機能のセットアップ SSH一括実行機能の動作確認 おわりに はじめに こんにちは、5G & IoT部/IoTサービス部門のIoT Connect Gateway (ICGW)サービス開発チームの岩田です。 我々のチームでは日頃からインキュベーション開発というものに取り組んでおります。 インキュベーション開発では、近い将来の需要や新規分野への展開を見据えた機能を実証実験的に開発し、実際に需要が上がった際に迅速に機能を商用展開することを目的としています。 本記事では、インキュベーション開発として実装されて機能の1つである SSH一括実行機能 を紹介します。 開発背景 ICGWでは2022年12月から リモートアクセス という機能の提供を開始しました。 リモートアクセス機能では、お客様の必要な時にセキュアなリモートアクセス用の経路をオンデマンドで提供します。 この機能を活用することで、お客様拠点や外出先から遠隔地の各デバイスにアクセスし、遠隔監視や設定変更などのメンテナンスを行うことができます。 ICGWを利用可能なSIMを装着したデバイスであれば、デバイス側に特別な設定をする必要はなく、SSH接続を含めた任意のデバイスポートにアクセスできます。 また、リモートアクセス経路を作成する際に、デバイスへアクセス可能なソースIPを制限できるのでセキュアな経路を確保できます。 利用料金に関しては、使用した月にのみ料金が発生する課金方式をとっているため、必要な時にだけ最低限のコストでご利用いただけます。 図1 リモートアクセス機能の概要図 リモートアクセス機能をさらに活用していく上で「あるデバイスでの設定変更やアップデートを他のデバイスにも同様に行いたい」というケースが想定できます。 例えば、各デバイスに蓄積されたログファイルを定期的に一括で取得したい・該当のモジュールやファームを一括で更新したい・最新の設定ファイルを各デバイスに配布したい、といったケースが考えられます。 デバイスの数が少ないうちは運用者が逐一接続して作業できますが、デバイスが増えるほど困難を伴います。 この課題を解決するために開発された機能がSSH一括実行機能になります。 機能紹介 図2 SSH一括実行機能の概要図 SSH一括実行機能は「特定のデバイスグループに対してSSH接続し、ユーザ定義したスクリプトを実行する機能」です。 利用の流れは以下のようになります。 SSHグループの設定 手動でSSH一括実行をトリガー リザルト画面で結果を確認 ステップ1では、一括実行対象のSIMや実行するスクリプトを登録します。 SSH接続では鍵認証方式を利用するため、鍵情報やログインユーザなどのセットアップも行います。 ステップ3では、実際にデバイス上で実行されたコマンドの結果をリザルト画面から確認できます。ログテキストやexitコードといった詳細情報を提供しています。 実際に使ってみた 今回は「各デバイスに蓄積されたファイルを一括でAmazon S3に送信する」というケースを例にとって、SSH一括実行機能を紹介します。 図3 各デバイスのファイルを一括でAmazon S3に送信するユースケース ユーザがSSH一括実行機能をトリガー ICGWが各デバイスに対してSSH接続しコマンドを実行 デバイスからICGWに対してストレージ機能を使いファイルを送信 送信されたファイルをAmazon S3へ転送 図3のフローを実装することを目標にセットアップをしていきます。 デバイスとして、Aterm MR10LN とRaspberry Piをそれぞれ2セット用意しました。 Atermには IoT Connect Mobile Type S のSIMを挿入してあります。 図4 AtermとRaspberry Pi 図5 ICGWとデバイス間の接続構成 ストレージ転送機能のセットアップ まず、デバイスからAmazon S3へデータを送信するためのセットアップを行います(図3のステップ3-4)。 デバイスから直接Amazon S3へデータを送信することも可能ですが、今回はデータの暗号化やクラウド接続をサポートできるICGWの ストレージ転送機能 を利用します。 ストレージ転送機能の詳細に関しては 過去の記事 で取り扱っておりますので、そちらもご参照ください。 図6 ストレージ転送機能の設定画面 ストレージ転送機能の設定画面では、ICGW側のデータの受け口である エントリーポイント やデータの転送先である 宛先設定 、付与するデータを設定する必要があります。 今回はICGWのポータルから図6のように設定しました。 ポイントとしては宛先設定のファイルパスを $YYYY-$MM-$DD/$imsi/log.txt とすることで、データ送信時にICGW側で自動的に日時やSIMの固有識別子であるIMSI(International Mobile Subscriber Identity)を埋め込んでくれるようにしています。 そのため、各デバイスから同一のコマンドでファイルを送信しても、Amazon S3上でファイル名が重複しないように転送できます。 デバイスからのファイル送信コマンドとして、以下のコマンドを実行します(ICGWのエントリーポイントは こちら をご参照ください)。 curl -v -X PUT --data-binary @./Documents/test/ssh/sample_log.txt http://***:8081/S3_ssh SSH一括実行機能のセットアップ 次に、ICGWからデバイスへSSH接続するためのセットアップを行います(図3のステップ2)。 以下のコマンドで、 raspberry-pi-zero という名前の公開鍵認証用キーペアの作成し、その公開鍵をRaspberry Piへ転送します。 # キーペア作成 ssh-keygen -t rsa -b 4096 -f raspberry-pi-zero # 公開鍵転送 ssh-copy-id -i ~/.ssh/raspberry-pi-zero.pub user@raspberrypi.local 鍵の準備ができたのちに、ICGWのポータル上でSSH一括実行機能の設定をします。 Secret Key には先ほど作成したキーペアの秘密鍵を、 Command にはストレージ転送機能のセットアップで使用したコマンドをそれぞれ登録します。 今回は2デバイスを対象に実行するので、 SIMs には該当の2SIMを登録しています。 図7 SSH一括実行機能の設定画面 SSH一括実行機能の動作確認 一通りの設定を終えたので、実際にSSH一括実行機能の動作を確認します。 図8 SSH一括実行機能のトップ画面 図8の EXECUTE から手動でトリガーします。 実行が終わったのちに、ICGWのポータル上から各デバイスに対するコマンドの実行ログを確認できます。 図9では Status や Exit Code が表示されていますが、さらに各IMSIを選択することで図10のような詳細な実行ログテキストも確認できます。 図9 SSH一括実行機能のログ画面 図10 SSH一括実行機能のログ詳細画面 ポータル上のログからSSH一括実行機能が問題なく動作していることがわかったので、Amazon S3にファイルが送信されているか確認します。 図11のように日付のフォルダが作成され、その中にIMSI毎のフォルダも作成されました。図12からIMSIのフォルダにはデバイスから送信されたファイルが格納されていることも確認できました。 図11 デバイスからAmason S3へファイルを送信した結果1 図12 デバイスからAmason S3へファイルを送信した結果2 以上で、SSH一括実行機能を活用した「各デバイスに蓄積されたファイルをAmazon S3に一括で送信する」ケースの実装および動作確認を行うことができました。 おわりに 今回はインキュベーション開発物である、SSH一括実行機能を紹介しました。 まだインキュベーション段階ということもあり、本機能は必要最低限のものとなっております。 さらなる機能追加として、定期的に実行できるようなスケジュール機能、デバイスに応じたコマンドを実行できるようなプレースホルダ機能などを検討しております。 皆様の反響次第では近い将来に商用展開できるかも(?)しれないので、ぜひお声をいただけると嬉しいです! 本記事を通して、ICGWに興味を持っていただけたら幸いです! ICGWに関するお問い合わせ先 IoT Connect Gatewayサービス詳細 ICGWに関するお問い合わせ先 トライアル、サービス導入に関するお問い合わせ 資料請求・お問い合わせフォーム 開発チームへのお問い合わせ(お手数ですが@を半角文字に置き換えてください) メールを送る
はじめに 当ポストは、低遅延配信の技術であるWHIP(WebRTC-HTTP Ingestion Protocol)を自分で動かしてみたい方へ向けた記事となります。 WebRTCを利用した配信映像の集信プロトコルであるWHIPは現在Internet-Draftではありますが、配信技術者やWebRTC技術者の注目を得て、実際に動かせる環境が整ってきました。 当ポストでは、WHIPが動く環境を作り、自前のWebRTCスタックをWHIPで使う簡単な方法を紹介します。 とはいえInternet-Draftということもあり、「WebRTCなら聞いたことあるけど、WHIPって何?配信とWebRTCが関係あるの?」という方も多いと思いますので、最初はWHIPの紹介から入りたいと思います。 WHIPとは WHIP は、WebRTCを利用したインジェストのためのHTTPSベースのシグナリングプロトコルです。 インジェストというのは、放送機器からメディアサーバーに映像音声を送信することを言います。 人によっては"アップストリーム"、"打ち上げ"などの方が馴染み深い言葉かもしれません。 つまりWHIPは、誤解を恐れずにいうとRTMPのような配信のアップストリームにWebRTCを使おうといった試みです。 さらにWebRTCは、リアルタイム性を重視した双方向コミュニケーションの技術スタックです。 Webで使えるビデオ通話の技術ですね。 WebRTCの実体は大別して以下の特徴を持ったプロトコルセットです。 リアルタイムメディア伝送のためのワイヤプロトコルのセット メディアストリームを設定・制御するための記述プロトコル(SDP) これらにより、どうやって端末間の通信を確立するか?どうやってパケットをほどき、どうやって映像・音声として解釈するか?といった課題を柔軟に解決しています。 最近はこのリアルタイム性やセッションの自由度などから、大規模配信のメカニズムとしてWebRTCの利用が人気を集めており、いくつかの企業がWebRTCベースのメディア配信ネットワークを展開しています。 さて、WebRTCをアップストリームに利用しようとしたとき、ひとつの課題が浮き上がります。 WebRTCを利用するサービスでは、それぞれが独自にシグナリングプロトコルを開発する必要があるということです。 セッションに必要な情報は用途によって異なるという考え方のため、WebRTCではセッション確立までのプロトコルが規定されていないことが理由です。 ただし放送の場合はメディアを送るためにエンコーダと呼ばれる専用の機器を用いることが多いため、WebRTCを利用したい場合、サービス毎に専用機器へシグナリングプロトコルを実装する必要があります。 そういった背景で立ち上がったのがIETFのWISH(WebRTC Ingest Signaling over HTTPS) WGであり、現在は放送機器からWebRTCメディアサーバーへのセッションを確立するためのシグナリングプロトコルである WebRTC-HTTP ingestion protocol (WHIP) がInternet-Draftとして提案されています。 このWHIPというプロトコルで、どういった順番でHTTPリクエストを出して、どういった内容のHTTPレスポンスを返してね、といったことが決められている訳です。 WHIPを体験してみる WHIPを体験してみるという場合でも、WHIPをこれから実装してみるという場合でも、まずは今実際に動作するソフトウェアのことを知っておくと役に立ちます。 簡単に、WHIPクライアントおよびWHIPサーバーの紹介と動かし方の解説をしたいと思います。 これ以降、配信映像の視聴方法としてブラウザは最新版のGoogle Chromeを推奨します。 simple-whip-server (WHIP server) 手軽に試せるWHIPサーバーは、janus-gatewayを用いた meetecho/simple-whip-server があります。 これはWHIPサーバーのエンドポイントになりつつ、janus-gatewayのAPIを操作してビデオルーム上にWHIPクライアントのメディアを流してくれます。 simple-whip-serverの動作条件としてHTTP, WebSocketを有効にしたjanus-gatewayが必要なので、まずはそのセットアップから解説します。 janus-gatewayのセットアップ WebSocketを有効にしたjanus-gatewayをビルドします。 まず janus-gatewayの依存解決 を参考に、依存環境を整えてください。 今回はREST APIとWebSocket APIを利用するので、最低限必要なのは当該ページのリストの内以下のものになります。 Jansson libconfig libnice OpenSSL libsrtp libmicrohttpd libwebsockets cmake 環境が揃ったら、リポジトリをcloneして autogen.sh を実行します。 $ git clone --depth 1 https://github.com/meetecho/janus-gateway $ cd janus-gateway $ sh autogen.sh すると configure という実行可能なスクリプトが生成されるので、これを実行します。 ここでjanusの関連ファイルのビルド先を --prefix で指定できます。 デフォルトが /opt/janus 以下なので、適当に設定します。 また、 configure を実行したら Makefile が生成され、 make できるようになるので実行します。 $ ./configure --prefix=/usr/local/janus --enable-websockets $ make ここで、 macOSを利用している方のみ 確認していただく内容があります。 src/transports/libjanus_websockets.la というファイルの中身を読んで、 dlname の値を確認します。 # The name that we can dlopen(3). dlname='libjanus_websockets.1.dylib' 上記のように、 libjanus_websockets.<version>.dylib のフォーマットで書き込まれていると思います。 この version の数字を覚えておいて、次は src/janus.c のプリプロセッサを確認します。 以下のようにライブラリの拡張子を指定している場所があります。 #ifdef __MACH__ #define SHLIB_EXT "0.dylib" #else この 0.dylib を先ほど確認した version の数字となるように編集してください。 例えば、 libtool 2.4.7 な私のmacOS環境で生成したファイルは libjanus_websockets.1.dylib となっていたので、以下のようにしておきます。 #ifdef __MACH__ #define SHLIB_EXT "1.dylib" #else 準備ができたら make install と、janus関連の設定ファイルを有効化するために make configs を実行します。 $ make install && make configs このあとクライアント側で映像コーデックにVP8とH.264を利用したいので、設定ファイルを一部修正します。 <prefix>/etc/janus/janus.plugin.videoroom.jcfg を編集し、 room-1234 の中の videocodec の値を vp8,h264 に変更してください。 room-1234: { description = "Demo Room" secret = "adminpwd" publishers = 6 bitrate = 128000 fir_freq = 10 #audiocodec = "opus" videocodec = "vp8,h264" # もともとは"vp8"のみで、コメントアウトされている record = false #rec_dir = "/path/to/recordings-folder" } この状態でjanusを実行して、最終的に以下のようなログが出れば成功です。 $ <prefix>/bin/janus (省略) Loading transport plugin 'libjanus_http.1.dylib'... HTTP transport timer started HTTP webserver started (port 8088, /janus path listener)... JANUS REST (HTTP/HTTPS) transport plugin initialized! このままjanusを実行させておいてください。以降の試験で利用します。 ついでに、別のプロセスでjanusのビデオルームをブラウザで開けるように、janus-gatewayの html ディレクトリ以下にあるデモHTMLをホストしてください。 $ cd html $ python -m http.server 下記URLが開ければ準備完了です。 http://localhost:8000/videoroomtest.html simple-whip-serverのセットアップ 次にWHIPのサーバーとなるsimple-whip-serverを用意します。 Node.jsが必要になります。 $ git clone --depth 1 https://github.com/meetecho/simple-whip-server $ cd simple-whip-server $ npm i これで準備ができました。 REST API, WebSocketが有効なjanus-gatewayのプロセスが立ち上がっていれば、 npm run start を実行すると以下のようなログが出力され、simple-whip-serverが実行されます。 $ npm run start > janus-whip-server@0.0.1 start > DEBUG=whip:*,-whip:debug,janus:*,-janus:debug,-janus:vdebug node src/server.js [1. Janus] Connecting to Janus: { address: 'ws://127.0.0.1:8188' } janus:info Connecting to ws://127.0.0.1:8188 +0ms janus:info Janus WebSocket Client Connected +13ms janus:info Janus session ID is 1549944700292951 +3ms janus:info Janus instance version: 1.1.3 (multistream) +2ms whip:info Connected to Janus: ws://127.0.0.1:8188 +0ms [2. WHIP REST API] WHIP REST API listening on *:7080 WHIP server prototype started! [ 'Janus OK', 'WHIP REST API OK' ] これでWHIPのサーバーサイドは準備できました。 ここまでで、以下の3つのアプリケーションが動作していることを前提として進めます。 janus-gateway janus-gateway/html の静的サーバー simple-whip-server 次に、janusのビデオ会議の部屋を作りつつ、WHIPクライアントが配信するためのリソースを作っておきましょう。 $ curl -H 'Content-Type: application/json' -d '{"id": "abc123", "room": 1234}' http://localhost:7080/whip/create simple-whip-serverが動いているときに http://localhost:7080 を開くことでWHIP配信先の管理ができるのですが、ここで Endpoint ID=abc123 であり VideoRoom=1234 であるエンドポイントが追加されていることを確認できます。 この状態で http://localhost:8000/videoroomtest.html を開いて、Startボタンを押し、ルーム名に 1234 を入力して Join the room ボタンを押すことで、このあとWHIPクライアントから配信した映像を視聴する画面に移ることができます。 WHIPサーバーを立て、WHIPクライアントが配信した映像を視聴する準備が整ったので、以降は三種類のWHIPクライアントを紹介します。 simple-whip-client (WHIP client) WHIPのクライアント、つまりインジェストを行うソフトウェアとして最初に紹介するのは、simple-whip-serverと対になる meetecho/simple-whip-client です。 かなりシンプルな実装であり、自作のWHIPサーバーの細かい検証をしたい場合では一番扱いやすいと思います。 依存環境として、以下が必要になります。 pkg-config GLib libsoup~=2.4 GStreamer>=1.16 gst-plugins-base gst-plugins-bad libsoup~=2.4 について、今libsoupを入れようとすると3系が入るので、2系を明示的にインストールするよう注意してください。 また、3系がシステムデフォルトになっている場合、ビルド時にpkg-configの参照先が2系になるように注意してください。 例えば私の環境では、ビルド時の環境変数 PKG_CONFIG_PATH に /usr/local/libsoup/2.74.2/lib/pkgconfig を追加しました。 simple-whip-clientのセットアップは以下です。 $ git clone --depth 1 https://github.com/meetecho/simple-whip-client $ cd simple-whip-client $ make make だけで whip-client というバイナリが作成されます。 実行する際は、 -A および -V オプションで配信する音声映像としてGStreamerのパイプラインを入力できます。 GST_DEBUG =WARNING ./whip-client -u " http://localhost:7080/whip/endpoint/abc123 " \ -A " audiotestsrc ! audioconvert ! audioresample ! queue ! opusenc ! rtpopuspay pt=100 ssrc=1 ! queue ! application/x-rtp,media=audio,encoding-name=OPUS,payload=100 " \ -V " videotestsrc ! videoconvert ! queue ! vp8enc deadline=1 ! rtpvp8pay pt=96 ssrc=2 ! queue ! application/x-rtp,media=video,encoding-name=VP8,payload=96 " 起動オプションも豊富で、WHIPのInternet-Draftにあるoptionalな実装を無効にしたりできます。 起動オプションはコマンドライン引数なしの実行か、 -h オプションをつけて実行することで確認できます。 GStreamer (WHIP client) ソフトウェアの音声/映像処理によく使われるGStreamerでも、 バージョン1.22 からWHIPがサポートされました。 利用するには、 gst-plugins-rs が必要です。 ここで追加された whipsink を利用すれば、以下のようなパイプラインでgstreamerから映像配信ができます。 gst-launch-1. 0 whipsink name =whip whip-endpoint =" http://localhost:7080/whip/endpoint/abc123 " \ audiotestsrc ! audioconvert ! opusenc ! rtpopuspay pt = 100 ! queue ! " application/x-rtp,media=audio,encoding-name=OPUS,payload=100 " ! whip. \ videotestsrc ! videoconvert ! queue ! vp8enc deadline = 1 ! rtpvp8pay pt = 96 ! queue ! " application/x-rtp,media=video,encoding-name=VP8,payload=96 " ! whip. OBS Studio (WHIP client) OBS Studioでは現在PRのDraftという状況ですが、 Sean-Der/obs-studio でWHIPを使うプラグインが開発されています。 PRは #7926 で、バイナリが欲しい場合は自分でビルドする他、OBS StudioではGitHub Actionsでのビルドが行われているので自身の環境にあったバイナリをArtifactからダウンロードすることもできます。 下記ページの最新のビルドから、Artifactsにアップロードされているファイルをダウンロードできます。 macos-x86_64 のように対応するOS・CPUアーキテクチャがファイル名に記されているので、自分の環境にあったパッケージをダウンロードしてください。 Actions・obsproject/obs-studio 自分でビルドするか、Actionsからダウンロード・インストールしたOBS Studioを利用すると、配信先の設定の選択肢に WHIP があります。 これを選択し、サーバーに http://localhost:7080/whip/endpoint/abc123 を入れることでOBS StudioからWHIPでの配信ができます。 おわりに 当ポストではWHIPのサーバーとしてsimple-whip-serverを、クライアントとしてsimple-whip-client・GStreamer 1.22・OBS Studioを紹介しました。 この記事がWHIPへの興味に繋がったら幸いです。 最後に宣伝をさせてください。 NTT Comには Smart vLive というサービスがあり、実はWebRTCを利用した配信をしています。 インターネット配信におけるWebRTCのリアルタイム性に注目しており、インジェスト側ではなくメディアを配信する側でWebRTCを利用しています。 本ポストでは「なんで配信をWebRTCでしたいの?」という論点を取り上げませんでしたが、Smart vLiveの事例を見ていただくとどんな利用シーンがあるのかイメージしやすいかと思います。 私が個人的に好きな事例はオークション/ライブコマースです。 リアルタイム性がそのまま価値につながる利用シーンの1つだと思います。 オンサイトとリモートの時間的優位性を極力減らしたときにどんな価値が生まれるのか? 未来の当たり前に向かって、技術開発はもちろん、こういった視点での価値創出も一緒に取り組んでくれる仲間をNTT Comでは募集しています。 WebRTC配信技術の開発をしている私のチームの募集ポストは こちら になります。
2023/5/19更新: 本記事のタイトルを「インターンシップ体験記 ~RedTeamでの攻撃技術検証業務~」から「インターンシップ生があるSaaSを用いた未知のC2脅威を実証してみた」に変更しました。内容に変更はありません。 イノベーションセンター RedTeamプロジェクトでは、2月に現場受け入れ型インターンシップを実施しました。 本記事は、本取り組みに参加していただいたインターンシップ生による寄稿となります。 インターンシップ生本人の希望により匿名での投稿とさせていただきます。 ※今回注目したあるSaaSに関する発展的な攻撃テクニック(本記事記載のC2への応用を含む)について、NTTコミュニケーションズ RedTeamとして国内外のカンファレンスへ投稿する予定です。 そのため、本記事では具体的なSaaS名の記載を控えます。 よろしくお願いいたします。 はじめに こんにちは、今回NTTコミュニケーションズのインターンシップに参加させて頂いた者です。 現在大学3年生で、大学ではWebセキュリティ、特にXSSの検知・防御に関する研究をしています。 2023年2月に2週間、RedTeamのメンバーとして業務体験をさせていただきました。 この記事ではインターンシップで行った取り組みについて紹介したいと思います。 概要 今回私は、RedTeamサービスを提供するにあたっての攻撃技術の開発・検証業務を行いました。 今回のインターンシップでは、初日と最終日の2日間を現地にて実施し、他の日程はリモートでの実施でした。 参加に至った経緯 私は元々サイバーセキュリティ分野に興味があり、これまでに脆弱性診断、PSIRT(脆弱性通報対応)、インシデントレスポンス、セキュリティツール開発などのインターンシップに参加しました。 インターンシップに参加する中で特にオフェンシブセキュリティに興味を持ち、RedTeamの業務体験ができるインターンシップを探したところこちらのインターンシップを見つけ、今回応募させていただきました。 また、これまでに参加したインターンシップでは長くとも4、5日という期間でしたが、今回は2週間の現場受け入れ型インターンシップということで、 より実務に近い部分で深くセキュリティエンジニアとしての業務を体験できるという点にも興味がありました。 取り組んだこと RedTeamの受け入れポストの応募要項としては、以下のような記述がありました。(2023年2月16日時点) 攻撃者視点を持ち企業のセキュリティ強化をミッションとするRedTeam ●業務内容 RedTeamサービスに関する攻撃技術の開発・検証を経験していただきます。 ■主な業務内容 MITRE ATT&CKをフレームワークとした攻撃技術の開発・検証 実際のサイバー攻撃と同様の技術を用いた、演習形式の企業セキュリティ対策評価 ■RedteamPJの業務一例 https://engineers.ntt.com/entry/2021/12/09/103248 ●応募要件 【必須】 RedTeamに興味があり、攻撃技術の深堀り、習得する意欲のある方 Pythonを用いたプログラミング経験がある方。 【推奨】 情報、通信、コンピュータ系、セキュリティ専攻学科の方 CTFなどのセキュリティコンテスト入賞経験 ●受け入れ会社 NTTコミュニケーションズ株式会社 ●勤務地 〒108-8118 東京都港区芝浦3-4-1 グランパークタワー 現場受け入れ型インターンシップコース | インターンシップ情報 | NTTドコモ新卒採用 主な業務内容の項にあるように、RedTeamサービスに関する攻撃技術の開発・検証に関する業務を行いました。 一般的にSaaSを悪用したC2の脅威について注意喚起されている事例がありますが、今回はまだ世の中に事例がない、 あるSaaSとそのエージェントの仕組みを悪用したC2のPoC(Proof of Concept: 概念実証)コードを開発しました。 初日に取り組むテーマを2つ提示していただき、興味のあるほうを選ぶという形で今回のテーマを進めていくことになりました。 今回開発したC2について まずC2とは、Command & Controlの略で、攻撃者が対象のホストへ侵入した後にホストと攻撃者の間で通信を確立し、 ネットワーク経由で外部からコマンドによる操作が可能な状態を維持する技術です。 今回注目したSaaSでは公式エージェントが提供されており、SaaS利用者はエージェントをインストールしたホストに対し、 SaaSを介して任意の処理を実行させることができます。 攻撃者がこのSaaSをC2として悪用できる可能性があり、今回はその脅威について調査し、実際に実現可能であるかを検証しました。 このSaaSをC2に利用する攻撃者側のメリットは、「通信先が攻撃者の用意したサーバーなどではなくSaaSとなるため悪性通信の判別が難しい」、 「公式から提供されているエージェント実行ファイルからコマンドを実行するため検知されにくい」という点です。 結果として、実際にC2の仕組みをCLIツールとして実装し、C2通信が可能であることを検証によって確かめられました。 また、Microsoft Defender for Endpoint(MDE)を有効にしたWindows環境下で検証したところ、通信の過程では検知がされないという結果となりました。 実装について 言語はPython3で、 Click というCLIツール用のライブラリを使用して開発しました。 コマンドとしては、以下のような構成で実装しました。 シェルコマンドによる命令実行 エージェントに付属のスクリプトエンジンによる命令実行 ファイルアップロード ファイルダウンロード ログ閲覧機能 ファイルアップロード/ダウンロードは、C2を通じて攻撃者と標的ホスト間でファイルを送受信するための機能です。 この機能は、目的達成に必要なファイルの転送やデータの持ち出しのために利用されることを想定しています。 命令の実行やファイルダウンロード/アップロードはSaaSやそのエージェントの機能を利用して実行し、出力結果をログ閲覧機能から確認するという形式になりました。 攻撃者が悪用する場合の実用性に関する検証 提供されているエージェントはシェルコマンドの実行及び、エージェント自身に付属のスクリプトエンジンで命令を実行できます。 付属のスクリプトエンジンを用いる場合、PowerShell等を使用しないため、 Antimalware Scan Interface (AMSI) による検知を回避できる可能性があります。 実際に悪性ファイルとしてInvoke-Mimikatz.ps1 1 を用い、付属のスクリプトエンジンでの命令実行により配布サイトからファイルダウンロードをする際にAMSIにより検知されるかについて検証しました。 結果的にファイルを保存する時点で検知されましたが、悪性ファイルを配信するURLへの通信という段階では検知がされないということが確かめられました。 企業の業務環境などでは認証プロキシが使用されていることがあります。 これらの環境を想定し、認証プロキシ下でC2通信ができるかについて検証しました。 結果として、現状提供されているエージェントはBASIC認証以外には対応しておらず、Kerberos認証やNTLM認証といった認証プロキシ下で通信させるには工夫が必要であるということがわかりました。 エージェントをサービスとして動作させるためには管理者権限が必要となります。 ユーザ権限下で永続化が可能であるかの検証として、永続化の代表的な手法である Boot or Logon Autostart Execution を検証しました。 Windowsでは、 C:\Users\[Username]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup などに配置したファイルが起動時に自動的に実行されるという機能があります。 ここに、VBScriptで記述したエージェントを起動させるためのスクリプトファイルを配置し、実際に起動時にエージェントが起動することを確かめられました。 PoC全体像 成果報告会について 最終日の前日にセキュリティプロジェクト内で、最終日にはNTTドコモグループ全体で、業務体験を通して得られた成果の報告会を行いました。 特に最終日の成果報告会では、セキュリティエンジニアのポストとして参加したインターン生以外に、ソフトウェアエンジニア、 ネットワークエンジニア、AIエンジニア、ビジネス企画、マーケティング、デザイナーなど様々な部署でのインターン生の成果発表を聞くことができました。 そのため、同年代の様々な就活生の取り組みや、他分野での業務イメージなどが掴めて良い経験となりました。 感想 自分の興味のある部分や実装していく中で思いついた提案などを元に、自由に開発や検証を進めさせていただいたため、インターンシップ期間を通して非常に多くのことが学べました。 業務を行うにあたって、学生が普段触れることのできないような企業向けセキュリティツールに触れることができたことも、とても貴重な経験となりました。 また、開発で詰まった際の相談や検証環境の準備についても親身にサポートして頂き、とてもやりやすい環境で業務に取り組むことができました。 また、期間中にチーム構成や過去のプロジェクトについての説明の時間を設けていただいたり、他部署合同のミーティングに参加させていただいたりしたため、 実際の企業における業務や組織の構成という点でも理解が深まりました。 おわりに 本記事では2022年度冬インターンシップの参加記として取り組みや感想について書かせていただきました。 親身にサポートをしてくださったトレーナー、RedTeam、NTTコミュニケーションズの皆様には大変お世話になりました。 2週間ありがとうございました。 認証情報窃取等の機能を持つMimikatzをメモリ上に読み込み、その機能を利用できるようにするPowerShellスクリプト。 ↩
はじめに こんにちは、イノベーションセンターの野山です。 今回、NTTコミュニケーションズの IoT Connect Gateway (以降ICGW)を用いて、IoT/Edgeのアーキテクチャ検証をしました。 NTTコミュニケーションズの以下メンバーとともに行った結果を共有させていただこうと思います。 角田 佳史 (PS本部 5G&IoT部/IoTサービス部門) 鈴ヶ嶺 聡哲 (イノベーションセンター テクノロジー部門) 野山 瑛哲 (イノベーションセンター テクノロジー部門) PoCの目的とモチベーション 今回のPoC(Proof of Concept)には、主に2つのモチベーションがあります。 1. IoTアーキテクチャのユースケース検証 このプロジェクトでは、IoTのアーキテクチャにおける具体的なユースケースを検証し、その適用可能性を技術的観点から検証することを目指しました。 これにより、読者の皆様にもこの技術を使用するイメージを明確に伝えられるよう、共有したいと考えています。 2. Azureの新技術の調査・検証 また、今回のPoCではMicrosoft Azureにおける最新技術の調査および検証も重要な目的としています。 特に以下の技術要素が注目されており、それらの適用範囲や効果を検証しました。 Azure Arc Enabled k8s この検証を通じて、これらの新技術の特徴や利点、そして適用上の注意点などを明らかにし、 皆様に有益な情報を提供できることを目指しています。 アーキテクチャ概要 先ほど述べた2つのモチベーションに基づいて、以下のようなPoCを実施しました。 このセクションでは、アーキテクチャの概要と主要な要素について説明します。 PoCイメージ 概要として、以下のような画像イメージを想定してPoCを構築した形となります。 ユースケースとしては、製造業などの各拠点に点在する拠点から、部品(ネジ/カメラ/カプセル/etc.....)の故障検知のアーキテクチャを作成しました。 流れとしては以下となります。 地方の拠点から定期的に撮影した画像を、中央拠点に定期的にアップロードする(大体30s~1mくらいの間隔を想定) アップロードされると同時にAWSのS3に画像をバックアップする 中央拠点にアップロードされた画像はその都度、故障推論を行いその様子をリアルタイムで可視化する 地方拠点でアップロードされる画像は15種類くらいを想定しました。とはいえ物理的に地方拠点で設置して、というのはなかなか難しいので サンプルイメージ を用いてランダムにアップロードすることで、イメージに近づけています。 Rawな画像と故障推論された画像が可視化された次の図です。アップロードの頻度によって動的に変わっていきます。 アーキテクチャ概要 このようなPoCのイメージを実現したアーキテクチャ概要が下のイメージとなります。 説明するにあたり、このアーキテクチャを3つの機能(Upload/Eventdriven/Inference)に分けて説明します。 Upload 地方の拠点から、画像をUploadする部分となります。 多くの拠点や様々な画像をアップロードし、S3にバックアップをするためにNTT Comの製品であるIoTConnectGateway(ICGW)を使用しています。 ポイントとしては3つあります。 UploadするDevice側の追加・削除はICGWを通して任意に変更でき、拡張性が高い ICGWのMirroring機能を用いて、Device側は意識することなく、S3へバックアップされる Device側の固有設定をICGWで設定できるため、統括管理しやすい (ConfigManager機能) 概要 要素技術の説明(ICGW) 上記でポイントとしているICGWにどんなサービス/機能があるのかご紹介します。 今回のPoCで使用しているICGWのサービスは以下の3つです。 ストレージ転送機能 ミラーリング機能(近日商用リリース予定) コンフィグマネージャー ストレージ転送機能とコンフィグマネージャーに関する機能説明や取り組みは、 過去連載でも紹介されているのでご興味がある方はご参照ください。 IoT Connect Gatewayを使ってみた 番外編 第2回 ~インターンシップでStorage転送機能を使って開発してみた~ 【IoT Connect Gateway】コンフィグマネージャーのご紹介 【IoT Connect Gateway】コンフィグマネージャーで設定ファイルを生成してみよう ストレージ転送機能 ストレージ転送機能は、クラウドストレージへデータ転送をする機能です。 ICGWの基本機能であるプロトコル変換機能をベースに、デバイス固有のIMSIやIMEIなどのメタデータを付与した上で転送先のクラウドストレージへデータを転送できます。 概要 今回のPoCでは、Amazon S3やオンプレミス上で構築されたMinioへカメラ画像を送信するために、ストレージ転送機能とミラーリング機能を使用しています。 現在、ストレージ転送機能は、AWS S3互換のストレージのみ対応していますが、OSSであるMinioはS3互換なのでICGWの転送先として設定できます。 ただ、 現在のストレージ転送機能単体では、設定されたエンドポイントへのデータ送信時に、複数のクラウドサービスへ同時にデータを転送はできません 。厳密に言えば、複数の転送設定を作成し、転送先毎にデータを送信する仕組みを、IoTデバイスへ実装すれば実現可能です。 とはいえ、転送設定を追加する度に、IoTデバイス側で改修が必要になるため、FOTA(Firmware Over The Air)などの遠隔アップデートのような効率的なファームウェア・ソフトウェア管理の仕組みが無い場合は、見逃せないコストに繋がる可能性があります。 そこで、ICGWチームでは、あるエンドポイントにデータを1回送信するだけで、複数のクラウドサービスにデータを転送できる”ミラーリング機能”を開発しました。 記事執筆時点では、ミラーリング機能はベータ機能として一部ユーザのみに提供しており、今回のPoCを通じて試験的に活用し、必要に応じて機能を改善することで品質を高める取り組みを行っています。 ミラーリング機能 ミラーリング機能は、あるエンドポイントにデータを1回送信するだけで、複数のクラウドサービスにデータを転送できる機能です。クラウドサービスの転送設定(スタンダード・イベント・ファンクションの転送設定など)をミラーリングの転送設定へ紐付けることにより、1回のデータ送信で複数のクラウドサービスへデータを転送できるようになります。 今回のPoCでは、ミラーリングの転送設定にストレージ転送設定を紐づけており、オンプレミスストレージ(Minio)とクラウドストレージ(Amazon S3)に対して同時にデータを転送しています。今回はバックアップ用途で使用していますが、通信データのキャプチャ用途で使用し、ミラーリング機能の転送先クラウドサービスでログ解析を行うなど、問題切り分けやセキュリティにこのミラーリング機能が寄与できると考えています。 コンフィグマネージャー コンフィグマネージャーは、IoTデバイスごとの設定ファイルの生成と配信ができる機能です。IoTデバイス毎の設定ファイルの生成および配信設定は、ポータル上から簡単に行えます。 今回のPoCでは、カメラ画像のアップロード間隔を変更するためにコンフィグマネージャーを使用しており、IoTデバイスの要件に応じた設定ファイルの配信を実現しています。今回はアップロード間隔の変更に使用していますが、設定ファイルの内容次第で様々な要件に対応できます。 Eventdriven 中央拠点にUploadされた画像のEventをTriggerに推論するまでのEventを制御する部分となります。 ポイントとしては3つあります。 Kubernetes上で開発を効率的にするためAzureFunctionsを使用 複数のEventをハンドルするためにAzure EventGridを使用 これらはAzureArcの機能の一部としてオンプレでも使用可能 概要 要素技術の説明(Azure Arc Enabled K8s) 今回、Eventdrivenの機能を実装するにあたり Azure Arc Enabled K8sを使用しています。 主要な機能が5つあり、オンプレ/パブリッククラウドなど実行場所を広く選べる使用感の高さが魅力です。 またこの Azure Arc Enabled K8s には AzureFunctionsとEventgridの機能がリリースされており、概要としては以下となっています。 Eventdriven説明 これらの機能を用いてEventdrivenの機能を実装しており、 概要フローとしては以下となっています。 また概要フローの中には、さらに2つのサブフローが存在し、それぞれについて詳しくご紹介します。 イベントの送信 以下のようにAzureClIを使って、EventGridのリソースを作成できます。 ルーティング先のEndpointやPathを意識していれば簡単に作成できると思います。 実際の画面はこんな感じです。 推論の実行 また、Eventがルーティングされたあとに推論処理をトリガーするAzureFunctionsの展開方法についても概要を説明いたします。 Inference TriggerされたEventから推論する部分です。 ポイントとしては2つあります。 15種類の画像を推論するため、GPUの割当効率を考える必要がある。 この問題をマルチインスタンスGPUを用いて解決している。 概要 要素技術の説明(Mig) 上記での問題についてマルチインスタンスGPUを用いて解決しています。 まとめ 以下に今回用いた技術をまとめてみます。 本記事では、IoTアーキテクチャのユースケース検証と、Azureの新技術の調査・検証を目的としたPoCプロジェクトについて説明しました。 この検証を通じて、IoTアーキテクチャにおける具体的なユースケースの適用可能性を技術的観点から検証し、 EdgeにおけるICGWとAzureの主要技術(Azure Arc Enabled Kubernetes)の特徴や利点、適用上の注意点などが参考になれば幸いです。
はじめに こんにちは、インターン生の 魏心宇 と申します。 2023 年 2 月 6 日から 2 週間にわたって、NTT Com の現場受け入れ型インターンシップに参加させていただきました。 普段は大学で SR (セグメントルーティング) を用いたトラフィックエンジニアリングについて研究しています。 今回のインターンシップでは「SR を用いたキャリアネットワークの開発」をテーマに、NTT Com 発の OSS である Pola PCE への SRv6 機能実装・検証に取り組みました。 この記事では、2 週間の開発体験をご紹介します! インターンシップに参加したモチベーション 私は学部 3 年の冬、 NTT Com TechWorkshop 「プロのネットワークエンジニアと学ぶ!ISP ネットワークのつくりかた」 に参加したことがきっかけで、SR という斬新なネットワークアーキテクチャを知り、技術の素晴らしさに感銘を受けました。 SR を利用することで、従来では実現困難であった複雑な経路制御が簡単に実現可能となるため、国境を超えた高品質なネットワーク回線や特定のアプリに対するネットワークの混雑解消など様々な可能性を生み出し、新たなネットワークサービスを開拓できると期待しています。 NTT Com の R&D 部門であるイノベーションセンターでは SR をはじめとする次世代インターネット技術の研究開発が行われており、独自のアーキテクチャである Multi-AS SR をはじめとした先進的な社会実装の最前線となっています。 大学院に入り、日々の研究とネットワーク運用を通して最先端技術に触れる機会が増える中で、企業ではどのようなネットワーク技術が求められ活用されているのかを学びたいと思うようになり、今回のインターンシップに応募いたしました。 インターンシップで取り組んだこと 今回のインターンシップでは、SR-TE を一元的に管理するための OSS 実装である Pola PCE に対する SRv6 機能の追加と、複数のベンダーの機器(Cisco、Juniper)との相互接続を目標として定めました。 インターンシップの前提として、NTT Com イノベーションセンターではマルチベンダー機器環境で SR を検証しています。 検証内容については Multi-AS Segment Routing 検証連載 で公開されています。 SR、SR-TE、PCE とは何かについて詳しく紹介されているため是非参考にしてください。 [Multi-AS Segment Routing 検証連載#10] PCE を用いた SR-TE の一元管理 で紹介されている通り、SR-TE の実装には各 PE ルーターへの設定が必要であるため、台数が増えると管理が複雑になります。 そこでコントローラーを用いた SR-TE の一元管理により、パス計算の効率化や機器設定の簡素化などが期待できます。 Path Computation Element(PCE)は、前述した SR-TE の一元管理を実現するための技術です。 PCE には発行済み LSP/SR Policy を管理しない Stateless PCE と、これらの情報を管理する Stateful PCE が存在します。 Stateful PCE は既存の LSP/SR Policy を管理するため、それらを条件として考慮した複雑な経路を計算することが可能となります。 また、Stateful PCE には、クライアントである PCC からのリクエストに基づいた経路計算のみを行う Passive Stateful PCE と、自ら経路を発行し PCC へ送信する Active Stateful PCE が存在します。 Active Stateful PCE は新規 SR Policy の発行や既存 SR Policy の更新などの操作ができるため、SR Policy の集中的な管理に適しています。 PCE-PCC の間や複数の PCE 間の通信は、 RFC5440 により定義される Path Computation Element Protocol(PCEP)を用いて行われます。 Pola PCE は、SR-TE の一元管理を実現するための Stateful PCE であり、Active Stateful PCE として動作し、SR-TE の一元管理を実現します。 Pola PCE の概要は Pola PCE で SR 網の TE を体験してみよう! にて紹介されていますので、ぜひ参考にしてみてください。 インターンシップ参加時点では、Pola PCE の実装は SR-MPLS のみを対象としていました。 そのため、Pola PCE を Multi-vendor で動作する SRv6 PCE へと拡張することを今回のインターンシップの目標と定めました。 PCEP プロトコルの SRv6 拡張は draft-ietf-pce-segment-routing-ipv6 にて定義されています。 まだ Internet-Draft で議論中の技術であるため、各ベンダーの SRv6 PCC 機能の実装状況を確認しつつ、開発内容を調整する必要があります。 以下では、PCEP プロトコルの SRv6 拡張およびインターンシップでの実装内容を具体的に紹介します。 PCEP Extensions for SRv6 draft-ietf-pce-segment-routing-ipv6 では、RFC8664 と比べて主に以下の内容が追加されています。 SRv6 PCE Capability sub-TLV PCC/PCE は、PCEP セッション初期化フェーズ(OPEN object)において、 PATH-SETUP-TYPE-CAPILITY TLV に含まれる新しい Path Setup Type: 3 と新しい SRv6-PCE-CAPABILITY sub-TLV を介して、SRv6 をサポートする能力を示します。 SRv6-ERO Subobject SRv6 をサポートするために、ERO オブジェクトに含まれる新しい SRv6-ERO サブオブジェクトが定義されました。 SRv6-RRO Subobject SRv6 をサポートするために、RRO オブジェクトに含まれる新しい SRv6-RRO サブオブジェクトが定義されました。 実装内容 今回のインターンシップでの実装内容について、Pola PCE への SRv6-ERO Subobject の追加 を例に説明します。 パケットキャプチャによるプロトコルの確認・理解 RFC 準拠のコントローラー&プロトコルライブラリ開発の進め方 で紹介されている通り、PCEP メッセージは単一の Common header と複数の Object から構成されます。 それをより直感的に理解するため、関連の RFC を読みながら、パケットキャプチャツールである Wireshark を使って PCEP メッセージの構造を確認します。 上図は、実際に PCC から PCE 宛てに送信された PCRpt メッセージのパケットキャプチャです。 図の通り、PCEP メッセージは、1 つの Common header と複数の Object から構成されています。 Common header にはそれがどの PCEP メッセージであるかを示す Message type が格納されており、今回の例で Common header の Message type は 10 で、 RFC8231 の 8.2 節の定義の通り、PCRpt メッセージであることが分かります。 そして各 Object は Common object header と Object body から構成されていて、Common object header には、その Object を示す Object class と Object type が格納されています。 今回の例では Object class は 7、Object type は 1 であり、 RFC5440 の 7.9 節を参照すると Explicit Route Object (ERO)であることが分かります。 上図の ERO Object の内容を詳しく確認すると、黄色でハイライトされいる Non defined subobject (40) が 2 つあります。内容は次の通りです。 SRv6 関連の Subobject はまだ Internet-Draft で議論中のため、Wireshark ではまだうまく認識されていません。 そこで前述の draft-ietf-pce-segment-routing-ipv6 の 4.3.1 節を参照すると、SRv6-ERO Subobject は下記のように定義されています。 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |L| Type=40 | Length | NT | Flags |V|T|F|S| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Reserved | Endpoint Behavior | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | SRv6 SID (optional) | | (128-bit) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // NAI (variable, optional) // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SID Structure (optional) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ パケットキャプチャの内容を見ると、 Non defined subobject (40) の部分の 1 バイト目は A8 で、2 進数で変換すると 1010 1000 になります。 SRv6-ERO Subobject の定義と合わせて見ると、 1010 1000 の 1 ビット目は'L' Flag の値、2 ビット目から 8 ビット目の 0101000 は Type の値で 10 進数の 40 と合致しているため、SRv6-ERO Subobject は、 Non defined subobject (40) と表示されていることが分かります。 プロトコルライブラリの実装 - Pola PCE への SRv6-ERO Subobject の追加 これから Pola PCE へ SRv6-ERO Subobject を追加します。 まず、 pkg/packet/pcep/object.go に SRv6-ERO Subobject の定義を追加します。 const ERO_SUBOBJECT_SRV6 uint8 = 0x28 const ( NT_MUST_NOT_BE_INCLUDED uint8 = 0x00 // draft-ietf-pce-segment-routing-ipv6 4.3.1 NT_SRV6_NODE uint8 = 0x02 // draft-ietf-pce-segment-routing-ipv6 4.3.1 NT_SRV6_ADJACENCY_GLOBAL uint8 = 0x04 // draft-ietf-pce-segment-routing-ipv6 4.3.1 NT_SRV6_ADJACENCY_LINKLOCAL uint8 = 0x06 // draft-ietf-pce-segment-routing-ipv6 4.3.1 ) 次に、 draft-ietf-pce-segment-routing-ipv6 の 4.3.1 節を参照し、SRv6-ERO Subobject の構造体とパケット操作に関するメソッドを追加します。 パケット操作メソッドとしては、バイト列を構造体に格納する DecodeFromBytes() 、構造体をバイト列に変換する Serialize() の 2 つのメソッドと、新たに構造体を作成する NewSRv6EroSubObject 関数と SRv6-ERO Subobject から SID を抽出する ToSegment() メソッドが必要となります。 type SRv6EroSubobject struct { LFlag bool SubobjectType uint8 Length uint8 NaiType uint8 VFlag bool TFlag bool FFlag bool SFlag bool Behavior uint16 Segment table.SegmentSRv6 Nai netip.Addr } func (o *SRv6EroSubobject) DecodeFromBytes(subObj [] uint8 ) error { o.LFlag = (subObj[ 0 ] & 0x80 ) != 0 o.SubobjectType = subObj[ 0 ] & 0x7f o.Length = subObj[ 1 ] o.NaiType = subObj[ 2 ] >> 4 o.VFlag = (subObj[ 3 ] & 0x08 ) != 0 o.TFlag = (subObj[ 3 ] & 0x04 ) != 0 o.FFlag = (subObj[ 3 ] & 0x02 ) != 0 o.SFlag = (subObj[ 3 ] & 0x01 ) != 0 o.Behavior = binary.BigEndian.Uint16(subObj[ 6 : 8 ]) sid, _ := netip.AddrFromSlice(subObj[ 8 : 24 ]) o.Segment = table.NewSegmentSRv6(sid) if o.NaiType == 2 { o.Nai, _ = netip.AddrFromSlice(subObj[ 24 : 40 ]) } return nil } func (o *SRv6EroSubobject) Serialize() [] uint8 { buf := make ([] uint8 , 4 ) buf[ 0 ] = o.SubobjectType if o.LFlag { buf[ 0 ] = buf[ 0 ] | 0x80 } buf[ 1 ] = o.Length buf[ 2 ] = o.NaiType * 16 if o.VFlag { buf[ 3 ] = buf[ 3 ] | 0x08 } if o.TFlag { buf[ 3 ] = buf[ 3 ] | 0x04 } if o.FFlag { buf[ 3 ] = buf[ 3 ] | 0x02 } if o.SFlag { buf[ 3 ] = buf[ 3 ] | 0x01 } reserved := make ([] uint8 , 2 ) behavior := make ([] uint8 , 2 ) binary.BigEndian.PutUint16(behavior, o.Behavior) byteSid := o.Segment.Sid.AsSlice() byteSRv6EroSubobject := AppendByteSlices(buf, reserved, behavior, byteSid) return byteSRv6EroSubobject } func (o *SRv6EroSubobject) Len() ( uint16 , error ) { // The Length MUST be at least 24, and MUST be a multiple of 4. // An SRv6-ERO subobject MUST contain at least one of a SRv6-SID or an NAI. if o.NaiType == NT_MUST_NOT_BE_INCLUDED { // Type, Length, Flags (4byte) + Reserved(2byte) + Behavior(2byte) + SID (16byte) return uint16 ( 24 ), nil } else if o.NaiType == NT_IPV6_NODE { // Type, Length, Flags (4byte) + Reserved(2byte) + Behavior(2byte) + SID (16byte) + Nai (16byte) return uint16 ( 40 ), nil } else { return uint16 ( 0 ), errors.New( "unsupported naitype" ) } } func NewSRv6EroSubObject(seg table.SegmentSRv6) (*SRv6EroSubobject, error ) { subo := &SRv6EroSubobject{ LFlag: false , SubobjectType: ERO_SUBOBJECT_SRV6, NaiType: NT_MUST_NOT_BE_INCLUDED, VFlag: false , TFlag: false , FFlag: true , SFlag: false , Behavior: uint16 ( 1 ), Segment: seg, } length, err := subo.Len() if err != nil { return subo, err } subo.Length = uint8 (length) return subo, nil } func (o *SRv6EroSubobject) ToSegment() table.Segment { return o.Segment } そして、ERO Object から SR-ERO Subobject と SRv6-ERO Subobject を区別するために、ERO Object の DecodeFromBytes() メソッドを修正します。 func (o *EroObject) DecodeFromBytes(typ uint8 , objectBody [] uint8 ) error { o.ObjectType = typ if len (objectBody) == 0 { return nil } for { var eroSubobj EroSubobject if (objectBody[ 0 ] & 0x7f ) == 36 { eroSubobj = &SREroSubobject{} } else if (objectBody[ 0 ] & 0x7f ) == 40 { eroSubobj = &SRv6EroSubobject{} } else { return errors.New( "invalid Subobject type" ) } if err := eroSubobj.DecodeFromBytes(objectBody); err != nil { return err } o.EroSubobjects = append (o.EroSubobjects, eroSubobj) if objByteLength, err := eroSubobj.Len(); err != nil { return err } else if int (objByteLength) < len (objectBody) { objectBody = objectBody[objByteLength:] } else if int (objByteLength) == len (objectBody) { break } else { return errors.New( "srerosubobject parse error" ) } } return nil } ERO Object の新構造体を作成する NewEroSubobject 関数も同様に修正します。 func NewEroSubobject(seg table.Segment) (EroSubobject, error ) { if v, ok := seg.(table.SegmentSRMPLS); ok { subo, err := NewSREroSubObject(v) if err != nil { return nil , err } return subo, nil } else if v, ok := seg.(table.SegmentSRv6); ok { subo, err := NewSRv6EroSubObject(v) if err != nil { return nil , err } return subo, nil } else { return nil , errors.New( "invalid Segment type" ) } } これにより、Pola PCE へ SRv6-ERO Subobject に対する処理機能を追加できました。 以上では、Pola PCE への SRv6-ERO Subobject の追加を例に、今回のインターンシップでの Pola PCE 開発の流れを紹介しました。 それ以外にも、SRv6 に対応するため、Pola PCE における LSP Object の IPV6-LSP-IDENTIFIERS TLV の追加や、explicit SRv6-TE Policy を扱うための関数の修正などの変更を加えました。 詳しい説明は記事の長さの都合上、割愛しますが、ご興味のある方はこちらの PR をご参照ください。 動作検証 本章では、作成した実装を用い、複数のベンダーの機器(Cisco、Juniper)との相互接続検証を実施します。 検証環境は上図の通りで、環境の構築には OSS ツールの Containerlab を使用しました。 Containerlab を用いることで、YAML ファイルベースで簡単に検証環境を構築できます。 今回の検証用の Containerlab 設定ファイルはこちらの Repo で公開しています。 ぜひご活用ください。 SRv6 機能を追加した Pola PCE とベンダー機器との相互接続試験を行います。 まずは Containerlab の動作状態を確認します。 % sudo containerlab inspect INFO[0000] Parsing & checking topology file: nttcom-internship.clab.yml +---+---------------------------------+--------------+--------------------------------+--------+---------+----------------+----------------------+ | # | Name | Container ID | Image | Kind | State | IPv4 Address | IPv6 Address | +---+---------------------------------+--------------+--------------------------------+--------+---------+----------------+----------------------+ | 1 | clab-nttcom-internship-host01 | 2758bf898616 | wbitt/network-multitool:latest | linux | running | 172.20.20.5/24 | 2001:172:20:20::5/64 | | 2 | clab-nttcom-internship-host02 | ee82fd3f4bba | wbitt/network-multitool:latest | linux | running | 172.20.20.2/24 | 2001:172:20:20::2/64 | | 3 | clab-nttcom-internship-host03 | f2747f464ffd | wbitt/network-multitool:latest | linux | running | 172.20.20.8/24 | 2001:172:20:20::8/64 | | 4 | clab-nttcom-internship-pcc-rt01 | acb1ba1cb010 | vrnetlab/vr-vmx:22.4R1.10 | vr-vmx | running | 172.20.20.7/24 | 2001:172:20:20::7/64 | | 5 | clab-nttcom-internship-pcc-rt02 | 1928d17fae80 | ios-xr/xrd-control-plane:7.8.1 | xrd | running | 172.20.20.3/24 | 2001:172:20:20::3/64 | | 6 | clab-nttcom-internship-pcc-rt03 | f29848103688 | vrnetlab/vr-vmx:22.4R1.10 | vr-vmx | running | 172.20.20.6/24 | 2001:172:20:20::6/64 | | 7 | clab-nttcom-internship-pola-pce | 0dc707b9dd09 | ghcr.io/nttcom/pola:latest | linux | running | 172.20.20.9/24 | 2001:172:20:20::9/64 | | 8 | clab-nttcom-internship-xtc-pce | f31bc03d953a | ios-xr/xrd-control-plane:7.8.1 | xrd | running | 172.20.20.4/24 | 2001:172:20:20::4/64 | +---+---------------------------------+--------------+--------------------------------+--------+---------+----------------+----------------------+ 次に、Pola PCE のコンテナで Pola PCE を起動し、動作を確認します。 % sudo docker exec -it clab-nttcom-internship-pola-pce bash root@pola-pce:~# cat polad.yaml # polad.yaml global: pcep: address: "[fc00::ffff]" port: 4189 grpc-server: address: "127.0.0.1" port: 50051 log: path: "/var/log/pola/" name: "polad.log" ted: enable: false root@pola-pce:~# polad > /var/log/polad.log 2>&1 & [1] 65 root@pola-pce:~# ps -aux | grep polad root 65 0.0 0.0 1083748 11216 pts/1 Sl 07:18 0:00 polad root 73 0.0 0.0 3468 1720 pts/1 S+ 07:19 0:00 grep polad pola session コマンドにより PCEP Session を確認します。 root@pola-pce:~# pola session sessionAddr(1): fc00::1 sessionAddr(2): fc00::2 sessionAddr(3): fc00::3 pola sr-policy list コマンドにより各ルーター既存の SR Policy を確認します。 root@pola-pce:~# pola sr-policy list Session: fc00::1 PolicyName: vrf-100-policy-pcc-rt03 SrcAddr: fd00:ffff::1 DstAddr: 2a0b:2542:400:3:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:3:1:: Session: fc00::2 PolicyName: cfg_vrf-100-policy-pcc-rt03_discr_10 SrcAddr: fd00:ffff::2 DstAddr: 2a0b:2542:400:3:1:: Color: 100 Preference: 10 SegmentList: None Session: fc00::3 PolicyName: vrf-100-policy-pcc-rt01 SrcAddr: fd00:ffff::3 DstAddr: 2a0b:2542:400:1:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:1:1:: PolicyName: vrf-100-policy-pcc-rt02 SrcAddr: fd00:ffff::3 DstAddr: 2a0b:2542:400:2:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:2:1:: SR Policy のパラメータを指定する yaml ファイルを確認します。 root@pola-pce:~# cat policy_explicit_rt01.yaml # policy_explicit_rt01.yaml srPolicy: pcepSessionAddr: "fc00::1" srcAddr: "fd00:ffff::1" dstAddr: "2a0b:2542:400:2:1::" name: vrf-100-policy-pcc-rt02-by-pola color: 100 segmentList: - sid: "2a0b:2542:400:3:1::" nai: "fd00:ffff::3" - sid: "2a0b:2542:400:2:1::" nai: "fd00:ffff::2" root@pola-pce:~# cat policy_explicit_rt02.yaml # policy_explicit_rt02.yaml srPolicy: pcepSessionAddr: "fc00::2" srcAddr: "fd00:ffff::2" dstAddr: "2a0b:2542:400:1:1::" name: vrf-100-policy-pcc-rt01-by-pola color: 100 segmentList: - sid: "2a0b:2542:400:3:1::" nai: "fd00:ffff::3" - sid: "2a0b:2542:400:1:1::" nai: "fd00:ffff::1" pola sr-policy add コマンドにより SR Policy を新たに発行します。 root@pola-pce:~# pola sr-policy add -f policy_explicit_rt01.yaml -l success! root@pola-pce:~# pola sr-policy add -f policy_explicit_rt02.yaml -l success! 再び pola sr-policy list コマンドを実行し各ルーターの SR Policy を確認します。 root@pola-pce:~# pola sr-policy list Session: fc00::1 PolicyName: vrf-100-policy-pcc-rt03 SrcAddr: fd00:ffff::1 DstAddr: 2a0b:2542:400:3:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:3:1:: PolicyName: vrf-100-policy-pcc-rt02-by-pola SrcAddr: fd00:ffff::1 DstAddr: 2a0b:2542:400:2:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:3:1:: -> 2a0b:2542:400:2:1:: Session: fc00::2 PolicyName: cfg_vrf-100-policy-pcc-rt03_discr_10 SrcAddr: fd00:ffff::2 DstAddr: 2a0b:2542:400:3:1:: Color: 100 Preference: 10 SegmentList: None Session: fc00::3 PolicyName: vrf-100-policy-pcc-rt01 SrcAddr: fd00:ffff::3 DstAddr: 2a0b:2542:400:1:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:1:1:: PolicyName: vrf-100-policy-pcc-rt02 SrcAddr: fd00:ffff::3 DstAddr: 2a0b:2542:400:2:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:2:1:: 上記の pola sr-policy add コマンドおよび pola sr-policy list コマンドを実行すると、Pola PCE から以下のようなログが出力されます。 2023-04-14T11:39:28.367Z info Received Keepalive {"session": "fc00::1"} 2023-04-14T11:39:46.795Z info received CreateSRPolicy API request {"input": "{\"SRPolicy\":{\"pcepSessionAddr\":\"/AAAAAAAAAAAAAAAAAAAAQ==\",\"srcAddr\":\"/QD//wAAAAAAAAAAAAAAAQ==\",\"dstAddr\":\"KgslQgQAAAIAAQAAAAAAAA==\",\"color\":100,\"policyName\":\"vrf-100-policy-pcc-rt02-by-pola\",\"segmentList\":[{\"sid\":\"2a0b:2542:400:3:1::\"},{\"sid\":\"2a0b:2542:400:2:1::\"}]}}", "server": "grpc"} 2023-04-14T11:39:46.795Z info Send PCInitiate {"session": "fc00::1"} 2023-04-14T11:39:46.895Z info Received PCRpt {"session": "fc00::1"} 2023-04-14T11:39:46.895Z info Finish Stateful PCE request {"session": "fc00::1", "srpID": 1} 2023-04-14T11:39:48.829Z info Send Keepalive {"session": "fc00::2"} 2023-04-14T11:39:48.837Z info Received Keepalive {"session": "fc00::2"} 2023-04-14T11:39:51.430Z info received CreateSRPolicy API request {"input": "{\"SRPolicy\":{\"pcepSessionAddr\":\"/AAAAAAAAAAAAAAAAAAAAg==\",\"srcAddr\":\"/QD//wAAAAAAAAAAAAAAAg==\",\"dstAddr\":\"KgslQgQAAAEAAQAAAAAAAA==\",\"color\":100,\"policyName\":\"vrf-100-policy-pcc-rt01-by-pola\",\"segmentList\":[{\"sid\":\"2a0b:2542:400:3:1::\"},{\"sid\":\"2a0b:2542:400:1:1::\"}]}}", "server": "grpc"} 2023-04-14T11:39:51.430Z info Send PCInitiate {"session": "fc00::2"} 2023-04-14T11:39:56.697Z info Send Keepalive {"session": "fc00::3"} 2023-04-14T11:39:56.778Z info Received Keepalive {"session": "fc00::3"} 2023-04-14T11:39:58.285Z info Send Keepalive {"session": "fc00::1"} 2023-04-14T11:40:06.190Z info Receive GetSRPolicyList API request {"server": "grpc"} 2023-04-14T11:40:06.190Z info Send SRPolicyList API reply {"server": "grpc"} 2023-04-14T11:40:16.903Z info Received Keepalive {"session": "fc00::1"} 確認した結果、Pola PCE と各ルーターとの PCEP Session が確立されており、Juniper vMX ルーターである pcc-rt01 の SR Policy が発行され、pcc-rt01 からの既存 SR Policy のレポートも正しく受け取っていることがわかります。 Cisco IOS XRd ルーターである pcc-rt02 については既存 SR Policy のレポートが受け取れておらず、Pola PCE から pcc-rt02 に対して SR Policy を発行できそうに見えますが、pcc-rt02 側が正しく受け取れているかどうかは不明のため、もっと詳細を調べる必要があります。 Wireshark を利用して PCEP パケットをキャプチャします。 Containerlab 環境からのパケットキャプチャは以下のように行います。 Windows WSL2 環境から SSH 経由でパケットキャプチャをする場合のコマンド例: ssh $clab_host "sudo ip netns exec clab-nttcom-internship-pola-pce tcpdump -U -nni eth1 -w -" | /mnt/c/Program\ Files/Wireshark/wireshark.exe -k -i - macOS/Linux 環境から SSH 経由でパケットキャプチャをする場合のコマンド例: ssh $clab_host "sudo ip netns exec clab-nttcom-internship-pola-pce tcpdump -U -nni eth1 -w -" | wireshark -k -i - Cisco IOS XRd との相互接続検証 Cisco IOS XRd ルーターである pcc-rt02 側でのパケットキャプチャ結果を以下に示します。 パケットキャプチャ結果を確認すると、Pola PCE の実装通りに PCInitiate メッセージが送られましたが、pcc-rt02 からは PCReport メッセージが返ってきていません。 pcc-rt02 で show コマンドによって SR Policy の状態を確認すると、以下のように新規発行された SR Policy は存在していないことがわかります。 RP/0/RP0/CPU0:pcc-rt02#show segment-routing traffic-eng policy Fri Apr 14 13:43:15.021 UTC SR-TE policy database --------------------- Color: 100, End-point: 2a0b:2542:400:3:1:: Name: srte_c_100_ep_2a0b:2542:400:3:1:: Status: Admin: up Operational: down for 02:52:28 (since Apr 14 10:50:46.274) Candidate-paths: Preference: 10 (configuration) (inactive) Name: vrf-100-policy-pcc-rt03 Last error: SRv6 locator does not support USID Requested BSID: dynamic PCC info: Symbolic name: cfg_vrf-100-policy-pcc-rt03_discr_10 PLSP-ID: 1 Constraints: Protection Type: protected-preferred Maximum SID Depth: 19 Explicit: segment-list vrf-100-segment-list-pcc-rt03 (inactive) Weight: 10, Metric Type: TE SID[0]: 2a0b:2542:400:3:1:: SRv6 Information: Locator: WOLFLAB Binding SID requested: Dynamic Binding SID behavior: End.B6.Insert.Red Attributes: Forward Class: 0 Steering labeled-services disabled: no Steering BGP disabled: no IPv6 caps enable: yes Invalidation drop enabled: no Max Install Standby Candidate Paths: 0 また、初期設定による既存の SR Policy である vrf-100-policy-pcc-rt03 に関しても、 Last error: SRv6 locator does not support USID が原因で (inactive) が表示されます。 pcc-rt02 の SRv6 関連設定は以下のようになっています。 RP/0/RP0/CPU0:pcc-rt02#show running-config segment-routing Fri Apr 14 13:44:27.988 UTC segment-routing traffic-eng segment-lists srv6 sid-format usid-f3216 ! segment-list vrf-100-segment-list-pcc-rt03 srv6 index 10 sid 2a0b:2542:400:3:1:: ! ! ! policy vrf-100-policy-pcc-rt03 srv6 locator WOLFLAB binding-sid dynamic behavior ub6-insert-reduced ! color 100 end-point ipv6 2a0b:2542:400:3:1:: candidate-paths preference 10 explicit segment-list vrf-100-segment-list-pcc-rt03 weight 10 ! ! ! ! pcc source-address ipv6 fc00::2 pce address ipv6 fc00::ffff ! report-all ! ! srv6 locators locator WOLFLAB prefix 2a0b:2542:400:2::/64 ! ! ! ! pola sr-policy list コマンドによる既存 SR Policy の確認結果では、 SegmentList: None と表示され、SR Policy が学習されていません。 Cisco のドキュメント Segment Routing Configuration Guide for Cisco ASR 9000 Series Routers, IOS XR Release 7.8.x を参照したところ、インターンシップ参加時点(2023年2月)の最新版である Cisco IOS XR 7.8.1 では SRv6 policy が uSID 以外の SID 形式をサポートしていないようであり、これが原因と考えられます。 また同様に、Cisco のドキュメントからはインターンシップ参加時点で PCE-initiated SRv6 policies via PCEP 機能がサポートされていないことがわかります。 以上が原因で残念ながら今回のインターンシップでは Cisco IOS XRd との接続検証は成功しませんでした。 Juniper vMX との相互接続検証 Juniper vMX ルーターである pcc-rt01 側でのパケットキャプチャ結果を以下に示します。 パケットキャプチャ結果を確認すると、Pola PCE の実装通りに PCInitiate メッセージが送られ、pcc-rt01 から PCReport メッセージが返ってきていることがわかります。 pcc-rt01 で show コマンドによって SR Policy の状態を確認すると、以下のように新規発行された SR Policy である vrf-100-policy-pcc-rt02-by-pola が存在していることがわかります。 admin@pcc-rt01> show spring-traffic-engineering lsp To State LSPname 2a0b:2542:400:2:1::-100<c6> Up vrf-100-policy-pcc-rt02-by-pola 2a0b:2542:400:3:1::-100<c6> Up vrf-100-policy-pcc-rt03 Total displayed LSPs: 2 (Up: 2, Down: 0) 最後に、疎通確認を行います。 % sudo docker exec -it clab-nttcom-internship-host01 /bin/bash bash-5.1# ping -c 3 fd00:192:168:2::1 PING fd00:192:168:2::1(fd00:192:168:2::1) 56 data bytes 64 bytes from fd00:192:168:2::1: icmp_seq=1 ttl=62 time=4.00 ms 64 bytes from fd00:192:168:2::1: icmp_seq=2 ttl=62 time=3.61 ms 64 bytes from fd00:192:168:2::1: icmp_seq=3 ttl=62 time=3.77 ms --- fd00:192:168:2::1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 3.610/3.795/4.003/0.161 ms host01 から host02 への経路は、SR Policy(vrf-100-policy-pcc-rt02-by-pola) により pcc-rt01 -> pcc-rt03 -> pcc-rt02(緑色の線)経由になると期待されます。 pcc-rt03 の ge-0/0/0 でパケットキャプチャし、SR Policy の挙動を確認します。 % sudo ip netns exec clab-nttcom-internship-pcc-rt03 tcpdump -nni eth1 -v ip6 tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes 00:22:59.940361 IP6 (flowlabel 0x47e1e, hlim 255, next-header Routing (43) payload length: 128) fd00:ffff::1 > 2a0b:2542:400:3:1::: RT6 (len=2, type=4, segleft=1, last-entry=0, flags=0x0, tag=0, [0]2a0b:2542:400:2:40::) IP6 (flowlabel 0xe793a, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:1::1 > fd00:192:168:2::1: [icmp6 sum ok] ICMP6, echo request, id 13, seq 1 00:23:00.939071 IP6 (flowlabel 0x47e1e, hlim 255, next-header Routing (43) payload length: 128) fd00:ffff::1 > 2a0b:2542:400:3:1::: RT6 (len=2, type=4, segleft=1, last-entry=0, flags=0x0, tag=0, [0]2a0b:2542:400:2:40::) IP6 (flowlabel 0xe793a, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:1::1 > fd00:192:168:2::1: [icmp6 sum ok] ICMP6, echo request, id 13, seq 2 00:23:01.941300 IP6 (flowlabel 0x47e1e, hlim 255, next-header Routing (43) payload length: 128) fd00:ffff::1 > 2a0b:2542:400:3:1::: RT6 (len=2, type=4, segleft=1, last-entry=0, flags=0x0, tag=0, [0]2a0b:2542:400:2:40::) IP6 (flowlabel 0xe793a, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:1::1 > fd00:192:168:2::1: [icmp6 sum ok] ICMP6, echo request, id 13, seq 3 3 packets captured 3 packets received by filter 0 packets dropped by kernel 結果の通り、pcc-rt03 でパケットキャプチャして確認すると、pcc-rt01 から pcc-rt03 へ ICMP Request パケットが想定した経路で送られていることがわかります。 また、host02 から host01 へ ICMP Reply パケットについて、前述の原因により pcc-rt02 側で有効な SR Policy が存在しないため、経路は IGP に従って pcc-rt02 -> pcc-rt01(青色の線)になります。 同様に pcc-rt02 の Gi0/0/0/0 でパケットキャプチャして確認します。 % sudo ip netns exec clab-nttcom-internship-pcc-rt02 tcpdump -nni Gi0-0-0-0 -v ip6 tcpdump: listening on Gi0-0-0-0, link-type EN10MB (Ethernet), snapshot length 262144 bytes 00:45:20.822110 IP6 (flowlabel 0x5aab2, hlim 64, next-header IPv6 (41) payload length: 104) fd00:ffff::2 > 2a0b:2542:400:1:6::: IP6 (flowlabel 0x5aab2, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:2::1 > fd00:192:168:1::1: [icmp6 sum ok] ICMP6, echo reply, id 16, seq 1 00:45:21.820163 IP6 (flowlabel 0x5aab2, hlim 64, next-header IPv6 (41) payload length: 104) fd00:ffff::2 > 2a0b:2542:400:1:6::: IP6 (flowlabel 0x5aab2, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:2::1 > fd00:192:168:1::1: [icmp6 sum ok] ICMP6, echo reply, id 16, seq 2 00:45:22.822313 IP6 (flowlabel 0x5aab2, hlim 64, next-header IPv6 (41) payload length: 104) fd00:ffff::2 > 2a0b:2542:400:1:6::: IP6 (flowlabel 0x5aab2, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:2::1 > fd00:192:168:1::1: [icmp6 sum ok] ICMP6, echo reply, id 16, seq 3 3 packets captured 3 packets received by filter 0 packets dropped by kernel キャプチャした結果、ICMP Reply パケットの経路は想定通り pcc-rt02 -> pcc-rt01(青色の線)になっていることがわかります。 これにより、今回のインターンシップで実装した Pola PCE の SRv6 機能が正しく動作していることが確認できました。 まとめと今後の課題 本体験記では、インターンシップで取り組んだ Pola PCE への SRv6 新規機能実装・検証内容をご紹介しました。 前半では、Pola PCE への SRv6-ERO Subobject の追加を例に、今回のインターンシップでの開発の流れについて説明しました。 後半では、インターンシップ中に実施した複数のベンダーの機器(Cisco、Juniper)とPola PCE との相互接続検証を紹介しました。 結果として、Pola PCE へ実装した SRv6 機能が正しく動作していることが確認できました。 今回のインターンシップでは、実装状況の関係から、残念ながら本来の目標であった複数のベンダーの機器との相互接続は実現できませんでした。 SRv6 の TE は今後の発展が期待される分野であり、また私自身の研究にもつながるトピックです。 今後もベンダーの動向に注視しつつ、研究や運用に役立つ機能の開発に積極的に取り組んでいきたいと思います。 また、Pola PCE では次のステップとして、Dynamic SRv6-TE や BGP SR Policy NLRI への対応を検討しています。 これらの技術開発についても引き続き携わりたいと期待しています。 インターンシップの感想 わずか 2 週間のインターンシップでしたが、Pola PCE の開発準備から相互接続検証までの全プロセスに取り組むことができ、大変素晴らしい経験となりました。 Go 言語と PCEP 初心者の私にとっては大きな挑戦でしたが、Pola PCE のコア開発者の三島さんと竹中さんの丁寧な指導のお陰で、数々の課題を乗り越え、インターンシップの最終日までに開発目標を達成できました。 また、チーム全体の定例ミーティングへの参加を通して、Pola PCE の開発者の先輩社員の方だけでなく配属チームの社員の方々と交流でき、チーム全体の雰囲気を感じると共に普段の業務内容をより深く理解できました。 今回インターンシップで獲得した貴重な経験を今後の研究活動に活かしていきたいと思います。 トレーナーの三島さん、竹中さん、上長の木村さん、そしてお世話になった NTT Com の皆さん、2 週間大変貴重な経験をさせていただき、本当にありがとうございました。 トレーナーからのコメント トレーナーを担当したイノベーションセンターの竹中です。2週間のインターンシップお疲れ様でした。 今回のインターンシップでは、魏さんには主に SR PCE である Pola PCE の SRv6 拡張を実施していただきました。プロトコルやパケット構造の理解からはじめ、RFC や Internet-Draft とコードを比較しつつ拡張する部分を検討し、そして実際に機能拡張・動作確認まで行い成功させてくれました。インターン前は PCEP も Go 言語にもあまり馴染みがなかったということでしたが、その中でもプロトコルや実装を即座に理解し、手早く機能拡張されている様子はとても印象的でした。 また、本ブログでは SRv6 機能拡張について触れていただきましたが、それ以外に IPv6 underlay の環境情報を取得するための BGP-LS の各ベンダ実装状況など、PCE を活用する上で必要となる機能を調査していただきました。 SR PCE は SR 技術において様々な Traffic Engineering を行う上で今後重要となる技術です。 今回実施いただいた Pola PCE の SRv6 拡張によって、SRv6 環境においてより柔軟な TE の管理や検証が行えるようになりました。我々の SRv6 環境へ導入し、運用や検証に活用していきます! また、調査いただいたベンダの機能実装状況なども、今後の検証方針の決定やベンダへの問い合わせに活用させていただきます。 このインターンシップを通して得られた様々な知見が魏さんの今後の活動にも役立つことを願っています。 改めて、インターンシップへのご参加とご活躍、ありがとうございました!