🐯

Cloud Router で BGP の学習ルートをフィルタリングする新機能の紹介

2024/05/27に公開

はじめに

記事の目的

こんにちは、クラウドエース SRE部 に所属している\textcolor{red}{赤髪}がトレードマークの Shanks です。
好きなプロダクトは Cloud Router です。

本日は Cloud Router の新機能である、BGP ルート ポリシーを活用した学習ルートのフィルタリングについてご紹介いたします。
Cloud VPN や Cloud Interconnect でネットワーク空間を相互接続している方、とくに経路制御に悪戦苦闘している方には嬉しい内容をお届けします。

ターゲットとなる読者層

  • Cloud Interconnect を設計・運用・計画している方
    • Google Cloud と オンプレミス / 他クラウド を VPN で接続し、経路制御を行っている
  • Cloud VPN を設計・運用・計画している方
    • Google Cloud と オンプレミス / 他クラウド を VPN で接続し、経路制御を行っている
    • VPC ネットワーク と VPC ネットワーク を VPN で接続し、経路制御を行っている
  • BGP と周辺技術の知識を有する方

記事のゴール

  • 新機能「BGP ルート ポリシー」を使って経路制御の新しい方法を学ぶ

Cloud Router とは

本記事を閲覧いただいている読者の皆様はご存知と思いますので、プロダクト自体の詳細な説明は省きます。
Cloud Router とは、BGP(Border Gateway Protocol)を使用して対向ルータと Google Cloud との間でルート情報を広報する完全分散型のマネージド サービスです。
BGP スピーカーおよびレスポンダーとして機能するため、Google Cloud における BGP を利用した相互接続では必須のプロダクトです。

ルーティング ループ の落とし穴

loop

上述したとおり、Cloud Router は非常に素直な BGP スピーカーおよびレスポンダーとして機能します。
素直に機能する、というのは文字通り「対向ルータから広告されるルート情報をそのまま学習する」ため、そのように表現しました。

このように「そのまま学習する」というのは良い点でもあり、時として悩みの種となります。
それは「ルーティング ループ」を引き起こす可能性がある、ということです。

これは「Cloud Router のソフトウェア タスクは AS PATH Prepend を考慮するが、コントロール プレーンは AS PATH Prepend を考慮しない」という仕様に直結しています。
AS PATH Prepend の詳しい説明をしていくと本記事が埋まってしまいますので、詳細は以下の参考情報をご確認ください。

新機能「BGP ルート ポリシー」とは

release_note

上述のとおり、同じ広告範囲を広告・学習している場合、Cloud Router はルーティング ループを引き起こし、一部のパケットをドロップする恐れがあります。
それだけでなく、予想以上に対向ルータが大量の経路を広告した際にも一部のパケットをドロップする恐れがあります。
今までは Cloud Router レベルで対応する術がなく、対向ルータ側で制御するなどなんらかの対応措置が必要でした。

本記事で紹介する「BGP ルート ポリシー」機能を使えばその課題を解決することができます。
この機能は、BGP ルートをフィルタリングしたり、BGP アトリビュートを変更したりするためのルールを設定することができます。
また、受信と送信の両方で設定することができるため、Google Cloud と対向の��方にメリットがあります。

  • MED値 の変更による優先経路選択
  • 不要な BGP ルートのフィルタリング
  • AS PATH Prepend による経路制御

BGP ルート ポリシーでできること

BGP ルート ポリシーは IP アドレス ベースでのポリシーを設定できます。
ポリシーに合致した場合、以下のアクションを実行します。

  • AS PATH のインポート/エクスポート
  • AS PATH Prepend
  • MED値 のインポート/エクスポート
  • MED値 の変更
  • パケットの 通過/ドロップ
  • 次のポリシーの評価

試してみる

環境用意

Cloud VPN 同士で BGP 接続をする環境を実際に構築し、動作を確認しました。
幸いにも趣味で書いていた HA VPN 構成を構築する Terraform コードが手元にありましたので流用します。
一部の Terraform コードを掲載���ますが、本記事では Cloud VPN の環境構築の詳細は省きます。

Terraform コード抜粋
resource "google_compute_router" "route-filter-src" {
  provider = google

  project = local.project_id
  region  = "asia-northeast1"
  name    = "route-filter-src"
  network = google_compute_network.route-filter-src.name
  bgp {
    asn = 64514
  }
}
### 省略 ###
resource "google_compute_router_interface" "route-filter-src-to-dst-1" {
  provider = google

  project    = local.project_id
  region     = "asia-northeast1"
  name       = "route-filter-src-to-dst-1"
  router     = google_compute_router.route-filter-src.name
  ip_range   = "169.254.0.1/30"
  vpn_tunnel = google_compute_vpn_tunnel.route-filter-src-to-dst-1.name
}

resource "google_compute_router_peer" "route-filter-src-to-dst-1" {
  provider = google

  project                   = local.project_id
  region                    = "asia-northeast1"
  name                      = "route-filter-src-to-dst-1"
  router                    = google_compute_router.route-filter-src.name
  peer_ip_address           = "169.254.0.2"
  peer_asn                  = 64515
  advertised_route_priority = 100
  interface                 = google_compute_router_interface.route-filter-src-to-dst-1.name
}
### 省略 ###
resource "google_compute_ha_vpn_gateway" "route-filter-src" {
  provider = google

  project = local.project_id
  region  = "asia-northeast1"
  name    = "route-filter-src"
  network = google_compute_network.route-filter-src.id
}
### 省略 ###
resource "google_compute_vpn_tunnel" "route-filter-src-to-dst-1" {
  provider = google

  project               = local.project_id
  region                = "asia-northeast1"
  name                  = "route-filter-src-to-dst-1"
  vpn_gateway           = google_compute_ha_vpn_gateway.route-filter-src.id
  peer_gcp_gateway      = google_compute_ha_vpn_gateway.route-filter-dst.id
  shared_secret         = "cloudace"
  router                = google_compute_router.route-filter-src.id
  vpn_gateway_interface = 0
}

