同じガイドを IPv4 と IPv6 クライアントに提供する

LinuxBeginner
オンラインで実践に進む

はじめに

Riverlight Gathering には、IPv4 で動作するイベントガイドがあります。来場者には、到着案内とダウンロード可能なプログラムを含む同じ完全なガイドを IPv6 でも提供する必要があります。ネットワークアドレスは準備済みですが、Web サービスはまだ IPv6 で待ち受けておらず、ガイドの AAAA レコードも誤ったアドレスを指しています。

この 2 つの問題を分けて解決します。まずアプリケーションへの直接 IPv6 アクセスを動作させ、次に名前を修正します。IPv4、受付、他の DNS レコード、すべての元のページとダウンロードのバイト列は維持します。基本的なターミナル、パス、タブ操作と、アドレス、名前、ポートの識別が前提です。Nginx や IPv6 の管理経験は不要です。70 分は作者による見積もりです。

Guide Server と Guide Client は、この訓練インスタンスのカーネルを共有する隔離ネットワークノードです。別々の VM ではありません。変更するのは guide.conf の待ち受け文と guide.zone の対象 AAAA/SOA シリアル番号だけです。ダウンロードはクライアントの作業領域に保存します。ルート、アドレス、IPv6 のスイッチ、他のサイト、元のページ、プラットフォーム設定は変更しません。準備済みのローカルネットワークを使い、パブリック IPv6、RA、DHCPv6、トンネル、NAT64 は扱いません。

アドレスファミリーを比較する

このステップでは、動作中の IPv4 ガイドを読み、到達可能な IPv6 アドレスと、待ち受け中のアプリケーションを区別します。Guide Client から始めてください。ターミナルの開始位置は /home/labex/project/ipv6-guide/client です。シェルとディレクトリの状態は Guide Server とは独立して維持されます。pwd は現在のディレクトリを表示します。

pwd

IPv4 アドレスは、10.77.0.10 のような 4 つの十進数の部分で構成されます。IPv6 は 8 組の十六進数を使用します。各組の先頭のゼロは省略でき、1 つの :: で連続する全ゼロの組を置き換えられます。ここで fd77:7::10 は fd77:0007:0000:0000:0000:0000:0000:0010 を意味します。末尾の 10 は十六進数であり、IPv4 の末尾の十進数とは異なります。これらのプライベートな訓練用アドレスは、パブリックインターネットへの到達性を意味しません。

curl は HTTP リソースを取得します。-4 は IPv4 を強制し、-f は HTTP エラー応答を失敗として扱い、-s は進行表示を隠し、-S はエラーを引き続き表示します。--noproxy '*' はすべてのホストでプロキシを使わない指定です。引用符によって * をファイル名に展開せず、文字どおりに扱います。ポート 8080 はガイドアプリケーションを選びます。-o は受信バイト列をファイルに保存し、v4 は準備済みの出力ディレクトリです。

curl --noproxy '*' -4 -fsS http://guide.riverlight.test:8080/index.html -o v4/index.html

保存が成功しても通常は何も表示されません。head -c 180 はファイルを変更せず、先頭 180 バイトを読みます。

head -c 180 v4/index.html

Riverlight Gathering を含む HTML が表示されるはずです。これが維持する正常な参照です。ブラウザで完全な外観を表示するには、後で保存するスタイルシートも必要です。

次に準備済み IPv6 アドレスを試します。ping -6 は IPv6 エコー要求を送り、-c 1 は 1 回で終了します。これはネットワーク到達性を調べるもので、HTTP のテストではありません。

ping -6 -c 1 fd77:7::10

応答が返るはずです。URL 内の IPv6 リテラルは角括弧で囲み、アドレス中のコロンとポートの区切りを区別します。URL 全体も引用符で囲みます。-6 は IPv6 を強制し、--max-time 3 は要求を 3 秒に制限します。

curl --noproxy '*' -6 -fsS --max-time 3 'http://[fd77:7::10]:8080/'

この要求は curl: (7) と接続拒否で失敗することが想定されています。IPv6 アドレスは存在してエコーに応答しますが、アプリケーションはその IPv6 エンドポイントを開いていません。一方、タイムアウトは制限時間内に有効な応答が来なかったことを意味し、即時の拒否とは異なります。どちらも IPv6 を無効にして解決しないでください。通常のデュアルスタックブラウザは IPv4 で再試行できるため、そこでページが見えても IPv6 の成功は証明できません。

