Help us understand the problem. What is going on with this article?

NSGで「明示的に許可した通信以外は全て拒否」を設定する際の考慮点

はじめに

セキュリティ要件として、「明示的に許可した通信以外は全て拒否したい」というのはよくあると思いますが、Azureでそれをやろうとした際にちょっとハマったポイントがあり、調べて「そうなんだ」と思ったので内容をまとめます。

今は仕事で(ほぼ初めて)Azureを触っているのですが、Azureのコンソールは(AWSに比べて)あまり優しくないな、というのが現時点の正直な感想です。

システム構成

(構成イメージ)
system.png

※やりたいこと

  • クライアントサーバ(VNet-A)からWebサーバ(VNet-B)にHTTP接続する
  • Webサーバの前段にALBを配置し、内部ロードバランシングを実施(ALBはWebサーバと同じサブネット上に配置)

環境情報

【クライアントサーバ】

  • Windows Server 2016 Datacenter
  • 自PCからの接続用にパブリックIP割り当てとRDP許可以外は全てデフォルトで構築

【Webサーバ】

  • Ubuntu Server 18.04 LTS
  • 構築後、NGINXをデフォルトでインストール
  • 自PCからの接続用にパブリックIP割り当てを実施
  • NSG設定は下記の通り(インバウンドルールのみ記載。アウトバウンドルールはデフォルト)
ソース ポート 宛先 許可/拒否
10.0.1.0/24 80 any 許可
10.0.1.0/24 22 any 許可
(自PCのIP) 22 any 許可

事象

Azureでセキュリティを厳密にするため、Webサーバ側のNSGに対し、個別にCIDR指定で許可したプロトコル(HTTPなど)以外のVirtualNetworkからの通信を全て拒否(Deny)するインバウンドルールを追加しました。

※追加設定

ソース ポート 宛先 許可/拒否
any * VirtualNetwork 拒否

NSG(AWSのSGも同様ですが)は優先度が高い(若い番号)のルールで許可されている方が優先されるはずでしたが、この設定を入れた瞬間にALB経由でのHTTP接続ができなくなりました。

事象切り分け

  • NSG追加前はALB経由で接続OK
  • NSG追加後もALBを経由しない場合(クライアントサーバからWebサーバに直接続する場合)は接続OK

エラーメッセージ

PS C:\Users\azureuser> curl http://10.1.1.4
curl : Unable to connect to the remote server
At line:1 char:1
+ curl http://10.1.1.4
+ ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

※参考までに成功時

PS C:\Users\azureuser> curl http://10.1.1.6

StatusCode        : 200
StatusDescription : OK
Content           : <!DOCTYPE html>
                    <html>
                    <head>
                    <title>Welcome to nginx!</title>
                    <style>
                        body {
                            width: 35em;
                            margin: 0 auto;
                            font-family: Tahoma, Verdana, Arial, sans-serif;
                        }
                    </style>
                    <...
RawContent        : HTTP/1.1 200 OK
                    Connection: keep-alive
                    Accept-Ranges: bytes
                    Content-Length: 612
                    Content-Type: text/html
                    Date: Tue, 18 Feb 2020 05:50:36 GMT
                    ETag: "5e4b58cf-264"
                    Last-Modified: Tue, 18 Feb 2020 ...
Forms             : {}
Headers           : {[Connection, keep-alive], [Accept-Ranges, bytes],[Content-Length, 612], [Content-Type,
                    text/html]...}
