/

ICTSC2019の二次予選にご参加いただいた皆さん、本当にお疲れ様でした。

本選に出場が決定した皆さま、おめでとうございます!本選でお会いすることを楽しみにしています。
また、残念ながら本選出場ラインに到達できなかった皆さまはぜひ経験をバネとし、次回以降のICTSCにご応募いただければと思います。

今回出題した全8問の問題文、及び問題解説を公開します。
過去の問題を解いた上で学習し、ぜひ今後の研鑽にご利用いただければと思います。

コンテナ

君k8s得意って言っていたよね?

ウェブ

すごく匿名ダイヤリー

トンネリング

トンネル (選択問題)

パケットフィルタ

つながらなくなりました!

ルーティング

ルーティング (選択問題)

IPv6

Welcome to Nginxのページを表示したい!

データベース

MySQLの復旧をお願いします!!

MySQLに繋がりません!

 /

Q1

IPsec パラメータ「IPsecプロトコル」「暗号化」「認証」「Diffie-Hellman グループ」の4つを1番セキュアな組み合わせになるよう選択ください。

IPsecプロトコル

  • A: AH
  • B: ESP

暗号化

  • C: DES
  • D: 3DES
  • E: AES

認証

  • F: MD5
  • G: SHA

Diffie-Hellman グループ

  • H: 1
  • I: 2
  • J: 5

問題解説

「IPsecプロトコル」

AHは「Authentication Header」の略であり、認証機能を持っています。ESPは「Encapsulated Security Payload」の略であり、ペイロード部に対して暗号化を行うことができます。よって暗号化が行われるESPの「B」が正答となります。

「暗号化」

「電子政府における調達のために参照すべき暗号のリスト」*1より共通鍵暗号を抜粋

分類暗号技術
64 ビットブロック暗号該当なし
128 ビットブロック暗号AES , Camellia
ストリーム暗号KCipher-2

よって選択肢内にある「E」が正答となります。

「認証」

「暗号の危殆化に関する調査 報告書」*2の報告書に

ハッシュ関数においては、MD5 が既に危殆化している状態であると専門家の間では認識されおり、数分程度の探索でコリジョンが発見できるとの報告がなされている。

等の記載からSHAの「G」が正答となります。

「Diffie-Hellman グループ」

グループID鍵長
1768 ビット
21024 ビット
51536 ビット

上の表より共有鍵が最長となる5の「J」が正答となります。

Q2

正しいMTUの計算を選択ください。なお環境として「NGN_PPPoE」「L2TPv3」「IPsec ( プロトコルESP、暗号AES256、認証SHA-1 ) 」を使用しているものとします。

  • A: 1366
  • B: 1296
  • C: 1336
  • D: 1454

問題解説

PPPoE MTU1454
IP header (IPsec)20
SPI4
Sequence Number4
初期化ベクトル (AES 256)16
ESP 認証データ (SHA 1)12
=小計1398
=1398 以下で最大の 16 の倍数1392
Padding 長1
プロトコル (次ヘッダ)1
=小計1390
IP header (L2TPv3)20
UDP (L2TPv3)8
L2TPv312
Ethernet14
=L2TPv3 MTU1336

上の表より1336byteの「c」が正答となります。

Q3

インターネットVPNを実現する技術であり、楕円曲線DHを用いて鍵交換を行い、Linux Kernelのメインラインにマージされることが決定したものは以下のうちどれか。

  • A: IPSec
  • B: OpenVPN
  • C: WireGuard
  • D: VXLAN

問題解説

正答はC: WireGuardです。

IPSec, OpenVPNは共に楕円曲線DHを用いて鍵交換を行いますが、Linuxのメインカーネルにマージされておらず、利用する場合にはカーネルモジュールに追加するなどの追加作業が必要となります。

VXLANはL2ネットワークを延伸するためのプロトコルであり、DH鍵交換を行いません。

Q4

4G/LTEパケット交換網において、ユーザプレーンとコントロールプレーンで利用されるトンネリングプロトコルの組み合わせとして正しいものは次のうちどれか。

  • A: ユーザプレーン: GTPv0-U コントロールプレーン: GTPv1-C
  • B: ユーザプレーン: GTPv0-U コントロールプレーン: GTPv2-C
  • C: ユーザプレーン: GTPv1-U コントロールプレーン: GTPv1-C
  • D: ユーザプレーン: GTPv1-U コントロールプレーン: GTPv2-C

問題解説

正答はD: ユーザプレーン: GTPv1-U コントロールプレーン: GTPv2-Cです。

GTPv0-UとGTPv1-Cはそれぞれ3G時代に利用されていたユーザプレーンとコントロールプレーンのプロトコルであり、4G/LTE時代に利用されていたものとは別のプロトコルです。

ユーザプレーンとコントロールプレーンそれぞれが正しく4G/LTE時代に利用されているDが正解となります。

 /

問題文

先輩がMySQLサーバを立てて、新しく運用を開始したらしい。

そのサーバを利用するため、rootパスワードを教えて貰ったため、今までどおりのログインコマンドを試してみた。

$ mysql -uroot -p -h 192.168.0.100

だが、なぜかログインエラーが出てしまい先輩のサーバにアクセスできない。先輩はサーバ上で正しく動いているらしいので、トラブルシューティングのためにそのサーバへのアクセス権限をもらった。

クライアントサーバから上記のコマンドを実行し、rootユーザがログインできるように変更を加え、下記の内容を報告してほしい。

  • ログインできるようになるためどのような作業を行ったのか
  • なぜログインが行えなかったのか

問題サーバー

クライアント

  • IPアドレス: 192.168.0.101
  • ユーザー: admin
  • パスワード: USerPw@19

サーバ

  • IPアドレス: 192.168.0.100
  • ユーザー: admin
  • パスワード: USerPw@19
  • DBユーザー: root
  • DBパスワード: root

問題解説

本問題ではMySQL 8系から導入された認証形式であるcaching_sha2_passwordが古いMySQLクライアントでは対応していないために発生しているエラーでした。

クライアントサーバから実際にログインしてみようとコマンドを実行すると以下のようなエラーが出ていたかと思います。

$ mysql -uroot -p -h 192.168.0.100
Enter password:
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

このエラーメッセージからなんらかの認証回りでエラーが起きており、回答に気づくシナリオでした。

実際にMySQLサーバの起動しているホストにログインするとMySQL 8系のパッケージがインストールされており、クライアント側のサーバではMySQL 5.7.21のパッケージがインストールされていました。

具体的な回答としては以下のものを想定していました。

  • クライアント側のサーバにインストールされているMySQLクライアントのバージョンをcaching_sha2_passwordに対応したものをインストールする
    • 5.7系であれば5.7.23以上、8系であればどのバージョンでも対応しています
  • rootユーザのログインに用いる認証形式を古い形式に変更する
    • mysql_native_passwordに変更する事で古いMySQLクライアントでもログインすることが可能になります

ちなみに、問題文の中で「先輩がMySQLサーバを立てて運用を開始した」という文面がありましたが、実際にMySQLサーバ側からmysqlコマンドを用いると特にエラーが出力されないままログインに成功します。
MySQLサーバ側にはMuSQL 8系のパッケージがインストールされており、MySQLクライアントも8系のものがインストールされているためcaching_sha2_passwordに対応しておりログインが可能であった、というシナリオでした。

この問題を通して新しいMySQL認証プラグインであるcaching_sha2_passwordについて知っていただければ幸いです。

 /

問題文

あるデベロッパーから「dev環境と間違えて、prod環境のMySQLで直接truncate table sbtest3;を実行してsbtest3テーブルのデータを削除してしまいました、復旧をお願いします!!」と緊急の連絡を受けました。
このクエリの実行後、すぐに間違いに気づいたデベロッパーはサービスをメンテナンス状態にし、アプリケーションサーバを停止したそうです。

問1(q01)

truncate table sbtest3; というクエリが実行された日時をyymmdd HH:MM:SSのフォーマットで報告してください。
また、どのようにこの日時を特定したかを説明してください。

問2(q02)

truncate tableが実行される直前の状態(truncate tableが実行される1つ前のクエリが実行された状態)にデータを復旧し、復旧後checksum table sysbench.sbtest3;の結果を報告してください。
また、データの復旧に必要な手順を説明してください。

情報

状況

  • このMySQLは毎日定時にsysbench databaseのバックアップを取得していて(コンテスト問題の作成上truncate table文が実行された日まで)、偶然truncate文が実行される(数分)前にこの日のバックアップが完了していた
  • バックアップは以下のコマンドで取得されている
  • mysqldump --opt --single-transaction --master-data=2 --default-character-set=utf8mb4 --databases sysbench > /root/backup/backup.dump
  • mysql -u root -p < /root/backup/backup.dumpでバックアップが取得された時点に復旧できる
  • adminユーザからsudo suすることでrootユーザから操作してください

問題サーバー

  • IPアドレス: 192.168.0.1
    ユーザー: admin
    パスワード: USerPw@19
  • DBユーザー: root
  • DBパスワード: root

ゴール

  • 問1, truncate table sbtest3; というクエリが実行された日時を特定し、その特定方法を説明していること
  • 問2, MySQLのデータが復旧し、その手順の説明とchecksum table sysbench.sbtest3;の結果が報告されていること
  • 問1に正解すると部分点が与えられます。

問題解説

「本番環境で間違ってtruncate table ...を実行してしまったから、その直前の状態までデータ復旧してほしい!!」
というデータベースの復旧問題でした。

あまり想像して楽しくなる状況ではありませんが、ソフトウェア開発をする上でデータベースのデータの復旧方法を知っておいても損はないと思います。
そこで、MySQLを例にバックアップと更新ログを利用して任意のタイミングまでデータを復旧する問題を出題しました。
DBMSごとの際はありますが、基本的にデータベースの復旧方法(特にロールフォーワードリカバリ)の概念は同じですので、今後使うDBMSでこういった状況に対応できるかを考えてみてください。

具体的な解法を説明する前にMySQLにおけるリカバリ方法、バイナリログ、バックアップについて説明します。

ポイント・イン・タイム・リカバリ (PITR)

データベースのバックアップを定期的に取得するだけでは、その時点のデータを復元することしかできないため、バックアップ以降の更新データを失うことになります。
そこで、データの永続化を保証する多くのデータベースでは、バックアップとは別にデータの更新情報を保持しておき、バックアップとそれ以降のデータ更新を復元することで任意の時点のデータをリカバリできるようにしています。このようなリカバリ方法をポイントインタイムリカバリ(PITR)と言います。

バックアップ以降のデータ更新情報をどのように保持するかはDBMSによって異なりますが、MySQLでは後述するバイナリログを利用することで取得できます。

バイナリログ

バイナリログにはMySQL serverで実行された更新がイベントという形で出力されています。
イベントには直接実行されたクエリが出力されているわけではなく、行ごとの変更分が特定のフォーマットにしたがって出力されています。
この他にもバイナリログそのもののバージョンやサーバの設定などのメタ情報も含まれており、これを利用してリカバリやレプリケーションを行うことができます。
truncate table ...を含むDDLはSTATEMENTが直接書かれていたり、推奨されませんが、DMLを直接STATEMENTに出力したりも出来ます。詳しくはバイナリログのドキュメントを参照してください

バイナリログの中身はmysqlbinlogコマンドを使うことで確認でき、より詳細に確認したい場合は--base64-output=DECODE-ROWS -vvなどのオプションをつけることで、実際に実行されたSQL文とは異なりますが、SQL文として復元されたものを確認できます。ただしクエリはコメントアウトされているので、このオプションをつけた結果をリカバリに使うことは出来ません。

バイナリログから特定の期間の更新を取得するには時間で指定する方法とバイナリログ中のオフセットを利用する方法がありますが、時間単位での指定は秒単位でしかできないため、リカバリにはオフセットを用いて指定する --start-position,--stop-positionを利用することをおすすめします。(秒間1クエリしか実行していない、なんてサービスはほとんどないはず)

バックアップ

MySQLにおけるバックアップ方法はいくつもあり実際は要件に合わせて選択しますが、今回はMySQL標準の論理バックアップクライアントのmysqldumpを利用してバックアップしました。
オプションの説明は省略しますが、問題環境では以下のコマンドでsysbench databaseの完全バックアップが取得されていました。

mysqldump --opt --single-transaction --master-data=2 --default-character-set=utf8mb4 --databases sysbench > /root/backup/backup.dump

--master-data=2が指定されていることから、バックアップを行ったホストに対してレプリケーションを繋ぐ際のコマンド(CHANGE MASTER...)がコメントアウトされて出力されます。この出力を見ることで、バックアップ以降の更新がバイナリログのどこから始まっているかをバイナリログのオフセットとして確認できます。

