VM屋がIaaSを使うと、だいたいVMから始まる
VMwareなどの仮想化基盤をやっていた人がIaaSを使い始めると、どうしてもVMの構築やストレージに目が行く。
どのインスタンスタイプを使うのか。ディスクをどう構成するのか。スナップショットやバックアップをどうするのか。
もちろん、これらも重要であるし、突き詰めればかなり奥が深い分野である。しかし、この辺りは仮想化基盤をやっていた人であれば比較的入りやすい。
実は、その陰で意外と知られていなかった分野がある。
オンプレミスとクラウドをどう接続するか、である。
今ではできる人もだいぶ増えた……と願いたいところであるが、クラウドが普及し始めた頃、インフラ系のエンジニアでもここまで自分で構築できる人はかなり少なかった印象がある。
ただし、それも無理はない。
まず、当時はクラウドとのVPN接続に使えるルーターが限られていた。比較的安価なものではYAMAHAのルーターなどがあったが、「安価」といっても10万円前後する。
さらにクラウド側も、VPN用のゲートウェイを作れば終わりというわけではない。ゲートウェイ自体の利用料金があり、通信すれば転送料金もかかる。AWSやAzureで試そうとすると、VMの無料枠だけで遊ぶようにはいかない。
そして、自宅やオンプレミス側にはインターネットから到達可能なパブリックIPv4も必要になる。
もう一つ大きいのが、VM系のインフラエンジニアは、必ずしもネットワークに詳しいわけではないということである。
「BGPって何?」
「L2TPって何?」
というところから始まることも珍しくない。
実際の案件でクラウドとオンプレミスを接続する必要が出てくれば、ネットワーク担当者やネットワーク系SIerに依頼する。それでシステムとしては完成するため、VM担当者自身がVPNやルーティングを詳しく理解する必要もない。
結果として、
クラウド上にVMを作ることには非常に詳しいのに、そのVMと自社ネットワークがどうつながっているのかはよく知らない
という、少し不思議な状態が起こるのである。
そこでOracle Cloud
ここで面白いのがOracle Cloud Infrastructure(OCI)である。
OCIではFree Tierの範囲でもVMを動かすことができる。そして、Site-to-Site VPNを使ったオンプレミスとの接続も試すことができる。
これはホームラボ用途としてはかなり太っ腹である。
なお、Oracle Cloudからお金をもらっているわけではない。単純におすすめなだけである。
以前、IPv6ではOCIと自宅をつないでいたが、IPv4についてはOCI側のSite-to-Site VPNまで作ったところで止まっていた。自宅側のEdgeRouterを設定していなかったため、そのまま放置していたのである。
せっかくなので今回、次の構成を実際につないでみることにした。
自宅LAN
│
EdgeRouter
│
Internet
│
Site-to-Site VPN
│
OCI VCN
│
OCI VM
今回の自宅環境では、IPv6についてはGUAを使って直接接続できるため、Site-to-Site VPNを使わない構成にしているが、今回はIPv4である。
これなら、単にクラウド上にVMを作るだけではなく、
「オンプレミスとクラウドをネットワークとして接続する」
ところまでホームラボで体験できる。
そしてOCIのAMD64の最小インスタンスであれば、Free Tierで小さなVMを2台使うことができる。
せっかく2台あるので、1台を普通の検証用VM、もう1台をBotデコイにしてみることにした。
余った1台をBotの囮にする
デコイ(decoy)とは「囮」という意味である。
インターネットにWebサーバを公開すると、検索エンジンに登録したり、URLを誰かに教えたりしなくても、Botやスキャナがやってくる。
以前から、Webサーバを立ち上げるとすぐにアクセスが来るので不思議に思っていた。そこで今回は、実際にはどのくらいでアクセスが来るのかを調べてみることにした。
構成は次のようにした。
Internet
│
▼
「みつきま臼」
nginx
│
▼
access.log
│
▼
Bot / Scannerらしいアクセスを検出
│
▼
Discord
Webサイト自体は、HTTPのアクセステストに使われた某芸能人風ホームページにしている。とにかく軽く、HTTP/HTTPSの疎通確認には都合がよい。
パロディページなので、内容もそれなりに笑えるものにしてある。
そして
/.env や /.git/config、/server-status などを探しに来るスキャナが現れたら、🚨 みつきま臼が物色されています
とDiscordへ通知する仕組みである。