Images            : {}
InputFields       : {}
Links             : {@{innerHTML=nginx.org; innerText=nginx.org; outerHTML=<A href="http://nginx.org/">nginx.org</A>;
                    outerText=nginx.org; tagName=A; href=http://nginx.org/}, @{innerHTML=nginx.com;
                    innerText=nginx.com; outerHTML=<A href="http://nginx.com/">nginx.com</A>; outerText=nginx.com;
                    tagName=A; href=http://nginx.com/}}
ParsedHtml        : System.__ComObject
RawContentLength  : 612

調査のためにやったこと

通信のどこで詰まっているかを調べるため、クライアントサーバ上でパケットキャプチャーを取得しました。

(Azureライクなやり方もあるのかもしれませんが)

Windows Serverでのパケットキャプチャー取得手順

手順はこちらの記事を参考にしました。

https://qiita.com/legitwhiz/items/59794b2a97e4fe1aba21

ただ、netshコマンドで作成した.etlファイルを.pcap形式に変換する際に使う「Microsoft Message Analyzer」は既に配布終了となっているそうです。

代替ツールがMicrosoftから提供されているので、今回はそちらを使用しました。

etl2pcapng(github)

※参考情報
https://troushoo.blog.fc2.com/blog-entry-416.html

解析結果

接続NG/OK時のキャプチャーはそれぞれ下記の通りです。

【接続NG時】
pcap_NG.png

【接続OK時】
pcap_OK.png

※要点

  • 「10.0.1.5」がクライアントサーバ
  • 「10.1.1.4」がALB
  • 「10.1.1.6」がWebサーバ
  • 成功時は「10.1.1.4」から「10.0.1.5」に200が返却されている(接続OK時のNo.44)
  • 「[TCP Retransmission]」は通信エラーで再送しました的なメッセージ

これだけ見てもなかなか難しい間違い探しになりますが、共通点として、目的の宛先に繋ぐ前に「168.63.129.16」というアドレスに対して接続を行っているように見えました。
何かの手がかりになると思い、このアドレスが何者かについて調べました。

168.63.129.16とは?

調べてみたら、Microsoftのサイトに情報がありました。

https://docs.microsoft.com/ja-jp/azure/virtual-network/what-is-ip-address-168-63-129-16

IP アドレス 168.63.129.16 は、Azure プラットフォーム リソースへの通信チャネルの使用を容易にするために使用される仮想パブリック IP アドレスです。

これは、既定のネットワーク セキュリティ グループの規則によって許可されています。 インバウンドとアウトバウンド両方向のすべてのローカル ファイアウォール ポリシーで、この IP アドレスを許可することをお勧めします。

要するに、Azureが提供するサービスにアクセスするためのパブリックIP、ということです。
AWSでもS3などのリージョンサービスはパブリックネットワーク上にあるため、そのサービスを利用するためにはインターネット接続(もしくはVPCエンドポイントによるプライベート接続)が必要になりますが、おそらくそれと似たような話なのだと思います。

理屈はさておき、NSGで「VirtualNetwork」からの通信を拒否したことにより、ALBを含むAzureサービスを利用するために必要な「168.63.129.16」への通信も遮断されてしまったため、ALB経由で通信ができなくなったのが原因だと考えられます。

検証①

上記を踏まえ、先程追加した定義の上にパブリックIPの通信を許可する設定を追加しました。

ソース ポート 宛先 許可/拒否
168.63.129.16 * any 許可
any * VirtualNetwork 拒否

その結果、ALB経由でもHTTP接続が可能になりました。

検証②

一方で、ALBを前段にしてVMを構成するとNSGに「AzureLoadBalancer」の定義がデフォルト(優先度65001)で追加されますが、それを優先度を上げて定義したらどうなるか試してみました。

結論としてはこれでも接続OKでした。

ソース ポート 宛先 許可/拒否
AzureLoadBalancer * any 許可
any * VirtualNetwork 拒否

下記のページによると、「AzureLoadBalancer」のサービスタグはパブリックIPに変換されるとあるので、これでも同じ意味になるようです。
※「VirtualNetwork」はもう少し範囲が広いものの、パブリックIPも含めた定義になっているようです。

https://docs.microsoft.com/ja-jp/azure/virtual-network/service-tags-overview

まとめ

Azureはデフォルトだと同じVirtualNetworkからの通信は許可されてしまうため、「明示的に許可したもの以外は全て拒否」をしたい場合は、使用するサービスもサービスタグで明示的に許可を入れてあげる必要がある、とわかりました。

色々話を聞いていると、Azureも以前からするとかなり仕様が変わっていて、まだまだ発展途上ということらしいので、今後はアップデートに追いつけるようにしたいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした