設計思路#
文明 6(Civilization VI)このゲームのマルチプレイヤーオンラインは常に批判されています。
公式の「インターネット」オンラインモードは間違いなく中国のプレイヤーにとって不親切であり、不安定な国際リンクとファイアウォールの時折の干渉により、非常に高い遅延と頻繁な切断が発生します。文明のオンラインは UDP プロトコルに基づいているため、多くのプレイヤーは Zerotier/easyN2N などのツールを使用して仮想 LAN を構築し、直接 p2p で打開し、WinIPBroadcastを使用して文明の255.255.255.255
の部屋検索ブロードキャストを仮想ネットワークカードに転送することを考えました。または、より高度なツールであるinjciv6を使用します。これは、文明の送信、受信などの操作をフックし、元のブロードキャストを直接ユニキャストに変更します(これにより、ルーティングテーブルに従って仮想ネットワークカードに正しくルーティングできます)。しかし、実際のプレイ中に新たな問題が浮上しました:プロバイダーが UDP トラフィックに対して非常に不親切な QoS ポリシーを採用しており、しばらくするとパケットロスが発生し、重要なデータパケットが失われると、文明はプレイヤーを一時的に部屋から追い出して再読み込みし、「プレイヤーのデータが同期していません」と表示されます。通常、再読み込みには約 30 秒かかり、ゲームの進行に非常に影響を与えます。(私たち 6 人はほぼ毎ターン少なくとも 1 人が切断され、時折全員が切断されます)
これに対処するために、UDP パケットをいくつかの巧妙な手段で TCP パケットに偽装し、プロバイダーの信頼を得て、パケットロスの発生頻度を減らすことができます。すべての人が Linux マシンで文明をプレイする場合、性能の良いphantunを選択するのが良いですが、これはあまり現実的ではないため、マルチプラットフォームをサポートするudp2rawを選択します。
udp2raw を各プレイヤーのネットワークツールの出口に配置し、各ゲストプレイヤーがホストプレイヤーに接続できるようにすると、p2p ネットワークを構築するのはあまり現実的ではありません。ノード間のデータが双方向で到達可能であることを保証するために、スーパーノードを中継する仮想 LAN が必要です。したがって、WireGuard(UDP ベースの通信トンネルツール)をネットワーク構築のソリューションとして採用し、WireGuard サーバーと udp2raw(サーバーモード)を公衆インターネット上のサーバーに展開し、WireGuard クライアントと udp2raw(クライアントモード)を各プレイヤーの個人コンピュータに展開することで、私たちのニーズを満たすことができます!
設計のトポロジー図は大体以下のようになります。udp2raw は WireGuard の外側にあります:
サーバーのデプロイ方法#
前提条件:パブリック IP アドレスを持っていること。システムは Debian 11 ディストリビューションを例とします。
ソフトウェアのインストール#
sudo apt update
sudo apt install wireguard
# GitHubからudp2rawリリースをwgetし、/usr/local/bin/にインストールし、PATHに含めることを確認
# テスト
udp2raw --help
システムのポート転送を有効にする#
/etc/sysctl.conf
で以下の内容をコメント解除 / 追加します:
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
以下のコマンドを実行して設定を有効にします:
sudo sysctl -p
キーペアの生成#
cd /etc/wireguard
# ディレクトリ内のファイルのデフォルト権限を変更、デフォルト600
umask 077
wg genkey | tee server.key | wg pubkey > server.key.pub
これにより、現在のディレクトリにサーバーの秘密鍵server.key
ファイルと公開鍵server.key.pub
ファイルが作成されます。
次に、各クライアントのキーペアを 1 つずつ生成します:
# "10"の数字をnに変更し、(n-1)個のキーペアを生成、番号は2から始まります
seq 2 10 | xargs -I{} sh -c 'wg genkey | tee client{}.key | wg pubkey > client{}.key.pub'
WireGuard 設定ファイルの作成#
sudo su
echo "
[Interface]
PrivateKey = $(cat server.key)
Address = 10.8.0.1/24
DNS = 8.8.8.8
MTU = 1280
ListenPort = 4321
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE;
PostUp = rm -f /var/log/udp2raw.log
PostUp = nohup udp2raw -s -l 0.0.0.0:54321 -r 127.0.0.1:4321 -a -k 'testpasswd' --raw-mode faketcp &> /var/log/udp2raw.log &
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE
PostDown = killall udp2raw || true
" > wg0.conf
# 各クライアントの公開鍵ファイルをループして対応する[Peer]エントリを追加
for client_key in client*.key.pub; do
public_key=$(cat "$client_key")
peer_number=$(echo "$client_key" | grep -o '[0-9]\+')
# ピア番号に基づいてAllowedIPsを計算(client1は含めないこと)
allowed_ip="10.8.0.${peer_number}/32"
echo "[Peer]
PublicKey = $public_key
AllowedIPs = $allowed_ip
" >> wg0.conf
done
WireGuard を起動する際に udp2raw を静かに起動し、そのログを/var/log/udp2raw.log
に出力することに注意してください。
サービスを起動し、ファイアウォールを設定#
sudo systemctl enable wg-quick@wg0 --now
sudo ufw allow 54321/udp
クライアントの設定方法#
まず、サーバーで生成されたクライアントのキーペアを安全な手段で送信します。
WireGuard のインストールと設定#
公式サイトからWireGuardをダウンロードします。ソフトウェアを正常にインストールした後、新しい設定を作成します。(client3 を例に、Address は自分で変更する必要があります)
[Interface]
PrivateKey = ..... # client3.key
Address = 10.8.0.3/24 # あなたのプライベートIP
DNS = 8.8.8.8
MTU = 1280
[Peer]
PublicKey = ..... # server.key.pub
Endpoint = 127.0.0.1:3333
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25
udp2raw のインストールと設定#
まず、GitHub からudp2raw_multiplatformをダウンロードし、実行可能ファイルを環境変数 PATH のいずれかのディレクトリに配置します。
Windows システムの udp2raw faketcp は少し面倒で、手動でファイアウォールを設定する必要があります。Windows のネイティブファイアウォールが有効な状態であることを確認し、管理シェルでこのコマンドを実行します。-g
は、サービスを起動せず、手動で実行する必要がある 2 つのコマンドを出力します。ファイアウォール設定を調整するために使用します。【注意:後でパブリック IP が変更された場合、このステップを再度実行する必要があります】
# 123.xxx.xx.xを実際のパブリックIPに変更
udp2raw -c -l 0.0.0.0:3333 -r 123.xxx.xx.x:54321 -k "testpasswd" --raw-mode faketcp -g
このステップでは、Windows の特定のネットワークモジュールが不足しているというメッセージが表示される場合があります。インターネットで検索してインストールしてください。成功した場合、最後の 2 つのコマンドを一つずつコピーして実行します。最後に、通常のシェルで-g
を外したコマンドを実行し、このシェルを常に閉じないでください。
# 123.xxx.xx.xを実際のパブリックIPに変更
udp2raw -c -l 0.0.0.0:3333 -r 123.xxx.xx.x:54321 -k "testpasswd" --raw-mode faketcp
使用方法#
udp2raw を前面で実行し、WireGuard トンネルを起動し、easyN2N などの UDP テストツールでクライアント間の接続性をテストします。
その後、文明 6 を起動し、各ゲストコンピュータでinjciv6をクライアントモードで注入し、アドレスにホストの仮想 LAN IP 10.8.0.2
を入力すると、部屋を発見して参加できるようになります!