名前の入力ミスでは、名前解決の失敗を示す curl エラー 6 が出ることがあります。綴りを確認し、最初のコマンドを再実行します。保存パスの入力ミスはローカルの書き込みエラーになります。pwd と指定の v4/index.html パスを確認してください。これらは、到達できたサーバーが要求リソースの不在を知らせる HTTP 404 とも異なります。

Web サービスを IPv6 で待ち受けさせる

このステップでは、動作中の IPv4 リスナーを残し、独立した IPv6 リスナーを追加します。Guide Server に切り替えます。開始位置は /home/labex/project/ipv6-guide/config です。cat で準備済みのエンドポイント表と短い対象設定を読みます。

cat endpoints.tsv
cat guide.conf

ガイドのアドレスは 10.77.0.10 と fd77:7::10、ポートは 8080 です。受付のポート 8081 は維持します。server_name はサイト名を、root は元のページの場所を、index はホームページを選びます。波括弧で server をまとめ、各ディレクティブはセミコロンで終わります。

ss はカーネルのソケットを読みます。-l は待ち受け、-t は TCP、-n は数値のアドレスとポート、-p は所有プロセスを表示する指定です。

ss -ltnp

IPv4 の 10.77.0.10:8080 にある Nginx を見つけてください。ガイドの IPv6 リスナーはまだありません。受付の IPv6 ソケット :8081 はガイドのポートを提供しません。

完全なテンプレートで短いファイル全体を置き換えます。cat > guide.conf はこのファイルへ書き込み、以前の内容を置き換えます。<<'NGINX' は here-document の開始です。シェルは NGINX だけの行まで、後続の行を文字どおりの入力として読みます。最後のマーカーも含めてブロック全体を貼り付けます。先に cp でローカルのバックアップを作ります。2 番目のファイル名がコピー先です。

cp guide.conf guide.conf.before
cat > guide.conf <<'NGINX'
server {
    listen 10.77.0.10:8080;
    listen [fd77:7::10]:8080 ipv6only=on;
    server_name guide.riverlight.test;
    root /opt/labex/ipv6-guide/www;
    index index.html;
    error_page 404 /404.html;
}
NGINX

listen はアプリケーションのエンドポイントを開きます。新しい角括弧付きアドレスは IPv6 で、ipv6only=on によりこのリスナーを IPv6 専用にします。残した IPv4 行は独立して IPv4 を提供します。アドレスを設定するだけでは、この待ち受けソケットは作られません。

準備済みの guide-control は、このコース独立のサービスだけを検査または読み込みます。web-check は変更を適用せずに Nginx 設定テストを実行します。

guide-control web-check

syntax is ok と test is successful が表示されるはずです。セミコロン、括弧、アドレスを誤ると、エラーにファイルと行番号が表示されます。まだ何も適用されていません。上の完全なテンプレートを入力し直し、再検査します。元の正常な IPv4 設定に戻すには、cp guide.conf.before guide.conf でバックアップを復元できます。読み込み前に検査してください。プラットフォームの Nginx やネットワークを再起動しないでください。

web-load は再検査後にリロードを要求します。保存済み設定を適用しつつ、このコースのマスタープロセスは維持されます。ファイルを保存するだけではサービスは変わりません。

guide-control web-load
ss -ltnp

10.77.0.10:8080 と [fd77:7::10]:8080 の両方を Nginx が所有しているはずです。ログにエンドポイント使用中と出たら、完全なテンプレートとファイルを比較し、ss を確認します。無関係なサービスを止めないでください。

Guide Client に切り替えます。-w は本文の後に接続の事実を表示します。引用した書式の \n は改行で、curl は %{remote_ip} を実際の相手アドレス、%{http_code} を応答ステータスに置き換えます。

curl --noproxy '*' -6 -fsS --max-time 3 -w '\npeer=%{remote_ip} status=%{http_code}\n' 'http://[fd77:7::10]:8080/'

Riverlight の HTML に続いて peer=fd77:7::10 status=200 が表示されるはずです。ステータスだけでなく内容も読んでください。無関係なデフォルトページが 200 を返しても不正解です。この直接要求の成功によりアプリケーション層を切り分けられますが、ガイドの名前はまだ修正していません。

名前を動作中の IPv6 サービスへ向ける

このステップでは、対象 AAAA だけを直し、実際のキャッシュを自然に更新させます。Guide Client から始めます。DNS(Domain Name System)は名前をデータに対応付けます。A レコードは IPv4 を、AAAA は IPv6 を提供します。DNS 問い合わせ自体は IPv4 で通信しながら、IPv6 アドレスを返すこともできます。

