自宅サーバーのIPアドレスを隠してサーバーを公開する方法

適当なタイトルが思いつかなかった…

内容としては、クラウド上のVPSにフロントエンドサーバーを建てて、プロキシーのようにフロントエンドサーバーを経由してクライアントと通信させるということ。クライアントから見えるのはフロントエンドサーバーのIPアドレスってわけ。

結構上級者向けの内容。WireGuard、ファイアーウォールやNATの知識があることが前提。

大変参考にした記事: Internet Watch / 清水理史の「イニシャルB」:VPSを使って「マインクラフト」などの自宅ゲームサーバーを安全に公開する方法

ここからいくつかアレンジをしている。

  1. 自宅内のゲームサーバー上に直接WireGuardを置くのではなく、WireGuardで通信するゲートウェイサーバーを、ゲームサーバーとは別に独立して用意する
    →自宅内に複数台のサーバーがあったり、他に管理したいマシンがあるケースに対応できる
  2. ファイアーウォールをufwからnftablesに変更
  3. 普段Fedoraを利用していて、Fedoraで利用する方法も載せたかったので、今回は自宅のVPNゲートウェイをFedoraで構築。コマンドとファイルの配置場所が違うぐらいだけど…
  4. シンプルにするため、ここでは冗長化は扱わない

参考にした記事ではゲームサーバーで利用するケースが想定されているが、ポート番号やプロトコルの設定を変更すれば、様々なアプリケーションに対応可能。話題のパルワールドのサーバーでも、Webサーバーでも利用可能。

構成図

グローバルIPアドレスは例示用のものを使用している。

v6プラス 固定IP1の回線環境でテストしている。WireGuardの接続形態は参考元の記事と同じなので、恐らくMAP-E、DS-Liteでもいけるはず。ただし、MTUの調整は必要。


今回はパルワールドのサーバーを公開する場合の設定をしてみる。
パルワールドのサーバーで必要となるデフォルトのポートは下記の通り。

プロトコルポート番号用途
UDP8211ゲームポート
UDP27015クエリーポート

クエリーポートは開けなくても動いているけど一応載せておく。

また、WireGuardの待ち受けポートとして、今回はUDPの61267を使用する。

フロントエンドサーバーの設定

Ubuntu 22.04.4 LTSを使用。

WireGuardをインストール。nftablesはインストールされていた

sudo apt install wireguard

IPフォワードを有効化する

sudoedit /etc/sysctl.d/10-net-forward.conf

/etc/sysctl.d/10-net-forward.confの内容:

net.ipv4.ip_forward = 1

再起動

sudo reboot

再起動後、/etc/nftables.confを配置する。

/etc/nftables.confの内容:

flush ruleset

table inet firewall {
	chain inbound_ipv4 {
		# パルワールドのサーバーブラウザー上でPing値が表示されるようになる。お好みで
		icmp type echo-request limit rate 5/second accept
	}

	chain inbound_ipv6 {
		icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
	}

	chain inbound {
		type filter hook input priority filter; policy drop;
		ct state vmap { invalid : drop, established : accept, related : accept }
		iifname "lo" accept
		meta protocol vmap { ip : jump inbound_ipv4, ip6 : jump inbound_ipv6 }
		# ポートを追加・変更する場合は下の2行を変更
		iifname "eth0" tcp dport 22 accept # SSH
		iifname "eth0" udp dport { 8211, 27015, 61267 } accept # Palworld / WireGuard
	}

	chain forward {
		type filter hook forward priority filter; policy drop;
		iifname "eth0" oifname "wg0" accept
		iifname "wg0" oifname "eth0" accept
	}
}
table inet nat {
	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;
		ip saddr 192.168.100.0/24 oifname "eth0" masquerade
	}

	chain prerouting {
		type nat hook prerouting priority dstnat; policy accept;
		# ポートを追加・変更する場合は下の行を変更
		ip daddr 203.0.113.10 udp dport { 8211, 27015 } iifname "eth0" dnat ip to 192.168.100.100
	}
}

イーサーネットのインターフェイス名はeth0。必要に応じて置き換える。

簡単に説明。

table inet firewall(ファイアーウォール用テーブル)

chain inbound_ipv4

パルワールドのサーバーブラウザー上のPing値の計測は、サーバーに入ったあとに表示されるPing(RTT)値の計測とは異なり、ICMPが使用されている模様。同じUnreal Engineを使用しているLongvinterでも同じ挙動だったので、UE共通の仕様なのかも?

icmp type echo-requestの行をコメントアウトすると、ICMPがdropされるのでPing値は非表示になる。

chain inbound

ポートを追加・変更する場合はdportの括弧内の番号を変更する。TCPとUDPで行が分かれる。

TCP: SSHを許可。
UDP: パルワールド(ゲームポート)、パルワールド(クエリーポート)、WireGuardの通信を許可。

chain forward

eth0~wg0間の転送を相互に許可する。

table inet nat(NAT用テーブル)

chain postrouting

自宅のLANセグメントから出てきた通信のソースアドレスを、eth0のアドレスでマスカレード(ソースNAT)する。snatでも可能。

chain postrouting

フロントエンドサーバーへやってきて、自宅内のサーバーへ通す通信の行き先アドレスを、自宅内のサーバーのアドレスにデスティネーションNATする。

