Maple

Maple

探索文明6の最適なネットワーク技術——WireGuard + udp2raw

設計思路#

文明 6(Civilization VI)このゲームのマルチプレイヤーオンラインは常に批判されています。

公式の「インターネット」オンラインモードは、中国のプレイヤーにとっては明らかに不親切です。なぜなら、不安定な国際回線とファイアウォールの時折の干渉により、非常に高い遅延と頻繁な切断が発生するからです。文明のオンラインは UDP プロトコルに基づいているため、多くのプレイヤーは Zerotier/easyN2N などのツールを使って仮想 LAN を構築し、直接 p2p で穴を開けることを考えました。さらに、WinIPBroadcastを使用して、文明の255.255.255.255の部屋検索ブロードキャストを仮想ネットワークカードに転送するか、より高度なツールであるinjciv6を使用します。これは、文明の送信、受信などの操作をフックし、元のブロードキャストを直接ユニキャストに変更します(これにより、ルーティングテーブルに従って仮想ネットワークカードに正しくルーティングされます)。しかし、実際のプレイ中に新たな問題が浮上しました。プロバイダーが UDP トラフィックに対して非常に不親切な QoS ポリシーを適用しており、一定の時間が経過するとパケットロスが発生することがよくあります。そして、重要なデータパケットが失われると、文明はプレイヤーを一時的に部屋から追い出して再読み込みを行い、「プレイヤーのデータが同期していません」と表示されます。通常、再読み込みには約 30 秒かかり、ゲームの進行に非常に影響を与えます。(私たち 6 人はほぼ毎 2 ターンごとに少なくとも 1 人が切断され、時には全員が切断されます)

これに対処するために、UDP パケットをいくつかの巧妙な手段で TCP パケットに偽装し、プロバイダーの信頼を得て、パケットロスの発生頻度を減らすことができます。すべての人が Linux マシンで文明をプレイする場合、性能の良いphantunを選択するのが良いですが、これは現実的ではないため、マルチプラットフォームをサポートするudp2rawを選択します。

udp2raw を各プレイヤーのネットワークツールの出口に配置し、各ゲストプレイヤーがホストプレイヤーに接続できるようにするのはあまり現実的ではありません。ノード間のデータが双方向に到達可能であることを保証するためには、スーパーノードを中継する仮想 LAN が必要です。したがって、WireGuard(UDP ベースの通信トンネルツール)をネットワーク構築のソリューションとして採用し、WireGuard サーバーと udp2raw(サーバーモード)を公衆インターネット上のサーバーにデプロイし、WireGuard クライアントと udp2raw(クライアントモード)を各プレイヤーの個人コンピュータにデプロイすることで、私たちの要求を実現できます!

設計のトポロジー図は大体以下の通りで、udp2raw は WireGuard の外側にあります:

network

サーバーのデプロイ方法#

前提条件:パブリック IP アドレスを持っていること。システムは Debian 11 ディストリビューションを例にします。

ソフトウェアのインストール#

sudo apt update
sudo apt install wireguard

# GitHubからudp2rawリリースをwgetし、/usr/local/bin/にインストールし、PATHに含まれていることを確認
# テスト
udp2raw --help

システムのポートフォワーディングを有効にする#

/etc/sysctl.confに以下の内容を uncomment/add します:

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ファイルが作成されます。

次に、各クライアントのキーペアを一つずつ生成します:

# "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を入力すると、部屋を発見して参加できるようになります!

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。