/

ICTSC2020 本選にご参加いただいた学生の皆様、お疲れ様でした。

今回のICTSC2020を以ってICTSCは活動休止となり、学生の皆様は非常に驚かれたと思います。我々運営としても、こういった活動の場が無くなってしまうのは非常に寂しいですが、ここで培った知識・技術を今後に活かしていただければと思います。

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

Container

なぜか動きません!

docker-mailman

いつの間にか復活している君

コンテナに繋がらない

DNS

名前解決ができなくなった?

Webサーバーに繋がらない!

DNSサーバを作りたかったらしい

FTP

FTPなんもわからん

FTPが壊れちゃった!

k8s

Nginxが展開できない

証明書の取得ができない!!

Linux

このOpenstackなんか変だよぉ…

続・このOpenstackなんか変だよぉ…

まだだ、まだ終わらんよ

部署を統合したが…

LoadBalancer

リバースプロキシが動かない

Program

何かがおかしい。。。。

ボク わるいフレームワークじゃないよ

Routing

インターネット壊れた

あれ、おかしい。。。。

Tunnel

とんとんとんねる

GREが繋がらない!

Web

Server Sent Eventsが動作しない‼

 /

ICTSC2020の予選にご参加いただいた皆様、お疲れ様でした。

本戦に出場が決定した皆様、おめでとうございます。本戦で存分に力を発揮してもらいたいと思います。
また、残念ながら本戦出場ラインに到達できなかった皆様はぜひ経験をバネとし、次回以降のICTSCにご応募いただければと思います。

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

ルーティング

networkが作成できない?

経路を受け取れない

繋がらなくなっちゃった!

またビルド失敗しちゃった~…

ウェブ

WEBページが見れない

コンテナ

どこからもアクセスできなくなっちゃった

hostnameでつながらない!!

ダイエットしようぜ!

データベース

備品は何処へ

プログラミング

jsonが壊れた!!

 /

ICTSC2019 本選に参加してくださった皆さん、お疲れ様でした!また、参加していただきありがとうございました!!

以下はICTSC2019 本選で出題した問題の各解説へのリンク集です。ICTSC2019 本選に参加していただいたみなさんの復習や、次回以降参加する方の参考になれば幸いです。

各問題の解説は順次投稿します。2020年 3/1 中に投稿を完了する予定です。

一日目

コンテナ

ウェブ

トンネリング

パケットフィルタ

ルーティング

データベース

メール

その他

二日目

コンテナ

トンネリング

パケットフィルタ

ルーティング

データベース

IPv6

その他

 /
カテゴリー

問題文

概要

k8sクラスターにcert-managerをインストールしhttp01認証で証明書を発行するissuerを設定した。
その上でhostのnginxのpodを展開するDeploymentと、それを公開するService、Ingressを記述した/home/user/manifests/web.yamlを作成しapplyした。
しかし、なぜか証明書が発行されない。その理由と解決方法を報告してほしい。

トポロジを以下の図で示す。

前提条件

  • cert-managerで取得する証明書は自己署名証明書を使用している
    • hostcert-managerなど必要なものにはルートCA証明書をインストール済み
  • hostuserユーザーでkubectlコマンドが利用できる
  • host/home/user/manifestsに今回applyしたmanifestが保存されている
    • cert-manager.yaml ingress-controller.yaml root-ca.yaml変更しないこと
    • web.yamlの再展開(kubectl delete, kubectl applyなど)可
  • acme-serverには、追加でDNSサーバーが稼働しており以下のレコードが設定されている
        IN      NS      ictsc.test.
        IN      A       192.168.20.125

ca      IN      A       192.168.20.125
www     IN      A       192.168.20.1
  • lbにはkeepalivedがインストールされている。
    • 変更しないこと

初期状態

  • hostcurl -L www.ictsc.testを実行したとき以下のようなエラーになる
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
  • hostkubectl get certを実行したときwww-ictsc-test-tlsのREADYがFalseになっている

終了状態

  • hostcurl -L www.ictsc.testを実行したときにnginxの初期ページが表示される
    • 証明書が設定されている
  • hostkubectl get certを実行したときにwww-ictsc-test-tlsのREADYがTrueになっている

接続情報

lbhostのみSSHログインできる。

VM名ホスト名ユーザパスワード
lb192.168.20.1userictsc2020
host192.168.20.20userictsc2020
acme-server192.168.20.125
k8s-master192.168.20.129
k8s-worker1192.168.20.130
k8s-worker2192.168.20.131

解説

原因