dig は DNS に問い合わせます。@10.77.0.2 は、このゾーンを管理する準備済み権威サーバーを選びます。+noall +answer は他の部分を隠して応答行を表示します。

dig @10.77.0.2 guide.riverlight.test A +noall +answer
dig @10.77.0.2 guide.riverlight.test AAAA +noall +answer

A レコードは 10.77.0.10 で正しい状態です。現在の AAAA は fd77:7::99 で、動作中サービスと一致しません。クライアント独立のキャッシュリゾルバーに、ループバック 127.0.0.1 で問い合わせます。

dig @127.0.0.1 guide.riverlight.test AAAA +noall +answer

行には名前、TTL、IN、レコード種別、値が並びます。TTL は Time To Live の略で、キャッシュ応答を再利用できる残り秒数です。準備済みゾーンは 30 秒を使用します。この問い合わせで古いアドレスがキャッシュされることがありますが、正常です。

Guide Server に切り替え、ゾーン全体を読みます。

cat guide.zone

$TTL 30 は既定の有効期間です。@ はこのゾーンのルートを表します。SOA(Start of Authority)の括弧内の最初の数値が、ゾーンのバージョンを示すシリアル番号です。NS は権威サーバーを指定します。末尾にドットのある名前は完全な名前です。guide のような短い名前は riverlight.test に対する相対名です。ガイドの AAAA 以外をすべて維持し、今回の改訂ではシリアルを 1 から 2 に増やします。シリアルはゾーンの版を記録するもので、既存クライアントのキャッシュは消しません。

バックアップを取り、学習済みの here-document で短いゾーン全体を置き換えます。ZONE の単一引用符は $TTL のシェル変数展開も防ぎます。

cp guide.zone guide.zone.before
cat > guide.zone <<'ZONE'
$TTL 30
@ IN SOA ns.riverlight.test. admin.riverlight.test. (2 60 30 3600 30)
@ IN NS ns.riverlight.test.
ns IN A 10.77.0.2
guide IN A 10.77.0.10
guide IN AAAA fd77:7::10
desk IN A 10.77.0.10
desk IN AAAA fd77:7::10
contact IN TXT "Welcome desk opens at 10:00"
ZONE

dns-check はネイティブ BIND ゾーン検証を実行します。動作中の DNS は変更しません。

guide-control dns-check

loaded serial 2 と OK を確認します。この loaded は検証ツールがファイルを読んだ意味で、動作中の権威サーバーが変わった意味ではありません。解析エラーなら行番号を読み、完全なテンプレートを再入力して検査します。必要なら cp guide.zone.before guide.zone で元のファイルに戻せますが、誤った古い AAAA も戻ります。これは復旧の出発点であり、完成した答えではありません。

dns-load は検査後、非公開の制御チャネルでこのコースのゾーンだけをリロードします。

guide-control dns-load

Guide Client に切り替え、権威サーバーとキャッシュを別々に問い合わせます。

dig @10.77.0.2 guide.riverlight.test AAAA +noall +answer
dig @127.0.0.1 guide.riverlight.test AAAA +noall +answer

権威サーバーは fd77:7::10 を返すはずです。キャッシュは残り TTL が切れるまで古いアドレスを表示しても正常です。sleep 31 はキャッシュを変更せずに 31 秒待ちます。

sleep 31
dig @127.0.0.1 guide.riverlight.test AAAA +noall +answer

今度は正しい IPv6 アドレスになるはずです。グローバルキャッシュ消去やリゾルバー変更は不要です。権威側がまだ誤っているなら保存済みゾーンと dns-load に戻ります。権威側が正しくキャッシュだけ違うなら TTL を読み、制限した時間だけ待ち直します。AAAA を削除すると、IPv6 の名前アクセスを修復するのではなく失わせます。

最後に名前による IPv6 要求を強制します。

curl --noproxy '*' -6 -fsS --max-time 3 -w '\npeer=%{remote_ip} status=%{http_code}\n' http://guide.riverlight.test:8080/

Riverlight HTML と peer=fd77:7::10 status=200 が返るはずです。直接 IPv6 が成功し、名前だけ失敗するなら、リスナーを作り直すより DNS を調べます。

両方の方法で完全なガイドを読みダウンロードする

このステップでは、両アドレスファミリーで完全なガイドを使い、保護された受付とレコードを維持します。Guide Client から始めます。正しいホームページだけでは、詳細リンク、スタイル、完全なダウンロードの動作までは証明できません。

