メインコンテンツへスキップ
見出し画像

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通信を制御する

     
     
    ベンチャー→SES13年→現メガベンのインフラエンジニア。 自宅NW要塞でAI・Kubernetes・Local LLM・GPUを飼育中。 AIに開発を壊されて学んだ「任せ方・止め方・戻し方」を、成功談より失敗談多めで投下します。 Amazonアソシエイト参加

    あなたへのおすすめ