2020-03-30

graph LR
A[攻撃者<br>192.0.2.5]
B[踏み台<br>192.0.2.34]
C[攻撃対象<br>192.0.2.100]
A -- "
フラグ: SYN<br>
送信元: 192.0.2.100 (偽造)<br>
送信先: 192.0.2.34
"--> B
B -- "
フラグ: SYN,ACK<br>
送信元: 192.0.2.34<br>
送信先: 192.0.2.100
" --> C

TCP SYN/ACK リフレクション攻撃を食らってる話

しばらく前から時々受けていた迷惑アクセスが最近はひっきりなしに来る。DDoS 攻撃(Distributed Denial of Service Attack; 分散型サービス妨害攻撃) の一種であるTCP SYN/ACK リフレクション攻撃(参考1参考2)の踏み台にされている疑惑が揺るぎないものとなった。

TCP(Transmission Control Protocol) とはネットワークのプロトコルの一つで、このページを開くのにも使用されているHTTP(HyperText Transfer Protocol) の土台となっている非常に大事なプロトコルである。超さっくり説明すると、パケットの欠落や順序の入れ替わり、(稀だけど)重複が起こりうるIP(Internet Protocol) の上に実装され、通信に信頼性を与えるためのプロトコルである。

TCPでは光の速さで飛ぶ伝書鳩に過ぎないIPに「接続」という概念を与える。接続を開くには、以下の手順でパケットのやり取りを行う。

  1. まずSYN(synchronize)フラグが立っているパケットを相手に送信する。
  2. 受信側はSYNフラグとACK(acknowledge)フラグが立っているパケットを返信する。
  3. 送信側はそれを受けてACKのみのフラグが立っているパケットを送信する。

この一往復半のやりとりをthree-way handshakeと呼び、これが完了した後の状態をestablished(接続確立)として扱う。

それで、今回のTCP SYN/ACKリフレクション攻撃はどういう攻撃かというと、送信側が上記の手順2.のSYN/ACKパケットを無視するものである。受信側はパケットの欠落に備えSYN/ACKを複数回送信するので、手順1.のSYNパケット一つに付き手順2.のSYN/ACKパケットが複数発生する。

攻撃者は送信元アドレスを攻撃対象のアドレスに偽造してSYNパケットを送信することで、複数のSYN/ACKパケットが攻撃対象に「返信」されることになる。攻撃者が送信したパケットより攻撃対象に送信されるパケットのほうが大きいので増幅攻撃の一種である。

図解

[攻撃者]   ------------------------------->  [踏み台]    ------------------------------->   [攻撃対象]
192.0.2.5   フラグ: SYN                      192.0.2.34  ------------------------------->   192.0.2.100
            送信元: 192.0.2.100 (偽造)                   ------------------------------->
            送信先: 192.0.2.34                            フラグ: SYN,ACK
                                                          送信元: 192.0.2.34
                                                          送信先: 192.0.2.100

踏み台は送信元に返信しているつもりで、実は攻撃対象にパケットを、しかも複数送りつけてしまう。

今回、僕のサーバは上記の踏み台にあたる。攻撃の道具にされてしまっている形である。

もちろんこのような状況は見過ごせるものではないため対策を行いたかったのだが、結論から言うと降参であった。各々の攻撃のペースが遅すぎることが一番の理由。攻撃対象アドレス一つに対するSYNパケットは数秒空けて2回届き、さらにそれが2分間隔で5回ほど繰り返される。それで終わり。そのため、正常な接続をブロックせず、攻撃パケットだけをブロックすることが極めて難しい。

他にも色々試行錯誤や思考実験をしたが徒労に終わったので略。

とりあえずの妥協策として、SYN/ACK試行の数を減らすことにした。Linuxではカーネルパラメータnet.ipv4.tcp_synack_retries (tcp(7)も参照)で再試行の回数を設定することができる。デフォルトでは5だがこれを2に減らした。

# sysctl net.ipv4.tcp_synack_retries=2

再起動しても設定が残るようにするには、ディストリビューションによってやり方が変わると思うがArch Linuxでは/etc/sysctl.d/99-sysctl.confに書いてあげるといい。(Arch Wiki)

# echo 'net.ipv4.tcp_synack_retries = 2' >> /etc/sysctl.d/99-sysctl.conf

とりあえずはこれで勘弁していただきたい!申し訳ない!

色々調べてみたところこの攻撃は比較的最近、2018年下旬に見られ始めるようになったらしい。というのもこの攻撃、増幅率がかなり小さい。SYN/ACKはペイロード(「本文」のようなもの)を持っていないため非常に小さいパケットなので、増幅の手段としてはあまりおいしくないためである。(SYN/ACKはせいぜい数倍だが、代表的な増幅攻撃であるDNSリフレクション攻撃は数十倍に増幅できる。) 最近になって流行り始めたのはおそらくIoTの普及によるものと思われる。IoT機器を傀儡と化すことでボットネットがより大規模に持てるようになったので、塵も積もれば山となる理論でSYN/ACKリフレクション攻撃が有用になってきたのだろう。

迷惑な話だ。

一応、攻撃を受ける側(攻撃対象踏み台ではなく)の対策としては、RSTパケットを返答するようにするのが良いように思える。悪意のないサーバであれば、RSTパケットを受け取った時点でSYN/ACKの再送をやめるので、トータルの通信量を抑えることができる。後出しになってしまったが、SYN/ACKリフレクション攻撃はSYN flood攻撃とは全く異なる原理の攻撃である。名前は似ているけど。前者は帯域を食いつぶすVolumetric Attackの一種で、後者はTCP接続受付リソースを食いつぶすTCPに特化した攻撃である。

ブログがGoogle検索に出た

昨日のブログでブログへのリンクをblogからblog/index.htmlに変更したところ、なんと無事クロールが来てググって出るようになりました!まじかよ。こんなんでいいんかい。いや良くないけどとりあえずはこんなところで。

お問い合わせはこちらまで: @matil019 リプにブログのリンクを含めていただけるとスムーズに会話できます。
記事一覧