SRCDSの公開方法

これはSRCDSを外部に公開し、Valveのサーバブラウザに登録する為のドキュメントです。

基本的にFreeBSD+pfを想定していますが概念はLinuxでもWindowsでも同様なので、多少の知識があれば反映出来ます。

更新日
2007/05/07 エントリ作成

・最初にすべきこと

直接インターネットに繋がったPCでサーバを建てる例は少ないだろうと考えています。
その場合、ルータをインターネットへのゲートウェイとして使用すると思いますが
ここの設定次第で、外部から見えないなどの問題が発生することがあります。

▼以下の内容における前提条件:

インターネットへの接続にルータを使用している。
ゲームサーバはその内部のローカルネットワークに存在し、プライベートIPを与えられている。
DMZなどを使用せずに、NATのみで外部へと公開したい。

・最初の課題:ポートフォワーディング

▼SRCDSが使用するポート一覧

UDP 1200 (used for friends service)
UDP 27000 to 27015 inclusive
TCP 27020 to 27050 inclusive
UDP: 27015 and 27020 (default HLDS, SRCDS and HLTV port)
TCP: 27015 (SRCDS Rcon port)

ファイアウオールなどで通信をガチガチに絞っているのでなければ
ほとんどの場合、中から外はスルーのはずです。
従って、外部からゲームサーバへ接続するためのポートのみを明示的に開けるだけで問題ありません。
次に、そのポートをゲームサーバまでポートフォワーディングしてあげます。

上記のすべてのポートを開ける必要はありません。

▼必要なポート

UDP 27015(ゲームサーバ用)
TCP 27015(RCON用、外からコントロールしないなら開けない方が良い)
UDP 27020(HLTV用、外に公開しないなら開けない方が良い)

例:FreeBSD6.2のpf

ext_if = "ng0"   #WAN側インターフェイス
ext_addr = "ng0:network" #WAN側IPアドレス
int_if_1 = "em1"  #LAN側インターフェイス int_addr_1 = "192.168.1.1" #LAN側IPアドレス
srcds = "192.168.1.2"  #ゲームサーバのアドレス
rdr on $ext_if proto {tcp udp} from any to any port 27015 -> $srcds port 27015 #ゲームサーバ部分のポートフォワーディング rdr on $ext_if proto udp from any to any port 27020 -> $srcds port 27020 #HLTV用のポートフォワーディング
pass in quick on $ext_if proto {tcp udp} from any to ($ext_addr) port 27015 keep state #ゲームサーバ部分の穴開け
pass in quick on $ext_if proto udp from any to ($ext_addr) port 27020 keep state #HLTV用の穴開け

HLTVやRCONを"外から"使わないのであればUDP27015だけで大丈夫です。
むしろそれ以外のポートは開けるべきではありません。

