splapiがDoS攻撃されたっぽい。

各サイトではDoS/DDoS攻撃っぽいアクセスを受けたらアラートが飛ぶようになってるのですが、初めてアラートが飛びました。ちゃんと動いてよかったです。よくないけど。ちなみにsplapiは1秒以内に規定値以上のアクセスがあったり、同一IPで同時接続数が規定値以上を超えたりすると429が返るようになっています。(ブログは503)

time:27/Sep/2016:19:30:30 +0900 host:157.7.174.40       request:GET /regular/now HTTP/1.0       status:200   size:132 referer:-       ua:-    reqtime:0.017   upsttime:0.016
time:27/Sep/2016:19:30:30 +0900 host:157.7.174.40       request:GET /gachi/next HTTP/1.0        status:200   size:151 referer:-       ua:-    reqtime:0.015   upsttime:0.014
time:27/Sep/2016:19:30:30 +0900 host:157.7.174.40       request:GET /regular/next HTTP/1.0      status:200   size:126 referer:-       ua:-    reqtime:0.016   upsttime:0.014
time:27/Sep/2016:19:30:30 +0900 host:157.7.174.40       request:GET /gachi/now HTTP/1.0 status:200      size:163      referer:-       ua:-    reqtime:0.022   upsttime:0.021
time:27/Sep/2016:19:30:30 +0900 host:157.7.174.40       request:GET /regular/now HTTP/1.0       status:200   size:132 referer:-       ua:-    reqtime:0.015   upsttime:0.014
time:27/Sep/2016:19:30:30 +0900 host:157.7.174.40       request:GET /gachi/next HTTP/1.0        status:200   size:151 referer:-       ua:-    reqtime:0.020   upsttime:0.018
(以下429が出るまで続く)

splapiが攻撃されてるっぽいですが、攻撃するなら一番処理が重いはずの/gachiを狙えばいいはずなのでよくわかりません。

 ~  nslookup  157.7.174.40                                                876ms  2016年09月27日 20時12分00秒
Server:         210.188.224.11
Address:        210.188.224.11#53

Non-authoritative answer:
40.174.7.157.in-addr.arpa       name = cpanel01wh.tyo1.cloud.z.com.

Authoritative answers can be found from:

GMO系列ですね。403を返すようにしておきました。
GMOってレンタルサーバがDDoS受けたら解約迫るようなとこだったと思うのですが、自分がDDoSしてる場合はどうするのでしょう。ちなみにServersMan@VPS使ってた時にお名前VPSから攻撃食らったときは調査依頼送って無視されました。今回はどうでしょう。
DDoS攻撃されたらそこで試合終了!? レンサバから利用停止を宣告される前にできる8つの対策 – Qiita

巻き添えくらってアクセスできなくなった方は連絡いただければ対応しますので、お手数ですが連絡ください。

追記

アクセスログ見たら単体攻撃っぽかったのでタイトルをDDoSからDoSに変えました。
Dos攻撃とDDos攻撃の違いと対策についてまとめてみた
対象IPから攻撃はされてないけどちょくちょくアクセスされてますね。動かしてたスクリプトバグってただけなのかなぁ。

追記2

攻撃元から連絡があったので解除しました。サーバサイドで動かしているAPIを呼び出すスクリプトがDoS攻撃を受けて、そのスクリプトが(結果的に)踏み台になってDoS攻撃してたそうです。いくらなんでも理由がひでえと思ったのですが、パニックラビリンス聴いてたら脳みそキャンパスごじげんでどうでもよくなりました。
以下Qiitaのデザインパターンは参考になります。
サーバサイドで複数Web APIを呼び出すときのデザインパターン – Qiita
結局GMOからは連絡きませんでした。きました。

追記3

– (お客様センター) – 2016/10/03 18:54
xxxx 様

いつもご利用いただき、まことにありがとうございます。
Z.com お客様センター です。

ご案内にお時間を要しまして、申し訳ございません。

該当のユーザー特定を行い、弊社にて対応を行わせて
頂きました。

本件につきまして情報のご提供を頂き、誠にありがとうございました。

今後ともZ.comをよろしくお願いいたします。

なんというか…今後自分で契約してGMO系のサーバは使うことはないだろうな…。ドメインvalue-domainだけど…。

zshを諦めてfishを導入した。

fish-shellを使ってみませんか – Qiita
zsh から fish にした。 – yoshiori.github.io