resource "google_compute_vpn_tunnel" "route-filter-src-to-dst-2" {
  provider = google

  project               = local.project_id
  region                = "asia-northeast1"
  name                  = "route-filter-src-to-dst-2"
  vpn_gateway           = google_compute_ha_vpn_gateway.route-filter-src.id
  peer_gcp_gateway      = google_compute_ha_vpn_gateway.route-filter-dst.id
  shared_secret         = "cloudace"
  router                = google_compute_router.route-filter-src.id
  vpn_gateway_interface = 1
}

BGP ルート ポリシーを作成する

BGP ルート ポリシー は CEL(Common Expression Language)を用いて定義します。
CEL 自体は慣れれば書きやすく、学習コストも高くありませんので、ぜひ読者の皆様も試してみましょう。

# Ignore BGP routes within the range
# 192.168.99.0/24
name: ignore-route-filter
type: ROUTE_POLICY_TYPE_IMPORT
terms:
- priority: 1
  match:
    expression: >
      destination == '192.168.99.0/24'
  actions:
  - expression: drop()
定義している句 句と値の説明 補足
name 任意のポリシー名
type ROUTE_POLICY_TYPE_IMPORT or ROUTE_POLICY_TYPE_EXPORT 受信経路の制御をするときは「IMPORT」を、送信経路の制御をするときは「EXPORT」を指定する。
terms.priority ポリシーの優先度 低い値から順に評価される。
terms.match.expression.destination 経路の宛先
terms.actions.expression 条件がマッチした場合のアクション

今回は、以下のルールを定義しました。

  • 受信経路を制御するポリシー
  • 「192.168.99.0/24」が広告されたときを条件とする
  • 条件に合致した場合、ルート情報をドロップする
  • ルールの優先度は1(非常に高い)

ポリシーを設定する

CEL で記述した BGP ルート ポリシーを Cloud Router に設定するには、Cloud Router の BGP ピアに適用する必要があります。

ポリシーのアップロード

まずは、適用する BGP ルート ポリシーをアップロードします。
アップロードするには以下のコマンドを実行してください。
${} としている箇所は、適宜皆様の環境に合わせて読みかえてください。

$ gcloud beta compute routers upload-route-policy ${Cloud Router 名} \
  --policy-name ${BGP ルート ポリシー名} \
  --file-name ${BGP ルート ポリシーを定義した CEL ファイル名}.yaml \
  --file-format yaml \
  --project ${プロジェクトID} \
  --region ${リージョン}

ポリシーの適用

BGP ルート ポリシーをアップロードしたら、Cloud Router の BGP ピアに適用します。
適用するには以下のコマンドを実行してください。
${} としている箇所は、適宜皆様の環境に合わせて読みかえてください。

$ gcloud beta compute routers update-bgp-peer ${Cloud Router 名} \
  --peer-name ${適用する Cloud Router の BGP ピア名} \
  --import-policies '${BGP ルート ポリシー名}' \
  --project ${プロジェクトID} \
  --region ${リージョン}

VPC のルーティングテーブルを確認する

以下の画像のとおり、Before に表示されていた 192.168.99.0/24 のルート情報が、After で削除されていることが確認できます。
Cloud Router の BGP ルートがフィルタリングされ学習されないことで、VPC のルート情報から正常に削除されています。

Before

before

After

after

Cloud Router のルーティングテーブルを確認する

こちらも同様に、Before に表示されていた 192.168.99.0/24 のルート情報が、After で削除されていることが確認できます。

Before

$ gcloud compute routers get-status ${Cloud Router 名} \
  --project ${プロジェクトID} \
  --region ${リージョン} \
  --format json \
  | jq '.result.bestRoutes[] | select(.destRange == "192.168.99.0/24")'

### 省略 ###

{
  "asPaths": [
    {
      "asLists": [
        64514
      ],
      "pathSegmentType": "AS_SEQUENCE"
    }
  ],
  "creationTimestamp": "2024-05-xxTxx:xx:xx.xx-xx:xx",
  "destRange": "192.168.99.0/24",
  "kind": "compute#route",
  "network": "https://www.googleapis.com/compute/v1/projects/xxxxxxxxxx/global/networks/route-filter-dst",
  "nextHopIp": "169.254.1.2",
  "nextHopVpnTunnel": "https://www.googleapis.com/compute/v1/projects/xxxxxxxxxx/regions/asia-northeast1/vpnTunnels/route-filter-dst-to-src-2",
  "priority": 100,
  "routeType": "BGP"
}

After

$ gcloud compute routers get-status ${Cloud Router 名} \
  --project ${プロジェクトID} \
  --region ${リージョン} \
  --format json \
  | jq '.result.bestRoutes[] | select(.destRange == "192.168.99.0/24")'

### フィルタリングが正常に動作し学習しておらず、select文にヒットしないしないため何も出力されない

まとめ

Cloud Router で経路制御を扱う上で長らく求められてきたポリシー制御がついに登場しました。
個人的にはルーティングループを経験したことがあったため目頭が熱くなった気がします。
ルートのフィルタリングだけでなく、AS PATH Prepend や MED値 のポリシー制御といった魅力的な機能が本アップデートには含まれています。
ぜひ活用してみてください。

Discussion