注:FWで明示して落とすのは、当然のことながらダメです(;´Д`)
  要はデフォルトのブロックに引っかからなければOK

・二つ目の課題:ゲームの起動設定

SRCDSは、起動時の引数で指定したIPアドレスを元に、待ち受け用のUDPソケットを作成します。
特に指定が無ければ、デフォルトルートへ向いているLANのIPアドレスが使用されます。

通常、この部分を指定する必要はありませんが
ファイアウオールなどで通信を絞っている場合問題となることがあります。
また、サーバ側で認識できないアドレスを指定すると、UDPソケットを作成できずにサーバが起動せずに落ちるか
起動してもポートが存在しないために接続することが出来ません。

▼接続できない例:

インターネット ---- [WAN] ルータ [NAT - LAN] ----- [LAN] サーバ

このような構成の際に、WAN側のIPアドレスでサーバを起動することは出来ません。

・三つ目の課題:Valveのサーバブラウザ

ここまでは普通のポートフォワーディングなので問題は無いのですが
最大の難関はここからとなります。

Valveのサーバブラウザは、登録しにきたサーバの送信元IPアドレス(source address)と送信元ポート(source port)を
サーバリストに加えて、そのリストをクライアントへ渡す仕様になっています。

この一連の動作でsource addressは問題無くとも、source portの方で問題が発生することがあります。
これはNAPT機器(ソフト)の実装方法の差異によって問題が発生したり、しなかったりしますが
原因を考えると、すべての機器で静的NAPT(静的IPマスカレード)を組むことをお奨めします。
(仕組みを考えると、今問題が起きないからといって、将来も発生しないとは言い切れない)
ちなみに、実装的にはランダムなポートが割り当てられるのが本来の形だと私は思います。

▼原因

原因になるのはプライベートIPからグローバルIPへと、ポートを含めて変換する機能(要するにNAPT : Network Address Port Translation)の部分です。

NATは、プライベートIPからグローバルIPへと変換するための機能で
プライベートIPとグローバルIPを1on1で変換します。
そのため、一つのグローバルIPしか持たない場合、同時に一台しか外のネットワークを利用することが出来ません。

そこで、IPアドレスに加えてポート番号をベースにセッション管理することで、一つのグローバルIPアドレスから
プライベートIPアドレスを持つ複数のネットワークデバイスが外部のネットワークを利用出来るようになりました。
これがNAPTと呼ばれるものです。

参考:RFC2663で見るNAT

要はLAN内で発生したパケットがNAPTを通過する際に、ソースポートとは別のランダムなポートが割り当てられ、外へと流されることによって
Valveのサーバから見た場合「グローバルIP:NAPT変換後のポート番号」がsourceと見なされてサーバリストに加えられるのが直接の原因となり
グローバルなサーバブラウザのリストに出てこない(リストにはあるが、ポート番号が違うので接続できない)と言う現象が発生します。
そのため、FWのオープンでないポートに対して、大量のUDPパケットが世界中から届きますが、すべて破棄されるでしょう。

たとえリストに載らなくても、ポートフォワーディングがうまくいってる場合、「グローバルIP:ポート」で直接指定するとサーバそのものは外部から見えるし、接続してゲームを始めることが出来ます。
しかしグローバルのサーバリストに載らないため、野鯖として運用するには問題があります。

▼対策

これの対策は、簡単なものから難しい物までいくつか考えられます。

1,グローバルIPを割り振る
解決策としてはもっとも手軽です。といっても複数の固定IPを所有することは、所詮個人では無理があります。
そのためSRCDSを動かすサーバをルータにしてしまえば良いのです。FreeBSD、Linuxなら選択肢に入れても良いかもしれません
ネットワークレイテンシも最小にすることが出来ます。ただ、マシンスペックは十分に考えて選択しないと、ゲームサーバの部分に影響が出ます。

猫鯖では、当初NAPTの問題が解決できなかったため、ゲームサーバをルータにすることで解決しました。
その後テスト用のサーバを動かして探ってみたところ、原因が判明しましたが、手持ちの機材の問題からそのままにされています。

2,通常とは逆向きの静的NAPTを設定する
通常の静的NAPTは、外から中へと設定するものですが、中から外へ出るときのポートも設定してあげれば問題は解決します。

下記はテスト鯖を動かしていたときのpfのコンフィグです。


nat on $ext_if proto udp from $srcds port 27035 to any -> ($ext_if) static-port

srcds(鯖)からのポート27035から任意のホストへ向けたセッションを、外側インターフェイスにポート番号の変換無しでNAPTするルールの例です。
逆向きのNAPTが設定できるかどうかはルータによって設定が異なるはずですので(設定そのものが出来ない場合も有り得る)
マニュアルを良く読んで設定してください。

3,GapNATを使用する
対応したルータを持っているなら、もっとも影響の少ない選択肢がこれだと思われる。
GapNATはLAN内の一つのネットワークデバイスにISPから割り当てられたグローバルIPを割り振り、そのアドレスで通信する。
標準で外から中へのポートはすべて閉じられているので、「GapNAT通過制限」のところで通すべきポートを開ける。
詳しくはマニュアルやFAQを参照して設定してください。

参考:-GapNAT FAQ-

 

タイトルとURLをコピーしました