cert-managerはhttp01認証を行うときにacme challengeが行えるかセルフチェックを行います。その際、www.ictsc.testつまり192.168.20.1宛てにGETリクエストを行いますが、このリクエストの戻りのパケットがnginxのPODから直接cert-managerのPODに送られてしまいます。
その時の送信元アドレスが、リクエストの送信時の宛先と異なるためセルフチェックのリクエストは失敗してしまい証明書の取得が行われませんでした。

以下のようにセルフチェックが失敗していることを確認できます。

user@host:~$ kubectl describe challenges.acme.cert-manager.io
Name:         www-ictsc-test-tls-dhksj-696946275-1037365539
Namespace:    default
Labels:       <none&gt;
Annotations:  <none&gt;
API Version:  acme.cert-manager.io/v1
Kind:         Challenge
...
省略
...
Status:
  Presented:   true
  Processing:  true
  Reason:      Waiting for HTTP-01 challenge propagation: failed to perform self check GET request 'http://www.ictsc.test/.well-known/acme-challenge/c4mi9je6PJ87H9ulTtAPOu1xSjXEyDo9': Get "http://www.ictsc.test/.well-known/acme-challenge/c4mi9je6PJ87H9ulTtAPOu1xSjXEyDo9": dial tcp 192.168.20.1:80: connect: connection timed out
  State:       pending
...
省略
...

解決策

解決策としては以下のことが考えられます。

  • LBにhaproxyやnginxなどのリバースプロキシを用いる
  • LBにヘアピンNATの設定を行う

今回は、keepalivedを変更できないのでヘアピンNATの設定を行います。

/etc/sysctl.confに以下の設定を追記し更新します。

$ sudo vim /etc/sysctl.conf
net.ipv4.vs.conntrack=1 # 最終行に追記

$ sudo sysctl -p

iptablesで内部からの通信をMASQUERADEする設定を行い永続化します。

$ sudo iptables -t nat -A POSTROUTING -s 192.168.20.128/25 -m ipvs --vaddr 192.168.20.1/32 -j MASQUERADE
$ sudo netfilter-persistent save

/home/user/manifests/web.yamlをapplyし直すとkubectl get certでREADYがTrueになることを確認できます。
またcurl -L www.ictsc.testで正常にnginxのページが表示されます。

user@host:~/manifests$ kubectl delete -f web.yaml
deployment.apps "web" deleted
service "web" deleted
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions "a-web" deleted

user@host:~/manifests$ kubectl apply -f web.yaml
deployment.apps/web created
service/web created
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
ingress.extensions/a-web created

user@host:~/manifests$ kubectl get cert
NAME                 READY   SECRET               AGE
www-ictsc-test-tls   True    www-ictsc-test-tls   35s

user@host:~/manifests$ curl -L www.ictsc.test
<!DOCTYPE html&gt;
<html&gt;
<head&gt;
<title&gt;Welcome to nginx!</title&gt;
<style&gt;
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style&gt;
</head&gt;
<body&gt;
<h1&gt;Welcome to nginx!</h1&gt;
<p&gt;If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p&gt;

<p&gt;For online documentation and support please refer to
<a href="http://nginx.org/"&gt;nginx.org</a&gt;.<br/&gt;
Commercial support is available at
<a href="http://nginx.com/"&gt;nginx.com</a&gt;.</p&gt;

<p&gt;<em&gt;Thank you for using nginx.</em&gt;</p&gt;
</body&gt;
</html&gt;

採点基準

  • 理由が説明できている 20%
  • 解決方法が記述されておりその解決方法で解決が可能 80%

さいごに

問題を解いていただきありがとうございました。

また上記のような想定解法での解答はなく、以下のような解答を頂きました。DNATの解法は、想定はしていたのですがCoreDNSは完全に想定しなかったので、確かにそういう方法もあるのかと思いました。(self checkとは?という感じではありますが、問題の終了条件を満たせるので満点としました。)

  • CoreDNSのレコードを変更しingress controllerのPODのIPアドレスを名前解決するようにする
  • lbでk8sのいずれかのノードにDNATをする
 /
カテゴリー

はじめに  

作問者のabeです. この問題は昔バックアップパーティションに救われた経験から作りました.

概要  

ベテランエンジニアの虎魂くんはWEBサーバの運用を行っていました. ある日,記憶から消えかけていたような昔のプロジェクトのお客さんから電話がありました.

どうやらWEBサーバにアクセスするとエラーページが表示されるようです. 原因の理由と解決方法を回答してください.

前提条件  

  • WEBページのデータのバックアップはない.
  • WEBページの公開パスなどの変更は可能.

初期状態  

手元のPCから $ curl 192.168.11.1 をしてもエラーコードが帰ってくる.