なんだかんだで大学院いたときから周りがzsh使ってたのでzsh使っていたのですが、やっぱり使いこなせなかったのでユーザーフレンドリーだと話題のfishに移行しました。シェル食って生きてる人間とマウスないと何もできない私みたいな人間を一緒にすべきではなかった。

やったこと

omfの導入

oh-my-fish/oh-my-fish: The Fishshell Framework.
マウスが友達の人はomfコマンド使えないと辛いので導入します。

pecoプラグインの導入

oh-my-fish/plugin-peco: Browse your fish history with peco.

zプラグインの導入

oh-my-fish/plugin-z: Integration with z (autojump alternative).

vimのビルド

yumで入れたvimはfishに対応していないので、8.0をcloneしてビルドしました。
vim/vim: The official Vim repository

lessをvimのマクロに変更

config.fishはこんな感じになりました。

set -gx LANG ja_JP.UTF-8
set -gx LC_ALL ja_JP.UTF-8
set -gx LANGUAGE ja_JP.UTF-8

set -gx Z_SCRIPT_PATH ~/z/z.sh

set vim_version (vim --version | head -1 | sed 's/^.*\ \([0-9]\)\.\([0-9]\)\ .*$/\1\2/')
alias less "/usr/local/share/vim/vim$vim_version/macros/less.sh"

function fish_user_key_bindings
  bind \cr 'peco_select_history (commandline -b)'
end

themeはbobthefishを使いました。
oh-my-fish/theme-bobthefish: A Powerline-style, Git-aware fish theme optimized for awesome.

フォントはPowerline適用済みRictyDiminishedを使ってるのですが、mobaXtermとの相性が悪いのか原因不明で矢印がかけちゃいますね。なんだろうこれ。

fishを導入した

fishを導入した

サブマシンでスクショとったのでザギザギしてますがメインマシンはmactype入れてるのでもっときれいです。

追記

Z_SCRIPT_PATHはinit.fishが読み込まれる前に設定しないと、ログイン時に「Please install ‘z’ first!」というメッセージと一緒にエラーコード(リターンコードは1)を吐いてしまうので、WinSCPとかSFTP使おうとした時に「大きなSFTPパケット(1416128883 B)を受信しました。サポートしている最大パケットサイズは 102400 B です。(中略)メッセージが “Plea” で始まっています。」のようなエラーが発生します。
$OMF_CONFIG配下にbefore.init.fishを作って、その中でZ_SCRIPT_PATHを設定すると解消します。参考サイトは以下。
How can I install 'z' in fish? · Issue #2 · oh-my-fish/plugin-z
余計なお世話感がすごい。最悪プラグインいじってもいい気がします。

Nginx Helperで個別記事のキャッシュをパージできない。

Nginx Helper — WordPress Plugins
FastCGI Cacheを使ってるので、このプラグインを導入しているのですが、個別記事のキャッシュがうまくパージできないのでログを出して原因を調べました。

原因

パージ対象になっている記事のURLの末尾にスラッシュがついている。

このブログは個別記事のパーマリンク設定が/archives/%post_id%なのですが、キャッシュをパージする対象がなぜか/archives/hoge/ になってたせいで、キャッシュが削除できていませんでした。
WordPressかNginx Helper側のバグだと思うのですが、調べる元気が無いので諦めました。

対策

purge.phpのpurgeUrlメソッドに以下を追加して、archivesがURLに含まれる場合は末尾のスラッシュを削除するようにしました。

if(strpos($_url_purge,'archives') !== false){
  //URLのなかに'archives'が含まれている場合、スラッシュを削除
  $_url_purge = rtrim($_url_purge,"/");
}

なんかファルシがルシしそうですね。

(2016/12/23)追記

バージョン上がりましたがやっぱり改善されないですね。これはバグ原因みつけてPR出したほうがいいかもしれないと思い始めました。

(2017/03/16)追記

修正されたみたいです。よかった。

原因の切り分けをどうやるか。

たまたま見つけてしまったからには調査せずにはいられないのです。

該当時間のAPI実行結果

{
    "result": [
        {
            "end": "2016-06-28T11:00:00", 
            "maps": [
                "タチウオパーキング", 
                "キンメダイ美術館"
            ], 
            "rule": "ガチエリア", 
            "start": "2016-06-28T07:00:00"
        }, 
        {
            "end": "2016-06-28T15:00:00", 
            "maps": [
                "モズク農園", 
                "マヒマヒリゾート&スパ"
            ], 
            "rule": "ガチヤグラ", 
            "start": "2016-06-28T11:00:00"
        }, 
        {
            "end": "2016-06-28T19:00:00", 
            "maps": [
                "モンガラキャンプ場", 
                "マサバ海峡大橋"
            ], 
            "rule": "ガチエリア", 
            "start": "2016-06-28T15:00:00"
        }
    ]
}

