Fortigateのコンサーブモード conserve mode が実際の通信にどのような影響を与えるか?
勉強を兼ねて自宅構成で検証しました。
Fortigateのコンサーブモードとは
公式ナレッジベースからの引用
Conserve modeとはどのようなモードですか?
システム上で使用しているメモリ使用率が高まったときに、FortiGateは自己防御機能としてのConserve modeへ移行します。Conserve modeに移行したときには、FortiGateはメモリ領域を確保するための動作をとります。十分なメモリが回復された場合、システムはConserve modeを抜け(leaving/exiting)、自己防御機能を解除します。
メモリが少なくなってきた際の「節約モード」ということである。
また、以下では
Conserve modeになった時は、Antivirusの機能とパフォーマンスが影響を受けます。詳細については下記Related ArticlesにリストされているKB"Antivirus failopen and optimization"を参照してください。
「アンチウイルス機能とパフォーマンスが影響を受ける」と記載がある。
コンサーブモードの概要や設定、具体的な影響は以下のAdminGuideにあるとおり。
- メモリ利用率が 88%(=red) を超過すると、コンサーブモード発動
- メモリ利用率が 95%(=extreme) を超過すると、コンサーブモードのまま+新規セッションをドロップ
- メモリ利用率が 82%(=green) を下回れば、コンサーブモードが終了
これらはデフォルト値であり green < red < extreme になるように、70%~97% の間で設定可能である。
config system global
set memory-use-threshold-extreme 95
set memory-use-threshold-red 88
set memory-use-threshold-green 82
end
Proxy Inspection/Flow Inspectionのどちらも fail-open
の動作を規定できると書いてあるが、それぞれでデフォルト動作が全く逆のようである。
- Proxy Inspectionのデフォルトはpassで、プロキシとしてのセキュリティチェックがバイパスされる。
- Flow Inspectionのデフォルトはdisableで、フローベースのセキュリティチェックするセッションがドロップされる。
また、システムがその時点でコンサーブモードになっているかどうかは、以下のコマンドで確認可能。
diagnose hardware sysinfo conserve
今回の検証では「透過モード」「フローベース」を想定し、コンサーブモードに突入したときの影響を調査する。
調査には、ESXiにデプロイするFortigateVMを利用するが、強制的にコンサーブモードへ遷移させるため、仮想マシンの搭載メモリを減らしており、完全に現実世界の動作を再現できていない可能性がある。
検証
によると、ICMPのセッションタイムアウトは60秒で固定とのこと。
これを利用して、以下のようにテストを実施する。
- 下流PC→Fortigate→上流PCにPINGを継続的に発行する
- コンサーブモード(red/extreme)を強制的に発動
- PINGの状態を確認
- PINGを停止し、セッションタイムアウト(60秒)を待つ or セッションを強制的にクリアする
- PINGを再開して状態を確認
公式ページには、
redモードの動作
コンサーブモードはメモリを使いすぎると発動するが、なかなかそこまでメモリを使い切ることは難しい。
幸い、FortigateのVMで検証したため、仮想マシン自体のメモリを減らしたうえで、以下コマンドでスレッショルドを変更することでなんとかredモードにすることができた。
config system global
set memory-use-threshold-red 71
set memory-use-threshold-green 70
end
PINGを継続的に発行した状態でセッションテーブルを確認する。
まず、セッションフィルタでICMPだけに絞る。
このセッションフィルタは表示だけでなく、後述する diag sys session clear
するときのフィルタでもあり、これをやらずにセッションクリアすると、管理用のsshセッションや、そのほかの全通信のセッションがクリアされるので、注意が必要。
diagnose sys session filter proto 1
diagnose sys session list
PINGを継続的に発行しているため expire=59
で常時更新されていることがわかる。
つまり、セッションが「落ちる」ことはない。
session info: proto=1 proto_state=00 duration=2201 expire=59 timeout=0 flags=00000000 socktype=0 sockport=0 av_idx=0 use=3
origin-shaper=
reply-shaper=
per_ip_shaper=
class_id=0 ha_id=0 policy_dir=0 tunnel=/ vlan_cos=0/255
state=may_dirty br
statistic(bytes/packets/allow_err): org=130320/2172/1 reply=130320/2172/1 tuples=2
tx speed(Bps/kbps): 59/0 rx speed(Bps/kbps): 59/0
orgin->sink: org pre->post, reply pre->post dev=4->5/5->4 gwy=10.254.10.11/10.254.10.35
hook=pre dir=org act=noop 10.254.10.35:1->10.254.10.11:8(0.0.0.0:0)
hook=post dir=reply act=noop 10.254.10.11:1->10.254.10.35:0(0.0.0.0:0)
misc=0 policy_id=4 auth_info=0 chk_client_info=0 vd=0
serial=00018f3b tos=ff/ff app_list=0 app=0 url_cat=0
sdwan_mbr_seq=0 sdwan_service_id=0
rpdb_link_id=00000000 rpdb_svc_id=0 ngfwid=n/a
npu_state=0x041001 no_offload
total session 1
pingを停止して60秒待つと以下のようになる。
fortigate # diagnose sys session list
total session 0
fortigate #
60秒待たなくても、手動でクリアすればセッションが消える。
diagnose sys session clear
この状態で、新規にPINGを打とうとしても通らない。
が、下流PCでパケットキャプチャしたところ、ARPリクエスト⇔ARPリプライは通っていることがわかった。
そのうえ、セッションリストにもICMPとして出てきている。
diagnose sys session list
session info: proto=1 proto_state=00 duration=4 expire=55 timeout=0 flags=00000000 socktype=0 sockport=0 av_idx=0 use=3
origin-shaper=
reply-shaper=
per_ip_shaper=
class_id=0 ha_id=0 policy_dir=0 tunnel=/ vlan_cos=0/255
state=may_dirty ndr br
statistic(bytes/packets/allow_err): org=0/0/0 reply=0/0/0 tuples=2
tx speed(Bps/kbps): 0/0 rx speed(Bps/kbps): 0/0
orgin->sink: org pre->post, reply pre->post dev=4->5/5->4 gwy=10.254.10.11/10.254.10.35
hook=pre dir=org act=noop 10.254.10.35:1->10.254.10.11:8(0.0.0.0:0)
hook=post dir=reply act=noop 10.254.10.11:1->10.254.10.35:0(0.0.0.0:0)
misc=0 policy_id=4 auth_info=0 chk_client_info=0 vd=0
serial=00022135 tos=ff/ff app_list=0 app=0 url_cat=0
sdwan_mbr_seq=0 sdwan_service_id=0
rpdb_link_id=00000000 rpdb_svc_id=0 ngfwid=n/a
npu_state=0x041001 no_offload
total session 1
一時的にセッションフィルタをクリアして、他の通信もみてみると、わんさか出てくる。
diagnose sys session filter clear
diagnose sys session list
(いっぱいでてくる)
diagnose sys session filter proto 1
これは、FlowInspectionのデフォルト動作である「セキュリティチェックが必要な新規セッションをドロップ」と思われる。
FWポリシーに「Certificate-Inspection」だけが有効になっている通信は、セッションクリアしてもPING疎通可。
FWポリシーに「Webフィルタ」と「Certificate-Inspection」が有効になっている通信は、セッションクリア後にPING疎通不可。
ただし、ポリシーの順番で、「Webフィルタ」と「Certificate-Inspection」が先に来ている場合はPING疎通不可となった。
Certificate-Inspectionはフローベースのセキュリティチェックではないのだろうか?
ともかくWebフィルタがある場合は、ここに引っかかる。ということがわかった。
なお、FWポリシーの対象プロトコルはICMPとしたため「Webフィルタ」「Certificate-Inspection」の設定は何の意味もないが、デフォルト動作に引っ張られるようだ。
試しに fail-open
を有効にして、セキュリティチェックをバイパスできるかをチェックしてみる。
config ips global
set fail-open enable
end
この設定をいれることで、コンサーブモード(red)による疎通不可の回避ができるようになった。が、おそらく、なんのフィルタもしないので、セキュリティ的にはザル状態である。
アンチウィルスを含め、そのほかのFWポリシーはFortiGuardに接続できなくて使えていないため、検証はしていない。
extremeモードの動作
さらにスレッショルドを低く設定することで強制的にextremeモードを発動させて検証してみる。
config system global
set memory-use-threshold-extreme 72
set memory-use-threshold-red 71
set memory-use-threshold-green 70
end
この場合はpingを発行し続けた状態で diagnose sys session clear
してもセッションリストに載ってくることはなかった。通信セッションそのものがドロップされているためだと思われる。
セッションのexpireが続く限りはPINGは疎通し続けていた。
通信セッション自体が確立されないので、Proxy Inspection/Flow Inspectionのどちらであろうとも通信不能となる。たとえ fail-open
設定をしていたとしても、そもそも通信そのもののセッションが確立できずセキュリティフィルタまで到達しないため、通信は成立しない。
マルチキャスト通信への影響
自宅では、VyosでVRRPを動作させてたり、GNS3のCiscoでHSRPを動作させたりしているので、HSRP/VRRPの通信状況も調査してみた。
HSRP/VRRPのどちらもマルチキャストを利用しており、マルチキャストポリシーで許可の設定としている。
red/extremeのどちらのコンサーブモードでもマルチキャスト通信はポリシーで許可した通りに通過しており、上流PCでは下流からのVRRPが、下流PCでは上流からのHSRPが到着していた。
SNMPによるコンサーブモードの検知
FORTINET-FORTIGATE-MIB
(FortigateのWebUIから取得できるファイル)を見ると、以下のものがコンサーブモードに関連しているものとみられる。
なお、これ以降のSNMP関連コマンドを利用するためにMIBファイルを /usr/share/snmp/mibs
にそのままぶち込んでいる。(ちょっと横着してしまいました)
FORTINET-FORTIGATE-MIB::fgSIAdvMemEnterKerConsThrsh
FORTINET-FORTIGATE-MIB::fgSIAdvMemLeaveKerConsThrsh
FORTINET-FORTIGATE-MIB::fgSIAdvMemEnterProxyConsThrsh
FORTINET-FORTIGATE-MIB::fgSIAdvMemLeaveProxyConsThrsh
FORTINET-FORTIGATE-MIB::fgTrapAvEnterConserve
FORTINET-FORTIGATE-MIB::fgTrapAvBypass
ポーリングはいずれも「設定されている閾値」を取得するものであり、「現在コンサーブモードであるかどうか」を取得するものではないらしい。
PollingのOIDはfgSysInfoAdvMem
配下に所属するらしいので、これを取得してみる。
$ snmptranslate -Tp FORTINET-FORTIGATE-MIB::fgSysInfoAdvMem
+--fgSysInfoAdvMem(1)
|
+-- -R-- Gauge fgSIAdvMemPageCache(1)
+-- -R-- Gauge fgSIAdvMemCacheActive(2)
+-- -R-- Gauge fgSIAdvMemCacheInactive(3)
+-- -R-- Gauge fgSIAdvMemBuffer(4)
+-- -R-- Gauge fgSIAdvMemEnterKerConsThrsh(5)
+-- -R-- Gauge fgSIAdvMemLeaveKerConsThrsh(6)
+-- -R-- Gauge fgSIAdvMemEnterProxyConsThrsh(7)
+-- -R-- Gauge fgSIAdvMemLeaveProxyConsThrsh(8)
$ snmpwalk -v 2c -c ro fortigate.prosper2.net FORTINET-FORTIGATE-MIB::fgSysInfoAdvMem
FORTINET-FORTIGATE-MIB::fgSIAdvMemPageCache.0 = Gauge32: 502328 KB
FORTINET-FORTIGATE-MIB::fgSIAdvMemCacheActive.0 = Gauge32: 166144 KB
FORTINET-FORTIGATE-MIB::fgSIAdvMemCacheInactive.0 = Gauge32: 302628 KB
FORTINET-FORTIGATE-MIB::fgSIAdvMemBuffer.0 = Gauge32: 72 KB
FORTINET-FORTIGATE-MIB::fgSIAdvMemEnterKerConsThrsh.0 = Gauge32: 735680 KB
FORTINET-FORTIGATE-MIB::fgSIAdvMemLeaveKerConsThrsh.0 = Gauge32: 685520 KB
FORTINET-FORTIGATE-MIB::fgSIAdvMemEnterProxyConsThrsh.0 = Gauge32: 735680 KB
FORTINET-FORTIGATE-MIB::fgSIAdvMemLeaveProxyConsThrsh.0 = Gauge32: 685520 KB
コンサーブモード状態を確認するコマンドで閾値が確認できる。
fortigate # diagnose hardware sysinfo conserve
memory conserve mode: off
total RAM: 816 MB
memory used: 604 MB 74% of total RAM
memory freeable: 140 MB 17% of total RAM
memory used + freeable threshold extreme: 775 MB 95% of total RAM
memory used threshold red: 718 MB 88% of total RAM
memory used threshold green: 669 MB 82% of total RAM
トラップのOIDは以下のようになっていた。
$ snmptranslate -On FORTINET-FORTIGATE-MIB::fgTrapAvEnterConserve
.1.3.6.1.4.1.12356.101.2.0.605
$ snmptranslate -On FORTINET-FORTIGATE-MIB::fgTrapAvBypass
.1.3.6.1.4.1.12356.101.2.0.606
redモードに強制的に遷移したときのトラップは以下のように受信された。
$ sudo tcpdump -Z root -i ens192 udp port 162 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens192, link-type EN10MB (Ethernet), capture size 262144 bytes
13:39:17.528180 IP 10.254.254.193.162 > 10.254.10.251.162: C="ro" Trap(89) .1.3.6.1.4.1.12356.101.1.30 10.254.254.193 enterpriseSpecific s=605 309758 .1.3.6.1.4.1.12356.100.1.1.1.0="FGVMEVYY516CRLD9" .1.3.6.1.2.1.1.5.0="fortigate"
13:39:17.528319 IP 10.254.254.193.162 > 10.254.10.251.162: C="ro" V2Trap(113) .1.3.6.1.2.1.1.3.0=309758 .1.3.6.1.6.3.1.1.4.1.0=.1.3.6.1.4.1.12356.101.2.0.605 .1.3.6.1.4.1.12356.100.1.1.1.0="FGVMEVYY516CRLD9" .1.3.6.1.2.1.1.5.0="fortigate"
^C
2 packets captured
2 packets received by filter
0 packets dropped by kernel
v1/v2cが同時に発出されているため、このようになっているが、要するに .1.3.6.1.4.1.12356.101.2.0.605
つまり FORTINET-FORTIGATE-MIB::fgTrapAvEnterConserve
が送出されていることがわかる。
なお、コンサーブモードから復旧した場合のトラップは存在しないようだった。
結論
検証した環境である「透過モード」「フローベース」では fail-open
設定をデフォルト(=disable)としている場合は、red/extremeのどちらのコンサーブモードでも、セキュリティチェックを伴う通信は不可となることがわかった。
また、マルチキャストはコンサーブモードかどうかにかかわらず、通信可能であることがわかった。
以下、いいわけですが
- 限定的な構成(透過モード&フローベース)の1種類しか検証してないこと
- 実機ではなくVMでの検証であること
- ライセンスがトライアル用であること
- 搭載メモリを意図的に減少させていること
- コンサーブモード自体の動作が不安定な可能性があり、仕様通りの動作か不明であること
ということから、あくまで「いち検証の結果」ということで終了としたいと思います。
「fail-open
を期待して、コンサーブモードになるような仕掛けでセキュリティ的にザル状態にさせる。っていう攻撃が~~」みたいな記述がナレッジベースだかフォーラムにあって、おもわず「なるほどー」と思ってしまいました。
何を優先させるか?みたいなポリシーはあると思いますが、こういうのを見てしまうと fail-open
は他の手段でどうにもならなかったときの最後の手段として考えたいですね。
参考