本当のガイド名を使って、IPv4 で 4 つの元のリソースを保存します。準備済みの v4 フォルダーには、実際にダウンロードしたバイト列だけを保存します。各 -o パスは対応リソースの保存ファイルです。

curl --noproxy '*' -4 -fsS http://guide.riverlight.test:8080/index.html -o v4/index.html
curl --noproxy '*' -4 -fsS http://guide.riverlight.test:8080/visit.html -o v4/visit.html
curl --noproxy '*' -4 -fsS http://guide.riverlight.test:8080/style.css -o v4/style.css
curl --noproxy '*' -4 -fsS http://guide.riverlight.test:8080/programme.txt -o v4/programme.txt

IPv6 でも繰り返し、IPv4 の証拠を成功結果で上書きしないよう別々に保存します。

curl --noproxy '*' -6 -fsS http://guide.riverlight.test:8080/index.html -o v6/index.html
curl --noproxy '*' -6 -fsS http://guide.riverlight.test:8080/visit.html -o v6/visit.html
curl --noproxy '*' -6 -fsS http://guide.riverlight.test:8080/style.css -o v6/style.css
curl --noproxy '*' -6 -fsS http://guide.riverlight.test:8080/programme.txt -o v6/programme.txt

cmp は 2 ファイルをバイト単位で比較します。出力なしでプロンプトに戻れば一致し、差異が表示されればリソースが異なります。各リソースを比較してから完全なプログラムを読みます。

cmp v4/index.html v6/index.html
cmp v4/visit.html v6/visit.html
cmp v4/style.css v6/style.css
cmp v4/programme.txt v6/programme.txt
cat v6/programme.txt

WET WEATHER と最後の架空イベントについての注記まで読みます。ファイルの存在やサイズだけでは、完全な日程とアクセシビリティ情報が正しく届いたと証明できません。誤ったファイル同士が一致する場合も、cmp だけでは原本の内容だと判断できません。チェックでは準備済み原本と実際のサービスも照合します。

Saved Guide に切り替えます。Open IPv4 saved guide を選び、プログラムカードを読んでから Make a day of it を選び、到着とアクセシビリティ情報を読みます。そのページの Save the programme でプログラムをダウンロードします。ブラウザの Back で詳細からホームへ戻り、もう一度 Back で表示機能の選択ページへ戻ります。Open IPv6 saved guide を選び、同じリンクとダウンロードを繰り返します。どちらも同じ完全な Riverlight ガイドのはずです。

詳細とプログラムのリンクが動作する保存済み Riverlight ホーム全体

3 枚のプログラムカードを読み、訪問案内とダウンロードのリンクを使ってください。これは実際に保存したガイドです。

表示機能は Guide Client の v4 と v6 のファイルだけを読み、不足ファイルを取得しません。スタイルやページが欠けたら Guide Client に戻り、該当するファミリーとリソースの保存をやり直してブラウザを再読み込みします。ブラウザから表示機能への接続は表示用経路です。IPv6 を裏付けるのは、ターミナルでファミリーを強制した要求と実際の接続先であり、表示機能の URL ではありません。

Guide Client に切り替え、独立した受付が両ファミリーで使えることを維持します。

curl --noproxy '*' -4 -fsS http://desk.riverlight.test:8081/
curl --noproxy '*' -6 -fsS http://desk.riverlight.test:8081/

両方が Welcome desk: open 10:00–20:00. Keep this site available. を返します。維持した A と TXT を確認します。

dig @10.77.0.2 guide.riverlight.test A +short
dig @10.77.0.2 contact.riverlight.test TXT +short

10.77.0.10 と "Welcome desk opens at 10:00" を期待します。保護値が違えば、修正済みガイド AAAA は残しつつ、完全な元テンプレートから復元し、検査してリロードします。チェックを成功表示にするために、元ページのコピー、プロキシ追加、サービスプロセスの置き換え、アドレス変更を行わないでください。チェックは現在のサービスと保存結果を観察します。通常の GET と DNS 問い合わせはネイティブログを追加する場合がありますが、作業を読み込んだり修復したりはしません。

まとめ

正常な IPv4 ガイドに本物の IPv6 リスナーを追加し、AAAA を修正し、独立した DNS キャッシュを自然に更新させました。ファミリーを強制した要求で、元のホーム、到着ページ、スタイルシート、完全なプログラムが同じ内容で届きました。IPv4、受付、他のレコード、準備済みネットワークを維持しました。到達性、名前解決、待ち受け、正しいアプリケーション内容は別々の事実です。