ファイアウォールのルール評価
規則の判定位置と往復の通信を照合し、許可・破棄の条件を説明します。
説明
ファイアウォールの規則では、送信元・宛先アドレス、ポート、プロトコルなどを照合します。複数規則に一致する通信では、評価順と処理を終える条件が結果を左右します。
先に一致したacceptまたはdropで終了する規則表をPythonで評価します。これは一つの規則列の評価であり、複数チェーンや後段装置の最終判断まで含むものではありません。
規則の判定位置と往復の通信を照合し、許可・破棄の条件を説明します。
1検査する5タプルを表示する
送信元ポート53000からHTTPSの443番へ向かうTCPです。
from sp03 import *
print(PACKET検査する5タプルを表示する)
print(RULES)規則10は端末7から特定サーバーへの許可、規則20は同じ送信元ネットワークから443番への破棄です。
2各規則への一致を個別に調べる
この通信がどの規則に一致するかを確認します。
print([(r[0],matches各規則への一致を個別に調べる(PACKET,r)) for r in RULES])両方Trueです。規則に一致したことだけでは、最終処理を一つに決められません。
3先に一致した規則で評価を終える
番号が小さい順に評価します。
print(trace先に一致した規則で評価を終える(PACKET,RULES))規則10のacceptで終了し、20には進みません。この評価モデルでは許可です。
4広い破棄規則を前へ移す
規則20の優先番号を5へ変えます。
reordered広い破棄規則を前へ移す = [RULES[0],(5,*RULES[1][1:])]
print(trace(PACKET,reordered))規則5でdropになります。狭い例外許可が後ろにあっても到達できません。
5送信元を同じサブネットの別端末へ変える
192.0.2.8は規則10の/32には含まれません。
other = ('192.0.2.8',*PACKET[1:])
print(trace送信元を同じサブネットの別端末へ変える(other,RULES))10は不一致、20は一致してdropです。/32は一つのIPv4アドレス、/24は256個のアドレス範囲を表します。
6TCPとUDPの条件を確認する
宛先443のままプロトコルだけをUDPへ変えます。
udp = (*PACKET[:4],'udp')
print(traceTCPとUDPの条件を確認する(udp,RULES))
print(trace(udp,RULES,default='accept'))どちらの規則にも一致しません。最後のdropまたはacceptは既定処理の違いです。443番だけではTCP、UDP、アプリの内容まで同一とは言えません。
7ログ取得だけでは評価を終えない理由を確認する
評価途中を全件記録した結果と、終端処理の実行経路を比較します。
all_matches = [(r[0],matches(PACKET,r)) for r in RULES]
visited,verdict = traceログ取得だけでは評価を終えない理由を確認する(PACKET,RULES)
print('matches',all_matches)
print('visited',visited,'verdict',verdict)全件照合では20もTrueですが、実行経路に20はありません。ログの一致件数と実際に通った規則を分けて調べます。
まとめ
5タプルとアドレス範囲を確認します。
最初の終端処理まで規則順を追います。
不一致の通信には既定処理が適用されます。
操作履歴と解説を振り返れます。
Python 3.15 / 規則評価と固定の通信記録
from sp03 import *
print(PACKET)
print(RULES)('192.0.2.7', 53000, '198.51.100.20', 443, 'tcp')
[(10, '192.0.2.7/32', '198.51.100.20/32', 443, 'tcp', 'accept'), (20, '192.0.2.0/24', '0.0.0.0/0', 443, 'tcp', 'drop')]print([(r[0],matches(PACKET,r)) for r in RULES])[(10, True), (20, True)]
print(trace(PACKET,RULES))([(10, True, 'accept')], 'accept')
reordered = [RULES[0],(5,*RULES[1][1:])]
print(trace(PACKET,reordered))([(5, True, 'drop')], 'drop')
other = ('192.0.2.8',*PACKET[1:])
print(trace(other,RULES))([(10, False, '-'), (20, True, 'drop')], 'drop')
udp = (*PACKET[:4],'udp')
print(trace(udp,RULES))
print(trace(udp,RULES,default='accept'))([(10, False, '-'), (20, False, '-')], 'drop') ([(10, False, '-'), (20, False, '-')], 'accept')
all_matches = [(r[0],matches(PACKET,r)) for r in RULES]
visited,verdict = trace(PACKET,RULES)
print('matches',all_matches)
print('visited',visited,'verdict',verdict)matches [(10, True), (20, True)] visited [(10, True, 'accept')] verdict accept
演習完了