内容を見る限り、報告時間の前のデータが反映されてるので、(イカレコさんのリプライの内容は誤っていて、)クライアントに問題があるかアプリに問題があるかの2択なのですが、他に同一の事象が報告されてないならクライアント側に問題がありそうです。
自分の使ってるアプリに問題が発生した場合、「それが自分の端末だけで起こっているか」を調べた上で原因を切り分けると、不具合報告する前に自分で解決できることが多いのですが、なかなか難しいですね。Androidの場合、特定機種だけで起こる不具合とかもあると思うのでもっとややこしそうです。
私は以下の手順を踏むようにしています。

  1. TwitterとGoogleで不具合に関するキーワードで調べる
  2. Twitter等で同一の報告があるなら、アプリの公式サイトやTwitterを確認。報告があるなら対応を待つ。ないなら事象を報告。発生したときの手順、タイミング、手順を再度踏んで再現するかしないか、発生したエラー内容も合わせてわかる範囲で詳細に報告。スクショ・ログ・スタックトレースがあるなら添付。
  3. ソースコード(公開されているなら)、エラーコードを見て原因が特定できていたらそれも報告する。エビデンスのない予測程度までしかわからない事柄なら書かない。予測をかかれても開発者は困ることが多いですし、トーシローの予測なんて大体外れてます。
  4. 同一報告がないなら、自分の端末の問題を視野に入れて調査する。大体競合してるアプリとかキャッシュが悪さしてる場合が多い。ほかの端末でも再現しそうであれば、事象を報告する。
  5. 原因不明だった場合、開発が続いてるアプリなら報告、続いていないアプリならあきらめる。OSS、かつ自分でどうにかできそうな場合は、原因っぽそうなところの処理を改造する。場合によってはpull requestを送る。

ちなみにRight-Click to Calendarもおま環(Mac)なバグ報告をいただいていますが、そういうのは調査してもコストに対して得られる物がほとんどないので対応してません。

Let’s Encryptでsplapiをhttp/2に対応させた。

retrorocket.bizは強制的にhttpsで通信するようになっています。retrorocket.bizで試しに作ってるWebアプリがあって、そこから適当なAPIを呼ぼうと思ってJavaScriptからsplapiを呼んだらエラーになって自爆しました。SSL対応してないから当然ですね。
時代は常時SSLだし自爆したのでいい加減対応することにしました。
最初StartSSLで証明書を取得しようとしたのですが、手続きが心底めんどくさいのと、返事がめちゃくちゃ遅いのでLet's Encryptでさっさと証明書を取得することにしました。

証明書の取得は以下のサイトを参考にしました。gitとPythonが必須です。CentOS 7では特に問題なく動作しました。
Let’s Encrypt サーバー証明書の取得と自動更新設定メモ | あぱーブログ
splapiはリバースプロキシにnginxを使っているので、webrootを使用しました。
nginx用のオプションもあるらしいのですが、指定するとnginx.confを書き換えるとかいうとんでもない仕様だったので自前で設定します。

nginxのほうですが、/.well-known/acme-challenge/は403を返すと認証がこけたので、404を返すように指定しました。

        location ^~ /.well-known/acme-challenge/ {
                root /var/www/acme;
        }

        location = /.well-known/acme-challenge/ {
                return 404;
        }

証明書の取得用に実行したコマンドは以下。

./certbot-auto certonly --webroot -w /var/www/acme -d splapi.retrorocket.biz

/.well-known/acme-challenge/配下に認証用のファイルを作って、 http://ドメイン名/.well-known/acme-challenge/hogehoge にアクセスし、認証が終わったらファイルを消す、という動作をします。
/etc/letsencrypt/live/配下にシンボリックリンクが作成されるので、あとはssl_certificateとかに作成された証明書のパスを設定するだけでOKです。
nginx再起動まで5分もかからずに終わったのでめちゃくちゃ爆速ですね。

ssllabsの判定はAでした。
結構きつめの設定にしてるのと、Let’s Encryptへの対応状況がよくわからないので使用しているライブラリによってはSSLでAPIが呼べないかもしれません。
少なくともChrome52でJavaScript実行した時にエラーが出ないので私はこれでいいです。