キマグレアドベンチャー!

(中学の時に運営してたブラウザゲームの名前)

bungeecordでhaproxyを利用しつつ接続元のorigin ipを取得する方法

Javaminecraftサーバ(bungeecord+spigot)を運営されており、DDoS対策などでhaproxyをつかったリバースプロキシを利用されている方向けの記事です。

 

単純にリバースプロキシ(haproxy)を導入するだけだと、bungeecord上で各プレイヤーの接続元のIPアドレスが全てリバースプロキシサーバのIPアドレスになってしまいますので、何かと不都合がでます。proxycheck.ioなどと連携してVPN・プロキシ経由の接続をブロックするプラグインがまともに機能しなくなったり、IP-BANしたら全員入れなくなったり…

この記事では、リバースプロキシ環境配下でもプレイヤーの本来の接続元IPアドレス(これは英語文献ですと大体Origin IPなどと呼んでいます)をbungeecord上で識別できるようにするための設定方法をご紹介します。

ざっくりいうと、http(s)プロトコルでいうx-forwarded-forヘッダみたいなことができるということです。

 

・bungeecordのconfig.ymlを編集

・haproxyのhaproxy.cfgを編集

・【番外編】BotAttack防止設定

 

bungeecordのconfig.ymlを編集

proxy_protocolをfalse->trueに変更します。変更後は再起動で反映されます。

proxy_protocol: true

なお、この設定をすると以後後述の設定を施したhaproxy以外からは接続できなくなりますのでご注意ください。

haproxyのhaproxy.cfgを編集 

/etc/haproxy/haproxy.cfg を編集します。変更後は再起動(systemctl restart haproxy とか。OSによる)で反映されます。

フォワード先のIPアドレスとポートを指定している箇所があるかと思いますが、そこのオプションに”send-proxy-v2”を追加します。

#---------------------------
# minecraft server gateway
#---------------------------
listen minecraftsv01
    bind 0.0.0.0:25565
    mode tcp
    option tcplog
    balance roundrobin
    server mc01 <DestinationIP>:<DestinationPort> send-proxy-v2

【番外編】BotAttack防止設定

上述の設定でこの記事の本来の目標は達成されますが、上述のオプションを利用するとBotAttackに対して脆弱になりますので注意が必要です。

実際、私が運営している整地鯖にも今年(2019年)10月ごろにBotAttackによってサーバが非常に不安定となる事案が発生しました。

本来bungeecordには大量のログインリクエストによりサーバが過負荷となるのを防止するために、config.ymlに”connection_throttle”と”connection_throttle_limit”と呼ばれる、同一IPからの大量リクエストに対する応答を抑制するオプション*1が備わっているのですが、”proxy_protocol”がtrueとなってる環境では意図的に無効化されてしまう挙動となっているみたいです。

この無効化される挙動は2019/3以降にリリースされたbungeecordに該当します。

 

(ちなみに、元々私はこの仕組みを「IP関係なくbungee全体で大量ログインリクエスト発生時それをある程度リクエスト拒否してサーバ過負荷を抑える機能」と認識していたのですが、それはhaproxy環境下でたまたまそのように動作しただけで、その動作自体は不具合として認識されていたっぽいです。)

https://github.com/SpigotMC/BungeeCord/issues/2590

 

で、じゃあどう対策するんですか?という話 ですが、haproxy側で秒間のリクエスト数を制限することができますので、これを利用します。BotAttack中は新規ログインも張りづらくなる副作用は存在しますが、サーバ丸ごと過負荷に陥る事態は回避できますので、ログイン中のプレイヤーは快適にプレイし続けることが可能です。許容するリクエスト数は、サーバのログイン状況に応じて調整が必要です。

haproxy.cfgの編集例を記載しておきます。

#---------------------------------------------------------------------
# minecraft server gateway
#---------------------------------------------------------------------
frontend minecraft
    mode tcp bind 0.0.0.0:25565
    option tcplog

    tcp-request inspect-delay 5s

    acl too_fast fe_sess_rate gt 10
    tcp-request content reject if too_fast

    use_backend seichi

backend seichi
    mode tcp server mc1 <DestinationIP>:<DestinationPort> send-proxy-v2

赤字の部分がミソで、上記の例ですと新規リクエストが秒間10回以上来た場合、以降のリクエストは自動的に拒否してくれます。

ちなみに、”fe_sess_rate"などのhaproxy上で設定できるパラメータに関しては公式ドキュメント↓にかなり詳細な説明があります*2ので、設定を突き詰めたい方は読んでみると良いかもしれません。

https://cbonte.github.io/haproxy-dconv/

 

 

いつも通り勢いで書き切りましたので、ここがわかりづらい・もっと聞きたいなどあればコメント欄にお寄せいただけますと泣いて喜びます。記事ネタリクエストもお待ちしております。

*1:私の実体験上こういうオプションだと思っています 根拠はないんだ〜

*2:英語ですけどね!!!!!!!!!!google 翻訳とkiaiで読めなくはないですが、僕は読み始めて5msで疲れました