ゲームサーバー向けDDoS防御:10分攻撃時代のランブック
要点まとめ
「10分攻撃時代」のゲームサーバー向けDDoS防御ランブック。96%が10分未満で終わり、98%が1Gbps未満という現状に対応するため、UDPフラッドの検知・軽減・証跡保存を、nftablesとconntrack設計を使い、最初の10分で今すぐ実行できる具体的な対応手順を解説します。
あなたのマッチメイキングキューは21:14に止まる。21:19には復旧している。グラフを確認すると、620Mbpsのスパイクが6分間だけ記録されており、アラートがスマホに届く前に消えている。2人チームの誰もリアルタイムでは気づかず、プレイヤーは「ラグ」として処理した。
この形の攻撃は今や標準である。CloudflareのQ3 2026 DDoS脅威レポートによると、この四半期に軽減されたネットワーク層攻撃は1820万件、およそ毎時8,226件、つまり0.44秒に1件の割合だ。そのうち 96%は10分未満で終了 し、98%は1Gbps未満だった。1Tbps超の超大容量攻撃はQ2の805件からQ3は251件へ約69%減少した。同レポートは、Aisuru、KimWolf、JackSkid、MossadのIoTボットネットに対する法執行機関の摘発が原因としている。
巨人は減り、群れが増えた。そして「群れ」こそ、小規模なゲームバックエンドが最も対策を講じにくい脅威モデルである。それは同時に、プロバイダーの軽減ティアを発動するには小さすぎる一方で、単一のゲームインスタンスを飽和させるには十分な大きさだからだ。
このランブックは、その帯域帯のためのものである。
Q3 2026で実際に変わったこと
ゲームサーバーを運用しているなら、3つの変化が重要です。1つ目は持続時間です。短時間・低帯域の攻撃が前年比208%増加したのは、DDoS代行「ブーター」サービスに特徴的な動きです。安価で繰り返し利用でき、連続的に撃ち込まれます。1晩に1回ではなく、40回の攻撃を想定してください。
2つ目はベクターの移り変わりです。UDP 389上の公開ドメインコントローラを悪用するCLDAP反射は、H1を通じて猛威を振るっていましたが、四半期比99.5%激減し、攻撃全体のわずか0.05%になりました。攻撃者は止めたのではなく、手法をローテーションしたのです。DNS増幅は215%増加してネットワーク層攻撃の3.43%になり、一般的なUDPフラッドは14.06%から31.31%へ増加しました。
3つ目は標的の拡大です。メディア業界は最も攻撃されたままですが、Q2のシェアの約4分の3を失いました。インターネット基盤はトップ10圏外から6位に上昇し、消費者サービスとアダルトエンターテインメントが8位と9位で新たにランクインしました。ゲームは、消費者向けでレイテンシに敏感な標的の集まりの中に、まさに位置しています。
防御側への教訓は、先四半期のベクターを中心にプレイブックを作るなということです。UDPフラッド、DNS増幅、反射悪用、SYN枯渇という4つのカテゴリを中心に据え、それぞれの比率は動き続けると想定してください。
ゲームバックエンドで最初に壊れるもの
すべてが同時に壊れるわけではありません。壊れる順番を知っていれば、的外れな対応で消耗せずに済みます。
- ゲームポート。 正規のサーバーポートへのUDPフラッドは、CPUより先にNICキューを消費します。プロセスは生きているため、オーケストレータのヘルスチェックには「稼働中」と見えますが、パケットはカーネルで破棄されています。
- セッション/ログインエンドポイント。 HTTPフラッドは認証を直撃します。バーストの最中に切断されたプレイヤーは再入場できず、ゲーム内にいたプレイヤーは再接続ループが失敗して離脱していきます。
- リーダーボード読み取り。 ほとんどのゲームバックエンドで最も増幅率の高い読み取り経路です。クライアント1件のリクエストが、データベースの範囲スキャンへと展開されます。毎秒5,000リクエストは送信側にとっては簡単でも、処理側には高コストです。
- テレメトリ取り込み。 多くの場合、認証なしまたは緩いレート制限で、攻撃する側にとって最も安上がりなエンドポイントです。
- conntrackテーブル。 これを埋めると、SSHアクセスを含むホスト上のすべてのサービスが落ちます。4分の攻撃が4時間の障害に変わるのはこのためです。
反射攻撃には特に注意が必要です。トラフィックは正規のDNSリゾルバや他の第三者のサーバーから届くため、IPレピュテーションによるブロックは設計上失敗します。あなたを攻撃しているのは、無実のインフラなのです。
検知:グラフが動く前に発火するシグナル
ダッシュボードは遅れます。カーネルカウンタは遅れません。最も重要な先行指標は、1秒あたりのパケット数と1秒あたりのビット数の比率です。正規のゲームトラフィック300Mbpsは、標準的なペイロードサイズでは1秒あたり約25,000〜40,000パケットです。64バイトのパケットによる300MbpsのUDPフラッドは、1秒あたり約50万パケットに近くなります。同じ帯域でパケット数は15倍。帯域グラフが穏やかに見えている間に、ホストを殺してしまいます。
疑わしいホスト上で次を実行してください:
# socket and memory pressure summary
ss -s
# per-protocol counters and the ones that predict a lockup
nstat -az | grep -E 'UdpInDatagrams|UdpNoPorts|UdpInErrors|TcpExtListenDrops|TcpExtTCPReqQFullDrop'
# current conntrack table occupancy vs max
conntrack -C && sysctl net.netfilter.nf_conntrack_max
# what is actually arriving on the wire
tcpdump -nn -i eth0 'udp and not port 7777' -c 200
このように読みます:
UdpInDatagramsが上昇し、ゲームループの示すプレイヤー数が低下している = フラッド。UdpNoPortsがスパイクしている = ポート範囲をスキャンするスキャナー。しばしば前触れです。TcpExtTCPReqQFullDropが非ゼロ = SYNキューオーバーフロー。すでに正規のハンドシェイクを失っていることを意味します。conntrack -Cがnf_conntrack_maxの70%超 = ゲームサーバーだけでなく、ホスト全体の完全停止まであと数分です。
カーネル視点ではなくエンドポイント単位の視点が必要な場合は、UEFNサーバークラッシュ診断プロトコルで、ネットワーク層のストールとエンジン層のストールを切り分ける手順を説明しています。これはどのトリアージでも最初の判断です。
通過してしまうジャンクに対するプロセス内防御としては、ソケット層における送信元別トークンバケットが安価で効果的です。次のC#の例は、受信パケットがシミュレーションのtickに達する前にゲートします:
using System.Diagnostics;
using System.Net;
public sealed class PacketGate
{
private readonly Dictionary<IPAddress, Bucket> _buckets = new();
private readonly int _ratePerSecond;
private readonly int _burst;
// A legit client at 30 Hz sends ~30 packets/s. 120/s allows
// headroom for retransmits without letting a flood through.
public PacketGate(int ratePerSecond = 120, int burst = 240)
{
_ratePerSecond = ratePerSecond;
_burst = burst;
}
public bool Allow(IPAddress source)
{
long now = Stopwatch.GetTimestamp();
if (!_buckets.TryGetValue(source, out var bucket))
{
bucket = new Bucket { Tokens = _burst, LastRefill = now };
_buckets[source] = bucket;
}
double elapsed = (now - bucket.LastRefill) / (double)Stopwatch.Frequency;
bucket.Tokens = Math.Min(_burst, bucket.Tokens + elapsed * _ratePerSecond);
bucket.LastRefill = now;
if (bucket.Tokens < 1.0) return false;
bucket.Tokens -= 1.0;
return true;
}
private sealed class Bucket
{
public double Tokens;
public long LastRefill;
}
}
これが何をし、何をしないのかを明確にしておきます。利用可能な帯域内に収まる送信元別のジャンクをフィルタします。回線が飽和した後は何もできません。その時点では、コードが何を判断しようと、パケットはプロセスの上流で破棄されます。
復旧ランブック:最初の10分間
攻撃の96%は人間が対応する前に終わるため、ランブックの目的は攻撃への対処ではありません。攻撃が燃え尽きる間に証拠を記録し、被害範囲を縮めることです。
T+0〜T+2分:確認し、スケールしない。 インスタンスを追加したくなる反射的な反応を抑えてください。フラッドに向かってスケールすると、請求額と攻撃対象面積が増えるだけです。上記のカウンタでベクターを確認し、ppsと帯域を記録し、conntrackテーブルが埋まっていないか確認してください。埋まっている場合は、直ちにT+0の緊急ホスト保護へ移行してください。
T+2〜T+5分:非必須負荷を切り離す。 ゲームプレイ以外のすべてを無効にします。テレメトリのバッチ処理、リーダーボードの更新、ストアフロントのポーリング、ソーシャルフィードなどです。バックエンドがリモート設定に対応していれば、デプロイではなくフラグ1つの切り替えで済みます。
T+5〜T+10分:ホストレベルのレート制限を適用する。 カーネルによるフィルタリングは、アプリケーション層のフィルタリングより桁違いに低コストです:
table inet gameguard {
set udp_flood {
type ipv4_addr
flags dynamic, timeout
timeout 60s
}
chain input {
type filter hook input priority filter; policy drop;
iif lo accept
ct state established,related accept
tcp dport { 22, 443 } accept
tcp dport 7777-7800 accept
udp dport 7777-7800 accept
# drop fragmented UDP - your game protocol should never need it
ip frag-off & 0x1fff != 0 udp drop
# per-source UDP cap well above a real client's send rate
udp dport 7777-7800 update @udp_flood \
{ ip saddr limit rate over 200/second burst 400 packets } drop
}
}
nft -f gameguard.nft で読み込み、nft list ruleset と nft list set inet gameguard udp_flood で確認します。設定を誤って自分をロックアウトすると、ネットワークインシデントが物理アクセスインシデントに変わってしまいます。まずステージングでテストし、ルールはバージョン管理に入れておいてください。
T+10分以降:上流にエスカレーションする。 必要なのはホスト上ではなく、ネットワークエッジでのスクラビングまたはブラックホール機能です。多くのマネージドゲームホスティングプロバイダーはこれを提供しています。もし提供していなければ、次の攻撃までに解決すべき調達問題です。特に、1Gbps未満のUDP攻撃を軽減できるしきい値を尋ねてください。公表されているSLAのほとんどは、あなたが決して見ることのないテラビット級攻撃向けに書かれているからです。
その間ずっと、タイムスタンプ付きのログを残してください。攻撃開始時刻、ベクター、ピークpps、ピークGbps、変更内容とその時刻。ポストモーテムは軽減策そのものよりも価値があります。
ベクター別プレイブック:攻撃の形に応じた対応
UDPフラッド(攻撃の31.31%)。 ランダムまたは標的を絞ったポートに対して送信され、ホストにリスナーの確認とICMP unreachableの生成を強制します。ネットワーク層フォールバックアーキテクチャの記事では、プライマリトランスポートが攻撃されている間も、品質は落ちてもプレイ可能なモードを維持する方法を解説しています。対応:nftablesによる送信元別レート制限、ゲームポート以外のUDPポートをすべて閉じ、ホストでのICMP unreachable生成を無効にします。
DNS増幅(3.43%、215%増)。 オープンリゾルバへの送信元偽装クエリと、あなたに向けた大規模なレスポンスです。対応:送信元が正規のリゾルバのため、送信元ブロックはできません。吸収するか、レスポンスサイズとレートでフィルタするしかありません。自分自身がオープンリゾルバを運用していないことを dig +short txt chaos version.bind @your.ip で確認してください。応答があれば、今日中に閉じてください。
CLDAP(0.05%に激減)。 現在は静かですが、歴史的には巨大でした。ここでの注意点は、CLDAP増幅がUDP 389上で動作することです。LDAPが必要ない限り、ホストとクラウドファイアウォールの両方でフィルタしておいてください。攻撃者はローテーションで戻ってきたとき、無防備なポートへ再び戻ってきます。
SYNフラッド。 ボリュームというより、常にリソース枯渇を狙います。SYN cookiesを有効にし(sysctl -w net.ipv4.tcp_syncookies=1)、net.core.somaxconnを引き上げ、conntrackテーブルはデフォルトではなく、最悪の現実的なケースに合わせてサイズ設定してください。
予防:4分間のバーストを生き延びるアーキテクチャ
まずキャパシティの計算から。希望的観測を多く打ち砕くからです。64プレイヤー・100tickのサーバーは、プレイヤー1人あたり約15〜20KB/sを動かします。つまり、インスタンスあたり約1.2MB/s、約10Mbpsです。400Mbpsの攻撃は、そのインスタンスの正規トラフィックの40倍です。攻撃の98%が1Gbps未満であることを考えると、現在の分布におけるほとんどすべての攻撃は、単一のゲームインスタンスを押し潰すには十分な大きさでありながら、ティア1のスクラビングプロバイダーの自動軽減の関心を引くにはあまりにも小さいのです。
そのため、アーキテクチャには3つの制約が生じます。
アカウントプレーンとゲームプレーンを分離する。 ログインエンドポイント、リーダーボード読み取り、プレイヤーセーブがゲームサーバーと同じホスト上で動いている場合、ゲームポートへのフラッドはアカウントも巻き込み、プレイヤーは「すぐに戻ります」という画面にすら到達できません。horizOn上でアカウント関連サービスを運用する—認証、Cloud Save、リーダーボードはすべてそこで管理される—ということは、ゲームポートへのバーストが、全プレイヤーをプロフィールから締め出すことなく、ゲームプレイを劣化させるだけで済むことを意味します。
機能の切り離しを、デプロイではなく設定変更にする。 フラッドが来たとき、使える時間は数秒です。リモート設定があれば、高コストな読み取り経路を即座に無効化できます。ビルドをプッシュするしか選択肢がなければ、結局使われないでしょう。
ネットワーク障害を検知できるヘルスチェックを構築する。 プロセスチェックは、カーネルが90%のパケットを破棄している間も「healthy」と報告します。実際のゲームプレイ到達可能性、つまり実際のハンドシェイクを行い250ms以内の応答を期待する合成クライアントでプローブし、それをフェイルオーバーの判定に使ってください。
ベストプラクティス:今週中に対応すべき5つの変更
- 帯域だけでなくパケットレートでもアラートする。 95パーセンタイルppsの2.5倍をしきい値に設定する。帯域のみのアラートは短時間のバーストを完全に見逃します。pps異常検知は、1Gbpsリンクを備えたホスト上の300Mbpsフラッドを捉えます。帯域グラフでは決してフラグが立たないものです。
- conntrackテーブルを意図的にサイズ設定する。
net.netfilter.nf_conntrack_maxを、ディストリビューションのデフォルトではなく、ピーク時の同時セッション数に基づいて設定し、使用率70%でアラートする。この1つの変更で、最もよくある「攻撃が障害に化ける」エスカレーションを防げます。 - nftablesルールセットを事前に書き、四半期ごとにテストする。 デプロイ設定の隣にリポジトリへ保存する。インシデント中に未テストのファイアウォールルールを適用することは、2つ目のインシデントです。
- プレイヤー向けに縮退モードの契約を公開する。 軽減中にリーダーボードとチャットが10分間停止するなら、パッチノートとステータスページに明記してください。沈黙は「死んだゲーム」と受け取られます。このためのモデルが必要なら、侵害後バックエンドアーキテクチャの分析のレジリエンスパターンが、可用性インシデントにそのまま応用できます。
- すべての攻撃を構造化イベントとして記録する。 タイムスタンプ、ベクター、ピークpps、ピークGbps、持続時間、適用した軽減策。5件記録すれば自分のパターンが見えてきます。ほとんどのインディーバックエンドは、同じ曜日の同じ時間帯に、同じブーターから攻撃されています。
まとめ
2026年の脅威プロファイルは、テラビット攻撃に備え、400Mbps・6分間のバーストを無視するチームにとっては厳しいものになります。巨人は69%減り、群れは208%増えました。軽減策は自動化され、低コストで、カーネル内で行われる必要があります。アラートが読まれる前に終わる攻撃に対して、人間が行動することはないからです。
ダッシュボードではなく、カウンタから始めてください。送信元別レート制限を追加し、conntrackテーブルを適切にサイズ設定し、アカウントプレーンとゲームプレーンを分離し、10分ランブックが退屈に感じるまで繰り返し練習してください。
その分離の一部が、自分たちで持ちたくない地味な作業—プレイヤー認証、リビジョン対応のCloud Save、リーダーボード、インシデント中に切り替えられるリモート設定—なら、そこはhorizOnが処理します。その分、あなたのオンコール時間はゲームサーバーに向かいます。無料で試すか、次のローンチウィンドウの前にドキュメントを読んでください。