終了状態  

  • 障害前に表示されていたページが表示されること.
  • 手元のPCから $ curl 192.168.11.1 をするとステータスコード200のレスポンスが返ってくる.

採点基準  

  • /dev/sdbのパーティションが壊れていることに気が付く 30%
  • 障害前のWEBページが確認できる 70%

答え  

まずは終了状態の確認を行います.400番台なのでエラーが発生しています.

ictsc@web:~$ curl localhost
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>

一応Nginxが起動しているか確認します.起動しています.

ictsc@web:~$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2021-03-07 13:31:36 JST; 27min ago
       Docs: man:nginx(8)
   Main PID: 585 (nginx)
      Tasks: 2 (limit: 1168)
     Memory: 11.5M
     CGroup: /system.slice/nginx.service
             ├─585 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
             └─586 nginx: worker process

Warning: some journal files were not opened due to insufficient permissions.

/var/log/nginx/error.logを確認すると以下のエラーが出力されています.

2021/03/07 13:55:27 [error] 586#586: *1 directory index of "/mnt/data/" is forbidden, client: 127.0.0.1, server: _, request: "GET / HTTP/1.1", host: "localhost"

ls /mnt/data/で確認するとディレクトリが空なのがわかります. ここでパスを見てみるとmntである事がわかります. mntディレクトリはファイルシステムをマウントする用途に使われるので/etc/fstabを確認します.

以下のようなマウントポイントが設定されてました.

/dev/sdb1 /mnt/data ext4 defaults 0 0

対象のデバイスを確認します.

sudo gdisk /dev/sdb 

するとエラーメッセージが出力されます.抜粋した以下を確認するとメインのパーティションテーブルが壊れている事がわかります. しかし,バックアップは生きているようなので復旧していきます.

Main header: ERROR
Backup header: OK
Main partition table: ERROR
Backup partition table: OK

復旧するので1番を選択

Found invalid MBR and corrupt GPT. What do you want to do? (Using the
GPT MAY permit recovery of GPT data.)
 1 - Use current GPT
 2 - Create blank GPT

Your answer: 1

リカバリモードに入り,バックアップから復元し書き込みます.

Command (? for help): r

Recovery/transformation command (? for help): c
Warning! This will probably do weird things if you've converted an MBR to
GPT form and haven't yet saved the GPT! Proceed? (Y/N): y

Recovery/transformation command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sdb.
The operation has completed successfully.

マウントしてみます.

sudo mount -a

確認すると正常に復旧できた事がわかります.

ictsc@web:~$ cat /mnt/data/index.html 
<!DOCTYPE html>
<html lang="ja">
        <head>
                <meta charset="utf-8" />
                <link rel="stylesheet"  href="style.css">
                <title>タイトル</title>
                <script
                          src="https://code.jquery.com/jquery-3.3.1.min.js"
                            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
                              crossorigin="anonymous"></script>
        </head>
        <body>
                <main>
                        <p>ICTSC WEB!!!</p>
                </main>
        <script>
                $(function(){
                });
        </script>
        </body>
</html>

おわりに  

この問題は物理ディスクを2つ使うため,自分たちで仮想基盤を運用する本戦で出そうと思ってました. 150点問題としては多くのチームに解いていただけたので嬉しかったです.

gdiskではなくtestdiskを用いて回答していたチームもいました. どちらを使用しても終了条件を満たせるので満点にしています.

来年から社会人なので,最後の作問でしたが楽しかったです.

 /
カテゴリー

はじめに  

作問者のabeです. 実はこの問題は史実に基づいて作られた問題です.

回答を見ていると私と同じ罠に引っかかったチームが居て嬉しかったです(?).

問題文  

部長さんへ

新米エンジニアの捕鯨太郎です。 プロジェクトでWEBサーバを構築するとのことなので、 docker-composeを使用してWEBサーバを構築しました。 無事に起動し、WEBページも確認できたのですが、 再起動するとアクセスできなくなってしまいました。

自動的に再起動するように記述してあるので不可解です。 しかも、トラブルシュートしているといつの間にか アクセスできるようになります。自分には原因がわかりません。

お知恵を拝借したいのですが、 お時間をいただけないでしょうか。

前提条件  

  • ~/web-server/docker-compose.ymlがあり編集可能
  • docker ps -aなどで確認するとコンテナが起動している

初期状態  

踏み台から $ curl 192.168.17.1 をしても応答がない

終了状態  

再起動しても踏み台から $ curl -I 192.168.17.1 をするとステータスコード200のレスポンスが返ってくる

答え  

まずは初期状態を確認しましょう.

~ curl 192.168.17.1
curl: (7) Failed to connect to 192.168.17.1 port 80: Connection refused

