一覧CL-04-2 · 仮想ネットワーク

セキュリティグループとネットワークACL

戻りの宛先ポートと状態追跡を踏まえて、どの制御が通信を止めたかを規則とパケットから説明します。

説明

通信の許可を確認するときは、要求だけでなく応答も調べます。AWSのSecurity Groupは許可した通信の応答を追跡する一方、Network ACLは往路と復路をそれぞれの方向の規則で評価します。

10.0.1.10:49152から198.51.100.20:443へのTCPのSYNとSYN+ACKを使います。パケットの送信元・宛先ポートを読み、戻りを443宛てとして設定した誤りを直します。その後、ACLの番号順と、Security Groupの許可がない場合を確認します。

戻りの宛先ポートと状態追跡を踏まえて、どの制御が通信を止めたかを規則とパケットから説明します。

1要求と応答の四つのポート

固定パケットを数値で表示します。Flags [S]はSYN、[S.]はSYNとACKです。

tcpdump -nn -tt -Sアドレス・ポート・TCP番号を数値で表示する -r flow.pcap同じTCP通信の往復を読む 2>/dev/null

往路は10.0.1.10:49152→198.51.100.20:443、戻りは逆向きの443→49152です。戻りの送信元ポートは443ですが、宛先ポートはクライアント側の49152です。

2現在の許可規則

SGは外向き443を許可し、内向きの新規通信の許可はありません。ACLは両方向とも宛先443を許可した状態です。

cat sg.json状態追跡を行うSGの許可を読む cat acl.json方向別のACL規則を読む

SGとACLの両方に外向き443の許可がありますが、ACLの内向き規則が応答の宛先49152に合っていません。lowとhighは宛先ポートの範囲です。

3往路は許可されても戻りが拒否される

二つのパケットを順に規則へ照合します。SGは先の許可済み通信に対する逆方向を追跡します。

python3 filter.py往路から順にSGとACLを評価する

往路はSGとACLの両方でallowです。戻りのSGはtracked returnですが、ACLは一致する規則がなく*:denyになります。状態追跡でSGを通れても、独立したACLの拒否は残ります。

4戻りの宛先ポートを許可する

この例のクライアントが使う49152を含む、49152〜65535宛てを内向きに許可する案へ替えます。

cp acl-return.json acl.json戻りの宛先ポートに合うACLへ替える python3 filter.py同じパケットで再評価する

戻りはACL100:allowとなり、往復とも許可されます。応答を許可する範囲は、クライアント側が実際に使う一時ポートの範囲に合わせて決めます。

5追跡情報のない着信を確認

往路を処理せず、戻りと同じ形のパケットだけを評価します。

python3 filter.py --unsolicited先行する往路の記録なしで着信を評価する

ACLはallowでも、SGに既存の追跡情報と新規着信の許可がないためfinal=denyです。逆向きのIPとポートを持つことだけで、無条件に応答として通すわけではありません。

6先に一致したACLの拒否

内向きに番号90の拒否を加えた案を適用します。既存の許可は番号100です。

cp acl-deny-first.json acl.json許可より小さい番号の拒否を加える python3 filter.py最初に一致する番号を確認する

戻りは90:denyで拒否されます。ACLは小さい番号から評価し、最初に一致した規則を使うため、その後の100の許可には進みません。

7同じ拒否を許可の後ろへ置く

拒否の番号だけを110にした案へ替えます。

cp acl-deny-later.json acl.json拒否を番号100の許可より後ろへ移す python3 filter.py順序による結果の変化を確認する

戻りは100:allowとなり、110の拒否まで進みません。規則の存在だけでなく、番号と一致する範囲を合わせて確認する必要があります。

8ACLだけの許可では通信は成立しない

SGの外向き許可を取り除いた条件で、同じ往復を評価します。

cp sg-no-egress.json sg.jsonSGの新規外向き通信の許可を除く python3 filter.pySGとACLの両方の結果を読む

往路はSG=no allowで拒否され、戻りにも追跡情報がありません。SGとACLは別々の制御で、経路上で必要な許可をすべて満たす必要があります。

まとめ

戻りの宛先ポートは、要求時のクライアント側ポートです。

SGの状態追跡とACLの方向別評価を分けて確認します。

ACLでは最初の一致規則が適用され、他の制御の拒否をACLの許可で打ち消すことはできません。

操作履歴と解説を振り返れます。

シェル / Python 3

1
tcpdump -nn -tt -S -r flow.pcap 2>/dev/null
0.000000 IP 10.0.1.10.49152 > 198.51.100.20.443: Flags [S], seq 1000, win 64240, length 0
0.010000 IP 198.51.100.20.443 > 10.0.1.10.49152: Flags [S.], seq 9000, ack 1001, win 64240, length 0
2
cat sg.json cat acl.json
{
  "out": [
    {
      "cidr": "198.51.100.20/32",
      "low": 443,
      "high": 443
    }
  ],
  "in": []
}
{
  "out": [
    {
      "number": 100,
      "cidr": "198.51.100.20/32",
      "low": 443,
      "high": 443,
      "effect": "allow"
    }
  ],
  "in": [
    {
      "number": 100,
      "cidr": "198.51.100.20/32",
      "low": 443,
      "high": 443,
      "effect": "allow"
    }
  ]
}
3
python3 filter.py
out 10.0.1.10:49152 -> 198.51.100.20:443 SG=rule allow ACL=100:allow final=allow
in 198.51.100.20:443 -> 10.0.1.10:49152 SG=tracked return ACL=*:deny final=deny
4
cp acl-return.json acl.json python3 filter.py
out 10.0.1.10:49152 -> 198.51.100.20:443 SG=rule allow ACL=100:allow final=allow
in 198.51.100.20:443 -> 10.0.1.10:49152 SG=tracked return ACL=100:allow final=allow
5
python3 filter.py --unsolicited
in 198.51.100.20:443 -> 10.0.1.10:49152 SG=no allow ACL=100:allow final=deny
6
cp acl-deny-first.json acl.json python3 filter.py
out 10.0.1.10:49152 -> 198.51.100.20:443 SG=rule allow ACL=100:allow final=allow
in 198.51.100.20:443 -> 10.0.1.10:49152 SG=tracked return ACL=90:deny final=deny
7
cp acl-deny-later.json acl.json python3 filter.py
out 10.0.1.10:49152 -> 198.51.100.20:443 SG=rule allow ACL=100:allow final=allow
in 198.51.100.20:443 -> 10.0.1.10:49152 SG=tracked return ACL=100:allow final=allow
8
cp sg-no-egress.json sg.json python3 filter.py
out 10.0.1.10:49152 -> 198.51.100.20:443 SG=no allow ACL=100:allow final=deny
in 198.51.100.20:443 -> 10.0.1.10:49152 SG=no allow ACL=100:allow final=deny

演習完了