セキュリティグループとNACLを手で回す
目標
2つの装置の違いは、状態を記憶するかの1つだけで、残りの違いはすべてそこから出てきます。このラボは、クラウドアカウントなしで、ルール表を自分で書き、そのルール表を読む評価器を手で作って、その違いを目で見ます。
条件
- VPCは
10.42.0.0/16で、web・app・dbの3層があります。 - インターネットは、webの443にだけ入ってきます。
- webはappの8080を、appはdbの5432を呼び出します。
- appは外部のHTTPS(443)へ出ていきます。dbは外へ出ません。
ルール表の形式
セキュリティグループは5列です。相手の欄に、別のセキュリティグループ名を書けます。
그룹,방향,프로토콜,포트,상대
sg-db,inbound,tcp,5432,sg-app
ネットワークACLは6列です。番号が小さいものから見て、最初に合ったルールで終わります。
번호,방향,동작,프로토콜,포트범위,상대
100,outbound,allow,tcp,443,0.0.0.0/0
32767,outbound,deny,all,all,0.0.0.0/0
포트범위(プレースホルダーはポート範囲です)は、443のように1つだけ書くか、1024-65535のように範囲で書きます。프로토콜(プレースホルダーはプロトコルです)と포트범위(プレースホルダーはポート範囲です)には、allを使えます。
作るもの
| ファイル | 内容 |
|---|---|
/root/sgnacl/sg.csv |
3層のセキュリティグループのルール |
/root/sgnacl/nacl.csv |
appサブネットのNACL |
/root/sgnacl/nacl-ssh.csv・03-order.md |
順序の落とし穴と、その説明 |
/root/sgnacl/nacl_eval.py |
ルール表を読む評価器 |
/root/sgnacl/05-return.md |
応答が通るゲート |
/root/sgnacl/nacl-db.csv |
dbサブネットのガードレール |
/root/sgnacl/07-notes.md |
まとめ |
参考
ステップ4の評価器は、採点ツールが隠しているルール表でテストします。広い許可が前の番号にあり、狭い拒否があとにある表が入っているので、セキュリティグループの習慣どおりに拒否を優先させると、そこで引っかかります。
グループ参照で3層を結ぶ
3層のセキュリティグループのルールを、/root/sgnacl/sg.csvに그룹,방향,프로토콜,포트,상대(プレースホルダーはグループ、方向、プロトコル、ポート、相手です)の5列で書いてください。インターネットはsg-webの443にだけ入り、webはsg-appの8080を、appはsg-dbの5432を呼び出します。
sg-appとsg-dbの相手には、IPを書かないでください。別のセキュリティグループの名前をそのまま書けます。それがグループ参照です。
アプリサーバーが何台でも、オートスケーリングで増えても減っても、ルールを直す必要がなくなります。IPで書くと、サーバーが増えるたびにルールが増え、サーバーがなくなってもルールは残ります。
ポート22を0.0.0.0/0に開ける行は作らないでください。採点ツールがそれも見ます。
出ていく道と戻ってくる道を一緒に開ける
appサブネットのネットワークACLを、/root/sgnacl/nacl.csvに번호,방향,동작,프로토콜,포트범위,상대(プレースホルダーは番号、方向、動作、プロトコル、ポート範囲、相手です)の6列で書いてください。外部のHTTPS(443)へ出ていき、その応答が戻ってくる必要がありますが、外から入ってくるポート22と、出ていくポート3306は塞がれている必要があります。
NACLは状態を記憶しません。出ていく443を開けても、応答は別にルールを通る必要があり、応答はこちらのエフェメラルポート(1024–65535)へ戻ってきます。
最後にすべてを拒否する行を大きな番号で1つ置けば、書いていないものは自動的に塞がれます。そうすれば、ポート22とポート3306は、別に塞がなくてもかまいません。
番号は、100、200のように間を空けて付けてください。1、2、3と付けると、あとから間に差し込む場所がなく、すべて付け直しになります。
最初に合ったルールで終わる
100 전체 허용(プレースホルダーは全許可です)の次に200 tcp 22 거부(プレースホルダーは拒否です)を置いたルール表は、ポート22を塞げません。ポート22だけを塞いで残りは通すインバウンドのルールを/root/sgnacl/nacl-ssh.csvに書き、元の表がなぜだめなのかを/root/sgnacl/03-order.mdに書いてください。
NACLは、番号が小さいものから見て、最初に合ったルールで終わります。セキュリティグループのように、拒否が優先されるわけではありません。
そのため、狭い拒否を小さな番号に、広い許可を大きな番号に置きます。順序を変えるだけで、同じ2行が思いどおりに動作します。
説明には、번호、처음、22が含まれている必要があります(韓国語で、順に「番号」「最初」を意味する語と、数字の22です)。
評価器を自分で書く
/root/sgnacl/nacl_eval.pyを作成してください。python3 /root/sgnacl/nacl_eval.py <규칙파일> <방향> <포트> <상대IP>(プレースホルダーはルールファイル、方向、ポート、相手のIPです)で呼び出すと、1行目にallowまたはdenyだけを出力する必要があります。
ルールは3行です。同じ方向のルールだけを見て、番号の昇順で走査し、プロトコルとポートと相手がすべて合う最初のルールの動作をそのまま出します。どれにも合わなければdenyです。
アドレスがアドレス範囲に入るかは、ipaddress.ip_address(x) in ipaddress.ip_network(cidr)で見ます。ポート範囲は、443と1024-65535とallの3種類だけを扱えば十分です。
採点ツールは隠したルール表でテストします。広い許可が前の番号にあり、狭い拒否があとにある表が入っているので、拒否を優先させると、そこで引っかかります。
応答が通るゲートを数える
インターネットからsg-webの443に入ってきたリクエストの応答が出ていくとき、セキュリティグループとネットワークACLのそれぞれに何がさらに必要かを、/root/sgnacl/05-return.mdに4行以上書いてください。
セキュリティグループは、入ってきた接続を記憶します。そのため、応答に対するルールを別に書く必要はありません。
NACLは記憶しません。応答もルールを通る必要があり、応答が向かう先は相手のエフェメラルポートです。その範囲を数字で書いてください。
この違い1つのせいで、「インバウンドは開けたのに応答が来ない」で半日を費やします。
サブネット全体にガードレールをかける
dbサブネットがインターネットへ出ること自体をNACLで封鎖しつつ、VPC(10.42.0.0/16)内の通信は生かしておいてください。ルールは/root/sgnacl/nacl-db.csvに書きます。
セキュリティグループはインスタンスごとに付きますが、NACLはサブネット全体に付きます。そのため、「このサブネットはインターネットに出ない」のような広いガードレールに向いています。
VPCのアドレス範囲を許可するルールを小さな番号に、0.0.0.0/0を拒否するルールを大きな番号に置いてください。順序が逆だと、許可が永遠に適用されません。
appが5432で入ってくることと、その応答がエフェメラルポートへ出ていくことまで、生きている必要があります。
3つをまとめる
/root/sgnacl/07-notes.mdに3行以上。2つの装置の状態の扱いの違い、NACLの番号が決めるもの、セキュリティグループのルールをIPで書くと起きること。
本文に상태、번호、그룹 참조が含まれている必要があります(韓国語で、順に「状態」「番号」「グループ参照」を意味する語です)。