ポートを追加・変更する場合はdportの括弧内の番号を変更する。こちらもTCPとUDPで行が分かれる。サーバーを複数台に増やしたい場合は末尾参照。

ufwの停止とnftablesの起動を行う。

sudo systemctl stop ufw
sudo systemctl disable ufw
sudo systemctl start nftables
sudo systemctl enable nftables

ルールが正常に読み込まれていることを確認

sudo nft list ruleset

/etc/wireguard/wg0.confを配置

[Interface]
Address = 192.168.10.1/30
ListenPort = 61267
PrivateKey = <フロントエンドサーバーの秘密鍵>

[Peer]
PublicKey = <VPNゲートウェイの公開鍵>
AllowedIPs = 192.168.10.2/32, 192.168.100.0/24

AllowedIPs についてはここでは対向のインターフェイスのアドレスと、LANのネットワークアドレスを指定する。

WireGuardを起動する

sudo systemctl start wg-quick@wg0
sudo systemctl enable wg-quick@wg0

VPNゲートウェイの設定

Fedora Server 39 ネットワークインストール版を使用。

WireGuardをインストール。こちらもnftablesはインストールされていた

sudo dnf install wireguard-tools

IPフォワードを有効化する

sudoedit /etc/sysctl.d/10-net-forward.conf

/etc/sysctl.d/10-net-forward.confの内容:

net.ipv4.ip_forward = 1

再起動

sudo reboot

再起動後、/etc/sysconfig/nftables.confを配置する。

/etc/sysconfig/nftables.confの内容:

flush ruleset

table inet firewall {
	chain inbound_ipv4 {
		icmp type echo-request limit rate 5/second accept
	}

	chain inbound_ipv6 {
		icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
	}

	chain inbound {
		type filter hook input priority filter; policy drop;
		ct state vmap { invalid : drop, established : accept, related : accept }
		iifname "lo" accept
		meta protocol vmap { ip : jump inbound_ipv4, ip6 : jump inbound_ipv6 }
		iifname "enp1s0" tcp dport 22 accept # SSH
	}

	chain forward {
		type filter hook forward priority filter; policy drop;
		iifname "enp1s0" oifname "wg0" accept
		iifname "wg0" oifname "enp1s0" accept
	}
}

イーサーネットのインターフェイス名はenp1s0。必要に応じて置き換える。

Fedoraのデフォルトのファイアウォール、firewalldを停止して、nftablesを起動

sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo systemctl start nftables
sudo systemctl enable nftables

ルールが正常に読み込まれていることを確認

sudo nft list ruleset

/etc/wireguard/wg0.confを配置

[Interface]
Address = 192.168.10.2/30
ListenPort = 61267
PrivateKey = <VPNゲートウェイの秘密鍵>
MTU = 1380

[Peer]
PublicKey = <フロントエンドサーバーの公開鍵>
AllowedIPs = 0.0.0.0/0
Endpoint = 203.0.113.10:61267
PersistentKeepalive = 25

v6プラスのIPv4のMTUは1460。
WireGuardのペイロードサイズが80なので、WireGuardのトンネルで設定すべきMTUは、1460 – 80 = 1380となる。IPv4のみ使う気であればペイロードサイズが60らしいので、1400でもいけるかも
MTUを設定せずに使ったところ、一部サイトで通信できないことがありハマった。

AllowedIPs = 0.0.0.0/0ですべての行き先のトラフィックをVPNを通して通信させる。

WireGuardを起動する

sudo systemctl start wg-quick@wg0
sudo systemctl enable wg-quick@wg0

※WireGuardが起動すると、自動的にnftablesにいくつかルールが追加される。

最後に、WireGuardの接続ができていることを双方で確認

sudo wg

自宅内のサーバーの設定

  • デフォルトゲートウェイをVPNゲートウェイのIPアドレスに設定
    これを行うことでLANを出るすべての通信はVPNゲートウェイへルーティングされる。
  • MTUを1380に設定

サーバーを追加したい場合はどうする?

例えば、192.168.100.101というWebサーバーを追加したい場合は、フロントエンドサーバーのnftables.conf内の、inboundとpreroutingのチェーンを下記のようにする。

chain inbound {
	type filter hook input priority filter; policy drop;
	ct state vmap { invalid : drop, established : accept, related : accept }
	iifname "lo" accept
	meta protocol vmap { ip : jump inbound_ipv4, ip6 : jump inbound_ipv6 }
	iifname "eth0" tcp dport { 22, 80, 443 } accept # 80, 443ポート追加
	iifname "eth0" udp dport { 8211, 27015, 61267 } accept
}
chain prerouting {
	type nat hook prerouting priority dstnat; policy accept;
	ip daddr 203.0.113.10 udp dport { 8211, 27015 } iifname "eth0" dnat ip to 192.168.100.100
	# Webサーバー用のdnatルール追加
	ip daddr 203.0.113.10 tcp dport { 80, 443 } iifname "eth0" dnat ip to 192.168.100.101
}

最後のdnat ip toの部分の行き先のIPアドレスが変わるため、台数分、行を追加することになる。

コメントを残す

メールアドレスは公開されません


reCAPTCHAの認証期間が終了しました。ページを再読み込みしてください。