優れたソフトウェアと実用的なチュートリアル
1. クイックスタート
仕事をうまくやり遂げたいなら、まず道具を研がなければなりません。 ワイヤーガード 一般的なプロセスは次のとおりです。
準備
現在のカーネルバージョンを表示する
uname -r #4.18.0-348.2.1.el8_5.x86_64 uname -a #Linux mir4 4.18.0-348.2.1.el8_5.x86_64 #1 SMP 2021年11月16日火曜日 14:42:35 UTC x86_64 x86_64 x86_64 GNU/Linux cat /etc/redhat-release #CentOS Linuxリリース8.5.2111
システムカーネルをアップグレードする
dnf -y アップデート

CentOS 8.xにEPELリポジトリをインストールする
EPELは「Extra Packages for Enterprise Linux」の略で、CentOSおよびRHELサーバーで利用可能な追加パッケージを収録した無料のオープンソースリポジトリです。その名の通り、EPELリポジトリはCentOS 8およびRHEL 8のデフォルトパッケージリポジトリには含まれていない追加パッケージを提供します。
エペル公式サイト:https://fedoraproject.org/wiki/EPEL/zh-cn
dnf search epel #epel-next-release.noarch: Enterprise Linux Next リポジトリ構成用の追加パッケージ #epel-release.noarch: Enterprise Linux リポジトリ構成用の追加パッケージ # システム ソフトウェア リポジトリ内の epel-release バージョンを確認します dnf info epel-release # システム ソフトウェア リポジトリから epel ソースをインストールします dnf install epel-release # 次の URL を介して Web サイトから epel ソースをインストールします dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm # EPEL パッケージはこれらのリポジトリ内のパッケージに依存している可能性があるため、PowerTools リポジトリを有効にします dnf config-manager --set-enabled powertools # インストールが成功したら、リポジトリ内のパッケージの数をテストします sudo dnf --disablerepo="*" --enablerepo="epel" list available |トイレ -l
CentOS 8.xにELRepoリポジトリをインストールする
ELRepo リポジトリは、RedHat Enterprise (RHEL) およびその他の RHEL ベースの Linux ディストリビューション (CentOS、Scientific、Fedora など) をサポートするコミュニティ ベースのエンタープライズ Linux リポジトリです。
ELRepo は、ファイル システム ドライバー、グラフィック ドライバー、ネットワーク ドライバー、サウンド カード ドライバー、カメラ ドライバーなどのハードウェア関連のソフトウェア パッケージに重点を置いています。
#ELRepoリポジトリの公開鍵をインポートしますrpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org #ELRepoリポジトリのyumソースをインストールしますdnf install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm #カーネルのバージョンを確認しますdnf --disablerepo="*" --enablerepo="elrepo-kernel" list available
Wireguard をインストールする前に、eple および ELRepo リポジトリをサーバーにインストールする必要があります。
# ソフトウェアソースがインストールされたら、キャッシュをクリアします。dnf clean all # リポジトリのキャッシュを再作成します。yum makecache restart
インストール
公式インストールリファレンス:https://www.wireguard.com/install/
Centos8、Centos7、Ubuntu、MacOS を含むいくつかのオペレーティング システムのインストール方法を次に示します。
#CentOS8 dnf install elrepo-release epel-release dnf config-manager --set-enabled powertools dnf copr enable jdoss/wireguard dnf install wireguard-dkms wireguard-tools #CentOS7 yum install epel-release https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm yum install yum-plugin-elrepo yum install kmod-wireguard wireguard-tools # 非標準カーネルを使用している場合は、DKMS パッケージをインストールする必要があります yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm curl -o /etc/yum.repos.d/jdoss-wireguard-epel-7.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo yum install wireguard-dkms wireguard-tools #Ubuntu≥18.04 apt install wireguard #Ubuntu≤16.04 add-apt-repository ppa:wireguard/wireguard apt-get update apt-get install wireguard #MacOS brew install wireguard-tools

Windows クライアントのダウンロード アドレス:
- https://download.wireguard.com/windows-client/wireguard-amd64-0.1.1.msi
- https://download.wireguard.com/windows-client/wireguard-installer.exe

