お問い合わせスパムに対する防衛術(イッチ年生編)

# 前段
インフラ力が低いため、ipアドレスから〜とか、nginxで〜とかの対策する自信がなくて、入力内容をフィルタかけてどうにかしましたという感じの話です。イッチ年生向け内容ということで、ご笑納ください :pray: 

# 闇の魔術=スパムという解釈

> 「『闇の魔術』は−−」スネイプが言った。「多種多様、千変万化、流動的にして永遠なるものだ。それと戦うということは、多くの頭を持つ怪物と戦うに等しい。首を一つ切り落としても別の首が、しかも前より獰猛で賢い首が生えてくる。諸君の戦いの相手は、固定できず、変化し、破壊不能なものだ」
(ハリー・ポッターと謎のプリンス 第9章より)

マグル界のWeb上にも、スネイプ先生の言葉に該当するものが残念ながら存在します。そのうちの一つが、手を替え品を替え、徐々に進化しつつ、延々と日夜飛び交いつづける「スパムメール」ではないでしょうか。
主人がオオアリクイに殺されてみたり、外国の富裕層に遺産相続指定されてみたり、マグル界の闇の魔術はほんとうにユニークですね！

# めちゃ意味のない問い合わせがくる、つらい
そんなこんなで自分が担当しているプロジェクトも、お問い合わせフォームというものを持っていて、そこにスパム的お問い合わせが届くようになりました。
ただ、個人キャリアメールに届くような日本語文ではありませんでした。


※一部マスキングしました

```
▼お名前
Williamoramp

▼貴社名
[GAFA的名乗りが入ってるけどウソ]

▼電話番号
865[XXXXXXXX]

▼メールアドレス
[xxxxx]@[xxx].ru

▼お問い合わせ内容
Мы проверили вашу информацию. Выплата №23743 не была снята с вашего счета. Перейдите на сайт для завершения проверки http[...略...]
```

こんなのがドンドコ届きました。
他にもたくさん届くんですが、内容はまさしく多種多様です。でも訴えたい方向性は世界共通なんですかね。

- 支払いまだなんすけど早くしてくれませんかね？
- めちゃいいサービスあるんで登録どうっすか？
- いまならウン千万融資するけどいかがっすか？
- かわいいオネーチャンいるけどどうっすか？

...。


うっかり「磔の呪文」を画面越しに飛ばしたくなりますが、許されざる呪文はアズカバンで終身刑ですからね。いけないですね。


# まず挑戦 単語でフィルタ
本当は海外からのアクセスブロックとかが最善なのかもしれませんが、ごく一部で海外からも見てもらっているケースがあったりしたり、そもそもインフラ触るのが下手くそで対応に不安があったので、使っているサポートメール管理サービスのフィルタ機能を使用することにしました。ヘタレですみません。

フィルタ機能は、特定のキーワードを指定し、それらが含まれた問い合わせを自動で終了するように設定できるものでした。
とりあえず今回の問い合わせスパムは言語が特徴的なので、いくつかキーワードを抜粋して設定しました。

| 単語 | 意味 | 備考 |
| ------------- | --------   | ---- |
| Добрый вечер! | こんばんは! | ありがちな冒頭挨拶 |
| Поздравляем! | おめでとうございます! | ありがちな冒頭挨拶2 |
| Уважаемый | 親愛なる | ドーモ、スパム=サン |
| проверьте | 確認する | チェックしないとまずいぞ的文脈 | 
| вознаграждение | 報い(報酬?) | スパム頻出単語 | 
| Получите | ゲット | Получите вознаграждение で報酬ゲット! 的な感じらしい |
| Заберите | 奪う | Заберите вознаграждение  で報酬獲得! 的な感じらしい |

こんなに悲しいきっかけ学ぶ単語があろうか。

# 世の中そう上手くはいかない

一部の単語を登録してフィルタかけたとはいえ、こんなので多種多様な話題が全部フィルタできる訳がありませんでした。
さらに極めつけに次のようなお問い合わせが届きました。

```
▼お問い合わせ内容
Hot photo galleries blogs and pictures http:/...[略]
```

とうとうフツーの英語でもスパムが飛んでくるようになってしまった。


# 2度目の正直 電話番号バリデーション

スパムの特徴として、うっかり特徴的な外国語にばかり注目していたのですが、改めてスパムと特定できる項目として「電話番号」に気づきました。
最初のメールの時点で先にこれを思いつけばよかった...。

日本の電話番号にはルールが定められています。

- 「1」から始まるもの: 通報(110)とか時報(117)
- 「2~9」から始まるもの: 市内通話で使用

そして、「0」から始まるものが携帯や市外の固定電話への番号ですので、一般的に使用されている電話番号といえます。

電話番号のフォーマットについて、詳しくは総務省のページをご覧ください。
[総務省｜電気通信番号制度｜電話番号に関するQ&A](http://www.soumu.go.jp/main_sosiki/joho_tsusin/top/tel_number/q_and_a.html)

スパムの送信元では、国内通話のときに最初は「8」を押すらしく、改めて過去のスパムを振り返ったところすべて「8」から始まる番号となっていました。なるほど豆知識だ。
https://www.arukikata.co.jp/country/RU/info/phone.html

Webページ上のフォームから受け付けている問い合わせなので、市内通話の番号を載せられても困るので、バリデーションとして次のように設定しました。

```rb
# インフラはてんでダメなんですがRails触れるのでこうしました
validates :phone, format: { with: /\A[0０].+/, message: 'は市外局番から入力してください。' }, allow_nil: true
```

本当は桁数とかハイフンありなしとか厳密にいうと細かく考えるべきことあるかもしれないんですが、あくまで目的はスパム防止だと割り切ってガバガバなバリデーションです :bow: あと電話を万一掛けるときは目で見て判別するので全角でもいいかなとか、そんな感じの指定です。

とりあえず、一旦これでスパムが送られてくるのは止まりました。やったね。


# めでたし...?

果たしてこれで本当に、めでたしめでたし...、なのでしょうか？
冒頭の引用を振り返ると、スネイプ先生もこう仰っております。

> 首を一つ切り落としても別の首が、しかも前より獰猛で賢い首が生えてくる。


上記に `allow_nil: true` とあるように、実はこのお問い合わせフォーム、電話番号は任意項目のため省略できます。
スパムさんが律儀にも全部の項目を埋める系botさんだったため、うまく防げているといってもいいでしょう。
もし、電話番号欄を空のままPOSTされたり、先頭0の値を入れてこられたりしたら。
...その時は、改めてインフラ的手段での対抗をちゃんと勉強して試みたいと思います。

# おまけ

スネイプ先生のお言葉を探すためにハリポタ再読始めたらやっぱり面白いので年末年始は全巻読み直しで溶けそうです :book: