
80/443を開けるだけでは守れない #9|HAProxy・Squid・c-icap・ClamAVで作る公開経路
この記事で分かること
外部公開Serviceへ直接通信を渡さない理由
UCG-Fiber / FortiGate / HAProxy / Squid / c-icap / ClamAVの役割分担
実際に公開サイトへ飛んできた探索リクエストの例
`TCP_DENIED/403` が「ClamAVで検知した」という意味ではない理由
多段Securityは「全部通す」のではなく、どの段で止まったか分かることが重要
⏪ 前の記事:#8 家庭LANに会社PCを混ぜない
Web ServiceをInternetへ公開すると、アクセスしてくるのは利用者だけではない。
ログには、`.git`、GeoServer、WebDAV、PHPUnit、CGIといった「使っているかどうかも知らないSoftware」を片っ端から探すRequestが普通に混ざる。
80/443を開けたから安全なのではない。
80/443は、攻撃側にとっても正規の入口になる。
だから外部通信をApplicationまで一気に通さず、一段ずつ判断する構成にした。

概念的にはこうなる。
UCG-FiberとFortiGateで入口を分ける
Internet EdgeはUCG-Fiber。
内部Security BoundaryはFortiGate。
外から来た通信は必要な公開Portだけを次段へ渡す。
FortiGate側ではVIP / Firewall Policyを使ってDMZ入口へ渡す。
HTTP/HTTPSの入口はHAProxyに寄せている。
ここで外部通信をいきなりk3s NodeやVMへ当てない。
HAProxyは「どこへ渡すか」を決める
HAProxyでは、
Host
SNI
Path
Backend
などを見て、どのServiceへ渡すかを決める。
外部から見れば同じ443でも、内部では複数のServiceへ分かれる。
ここでTLS終端や転送制御も行う。
ただし、HAProxyはマルウェアScannerではない。
そこで次段へProxy/Inspection Layerを置いた。
Squidで「Webだから通す」をやめる
SquidはProxyとして、通信を一度受ける。
ここでACLや接続可否を判断する。
実際、公開Serviceには日常的に「普通の利用ではまず来ない」Requestが飛んでくる。
過去ログでは、例えば次のような探索があった。
/.git/objects/...
GeoServer系の探索
PROPFIND (WebDAV探索)
.../eval-stdin.php
CGI Path Traversal系送信元IPや公開Domainはここでは伏せる。
重要なのは、
公開した瞬間から、誰かが自分のサイトだけを狙っているわけではなくても、Internet全体を自動で走査するBot/Scannerに見つかる
ということだ。
公開IPへ直接、
`.git`
PHPUnit
WebDAV
CGI
GeoServer
など、使ってもいないSoftwareの既知Pathを片っ端から投げてくる。
「WordPressを使っていないからWordPress攻撃は来ない」ではない。
相手は先に確認してくれない。
`TCP_DENIED/403` はどこで止まったのか
Squidのaccess.logには、
TCP_DENIED/403
HIER_NONE/-のような記録が出ることがある。
これは、
Squidの入口で拒否され、次のUpstreamへ到達していない
という読み方ができる。
ここが重要だった。
「怪しいRequestを見つけた」
↓
「c-icap / ClamAVがVirusとして検知した」
ではない。
その前にACLで落ちている通信も多い。
一部の`.git`探索では、Upstream側との処理途中で `TCP_MISS_ABORTED/000` になった記録もあった。

つまり一口に「攻撃が来た」と言っても、
UCG/FWで止まった
HAProxyまで来た
Squid ACLで止まった
ICAPまで渡った
Backendへ到達した
では意味が全く違う。
c-icap / ClamAVは「通過するObject」を見る
c-icapとClamAVは、Proxy Chainを通過するContentを検査するために置いている。
SquidからICAPへ渡し、ClamAVでMalware検査する。
手元のログでは、
特定のMalware名を検知した実ログまでは確認できなかった。
ここは「ClamAVが毎日Virusを捕まえている」とは書かない。
むしろ、前段で雑なScanを落とし、通す必要があるContentだけを後段で検査するのが役割分担だ。
c-icapが静かだから無意味、でもない。
「そこまで届かなかった」のかもしれないからだ。
多段化の欠点
もちろん、良いことだけではない。
段数が増えるほど、
TLS終端位置
Source IP
X-Forwarded-For
X-Forwarded-Proto
Timeout
Header
Logging
が複雑になる。
実際に、FortiGate側のNATでSourceが同じに見えたり、HTTPS終端後に`X-Forwarded-Proto`の扱いで悩んだこともある。
Security Layerを増やすほど、
「どこで止まったか」を追えるLog設計
が必要になる。
80/443は「許可Port」であって「安全な通信」ではない
80/443しか開けていないから安全。
HTTPSだから安全。
これはどちらも言い過ぎだと思う。
Portは入口の種類を決めるだけ。
中身が何かまでは保証しない。
だから我が家では、
入口を狭くする + 段階的に判断する + Logを残す

を組み合わせた。
次回は逆方向。
外から入る通信だけでなく、ServerからInternetへ出る通信も自由にはしていない。
⏩ 次回:#10 サーバからInternetへ自由に出さない|内部SquidでOutbound通信を制御する