復旧手順

それでは実際に今回の問題環境でPITRを実施してデータを復旧する方法を説明します。

PITRの項で説明したように、まずはバックアップをリストアし、バックアップ以降でtruncate table sbtest3;の実行直前までの更新をバイナリログから抽出して適用することで復旧します。

mysqldumpによるダンプファイルの22行目に以下の出力があることからバックアップ以降の更新はbinlog.000018の34626719byte目以降ということがわかります。

-- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000018', MASTER_LOG_POS=34626719;

次に、バイナリログからmysqlbinlogコマンドを使ってtruncate table...を実行を表すイベントのオフセットを取得します。
問題環境ではデータの更新が記録されているのはbinlog.000018だけなので、このファイルについてだけ考えれば良いです。

$ mysqlbinlog --no-defaults --base64-output=DECODE-ROWS -vv --start-position=34626719  binlog.000018 | grep -B 10 truncate
/*!80001 SET @@session.original_commit_timestamp=1574235055802260*//*!*/;
/*!80014 SET @@session.original_server_version=80018*//*!*/;
/*!80014 SET @@session.immediate_server_version=80018*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 54452036
#191120 16:30:55 server id 1  end_log_pos 54452141 CRC32 0x7e67e1d2     Query   thread_id=11    exec_time=0 error_code=0    Xid = 189179
use `sysbench`/*!*/;
SET TIMESTAMP=1574235055/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255/*!*/;
truncate table sbtest3

この出力の# at {数字}を見ることでtruncate文を実行したのが54452036 byte目から始まるイベントとわかります。
また、次の行をみると191120 16:30:55に実行されたことがわかります (問1)

問1としてあえて秒単位でしかない実行時刻を解答してもらったのは、実際にこういった問題が起こった場合には似たようなクエリがアプリケーションの正常な処理として実行されていたり、実は何回も間違った後だったりするため確認作業を必要とすることが多いからです。
辛いですね。。。

ここまででわかったbinlogの状況を図1に整理してみます。

スクリーンショット 2019-12-08 15.10.27.png
図1 binlogの状況

バックアップを適用することで②の直前の状態にまでデータが復旧されるため、②から③までの更新情報を適用する必要があります。
①から②の部分も適用したチームも見られましたが、この部分の更新分はバックアップに含まれているので、重複した更新を適用してしまうことになります。

最後にここまでで取得したオフセットを--start-position--stop-positionで指定して抽出し、適用することでリカバリが完了します(問2)

mysqlbinlog --no-defaults --start-position=34626719 --stop-position=54452036 binlog.000018 | mysql -u root -p
# または
mysqlbinlog --no-defaults --start-position=34626719 --stop-position=54452036 binlog.000018 > recover.sql
mysql -u root -p < recover.sql

採点基準

  • 問1: 30%
  • 問2: 70%

問2の採点にはリカバリ後に実行してもらったchecksum table ...の結果を利用するつもりでしたが、問題環境ではバイナリログからの抽出位置を正しく指定しなくてもchecksumが同じ値になってしまうことがありました。
そのため解答中のリカバリ方法の説明で、バックアップ以降、truncate table文まで(図1の②~③部分)の更新分を抽出、適用していることを確認して正解としました。

 /

問題文

あなたはローカルネットワーク上にwebサーバを構築し、IPv6アドレスを使用してwebページに接続できるようにセットアップをしています。
webページへはhttp://nginx.icttoracon.netでアクセスできるようにしたいです。

nginxのホストには、すでにnginxのパッケージをインストール済みです。
CSR1000Vとnginxのホストには固定でIPv6アドレスを割り当てました。
クライアント(VNC Server)にIPv6アドレスが自動設定されるように、CSR1000VにはSLAACの設定を行いました。

しかし、クライアント(VNC Server)のブラウザからhttp://nginx.icttoracon.netにアクセスしてもWelcome to Nginxのページを表示させることができません。
このトラブルを解決し、Welcome to Nginxのページを表示させてください。

クライアントが増えても自動でアクセスできるよう、設定変更はCSR1000Vとnginxホストのみとしてください。
DNSサーバはCSR1000Vを使用します。
各ノードにはssh/telnet用にIPv4アドレスが設定されていますので必要に応じて使用してください。
予選終了後に実環境で採点されるので、スコアサーバでの解答は不要です。

