メインコンテンツへスキップ

ポート開放できない自宅回線で、OCI + WireGuard + Proxmoxを使ってMinecraft統合版サーバーを公開した話

    マンションの無料インターネット回線を使っていると、自分でルーターを管理できず、ポート開放ができないことがあります。
    自分の環境もまさにこれでした。
    そこで今回は、
    自宅のProxmox上でMinecraft Bedrock Serverを動かし、Oracle Cloud Infrastructure(OCI)のVMをインターネット側の入口として使う
    構成を作りました。
    最終的な構成はこんな感じです。

    Minecraftクライアント
            │
            │ UDP 51821
            ▼
    OCI VM(グローバルIPv4あり)
            │
            │ WireGuard
            ▼
    自宅 Proxmox
            │
            ▼
    Ubuntu VM
            │ UDP 19132
            ▼
    Minecraft Bedrock Dedicated Server

    OCIではMinecraft本体を動かさず、通信の中継だけを担当させています。

    技術スタック

    自宅側は、

    • Proxmox VE

    • Ubuntu VM

    • Minecraft Bedrock Dedicated Server

    • WireGuard

    OCI側は、

    • Ubuntu

    • WireGuard

    • iptables

    • iptables-persistent

    です。
    OCIのVMはMinecraft本体を動かさないので、かなり小さいインスタンスでも足ります。
    今回はA1 Flexの空きがなかったので、VM.Standard.E2.1.Micro を使いました。

    1. Proxmox上にUbuntu VMを作る


    まずProxmox上にUbuntu VMを作成しました。VMから普通にインターネットへ出られることを確認しました。

     ping -c 3 1.1.1.1

    Minecraft ServerとWireGuardはProxmox本体ではなく、このUbuntu VMの中で動かします。

    2. OCI VMの作成

    OCI VMを作る OCI側にもUbuntu VMを1台作成します。主に確認したポイントは以下です。パブリックIPv4が割り当てられている Internet Gatewayが存在する Route Tableが正しく設定されている Security Listが正しいSubnetに適用されている SSH鍵を使って接続します。

    ssh -i ~/.ssh/oci ubuntu@<OCI_PUBLIC_IP>

    3. WireGuardをインストール


    OCI側と自宅Ubuntu VM側の両方にWireGuardを入れます。

    sudo apt update && sudo apt install -y wireguard

    4. WireGuard鍵を作成


    OCI側では次のように鍵を作成しました。

    sudo sh -c 'umask 077; mkdir -p /etc/wireguard; wg genkey > /etc/wireguard/oci.key; wg pubkey < /etc/wireguard/oci.key > /etc/wireguard/oci.pub'

    自宅Ubuntu VM側では、

    sudo sh -c 'umask 077; mkdir -p /etc/wireguard; wg genkey > /etc/wireguard/home.key; wg pubkey < /etc/wireguard/home.key > /etc/wireguard/home.pub' 

    としました。
    WireGuardでは、 PrivateKey = 自分の秘密鍵 PublicKey = 相手の公開鍵 という関係になります。

    5. WireGuard用のIPアドレスを決める

    今回はWireGuard内で以下のIPアドレスを使いました。
    OCI : 10.100.0.1 自宅Ubuntu: 10.100.0.2
    OCI側の /etc/wireguard/wg0.conf はこのような構成です。

    [Interface] Address = 10.100.0.1/24 
    ListenPort = 51820 
    PrivateKey = <OCI_PRIVATE_KEY> 
    [Peer] PublicKey = <HOME_PUBLIC_KEY> 
    AllowedIPs = 10.100.0.2/32 

    自宅Ubuntu VM側は、

    [Interface] Address = 10.100.0.2/24 
    PrivateKey = <HOME_PRIVATE_KEY> 
    [Peer] PublicKey = <OCI_PUBLIC_KEY> 
    Endpoint = <OCI_PUBLIC_IP>:51820 
    AllowedIPs = 10.100.0.1/32 
    PersistentKeepalive = 25

    という構成にしました。

    6. OCIでUDP 51820を許可する

    OCIのSecurity ListでWireGuard用のUDP 51820を許可します。
    Source CIDR : 0.0.0.0/0
    Protocol : UDP Dest Port : 51820
    ここで注意したいのが、 ルールを追加したSecurity Listが実際にVMのSubnetへ適用されているか という点です。別のSecurity Listを編集していても通信は通りません。

    7. WireGuardが繋がらない

    WireGuardが繋がらない、ここでかなりハマりました。
    OCI側で、

    sudo tcpdump -ni any udp port 51820

    を実行すると、自宅から送信されたUDPパケット自体は確認できました。
    しかし、
    sudo wg を実行しても、 latest handshake が表示されません。
    つまり、

    インターネット
    ↓
    OCI
    
    まではパケットが届いているのに、
    
    OCI
    ↓
    WireGuard
    へ届いていない状態でした。


    8. 原因はOCI Ubuntu側のiptables

    OCI側で、

    sudo iptables -L INPUT -n -v

    を確認すると、通信をREJECTするルールが存在していました。
    そこでUDP 51820をINPUTチェーンの先頭で許可しました。

    sudo iptables -I INPUT 1 -p udp --dport 51820 -j ACCEPT

    その後、sudo wg を確認すると、
    latest handshake: ... が表示されるようになりました。
    さらに自宅Ubuntu側から、

    ping 10.100.0.1

    も通るようになりました。
    これでWireGuardトンネルは完成です。

    9. WireGuardを自動起動する

    OCIと自宅Ubuntuの両方で、

    sudo systemctl enable wg-quick@wg0

    を実行して、再起動後にもWireGuardが立ち上がるようにしました。

    10. iptablesの設定を保存する

    iptablesの設定は、そのままだと再起動すると消える可能性があります。
    そこで、

    sudo apt install -y iptables-persistent

    をインストールしました。
    設定変更後は、

    sudo netfilter-persistent save

    を実行して保存します。

    11. Minecraft Bedrock Dedicated Server導入

    Minecraft Bedrock Dedicated Serverは、自宅のUbuntu VM内で動かします。

    mkdir -p ~/bedrock-server

    でディレクトリを作り、公式のBedrock Dedicated Serverを展開します。 展開したディレクトリへ移動して、

    chmod +x bedrock_server
    LD_LIBRARY_PATH=. ./bedrock_server

    で起動します。 正常に起動すると、 IPv4 supported, port: 19132 Server started. などと表示されます。
    待ち受け状態は、

    sudo ss -lunp | grep 19132

    で確認できます。

    12. OCIでIP Forwardingを有効化する

    OCIへ来たMinecraft通信をWireGuardへ転送するため、IPv4 Forwardingを有効にします。

    sudo sysctl -w net.ipv4.ip_forward=1

    再起動後にも有効になるよう、

    echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-minecraft-relay.conf

    も設定しました。

    13. Minecraft用の外部ポート

    Minecraft Bedrockの標準ポートは、UDP 19132 です。ただし今回の環境では、なぜか外部からOCIのUDP 19132へ通信がうまく到達しませんでした。 そこで外部側だけ、UDP 51821 を使用することにしました。構成としては、

    インターネット
    ↓
    OCI:51821
    ↓
    自宅Ubuntu:19132

    としました。
    OCIのSecurity ListでもUDP 51821を許可します。

    14. OCIでDNATする

    OCIへ来たUDP 51821を、自宅Ubuntu VMの19132へ変換します。

    sudo iptables -t nat -A PREROUTING \
      -i ens3 \
      -p udp \
      --dport 51821 \
      -j DNAT \
      --to-destination 10.100.0.2:19132

    さらにWireGuard側へ送る通信をNATします。

    sudo iptables -t nat -A POSTROUTING \
      -o wg0 \
      -p udp \
      -d 10.100.0.2 \
      --dport 19132 \
      -j MASQUERADE

    15.iptables

    今度はFORWARDチェーンで詰まったOCIの外部インターフェースではUDP 51821の通信が確認できました。DNATのカウンタも増えていました。

    sudo iptables -t nat -L PREROUTING -n -v --line-numbers

    しかし、

    sudo tcpdump -ni wg0 udp port 19132

    では通信が確認できませんでした。
    原因を調べるため、

    sudo iptables -L FORWARD -n -v --line-numbers

    すると、Minecraft用のACCEPTルールよりも前にREJECTルールがありました。
    iptablesは上から順番にルールを処理するため、

    REJECT
    ↓
    ACCEPT

    という順番では、後ろのACCEPTルールまで到達しません。そこでMinecraft用のルールを先頭に追加しました。

    sudo iptables -I FORWARD 1 \
      -i ens3 \
      -o wg0 \
      -p udp \
      -d 10.100.0.2 \
      --dport 19132 \
      -j ACCEPT

    返信側の通信も許可します。

    sudo iptables -I FORWARD 1 \
      -i wg0 \
      -o ens3 \
      -m conntrack \
      --ctstate ESTABLISHED,RELATED \
      -j ACCEPT

    これで、

    Minecraft
    ↓
    OCI:51821
    ↓
    DNAT
    ↓
    WireGuard
    ↓
    Ubuntu VM:19132
    ↓
    Minecraft Bedrock Server
    ↓
    WireGuard
    ↓
    OCI
    ↓
    Minecraft

    という通信が完成しました。
    最後に、

    sudo netfilter-persistent save

    でiptables設定を保存しました。

    16. Minecraftから接続する

    Minecraft統合版からサーバーを追加します。

    サーバーアドレス : <OCI_PUBLIC_IP> 
    ポート : 51821

    これで、自宅ルーターのポート開放を行わずにMinecraftサーバーへ接続できました。

    17. Allow Listを有効にする

    今回は2人だけで遊ぶサーバーなので、Allow Listを有効にしています。 server.properties で、

    allow-list=true

    とします。
    Bedrock Serverのコンソールで、

    allowlist add プレイヤー名1
    allowlist add プレイヤー名2

    を実行。
    確認する場合は、

    allowlist list

    を使います。
    これで登録したプレイヤーだけが参加できます。

    18. Minecraft Serverをsystemdで自動起動する

    毎回手動でBedrock Serverを起動するのは面倒なので、systemdサービスにしました。例として、/etc/systemd/system/bedrock.service を作成します。 内容は以下のようにしました。

    [Unit]
    Description=Minecraft Bedrock Server
    After=network-online.target
    
    [Service]
    User=<USER>
    WorkingDirectory=/home/<USER>/bedrock-server/bedrock-server-1.26.44.3
    Environment=LD_LIBRARY_PATH=.
    ExecStart=/home/<USER>/bedrock-server/bedrock-server-1.26.44.3/bedrock_server
    Restart=on-failure
    RestartSec=5
    KillSignal=SIGINT
    
    [Install]
    WantedBy=multi-user.target

    設定を読み込みます。

    sudo systemctl daemon-reload

    自動起動を有効にして、そのまま起動します。

    sudo systemctl enable --now bedrock

    状態確認は、

    sudo systemctl status bedrock --no-pager

    です。
    Active: active (running)
    になっていれば起動しています。

    19. Ubuntu VMを再起動して確認

    最後にUbuntu VMを再起動しました。sudo reboot 再起動後、sudo wg でWireGuardを確認。 さらに、sudo systemctl status bedrock --no-pager でBedrock Serverを確認しました。 WireGuardとBedrock Serverの両方が自動起動していました。実際にMinecraftから接続してみたところ、Ubuntu VMを再起動したあとでも問題なくサーバーへ入ることができました。

    今回一番ハマったポイント

    今回特に苦戦したのは、OCIとUbuntu側のファイアウォールです。OCIには、Security List があります。 しかし、それとは別にUbuntu側にも、iptables があります。 そのため、OCIのSecurity Listでポートを開けただけでは必ずしも通信できません。

    sudo tcpdump -ni any udp port 51820
    sudo tcpdump -ni wg0 udp port 19132

    を使えば、パケットがどこまで届いているのかを確認できます。
    また、

    sudo iptables -L INPUT -n -v
    sudo iptables -L FORWARD -n -v --line-numbers

    を見ることで、iptablesに通信を止められていないか確認できます。 そしてiptablesでは、 ルールの内容だけではなく順番も重要 ということも今回かなり勉強になりました。 許可ルールが存在していても、その前にREJECTルールがあれば通信はそこで止まります。

    最終的な構成

    Internet
       │
       │ UDP 51821
       ▼
    OCI Public IPv4
       │
       │ DNAT
       ▼
    OCI wg0
    10.100.0.1
       │
       │ WireGuard
       ▼
    Ubuntu VM wg0
    10.100.0.2
       │
       │ UDP 19132
       ▼
    Minecraft Bedrock Dedicated Server
    

    この構成によって、 自宅側でポート開放できない環境でもMinecraft統合版サーバーを外部公開することができました。 Minecraft本体は自宅PCで動かし、OCIは通信の中継だけを担当します。 そのため、OCI側に高性能なVMを用意する必要がないのもメリットです。

    今後やりたいこと

    OCI自体を再起動しても自動復旧するか確認 昔遊んでいたMinecraftワールドをサーバーへ移行 ワールドの自動バックアップ Minecraft Serverの自動アップデート サーバー監視 などもやってみたいと思います。 ポート開放できない環境でMinecraftサーバーを公開したい人の参考になれば幸いです。


    あなたへのおすすめ