こうして、Site-to-Site VPNの実験をしていたはずなのに、なぜか最後はインターネットに「みつきま臼」を放流してBotを観察することになった。
とはいえ、これも立派なクラウドとネットワークの実験である。
IaaSはVMを作って終わりではない。
そのVMがどのネットワークに所属し、オンプレミスとどう接続され、インターネットからどう見え、どのような通信が実際にやってくるのか。
そこまで見てみると、単なる「クラウド上のVM」だったものが、急にネットワークの一部として見えてくるのである。
公開して10分でBotが来た
せっかくなので、Botが本当にやってくるのか実際に観察してみることにした。
まず mitsuki-mouse.masezou.com をDNSに登録し、IPv4のAレコードとIPv6のAAAAレコードを設定した。さらにLet’s Encryptで証明書を取得し、HTTPSでもアクセスできるようにした。
コンテンツは潔く
/var/www/html
├── index.html
└── mitsuki.jpg
だけ。
これで普通のWebサイトとしてインターネットに公開されたことになる。
そして待ってみた。
ものの10分ほどでBotが来た。
98.88.137.2 – – […] “GET / HTTP/1.1” 200 … “RecordedFuture Global Inventory Crawler”
143.244.168.161 – – […] “LEAKIX” 400 …
2a03:b0c0:2:d0::176f:2001 – – […] “LEAKIX” 400 …
2a03:b0c0:2:d0::176f:2001 – – […] “GET / HTTP/1.1” 200 … “Mozilla/5.0 (l9scan/2.0…)”
143.244.168.161 – – […] “GET /console/ HTTP/1.1” 404 … “Mozilla/5.0 (l9scan/2.0…)”
143.244.168.161 – – […] “GET /server-status HTTP/1.1” 404 … “Mozilla/5.0 (l9scan/2.0…)”
143.244.168.161 – – […] “GET /login.action HTTP/1.1” 404 … “Mozilla/5.0 (l9scan/2.0…)”
143.244.168.161 – – […] “GET /___proxy_subdomain_whm/login HTTP/1.1” 301 … “Mozilla/5.0 (l9scan/2.0…)”
しかも、単に
/ を見に来ただけではない。アクセスログを見ると、例えば次のようなURLを次々と探しに来ていた。
/.env
/.git/config
/.DS_Store
/server-status
/v2/_catalog
/graphql
/api/graphql
/info.php
/actuator/env
/.vscode/sftp.json
/?rest_route=/wp/v2/users/
もちろん、このサーバにはWordPressもDocker RegistryもGitリポジトリも置いていない。
少なくともアクセス内容を見る限り、特定のアプリケーションだけを狙っているというより、「何かあるかもしれない」ものを片っ端から探しているように見える。
さらに面白かったのは、IPv4だけではなくIPv6側にもアクセスが来たことである。
「IPv6ならアドレス空間が広大だから、そう簡単には見つからないだろう」と考えたくなるが、少なくとも今回の実験では、公開後かなり早い段階からIPv6側にもスキャナと思われるアクセスが観測された。
どうやって発見したのかは、このアクセスログだけでは分からない。DNS、証明書のCertificate Transparencyログ、既知のホスト情報など、発見経路はいくつも考えられる。
ここは推測で断定するより、
「DNSに登録してLet’s Encryptで証明書を取得し、公開したところ、約10分でIPv4/IPv6の両方に外部スキャンが来た」
という観測結果そのものが面白い。
さらに興味深いのは、発見された後の速さである。
12:20:02 RecordedFuture
12:20:38 IPv4/IPv6へのプローブ
12:20:39 LEAKIX
12:20:54 IPv6 l9scan
12:20:56 IPv4 l9scan
12:21:00 /console/
12:21:02 /server-status
12:21:05 /login.action
12時20分台に最初のアクセスが記録され、その数十秒後にはIPv4とIPv6の両方からプローブが始まり、さらに数十秒後には
/console/、/server-status、/login.action などの探索が始まっている。 「公開したら、そのうち誰かに見つかる」のではない。「見つかったら、ほぼ即座に物色が始まる」のである。
真っ当なお客さんが来ない
公開してしばらくアクセスログを眺めていて、もう一つ気付いたことがある。
真っ当なお客さんが来ない。
まあ、「みつきま臼」が真っ当なWebサイトなのかと言われると微妙なので、それはいい。
しかし、Botやスキャナにとっては、Webサイトの中身が真っ当かどうかなど関係ない。
公開されているWebサーバを見つければアクセスし、
/.env や /.git/config、/server-status、WordPressのAPIなどを片っ端から探していく。今回は遊びで動かしている小さなVMなので、「また来たw」で済む。
しかし、これが普通のWebサービスだったら話は変わってくる。
ページを返せばCPUを使う。ログを書けばストレージを使う。通信すればネットワーク帯域を使う。クラウドによっては転送量がそのまま料金にも影響する。
そして、広告で収益を得ているWebサイトだったら、さらに話がややこしい。
人間がページを見るのであれば、ページビューが増え、広告が表示され、その一部が収益になる。
ところがBotは、Webサーバにはアクセスしてくるが、人間の読者ではない。
つまり運営側から見ると、
人間
↓
Webサーバ → コンテンツを見る → 広告を見る → 収益になる可能性
Bot
↓
Webサーバ → リクエスト → CPU・通信・ログ → コスト
↓
広告を見る人はいない
という非対称な構造になる。
もちろん、検索エンジンのクローラのように、サイトを発見・インデックスして最終的に人間を連れてくるBotもあるので、Botを全部ひとまとめに「迷惑」とすることはできない。
しかし、今回観測したような脆弱な設定や管理画面を探し回るスキャンは、それとは別物である。
人間のお客さんが来る前に、Botのお客さんが来る。しかも金は払わず、サーバのリソースだけ使って帰っていく。
今回の「みつきま臼」では笑い話で済むが、大規模なWebサイトになるほど、この「人間ではないアクセスをどう扱うか」は無視できない問題になるのである。
Botが来たらDiscordに知らせる
アクセスログを眺め続けるのも面倒なので、Botやスキャナらしいアクセスを検出したらDiscordへ通知することにした。
構成は非常に単純である。
Internet
│
▼
みつきま臼
nginx
│
▼
access.log
│
▼
Python監視プログラム
│
▼
notify-discord.sh
│
▼
Discord
例えば
/.env や /.git/config、/server-status といった、普通にホームページを見ている人ならまずアクセスしないパスが来た場合には、🚨 みつきま臼が物色されています
とDiscordへ通知する。
ただし、1リクエストにつき1通知としてしまうと、スキャナが数十個のURLを連続して調べた瞬間にDiscordが通知だらけになる。
そこで、同じ送信元については一定時間通知を抑制する仕組みも入れた。また、IPv4なのかIPv6なのか、アクセス元IP、リクエストされたパス、HTTPステータス、User-Agentなども通知に含めるようにした。
これで普段は放置しておき、
「お、また誰かがみつきま臼を物色している」
というときだけDiscordを見ることができる。
VMの外側を見る
IaaSを使うというとVMを作ることに目が行きがちである。
しかし、実際にはその外側にルーティング、VPN、DNS、IPv4/IPv6、TLS、そしてインターネットから実際にやってくる通信がある。
今回やったことを並べてみても、
VM → VCN → ルーティング → Site-to-Site VPN → EdgeRouter → DNS → IPv4/IPv6 → TLS → nginx → インターネット上のBot
と、VMを起点にかなり広い範囲までつながっている。
VMを1台作っただけでも、そこから外へ一歩出ると、ネットワークの世界はかなり広いのである。
それにしても、ルータのBGPを整理していたら、OCIの残骸を発見ー>構築を完了させるー>VMがBotデコイに。なんだったんだw
みつきま臼のページをみて笑っていただければ。