file

接続情報

HostProtocolIPv4 addressUser/Pass
CSR1000Vtelnet192.168.0.1admin/admin
nginxssh192.168.1.2admin/admin

ゴール

VNCサーバのブラウザからhttp://nginx.icttoracon.netでWelcome to Nginxのサイトが表示されること
上記のアクセスがIPv6で行われていること
(恒久的な設定でなくても構わない)

問題解説

本問題には3つの原因があります。
順を追って調べてみましょう。

疎通性確認

まずはクライアントマシンからnginxホストまでIPv6で疎通性があるか確認してみます。
簡単な確認ではありますが、トラブル原因のレイヤをある程度限定できます。

ubuntu@ICTSC-VNC:~$ ping fc01::2 -c 4
PING fc01::2(fc01::2) 56 data bytes
64 bytes from fc01::2: icmp_seq=1 ttl=63 time=0.887 ms
64 bytes from fc01::2: icmp_seq=2 ttl=63 time=0.607 ms
64 bytes from fc01::2: icmp_seq=3 ttl=63 time=0.802 ms
64 bytes from fc01::2: icmp_seq=4 ttl=63 time=0.699 ms

--- fc01::2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3040ms
rtt min/avg/max/mdev = 0.607/0.748/0.887/0.110 ms

コマンドの結果から本問題は初期状態でIPv6の疎通性があることが確認できます。

名前解決

名前解決ができるかどうか試してみましょう。
ドメイン名からIPv6アドレスを取得するにはAAAAレコードを参照します。
例としてAAAAレコードを取得するコマンドを以下に示します。

ubuntu@ICTSC-VNC:~$ dig nginx.icttoracon.net AAAA

; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> nginx.icttoracon.net AAAA
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 40684
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;nginx.icttoracon.net.        IN  AAAA

;; Query time: 89 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Wed Dec 04 22:46:46 JST 2019
;; MSG SIZE  rcvd: 49
ubuntu@ICTSC-VNC:~$

AAAAレコードは取得できていません。
問題文でDNSサーバはCSRとされていますが、クライアントはどこを参照しているのでしょうか。

ubuntu@ICTSC-VNC:~$ cat /etc/resolv.conf | grep -v "^#"

nameserver 127.0.0.53
options edns0
search localdomain
ubuntu@ICTSC-VNC:~$ cat /run/systemd/resolve/resolv.conf | grep -v "^#"

nameserver 133.242.0.3
nameserver 133.242.0.4
search localdomain
ubuntu@ICTSC-VNC:~$ 

IPv4でDNSサーバを受け取っているようですが、CSRのIPアドレスではありません。
1つ目の原因はDNSサーバ(CSR)が参照できていないことです。

問題文からクライアントの設定変更ではなくルータの設定変更で対応する方針であることがわかります。
クライアントの設定とCSRの設定を確認すると、クライアントのIPv6アドレスはRAを用いた自動設定であることがわかります。
ただしDNSサーバのアドレスが配布されていません。
RAでIPv6アドレスが設定されている場合は、以下の2つの方法でDNSサーバを配布することができます。

  • ステートレスDHCPv6
  • RAを用いたDNS配布(RFC8106)

例としてRAのみでDNSの配布を行います。
IOS-XEのコマンドリファレンスを参照すると、以下の設定でDNSの配布が行えそうです。

csr1000v#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
csr1000v(config)#int gi 1
csr1000v(config-if)#ipv6 nd ra dns server fc00::1

クライアントで確認してみます。

ubuntu@ICTSC-VNC:~$ cat /run/systemd/resolve/resolv.conf | grep -v "^#"

nameserver 133.242.0.3
nameserver 133.242.0.4
nameserver fc00::1
search localdomain
ubuntu@ICTSC-VNC:~$ dig nginx.icttoracon.net AAAA

; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> nginx.icttoracon.net AAAA
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35863
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;nginx.icttoracon.net.        IN  AAAA

;; ANSWER SECTION:
nginx.icttoracon.net.    10  IN  AAAA    fc01::2

;; Query time: 12 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Wed Dec 04 22:51:49 JST 2019
;; MSG SIZE  rcvd: 77

ubuntu@ICTSC-VNC:~$

DNSサーバとしてfc00::1が設定され、AAAAレコードが正しく参照できています。

nginx設定

IPv6の疎通性があり、名前解決も行えているので一旦クライアントの作業を終え、nginxホストを確認してみます。
まずは80ポートの使用状況を確認してみます。

[admin@nginx ~]$ sudo lsof -i:80
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   1421  root    6u  IPv4   9815      0t0  TCP *:http (LISTEN)
nginx   1422 nginx    6u  IPv4   9815      0t0  TCP *:http (LISTEN)

typeを見るとIPv4となっており、nginxがIPv6アドレスで待ち受けていないことがわかります。
2つ目の原因はnginxはIPv6アドレスで待ち受けていないことです。
nginxがIPv6アドレスで待ち受けるよう、設定を変更します。

server {
    listen       80;
+   listen       [::]:80;
    server_name  localhost;

--- snip ---
[admin@nginx ~]$ sudo nginx -s reload
[admin@nginx ~]$ sudo nginx -s reload
[admin@nginx ~]$ sudo lsof -i:80
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   1421  root    6u  IPv4   9815      0t0  TCP *:http (LISTEN)
nginx   1421  root   10u  IPv6  10932      0t0  TCP *:http (LISTEN)
nginx   1540 nginx    6u  IPv4   9815      0t0  TCP *:http (LISTEN)
nginx   1540 nginx   10u  IPv6  10932      0t0  TCP *:http (LISTEN)

フィルタリング設定

nginxがIPv6で待ち受ける状態となりました。
しかしまだクライアントからアクセスができません。
nginxホストのディストリビューションを確認してみます。

[admin@nginx ~]$ ls /etc | grep release
centos-release
redhat-release
system-release
system-release-cpe
[admin@nginx ~]$ cat /etc/centos-release 
CentOS release 6.10 (Final)
[admin@nginx ~]$

CentOS6.10であるため、フィルタリングはiptablesで行っていると予想されます。
iptablesのルールを確認してみましょう。

[admin@nginx ~]$ sudo iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
ACCEPT     icmp --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh 
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:http 
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited 

一見すると問題が無いように見えますが、クライアントはWelcome to Nginxのページにアクセスできません。
それもそのはず、iptablesはIPv4のフィルタリング設定だからです。
実は初期状態からIPv4で80ポートは許可されており、クライアントはIPv4を用いてWelcome to Nginxのページを表示させることはできてました。

IPv6のフィルタリングはip6tableで行います。
ip6tableのルールを確認すると、80ポートのアクセスを許可しているルールが無いことがわかります。

[admin@nginx ~]$ sudo ip6tables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all      anywhere             anywhere            state RELATED,ESTABLISHED 
ACCEPT     ipv6-icmp    anywhere             anywhere            
ACCEPT     all      anywhere             anywhere            
ACCEPT     udp      anywhere             fe80::/64           state NEW udp dpt:dhcpv6-client 
ACCEPT     tcp      anywhere             anywhere            state NEW tcp dpt:ssh 
REJECT     all      anywhere             anywhere            reject-with icmp6-adm-prohibited 

3つ目の原因はIPv6の80ポートが拒否されていることです。
問題文には恒久的な設定ではなくて構わないとしか記載されていないので、80ポートを許可する方法か、プロセスを停止する方法があります。
問題としてはどちらで行ってもいいですが、望ましいのは80ポートを許可する方法です。
ip6tablesで80ポートを許可します。

[admin@nginx ~]$ sudo ip6tables -I INPUT 6 -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
[admin@nginx ~]$ sudo ip6tables -I INPUT 6 -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
[admin@nginx ~]$ sudo ip6tables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all      anywhere             anywhere            state RELATED,ESTABLISHED 
ACCEPT     ipv6-icmp    anywhere             anywhere            
ACCEPT     all      anywhere             anywhere            
ACCEPT     udp      anywhere             fe80::/64           state NEW udp dpt:dhcpv6-client 
ACCEPT     tcp      anywhere             anywhere            state NEW tcp dpt:ssh 
ACCEPT     tcp      anywhere             anywhere            state NEW tcp dpt:http 
REJECT     all      anywhere             anywhere            reject-with icmp6-adm-prohibited 

クライアントでアクセスしてみると、Welcome to Nginxのページが表示されます。