WEBページにアクセスできないのが確認できます. 次にコンテナの様子をみてみましょう.

user@docker:~$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                  PORTS                NAMES
4e7db3e7cc97        nginx:latest        "/docker-entrypoint.…"   3 minutes ago       Up Less than a second   0.0.0.0:80->80/tcp   web-server_nginx_1

あれあれ,起動しているな…

もう一度確認すると… いつの間にか復活してる!!!

~ curl 192.168.17.1 -I
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Sun, 07 Mar 2021 03:33:11 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 15 Dec 2020 13:59:38 GMT
Connection: keep-alive
ETag: "5fd8c14a-264"
Accept-Ranges: bytes

確認作業を行っているうちに復活してしまいました.

実はdockerコマンドを叩くとデーモンが起動するという罠があります.先ほどのdocker ps -aを見てみるとUp Less than a secondとあり,起動したてなのがわかります.

以下のコマンドで確認するとデーモンは起動していますが,enableになっていない事がわかります.

ictsc@docker:~$ systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2021-03-07 12:32:53 JST; 9min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 2176 (dockerd)
      Tasks: 17
     Memory: 114.7M
     CGroup: /system.slice/docker.service
             ├─2176 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
             └─2362 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.18.0.2 -container-port 80
             

ictsc@docker:~$ systemctl is-enabled docker
disabled

そう,enableのし忘れですね.以下のコマンドで解決です.

systemctl enable docker

採点基準  

dockerサービスをenableできたか.

おわりに  

前提条件に書いた2点,docker-compose.ymlが編集可能である,docker ps -aすると起動している, に引っかかってくれたチームがいて嬉しかったです.

冷静に確認されると一瞬で解決してしまう問題なので簡単枠で出題しました.

 /
カテゴリー

概要

BGPの検証ネットワークを構築してみたところ、PC1<–>PC2間でpingが飛ばないという現象が起きました。
ただしR3実環境ではとある組織の所有物なので設定の変更はできないものとし、R3は何かしらのダイナミックのルーティングプロトコルが動作しているときいている。
PC1<–>PC2間の間で通信ができないので原因を突き止めてほしい。

前提条件

  • static routesを書かないで
  • R3にはsshできません

初期状態

手元のPCから $ ping 192.168.19.30 をしても応答がない。

終了状態

PC1からPC2までpingが正しく飛ぶ。

解説

想定解

この問題はMTUの不一致でOSPFのネイバーがR2<–>R3間で確立できておらずEBGPのピアが張れないため、PC1<–>PC2間で通信ができないという問題でした。
この問題はR3が触れないためR3のR2側のインターフェースのMTUを割り出す必要があります。
割り出しにはPCからのpingを使います。ping -s MTU値 -M do IPアドレスを使えばIPアドレスまでの経路で指定したMTU値でpingが通れるかどうかを調べることができます。
PC1でping -s MTU値 -M do 192.168.19.26を実行し、もし経路上のMTUより指定したMTU値が大きい場合は以下のように経路上のMTUの上限を通知してくれます。

user@PC:~$ ping -s 1450 -M do 192.168.19.26
PING 192.168.19.26 (192.168.19.26) 1450(1478) bytes of data.
ping: local error: message too long, mtu=1350
ping: local error: message too long, mtu=1350
ping: local error: message too long, mtu=1350
^C
--- 192.168.19.26 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2034ms

ここで注意すべきはpingの宛先IPアドレスでPC1からpingが通らないと思って192.168.19.26ではなく192.168.19.25に上記のオプションでpingを飛ばすと192.168.19.25のインターフェースのMTU値は見ることができません。このオプションのpingのパケットが出ていくインターフェースのMTU値しかわからないので192.168.19.26まで飛ばしてパケットを192.168.19.25から出す必要があります。

なお上記オプションでMTU値を変えて複数回pingをする場合、linuxがMTU値をキャッシュするためpingをする前にsudo ip route flush cacheを実行してキャッシュを削除する必要があります。

R3のMTU値が解ればR2のR3側のインターフェースに同じMTU値を設定すればOSPFのネイバーが確立できるのでEBGPのネイバーも張ることができ、PC1<–>PC2間でpingが通るようになります。

その他解法

実際の本選参加者は上記のようなまどろっこしい解法は行わずR2のVyOS上でtcpdumpを行いOSPFのパケットの中身を見てMTU値を割り出していました。おそらくそちらのほうがメジャーなやり方ですが、tcpdumpを使えない環境等でpingでMTU値を割り出す方法も知っていると便利かと思います。

採点基準

この問題は50点問題なので部分点などは与えずPC1<–>PC2間で疎通が取れるようになる解答のみに点数を与えています。