この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
ネットワークACL(NACL)設定をCloudFormation テンプレートで展開してみます。 使用するCFnリソースの説明と実際の展開例の紹介を行います。
※ 実際には NACLを導入する前に、セキュリティグループによるトラフィック制御で 代用できないか、オンプレ側セキュリティアプライアンスで対応できないか、 など検討すると良いです。
セキュリティグループに関する話は以下ブログに良くまとまっているので参照下さい。
CFnリソース解説
ざっくりとしたイメージは以下の通り。赤字で示した部分が NACL設定で必要なリソースです。
AWS::EC2::NetworkAcl
NACLを新規作成するためのリソースです。 NACLを設定する VPCを指定しましょう。
以下 リソース記述例です。
Nacl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VpcId
Tags:
- Key: Name
Value: xxx-nacl
ちなみに、これだけだと インバウンド/アウトバウンド通信をすべて拒否する NACLになります。
AWS::EC2::SubnetNetworkAclAssociation
NACL関連付けを行うためのリソースです。 関連付けを行いたいサブネット毎に作成します。
以下 リソース記述例です。
NaclAssoc:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
NetworkAclId: !Ref Nacl
SubnetId: !Ref SubnetId
AWS::EC2::NetworkAclEntry
実際の NACLのルール 1つ1つが このリソースに当たります。
マネコンの表記と、実際の CFnリソース記述との関連を表したイメージが以下になります。
各プロパティを以下説明します。
- NetworkAclId
ルールを挿入したいNACLのIDを指定します。
-
Egress
アウトバウンドルールの場合は
true
、インバウンドルールの場合はfalse
を指定します。 -
RuleNumber
ルール番号を指定します。
※ NACLはルール番号の昇順で見ていって、最初にマッチしたルールが適用されます。 設計で注意が必要です。
-
Protocol
IPプロトコルを指定します。以下早見表です。
プロトコル 指定する番号 ICMP 1 TCP 6 UDP 17 すべて -1 - PortRange
UDP/TCP のポート範囲を指定します。
-
Icmp
※
Protocol
で ICMPを選択した場合に必須です。 ICMPコードおよびタイプを記します。以下, Icmpパラメータの記述例です。
# これは Echo Reply (すべての Code) Icmp: Type: 0 Code: -1 # これは Echo Request (すべての Code) Icmp: Type: 8 Code: -1
ICMP Type/Code の詳細は以下参照ください。
- CidrBlock
CIDR表記で IPアドレスレンジを指定します。
-
RuleAction
許可
allow
もしくは 拒否deny
です。
ユースケース/展開例
以下のようなケースを考えます。
要件は以下の通り。 AWSからオンプレへの方向への通信を制御します。
- AWS(VPC)内 通信 や NATGW 経由のアウトバウンド通信 は
すべて許可したい
- オンプレ → AWS への方向の通信は
すべて許可したい
- AWS → オンプレ への方向の通信は基本的に
すべて拒否したい
- ただし オンプレサーバー
192.168.0.200
への通信(TCP/1218ポート
) は業務システムの都合上どうしても利用しないといけないため、許可する
- ただし オンプレサーバー
上記要件を満たす NACLを展開してみましょう。
NACL 設計
NACL設計の際は以下気をつけましょう。
- ルール番号の若い順番に評価されること
- ルール数の上限は 20 (上限緩和申請で 40)
- インバウンドのルール
ルール番号 タイプ プロトコル ポート範囲 送信先 許可/拒否 備考 100 すべてのトラフィック すべて すべて 0.0.0.0/0 ALLOW デフォルトALLOW * すべてのトラフィック すべて すべて 0.0.0.0/0 DENY デフォルトDENY 今回の制御は 「AWSからオンプレへのアウトバウンド通信」がメインなので、 インバウンドルールは触りません。すべて 許可(ALLOW)とします。
-
アウトバウンドのルール
ルール番号 タイプ プロトコル ポート範囲 送信先 許可/拒否 備考 1 すべてのトラフィック すべて すべて 10.0.0.0/16 ALLOW AWS(VPC)内通信 2 カスタムTCPルール TCP 1218 192.168.0.200/32 ALLOW 特定オンプレサーバーへの通信 10 カスタムTCPルール TCP 1024-65535 192.168.0.0/16 ALLOW エフェメラルポート(TCP) 11 カスタムTCPルール UDP 1024-65535 192.168.0.0/16 ALLOW エフェメラルポート(UDP) 12 カスタムICMPルール ICMP Echo Reply 192.168.0.0/16 ALLOW Ping 確認用 50 すべてのトラフィック すべて すべて 192.168.0.0/16 DENY オンプレへの通信 100 すべてのトラフィック すべて すべて 0.0.0.0/0 ALLOW デフォルトALLOW * すべてのトラフィック すべて すべて 0.0.0.0/0 DENY デフォルトDENY 設定したルールの概説は以下の通り。
- ルール番号:1 - AWS(VPC)内通信を許可します
- ルール番号:2 - 特定オンプレサーバーへの通信を許可します
- ルール番号:10,11,12
- 基本的には後述の ルール(50番) で
AWS→オンプレ: (AWSからみて)行きの通信
を拒否しますが、オンプレ→AWS: (AWSからみて)戻りの通信
は許可しないといけません - そのために TCP/UDP では戻り通信に使われるポート(エフェメラルポート)を、 ICMPでは オンプレからの ping 疎通確認を想定して Echo Reply を許可しています
- 基本的には後述の ルール(50番) で
- ルール番号:50 - オンプレへの通信を拒否します
- ルール番号:100 - デフォルトALLOWです。これが無いと NATGW経由アウトバウンドができません
CloudFormation
前述の NACL設計をそのまま CFnテンプレート化しました。 パラメータとして NACLを適用する VPC ID や Subnet IDを指定します。
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
# プレフィクス
Prefix:
Type: String
Default: sample-env
# NACL生成する VPC
VpcId:
Type: AWS::EC2::VPC::Id
# VPC CIDR
VpcCidr:
Type: String
Default: 10.0.0.0/16
# NACL関連付けする サブネット
SubnetId:
Type: AWS::EC2::Subnet::Id
Resources:
# ### NACL生成
Nacl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VpcId
Tags:
- Key: Name
Value: !Sub ${Prefix}-nacl
# ### NACLの関連付け
NaclAssoc:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
NetworkAclId: !Ref Nacl
SubnetId: !Ref SubnetId
# ### インバウンドルール
# すべて許可
NaclEntryInbound:
Type: AWS::EC2::NetworkAclEntry
Properties:
Egress: false
RuleNumber: 100
RuleAction: allow
Protocol: -1
CidrBlock: 0.0.0.0/0
NetworkAclId: !Ref Nacl
# ### アウトバウンドルール
# VPC内はすべてALLOW
NaclEntry001:
Type: AWS::EC2::NetworkAclEntry
Properties:
Egress: true
RuleNumber: 1
RuleAction: allow
Protocol: -1
CidrBlock: !Ref VpcCidr
NetworkAclId: !Ref Nacl
# 特定サーバーへの通信は ALLOW
NaclEntry002:
Type: AWS::EC2::NetworkAclEntry
Properties:
Egress: true
RuleNumber: 2
RuleAction: allow
Protocol: 6
CidrBlock: 192.168.0.200/32
PortRange:
From: 1218
To: 1218
NetworkAclId: !Ref Nacl
# オンプレへの戻り通信(TCP/UDP エフェメラルポート)は ALLOW
NaclEntry010:
Type: AWS::EC2::NetworkAclEntry
Properties:
Egress: true
RuleNumber: 10
RuleAction: allow
Protocol: 6
CidrBlock: 192.168.0.0/16
PortRange:
From: 1024
To: 65535
NetworkAclId: !Ref Nacl
NaclEntry011:
Type: AWS::EC2::NetworkAclEntry
Properties:
Egress: true
RuleNumber: 11
RuleAction: allow
Protocol: 17
CidrBlock: 192.168.0.0/16
PortRange:
From: 1024
To: 65535
NetworkAclId: !Ref Nacl
# オンプレへの戻り通信(ping EchoReply)は ALLOW
NaclEntry012:
Type: AWS::EC2::NetworkAclEntry
Properties:
Egress: true
RuleNumber: 12
RuleAction: allow
Protocol: 1
Icmp:
Code: -1
Type: 0
CidrBlock: 192.168.0.0/16
NetworkAclId: !Ref Nacl
# それ(戻り通信)以外のオンプレへの通信は すべてDENY
NaclEntry050:
Type: AWS::EC2::NetworkAclEntry
Properties:
Egress: true
RuleNumber: 50
RuleAction: deny
Protocol: -1
CidrBlock: 192.168.0.0/16
NetworkAclId: !Ref Nacl
# デフォルトのALLOW
NaclEntry100:
Type: AWS::EC2::NetworkAclEntry
Properties:
Egress: true
RuleNumber: 100
RuleAction: allow
Protocol: -1
CidrBlock: 0.0.0.0/0
NetworkAclId: !Ref Nacl
確認
CFn 展開後の設定を見てみます。
- インバウンドのルール
-
アウトバウンドのルール
設計通りの内容になっていました。
おわりに
NACLはステートレスなので戻り通信のことを考えることが大変ですね。 できれば (AWS側は) Security Group、 (オンプレ側は) ステートフル制御対応のNW機器/Firewall で全てステートフルで済ませたいところです。
それら対応が難しい場合は NACLによる設計を検討下さい。 少しでもどなたかのお役に立てば幸いです。
参考
▼ Developers.IO
▼ AWS Document