Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

ドメイン単位で外向き通信を許可する

By Joshua FoxAug 28, 20237 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

セキュアなアプリケーションを構築する際は、Virtual Private Cloud(VPC)の外への接続を遮断するのが一般的です。とはいえ、サードパーティAPIを呼び出す必要があるなど、一部の通信だけは通したい場面もあります。

Lovecraft風の「ドメインへのゲートウェイ」。Credit: StableDiffusion

定番の方法は、Google Cloud PlatformのFirewallやAWSのNetwork ACLで、必要なIPアドレスにだけ外向き通信を許可するやり方です。ただしIPアドレスは時間とともに変わる可能性がある一方、api.example.com のようなFully Qualified Domain Name(FQDN)は安定した公開エンドポイントとして機能します。そのため、ほとんどのアプリケーションはIPアドレスではなくFQDNを指定するように構成されます。

本記事では、特定のFQDNにのみエグレスを許可する方法を取り上げ、それぞれの長所と短所を整理します。

低コストで運用しやすく、堅牢かつシンプルな選択肢を中心に見ていきます。

あわせて、Kubernetes対応という観点も確認します。たとえばアプリケーションをKubernetesで動かしている場合、特定のKubernetesネームスペースからのみエグレスを許可したい、というケースが考えられるためです。

さらに、ドメイン単位のきめ細かな制御が必要になることもあります。名前ベースのバーチャルホスティングのように、1つのIPアドレスが複数のドメインを抱えるケースがあるためです。本記事で紹介する解決策の多くはこの点を考慮しておらず、あるIPアドレスを持つドメインへのアクセスを許可すると、同じIPの背後にあるすべてのドメインへの通信も許可されてしまいます。これに対応できる選択肢もあわせて紹介します。

本記事で取り上げる選択肢は次のとおりです。

  • セルフマネージドプロキシの代表例としてのSquid
  • ディープパケットインスペクションによりバーチャルホスティング下でもドメイン単位の制御が可能なAWS Network Firewall
  • サーバーレスサービスの手軽さでFQDN制御を実現するGoogle Firewallの新機能
  • ドメイン単位、さらにはURL単位までのきめ細かな制御を加える、新しいGoogle Secure Web Gateway
  • Kubernetes対応の選択肢:CiliumとIstio

(OSI層についての補足:ドメイン名とDNSはOSIネットワークモデルの「アプリケーション層」、すなわちLayer 7に位置するため、FQDNによるエグレス制御は「Layer 7 Egress Control」とも呼ばれます。一方、IPアドレスはLayer 3で定義され、一般的なファイアウォールやNetwork ACLで制御されます。)

自前で実装する場合

まずは自前で実装するとどうなるかを考えてみましょう。推奨はしませんが、各ソリューションが内部で何をしているかを理解する手がかりになります。

アプリケーションがサードパーティAPIのFQDNを使うように構成されていても、ドメイン名が意味を持つのは接続を試みる前、つまりクライアントがドメイン名からIPアドレスを引くタイミングまでです。それ以降の通信はIPアドレスでやり取りされるため、ブロック対象もIPアドレスになります。

また、1つのFQDNが複数のIPアドレスに対応していることもあります。これは通常のDNSルックアップで全IPが返るため問題にはならず、複数IPのリストに対してアクセスを許可すれば対処できます。

仕組みとしては、まず必要なIPアドレス以外の通信をすべて遮断するFirewallまたはNetwork ACLを用意します。

そのうえで、APIのFQDN api.example.com の現在のIPアドレスをDNSで定期的に確認するアプリケーションを書いてデプロイします(低コストで動かすなら、定期トリガーで実行するGCP Cloud FunctionsやAWS Lambdaが好適です)。IPアドレスが変わったまれなケースでは、そのアプリケーションがFirewallまたはNetwork ACLを更新する、という流れです。

セルフマネージドのリバースWebプロキシ

FQDNエグレス制御の「定番」のひとつがリバースWebプロキシで、オープンソースで最もよく知られているのがSquidです。クラウドのルーティング機能を使ってすべての外向き通信をSquidプロキシが動くVMに通し、ACLホワイトリストに設定されたドメイン名とIPアドレスが一致するかを確認したうえで、一致すれば転送します。

Squidは AWS Marketplaceで利用できます。アーキテクチャの解説はこちらの記事を参照してください。GCPでも Marketplaceから入手でき、ネットワーク構成の解説もあります。SquidやDiscrimiNAT、AviatrixといったプロキシによるFQDNエグレス制御についてはこちらの議論も参考になります。

VM上で動くSquidのようなプロキシには、OSのアップグレードやクラッシュ対応などの運用負荷が伴います。さらに、ロードバランス構成を別途組まない限りはすべての通信が1台のVMに集中するため、負荷が高くなりがちで堅牢性に影響するうえ、必要量を超える大きめのVMを24時間365日稼働させる費用が発生する可能性もあります。

AWS Network Firewall

AWS Network Firewallはディープパケットインスペクションを行うため、より強力なフィルタリングが可能です。そのため、AWS Network ACLに近い性質を持つGoogle Firewallとは厳密には同列に比較できません。

AWS Network Firewallは ステートフルなドメインリストルールグループを使ってFQDNエグレス制御をサポートします。HTTPSトラフィックのTCPコネクション確立時に送られるServer Name Indicator(SNI)を利用することで、バーチャルホスティング環境でもドメインを区別できます。

Network FirewallはRoute 53 DNS Firewallと統合可能で、こちらはDNS解決の試行をブロックします。たとえばVPC内のアプリケーションから api.example.com へのDNSクエリがIPアドレスに解決されなくなります。ただし、DNS Firewall自体はそのIPアドレスへのアクセスを止めるものではなく、その役割を担うのはNetwork Firewallです。

Network Firewallは有力な選択肢ですが、コストがかさみがちです。複雑なマルチネットワークのエンタープライズ環境を想定したサービスといえます。(AWS上のFirewall系サービスのユースケース比較については、DoiT Blogの拙稿もご覧ください。)

Google FirewallとWeb Gateway

VMを自分で運用するより、クラウドプロバイダーがフルマネージドで提供する仕組みを使えるほうが楽です。そして今、Googleはまさにそのための選択肢を相次いで投入しています。

Google Firewallには新たな FQDN Objects機能が加わり、現在は限定プレビュー中です。30秒ごとにCloud DNSで外部サービスの現在のIPアドレスを取得します。

同じく限定プレビュー中の Secure Web Gateway(Secure Web Proxyに名称変更)も、ドメイン単位の制御を可能にします。仕組みとしては、GCP Certificate Managerに保管したSSL証明書へのアクセスを与え、HTTPSトラフィックを復号・暗号化できるようにします。この深いアクセスにより、バーチャルホスティング環境であってもドメイン単位でエグレスを制御できます。HTTPリクエスト全体を確認できるため、URL単位の制御まで実現可能です。

Cilium

ここまでの解決策はVPCレベルで動作するものでした。しかし、アプリケーションをKubernetes上で動かしている場合、Kubernetesの概念に沿ったエグレス制御が欲しくなるかもしれません。その場合は CiliumNetworkPolicyを導入できます。これはCustom Resource Definition(CRD)で、ドメイン名からIPアドレスへの解決ロジックを実行し、eBPFベースのCiliumネットワーク層で通信をブロック・許可します。(DoiTブログの2本記事もあわせてご覧ください。)このCRDはKubernetes対応で、ネームスペース単位でPodを区別できるため、外部APIへのアクセスを許可するPodと許可しないPodを分けて指定できます。もうひとつのCRD CiliumClusterwideNetworkPolicy も同様の機能を提供しますが、設定はネームスペースを横断してクラスター全体に適用されます。

この方式では、追加のCiliumネットワーク層が必要になるぶん、クラスターにいくらかの複雑さが加わります。Ciliumのドキュメントによれば、近い将来「すべての機能が標準のリソース形式に統合され、このCRDは不要になる」見込みです。標準仕様はまだ公開されていませんが、Kubernetes Networking Special Interest Groupが現在策定を進めています。

Istio

最も多機能な選択肢を提供するのがIstioサービスメッシュです。Istioはトラフィックを完全に掌握し、ServiceEntryで定義したもの以外のエグレスをすべて遮断できます。resolution: DNS を指定すると、クライアント(Pod)が接続しているIPアドレスに依存せず、定期的にDNSでドメイン名を解決するようIstioに指示できます。Istioサービスは選択したネームスペースにのみ公開可能です。Istioは最も強力な制御を提供しますが、サービスメッシュとしての豊富な機能を備えるぶん、Ciliumよりも複雑になります。

結局どれを選ぶか

選択肢は多彩です。実績豊富なSquid(あるいは他のリバースWebプロキシ)、新しいマネージドサービスのGoogle Firewall FQDN ObjectsとAWS Network Firewall、HTTPプロキシ型のSecure Web Gateway、そしてKubernetes対応のCiliumとIstioがあります。

安定したマネージドソリューションを求めるなら、おすすめは新しいGoogle Firewall(成熟を待ったうえで)と、価格が予算に合うのであればAWS Network Firewallです。Kubernetesネームスペース単位での制御が必要なら、最もシンプルな解はCilium CRDで、Kubernetesネイティブな標準仕様が登場したらそちらに移行するとよいでしょう。

追記

2023年8月:同僚が

本記事執筆時点ではアルファ版だったGoogleの新リリースを踏まえ、これらのトピックについてより技術的に踏み込んだ記事を最近公開しました。