Android および iOS では、アプリ ストアから関連クライアントをダウンロードできます。
https://www.wireguard.com/install/#installation


リレー サーバーで IP アドレス転送を有効にします。
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
このマシンで NAT 変換を許可するための iptables ルールを追加します。
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i wg0 -o wg0 -m conntrack --ctstate NEW -j ACCEPT iptables -t nat -A POSTROUTING -s 192.0.2.0/24 -o eth0 -j MASQUERADE
eth0 を、実際に使用するネットワーク カード インターフェイスの名前に変更する必要があります。
設定ファイルの記述
設定ファイルは任意のパスに配置できますが、絶対パスで参照する必要があります。デフォルトのパスは/etc/wireguard/wg0.confです。
# 設定ファイルを作成する vi /etc/wireguard/wg0.conf
キーを生成する
秘密鍵を生成する
wg genkey > example.key
公開鍵を生成する
WG パブキー < 例.キー > 例.key.pub
開始と停止
$ wg-quick は /full/path/to/wg0.conf を起動します
$ wg-quick で /full/path/to/wg0.conf をダウンロードする
# 启动/停止 VPN ネットワークインターフェース
$ IPリンク設定wg0アップ
$ IPリンクセットwg0ダウン
# VPNネットワークインターフェースの登録/登録解除
$ IPリンク追加デバイスwg0タイプWireguard
$ IPリンク削除デバイスwg0
# ローカルVPNアドレスの登録/登録解除
$ IPアドレスを追加 dev wg0 192.0.2.3/32
$ IPアドレス削除 dev wg0 192.0.2.3/32
# VPNルートの追加/削除
$ IPルート追加 192.0.2.3/32 dev wg0
$ IPルート削除 192.0.2.3/32 dev wg0
情報を見る
インタフェース:
# システムVPNインターフェース情報を表示
$ IPリンクショーwg0
# VPNインターフェースの詳細を表示
$ wg すべて表示
$ wg ショー wg0
住所:
# VPNインターフェースアドレスを表示
$ IPアドレス表示 wg0
ルーティング
# システムルーティングテーブルの表示
$ IPルート表示テーブルメイン
$ IPルート表示テーブルローカル
# 特定のIPへのルートを取得する
$ IPルート取得 192.0.2.3
ワンクリックインストール
ワンクリックインストールについては、このプロジェクトを参照してください: WireGuardインストーラ[3]
2. 構成の詳細
WireGuardはINIを使用します[4] 設定ファイルの形式は/etc/wireguard/wg0.confです。設定ファイルは任意のパスに配置できますが、絶対パスで参照する必要があります。デフォルトのパスは/etc/wireguard/wg0.confです。
設定ファイルは${WireGuardインターフェース名}.confという名前にする必要があります。通常、WireGuardインターフェース名はwgで始まり、0から始まる番号が付けられますが、正規表現^[a-zA-Z0-9_=+.-]{1,15}$に一致する限り、他の名前を使用することもできます。
wg コマンドを使用して VPN を手動で構成することもできますが、通常は、より強力でユーザーフレンドリーな構成エクスペリエンスを提供し、構成ファイルを通じて構成を管理できる wg-quick を使用することをお勧めします。
以下は構成ファイルの例です。
[インタフェース]
# 名前 = node1.example.tld
アドレス = 192.0.2.3/32
リスンポート = 51820
秘密鍵 = localPrivateKeyAbcAbcAbc=
DNS = 1.1.1.1,8.8.8.8
テーブル = 12345
MTU = 1500
PreUp = /bin/example arg1 arg2 %i
PostUp = /bin/example arg1 arg2 %i
プリダウン = /bin/example arg1 arg2 %i
PostDown = /bin/example arg1 arg2 %i
[ピア]
# 名前 = node2-node.example.tld
許可されたIP = 192.0.2.1/24
エンドポイント = node1.example.tld:51820
公開鍵 = リモート公開鍵AbcAbcAbc=
永続キープアライブ = 25
[インタフェース]
このセクションでは、ローカルVPN設定を定義します。例:
ローカル ノードは、独自のトラフィックのみをルーティングし、1 つの IP のみを公開するクライアントです。
[インタフェース]
# 名前 = phone.example-vpn.dev
アドレス = 192.0.2.5/32
秘密鍵 =ローカル ノードは、トラフィックを他のピアに転送し、VPN サブネット全体のルーティングを公開するリレー サーバーです。
[インタフェース]
# 名前 = public-server1.example-vpn.tld
アドレス = 192.0.2.1/24
リスンポート = 51820
秘密鍵 =
DNS = 1.1.1.1
① # 名前
これはINI構文の標準コメントであり、設定のこの部分がどのノードに属しているかを示すために使用されます。この設定部分はWireGuardによって完全に無視され、VPNの動作には影響しません。
②住所
ローカルノードがルーティングするアドレス範囲を定義します。通常のクライアントの場合は、ノード自体の単一のIPアドレス(CIDRで指定、例:192.0.2.3/32)を設定します。リレーサーバーの場合は、ルーティング可能なサブネット範囲を設定します。
例えば:
通常のクライアントは自身のトラフィックのみをルーティングします: アドレス = 192.0.2.3/32 他のピアノード(ピア)にトラフィックを転送できるリレーサーバー:アドレス = 192.0.2.1/24 複数のサブネットまたは IPv6 サブネットを指定することもできます: アドレス = 192.0.2.1/24,2001:DB8::/64
③ リッスンポート
ローカルノードがリレーサーバーの場合、このパラメータでVPN接続をリッスンするポートを指定する必要があります。デフォルトのポート番号は51820です。通常のクライアントではこのオプションは必要ありません。
④ 秘密鍵
ローカルノードの秘密鍵は、すべてのノード(リレーサーバーを含む)に設定する必要があります。他のサーバーと共有することはできません。
秘密鍵は、コマンド wg genkey > example.key で生成できます。
⑤ DNS
DHCP経由でクライアントにDNSサーバーをアナウンスします。クライアントはここで指定されたDNSサーバーを使用してVPNサブネット内のDNSリクエストを処理しますが、このオプションはシステムで上書きすることもできます。例:
設定されていない場合は、システムのデフォルトのDNSが使用されます。 単一のDNSを指定できます: DNS = 1.1.1.1 複数の DNS を指定することもできます: DNS = 1.1.1.1,8.8.8.8
⑥ テーブル
VPNサブネットで使用されるルーティングテーブルを定義します。デフォルトでは設定は不要です。このパラメータには、注意が必要な2つの特別な値があります。
テーブル = オフ : ルートの作成を無効にする テーブル = 自動 (デフォルト) : ルートをシステムデフォルトテーブルに追加し、デフォルトルートに対する特別な処理を有効にします。
例: テーブル = 1234
⑦ MTU
ピアに接続されたMTU(最大転送単位)を定義します。デフォルトでは設定する必要はなく、通常はシステムによって自動的に決定されます。
8 プレアップ
VPNインターフェースを起動する前に実行するコマンド。このオプションは複数回指定でき、順番に実行されます。
例えば:
ルートを追加: PreUp = ip rule add ipproto tcp dport 22 table 1234
⑨ ポストアップ
VPNインターフェースの起動後に実行するコマンド。このオプションは複数回指定でき、順番に実行されます。
例えば:
ファイルまたはコマンドの出力から構成値を読み取ります。
PostUp = wg セット %i 秘密キー /etc/wireguard/wg0.key <(some command here)ファイルにログ ラインを追加します。
PostUp = echo "$(日付 +%s) WireGuard が開始しました" >> /var/log/wireguard.logWebHookの呼び出し:
PostUp = カール https://events.example.dev/wireguard/started/?key=abcdefgルートを追加します:
PostUp = IPルール追加 IPプロトコル TCP ポート 22 テーブル 1234パケット転送を有効にするには、iptables ルールを追加します。
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADEWireGuard にピア ドメイン名の IP アドレスを再度解決させる:
PostUp =resolvectl domain %i "~.";resolvectl dns %i 192.0.2.1;resolvectl dnssec %i yes
⑩ プレダウン
VPNインターフェースを停止する前に実行するコマンド。このオプションは複数回指定でき、順番に実行されます。
例えば:
ファイルにログ ラインを追加します。
PreDown = echo "$(date +%s) WireGuardがダウンしています" >> /var/log/wireguard.logWebHookの呼び出し:
プレダウン = カール https://events.example.dev/wireguard/stopping/?key=abcdefg
⑪ ポストダウン
VPNインターフェースを停止した後に実行するコマンド。このオプションは複数回指定でき、順番に実行されます。
例えば:
ファイルにログ ラインを追加します。
PostDown = echo "$(date +%s) WireGuardがダウンしています" >> /var/log/wireguard.logWebHookの呼び出し:
PostDown = カール https://events.example.dev/wireguard/stopping/?key=abcdefgiptables ルールを削除し、パケット転送をオフにします。
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[ピア]
1つ以上のアドレスへのトラフィックをルーティングできるピアを定義するVPN設定。ピアとは、トラフィックを他のピアに転送するリレーサーバー、またはパブリックネットワークまたはプライベートネットワークを介して直接接続するクライアントを指します。
リレーサーバーはすべてのクライアントをピアとして定義する必要があります。NATの背後にあるノードはルートが到達不可能なため、リレーサーバー以外のクライアントはピアとして定義できません。トラフィックを自身にのみルーティングするクライアントの場合、リレーサーバーのみがピアとなり、その他のノードは直接アクセス可能でなければなりません。
たとえば、次の構成では、public-server1 はリレー サーバーとして使用され、他のクライアントは直接接続されているか、NAT の背後にあります。
パブリックサーバー1(リレーサーバー)[ピア]:パブリックサーバー2、ホームサーバー、ラップトップ、電話 public-server2(直接接続クライアント)[ピア] : public-server1 ホームサーバー(クライアントはNATの背後にある) [ピア] : public-server1、public-server2 ラップトップ(NATの背後にあるクライアント) [ピア] : public-server1、public-server2 電話(クライアントはNATの背後にある) [ピア] : public-server1、public-server2
設定例:
ピアは、自分自身にのみトラフィックをルーティングするルーティング可能なクライアントです。
[ピア]
# 名前 = public-server2.example-vpn.dev
エンドポイント = public-server2.example-vpn.dev:51820
公開鍵 =
許可されたIP = 192.0.2.2/32ピアとは、NAT の背後にあるクライアントであり、自分自身に対してのみトラフィックをルーティングします。
[ピア]
# 名前 = home-server.example-vpn.dev
エンドポイント = home-server.example-vpn.dev:51820
公開鍵 =
許可されたIP = 192.0.2.3/32ピア ノードは、トラフィックを他のピア ノードに転送するリレー サーバーです。
[ピア]
# 名前 = public-server1.example-vpn.tld
エンドポイント = public-server1.example-vpn.tld:51820
公開鍵 =
#はVPNサブネット全体にトラフィックをルーティングします
許可されたIP = 192.0.2.1/24
永続キープアライブ = 25
① エンドポイント
リモートピアのパブリックネットワークアドレスを指定します。ピアがNATの背後にある場合、または安定したパブリックネットワークアドレスを持たない場合、このフィールドは無視されます。通常はリレーサーバーエンドポイントはもちろん、安定したパブリックIPを持つノードも指定できます。例:
IPで指定:
エンドポイント = 123.124.125.126:51820ドメイン名で指定:
エンドポイント = public-server1.example-vpn.tld:51820
② 許可されたIP
このピアから許可されるVPNトラフィックの送信元アドレス範囲。このフィールドは、ローカルルーティングテーブルでwg0にバインドされるIPアドレス範囲としても使用されます。ピアが通常のクライアントの場合は、ノード自体の単一のIPアドレスを設定します。ピアがリレーサーバーの場合は、ルーティング可能なサブネット範囲を設定します。, を使用して、複数のIPアドレスまたはサブネット範囲を指定できます。このフィールドは複数回指定することもできます。
パケットのルーティング方法を決定する際、システムはまず最も具体的なルートを選択し、一致するルートが見つからない場合は、より一般的なルートを選択します。例えば、192.0.2.3 宛てのパケットの場合、システムはまずアドレスが 192.0.2.3/32 のピアを検索し、該当するピアが見つからない場合は、アドレスが 192.0.2.3/32 のピアを検索します。以下同様に処理が続きます。
例えば:
ピアは、自身のトラフィックのみをルーティングする通常のクライアントです。
許可されたIP = 192.0.2.3/32ピアはトラフィックを他のピアに転送するリレー サーバーです。
許可されたIP = 192.0.2.1/24ピアノードは、外部ネットワークトラフィックやVPNトラフィックを含むすべてのトラフィックを転送するリレーサーバーです。その用途は以下のとおりです。
許可されたIP = 0.0.0.0/0,::/0ピアとは、自身と他のピア間のトラフィックをルーティングするリレー サーバーです。
許可されたIP = 192.0.2.3/32,192.0.2.4/32ピアとは、自身のトラフィックとそれが含まれるイントラネットのトラフィックをルーティングできるリレー サーバーです。
許可されたIP = 192.0.2.3/32,192.168.1.1/24
③ 公開鍵
ピアノード(peer)の公開鍵は、すべてのノード(リレーサーバーを含む)で設定する必要があります。他のピアノード(peer)と共通の公開鍵を共有できます。
公開鍵はwg pubkeyコマンドで取得できる。 < 例.キー > example.key.pub 、ここで example.key は上記で生成された秘密鍵です。
例えば: PublicKey = somePublicKeyAbcdAbcdAbcdAbcd=
④ 永続キープアライブ
NAT の背後にあるピアからパブリック ネットワーク上で到達可能なピアへの接続の場合、NAT の背後にあるピアは定期的に送信 ping パケットを送信して接続を確認し、IP が変更された場合はエンドポイントを自動的に更新する必要があります。
例えば:
ローカル ノードはピア ノードに直接接続されています。接続チェックは必要ないため、このフィールドを指定する必要はありません。 ピアは NAT の背後にあります: 接続を維持するのはクライアント (接続の開始者) の責任であるため、このフィールドを指定する必要はありません。 ローカル ノードは NAT の背後にあり、ピア ノードはパブリック ネットワーク上でアクセス可能です。フィールド PersistentKeepalive = 25 を指定する必要があります。これは、接続を確認するために 25 秒ごとに ping が送信されることを意味します。
3. 高度な機能
IPv6
これまでの例では主にIPv4を使用していますが、WireGuardはIPv6もサポートしています。例えば:
[インタフェース]
許可されたIPアドレス = 192.0.2.3/24, 2001:DB8::/64
[ピア]
...
許可されたIP = 0.0.0.0/0、::/0
すべてのトラフィックを転送する
VPN サブネットとパブリック ネットワーク トラフィックを含むすべてのトラフィックを VPN 経由で転送する場合は、[Peer] の AllowedIPs に 0.0.0.0/0、::/0 を追加する必要があります。
IPv4トラフィックのみを転送する場合でも、VPN外へのIPv6パケットの漏洩を防ぐため、IPv6ネットワークセグメントを指定する必要があります。詳細については、reddit.com/r/WireGuard/comments/b0m5g2/ipv6_leaks_psa_for_anyone_here_using_wireguard_toをご覧ください。[5]
例えば:
[インタフェース]
# 名前 = phone.example-vpn.dev
アドレス = 192.0.2.3/32
秘密鍵 =
[ピア]
# 名前 = public-server1.example-vpn.dev
公開鍵 =
エンドポイント = public-server1.example-vpn.dev:51820
許可されたIP = 0.0.0.0/0、::/0
一般的に、VPNを空への梯子として使う場合のみ、すべてのトラフィックを転送する必要があります。これ以上は説明しません。ここまでにしておきましょう。
NAT間接続
2 つのピアが NAT の背後にあり、リレー サーバーを介さずに直接接続する場合は、静的パブリック IP を使用するか、DDNS を通じて FQDN を動的に更新して、少なくとも 1 つのピアに安定したパブリック ネットワーク出口があることを確認する必要があります。
WebRTCプロトコルは、2つのNAT間の接続を動的に設定し、シグナリングサーバーを介して各ホストのIPとポートの組み合わせを検出できます。しかし、WireGuardにはこの機能がありません。他のホストを動的に検索するためのシグナリングサーバーは存在せず、Endpoint+ListenPortをハードコードし、PersistentKeepaliveを介して接続を維持することしかできません。
NAT 間接続の前提条件をまとめると次のようになります。
少なくとも1つのピアノードに固定のパブリックIPアドレスが割り当てられています。どちらのピアノードにも固定のパブリックIPアドレスが割り当てられていない場合は、DDNSを使用して安定したドメイン名を維持できます。 少なくとも 1 つのピア ノードが UDP ListenPort を指定しており、その NAT ルータは UDP 送信元ポートのランダム化を実行できません。そうでない場合、返信パケットは以前に指定された ListenPort に送信され、ルータによって破棄され、新しく割り当てられたランダム ポートには送信されません。 接続の永続性を維持できるように、すべてのピアは [Peer] 構成内の他のピアで PersistentKeepalive を有効にする必要があります。
コミュニケーションの双方にとって、サーバNAT ルータが NAT の背後にあるピア ノードへの転送ルールを指定しない場合は、UDP ホール パンチが必要です。
UDP ホールパンチの原理:
Peer1はPeer2にUDPデータパケットを送信しますが、Peer2のNATルーターはパケットの送信先が不明なため、パケットを破棄します。しかし、これは問題ではありません。このステップの目的は、Peer1のNATルーターがUDP応答を受信し、それをPeer1に転送できるようにすることです。 Peer2はPeer1にUDPデータパケットを送信します。前のステップにより、Peer1のNATルーターは一時的な転送ルールを確立し、UDP応答を受信できるため、データパケットを受信してPeer1に転送できます。 Peer1はPeer2にUDP応答を送信します。前のステップの効果により、Peer2のNATルーターは既にUDP応答を受信できるため、データパケットを受信してPeer2に転送できます。
最初のパケットを送信し、それを拒否し、その後ルーターの確立された転送ルールを使用して応答を受信するこのプロセスは、「UDP ホール パンチング」と呼ばれます。
UDPパケットを送信すると、ルーターは通常、送信元アドレス/ポートを宛先アドレス/ポートにマッピングする一時的なルールを作成し、その逆も同様にマッピングします。宛先アドレス/ポートから返されたUDPパケットは、元の送信元アドレス/ポートに転送されます。これは、NATの背後にあるほとんどのUDPアプリケーション(BitTorrent、Skypeなど)が動作する仕組みです。この一時的なルールは一定期間後に期限切れになるため、NATの背後にあるクライアントは、接続の持続性を維持するために、PersistentKeepaliveを介して定期的にパケットを送信する必要があります。
2 つのピアが NAT の背後にある場合、UDP ホール パンチングが機能するには、2 つのノードがほぼ同時にパケットを相互に送信する必要があります。つまり、両方の側がお互いのパブリック ネットワーク アドレスとポート番号を事前に知っている必要があり、これは wg0.conf で指定できます。
UDPホールパンチの制限
2019年以降、以前使われていた多くの昔ながらの穴あけ方法はもはや効果がありません。かつて最も有名だったのはpwnatでした。[6] NATによって生み出された新しいホールパンチング方式。プロキシ、サードパーティサーバー、UPnP、DMZ、セキュア化、DNS変換を必要とせずに、NAT内でP2P通信を実現します。その原理も非常にシンプルです。
この問題は、クライアントをインターネット上のランダムなICMPホップのふりをすることで解決されます。これにより、サーバーはクライアントのIPアドレスを取得できます。tracerouteコマンドも、この技術を使用してインターネット上のホップを検出します。
具体的には、サーバーが起動すると、固定された ICMPエコー要求パケット(ICMPエコー要求パケット)。当然ながら、3.3.3.3からの応答は受信できません。 ICMPエコーパケットしかし、3.3.3.3 はアクセス可能なホストではないため、ICMP エコーパケットを送信するためにこのホストになりすますことは避けたいところです。pwnat テクノロジの実装原理は、クライアントがサーバーに接続しようとすると、(サーバーの IP アドレスを知っている)クライアントがサーバーに ICMP エコーパケットを送信するというものです。 ICMP 時間超過パケット(ICMP時間超過パケット)。このICMPパケットには、サーバーから3.3.3.3に送信された元の固定時間パケットが含まれています。 ICMPエコー要求パケット。
なぜそうするのでしょうか?インターネット上のICMPホップを装い、サーバーに元の ICMPエコー要求パケット3.3.3.3にアクセスできません。NATはスマートデバイスなので、すぐに気付くはずです。 ICMP 時間超過パケットサーバー内のデータパケットは送信される ICMPエコー要求パケットそうすれば ICMP 時間超過パケットクライアントからの完全な IP パケット ヘッダーを含めて NAT の背後にあるサーバーに転送されるため、サーバーはクライアントの IP アドレスを認識できます。
現在、この種のUDPホールパンチング方式には多くの制限があります。詳細については、前の記事UDPホールパンチングに加えて、2つのピアノードのパブリックネットワークアドレスとポート番号をハードコードされた方法で指定することもできます。この方法は、ほとんどのNATネットワークで有効です。
送信元ポートのランダム化
すべてのピアが、UDP送信元ポートの厳格なランダム化を伴うNAT(ほとんどの携帯電話ネットワークなど)の背後にある場合、NAT間接続は確立できません。どちらの側もListenPortをネゴシエートできず、pingパケットを送信した後にNATがそのポートに送信されたトラフィックを受信できることを保証できないため、ホールパンチングを初期化できず、接続に失敗します。したがって、LTE/3GネットワークではP2P通信は一般的に不可能です。
シグナリングサーバーの使用
前のセクションで述べたように、すべてのピアがNATの背後にあり、UDP送信元ポートが厳密にランダム化されている場合、NAT間の接続は直接実現できませんが、サードパーティのシグナリングサーバーを介して実現できます。シグナリングサーバーは中継局に相当し、通信相手に相手のIPアドレスとポート番号の情報を伝えます。参考までに、いくつかのプロジェクトをご紹介します。
高橋拓/wg-connect[7] git.zx2c4.com/wireguard-tools/tree/contrib/nat-hole-punching[8]
動的IPアドレス
WireGuardは起動時にのみドメイン名の解決を行います。DDNSを使用してドメイン名の解決を動的に更新する場合は、IPアドレスが変更されるたびにWireGuardを再起動する必要があります。現在推奨されている解決策は、PostUpフックを使用して数分または数時間ごとにWireGuardを再起動し、ドメイン名の解決を強制することです。
一般的に、NAT 間の接続は非常に不安定であり、他の多くの制限があるため、リレー サーバーを介して通信することをお勧めします。
NAT 間構成の例:
ピア1:
[インタフェース]
...
リスンポート = 12000
[ピア]
...
エンドポイント = peer2.example-vpn.dev:12000
永続キープアライブ = 25
ピア2:
[インタフェース]
...
リスンポート = 12000
[ピア]
...
エンドポイント = peer1.example-vpn.dev:12000
永続キープアライブ = 25
詳細情報:
samyk/pwnat[9] en.wikipedia.org/wiki/UDP_hole_punching[10] stackoverflow.com/questions/8892142/udp-hole-punching-algorithm[11] stackoverflow.com/questions/12359502/udp-hole-punching-not-going-through-on-3g[12] stackoverflow.com/questions/11819349/udp-hole-punching-not-possible-with-mobile-provider[13] ワイヤーガード/ワイヤーガード@ マスター
/contrib/examples/nat-hole-punching[14]staaldraad.github.io/2017/04/17/nat-to-nat-with-wireguard[15] golb.hplar.ch/2019/01/expose-server-vpn.html[16]
サブネットIPを動的に割り当てる
これは、エンドポイントではなく、DHCP に類似した、ピア ノード (ピア) の VPN サブネット IP の動的な割り当てを指します。
WireGuardは、サブネットIPを動的に割り当てる機能を正式に開発中です。具体的な実装はWireGuard/wg-dynamicでご覧いただけます。[17]
もちろん、PostUp を使って実行時にファイルから IP 値を読み取り、Kubernetes の CNI プラグインのように IP を動的に割り当てるシステムを実装することもできます。例えば、次のようになります。
[インタフェース]
...
PostUp = wg set %i allowed-ips /etc/wireguard/wg0.key <(some command)
実用的なヒント
peers.conf ファイルの共有
WireGuardの設定を簡素化する秘密の機能をご紹介します。ピアの公開鍵がローカルインターフェースの秘密鍵と一致する場合、WireGuardはそのピアを無視します。この機能により、すべてのノードで同じピアリストを共有できます。各ノードは個別の[Interface]を定義するだけで、たとえリストにノードが含まれていても無視されます。具体的な方法は以下の通りです。
各ピアには、[Interface] セクションの設定のみが含まれる個別の /etc/wireguard/wg0.conf ファイルがあります。 各ピア ノード (ピア) は、すべてのピアが含まれる同じ /etc/wireguard/peers.conf ファイルを共有します。 PostUp フックは、Wg0.conf ファイルで、PostUp = wg addconf /etc/wireguard/peers.conf という内容で設定する必要があります。
peers.confを共有する方法は数多くあります。Ansibleなどのツールを使って配布したり、Dropboxなどのネットワークディスクと同期したり、Cephなどの分散ファイルシステムを使って異なるノードにマウントしたりすることも可能です。
ファイルまたはコマンド出力から構成を読み取ります
WireGuardは、任意のコマンドまたはファイルの出力からコンテンツを読み取って設定値を変更することもできます。この機能は、キー管理を容易にするために使用できます。例えば、Kubernetes SecretsやAWS KMSなどのサードパーティサービスから実行時にキーを読み取ることができます。
コンテナ化
WireGuardはコンテナ内でも実行できます。最も簡単な方法は、--privileged および --cap-add=all パラメータを使用して、コンテナがカーネルモジュールをロードできるようにすることです。
コンテナ内で WireGuard を実行し、ネットワーク インターフェイスをホストに公開することができます。また、ホスト内で WireGuard を実行し、特定のコンテナにインターフェイスを公開することもできます。
具体的な例として、vpn_testコンテナがすべてのトラフィックをWireGuardリレーサーバー経由でルーティングする例を示します。この例で示されているコンテナ設定は、docker-compose構成ファイル形式です。
リレー サーバー コンテナーの構成:
バージョン: '3'
サービス:
ワイヤーガード:
画像: linuxserver/wireguard
ポート:
- 51820:51820/udp
キャップ追加:
-NET_ADMIN
-SYS_MODULE
ボリューム:
- /lib/modules:/lib/modules
- ./wg0.conf:/config/wg0.conf:ro
リレーサーバーのWireGuard構成wg0.conf:
[インタフェース]
# 名前 = relay1.wg.example.com
アドレス = 192.0.2.1/24
リスンポート = 51820
秘密鍵 = oJpRt2Oq27vIB5/UVb7BRqCwad2YMReQgH5tlxz8YmI=
DNS = 1.1.1.1,8.8.8.8
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[ピア]
# 名前 = peer1.wg.example.com
公開鍵 = I+hXRAJOG/UE2IQvIHsou2zTgkUyPve2pzvHTnd/2Gg=
許可されたIP = 192.0.2.2/32
クライアント コンテナの構成:
バージョン: '3'
サービス:
ワイヤーガード:
画像: linuxserver/wireguard
キャップ追加:
-NET_ADMIN
-SYS_MODULE
ボリューム:
- /lib/modules:/lib/modules
- ./wg0.conf:/config/wg0.conf:ro
vpn_テスト:
画像: curlimages/curl
エントリポイント: curl -s http://whatismyip.akamai.com/
ネットワークモード: 'service:wireguard'
クライアント側の WireGuard 構成 wg0.conf:
[インタフェース]
# 名前 = peer1.wg.example.com
アドレス = 192.0.2.2/32
秘密鍵 = YCW76edD4W7nZrPbWZxPZhcs32CsBLIi1sEhsV/sgk8=
DNS = 1.1.1.1,8.8.8.8
[ピア]
# 名前 = relay1.wg.example.com
エンドポイント = relay1.wg.example.com:51820
公開鍵 = zJNKewtL3gcHdG62V3GaBkErFtapJWsAx+2um0c0B1s=
許可されたIP = 192.0.2.1/24,0.0.0.0/0
永続キープアライブ = 21