/

問題文

社内にVyOSを導入することが決まった。
そこで、社内のインフラを構築する前に以下の図の様なテスト環境で検証を行った。
VyOSにDNSのキャッシュサーバとDHCPサーバを起動し、下に接続されているUbuntuにIPアドレスを割り当てた。
しかし、Ubuntuから外部のサーバにアクセスしようとしたが接続できずICMPを送っても応答がない。ところが、VyOSからICMPを外部のサーバに送ると応答が返ってくる。
なので、Ubuntuから外にアクセスできる様に解決してほしい。ただし、Ubuntuに直接接続することはできず、VyOSからはアクセスできるようになっている。

スタート

  • Ubuntuから外部のサーバにアクセスできない
  • VyOSからはアクセスが可能

ゴール

  • Ubuntuから外部にアクセスできる

情報

サーバ IP アドレス アカウント パスワード
vyos 192.168.20.80 admin PxZsMqycN4a4nzlk1Xg7
client 192.168.20.2 admin kopvVL3cT2tkALu4nQnD

トラブルの概要

この問題ではVyOSがNATをして下に接続されているUbuntu Server(以下clientとする)が外とアクセスできるような構成になっていました。しかし、何らかトラブルでclientが外と全く疎通が取れない状態でした。VyOSから8.8.8.8にpingをすると応答が帰ってくるという状態でした。

解説

問題文を読んだだけで大抵の人はVyOS側に問題があることに気づいたかと思われます。答えはVyOSのNATの設定に不備がありclientが外に繋げられなかったということです。

解答例

NATの設定を確認するためにshow natを打つと以下のように表示されます。

nat {
source {
rule 1 {
outbound-interface eth1
source {
address 192.168.20.0/26
}
translation {
address masquerade
}
}
}
}

今回の場合、VyOSが対外に接続しているインターフェースはeth0なのにoutbound-interface eth1となっています。これが原因な訳でこれを消すか上書きしてあげることで疎通が取れるようになるはずです。以下のような手順で上書きをしてみます。

# set nat source rule 1 outbound-interface eth0
# commit
# save

この後に8.8.8.8に対してpingをすると以下のように接続できていることがわかります。

$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=61 time=12.8 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=61 time=11.8 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=61 time=10.4 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=61 time=9.57 ms

採点基準

  • 外部に疎通できないことを指摘
  • 解決方法の提示
  • そのあとに疎通できることを提示

講評

この問題はウォームアップ問題として作成しました。なのでほとんどのチームが解答してくれました。実はVyOSは一回も触ったことがありませんでした。だそうにも難しくすることができないので実際に自分がミスしたところを出せばいいのではと思い出題しました。

 /

問題文

以下の図のようなDMZとLOCALの2つの空間が接続されている内部向けDNSサーバと、外部向けのwebサーバがあり、webサーバは8000番で待ち受けている。
LOCALからそのwebサーバの8000番に対しFQDNでアクセスしても表示されないと社内の各所から連絡があった。

そのため、内部からwebサーバにFQDNでアクセスできる様に解決してほしい。
ただし、既に構築してあるこのDNSサーバを使い、FQDNで正常にアクセスできることを証明してほしい。

制約

この問題での制約は問題文で指示されている通り、図にあるdns-serverを必ず使用することです。

スタート地点

  • DNSの問い合わせができない

ゴール地点

  • DNSの問い合わせができる
  • 正常に問い合わせができているかをコマンドを使用して証明する
  • 健全なDNSサーバを構築する

必要情報

  • ドメイン: ictsc.local
  • ホスト:
  • web-server: www.ictsc.local
  • dns-server: dns.ictsc.local

情報

サーバ IP アドレス アカウント パスワード
dns 192.168.4.70 admin e4EYoNiTlII4zEE7udxG
web 192.168.4.71 admin Eaa4mXBsgygxag934x3H

トラブルの概要

図のように各サーバは2つのNICをもちそれぞれDMZとLOCALに接続されていました。トラブルの概要としてLOCAL側からdns-serverに対して名前解決の問い合わせをしてもドメインと紐づけられているIPアドレスが帰ってこないというものでした。

解説

このトラブルは/etc/bind/以下にDMZとLOCALの空間から名前解決できるように定義されたzoneファイルが不適切のため発生していました。それがこの4つのファイルです。

  • 0.4.168.192.in-addr.arpa
  • 64.4.168.192.in-addr.arpa
  • ictsc.local-0.zone
  • ictsc.local-64.zone

トラブルの原因としてこの4つのファイル全てに共通して以下の3つがありました。

  • SOAレコードを定義する箇所で最初の@が抜けている
  • SOAレコードのhostmaster-emailの最後に.がついていない
  • SOAレコードを括弧で囲むときに最後が)ではなく}となっている

問題の初期状態は以上の3つが原因でDMZとLOCALから名前解決ができませんでした。なので適切な状態に書き直して名前解決ができることを提示すると基準点となります。満点にするためにはゴール地点に記載した通り健全なDNSサーバを構築するまで行うことです。実はこのdns-serverはDMZからictsc.local以外の名前解決をしてしまいます。つまりオープンリゾルバ状態でした。なので外部からはictsc.local以外は受け付けないように設定を変更する必要があります。それには以下のファイルを書き換える必要があります。

  • named.conf.default-zones

解答例

まず、/etc/bind/以下の0.4.168.192.in-addr.arpaを書き換えます。これはDMZの空間からの逆引きを解決するためのファイルです。

$TTL 3600
IN SOA dns.ictsc.local. root.ictsc.local (
2018022400
3600
900
604800
86400
}

IN NS dns.ictsc.local.
10 IN PTR dns.ictsc.local.
11 IN PTR www.ictsc.local.

これを先ほど指摘した3つの原因を以下のように修正します。

$TTL 3600
@ IN SOA dns.ictsc.local. root.ictsc.local. (
2018022400
3600
900
604800
86400
)

IN NS dns.ictsc.local.
10 IN PTR dns.ictsc.local.
11 IN PTR www.ictsc.local.

これを他のファイルも同様に修正し、サービスの再起動を行うことで名前解決ができるようになります。
次にオープンリゾルバを解決するためにnamed.conf.default-zonesを修正します。このファイルの中にinternalexternalのゾーンによって読み込むファイルを記述している箇所があります。そこにmatch-clientsを追加して適切な空間を記述することでオープンリゾルバを回避することができます。

採点基準

  • 上記のトラブルを指摘
  • 対策後にちゃんと名前解決ができていることを提示
  • オープンリゾルバとして動作してしまっているのでそれを指摘して対処(加点対象)

講評

この問題はウォームアップ問題として作成しましたが実際に解答を送ってくれたチームは半分ぐらいで想定と違う結果となり驚きました。その中でもちゃんと最後まで解けていたのは1チームのみでした。

 /

問題文

今まで使っていたサーバが老朽化してしまったため、新しくサーバのマイグレーションを行うこととなった。
現在はそのマイグレーション前の移行作業中なのだが、cronで動作させていたスクリプトが実行されない。

そのため、新しいサーバでcronが正しく実行されるように設定の変更を行ってほしい。

スタート

旧サーバで実行されているcronに登録されているスクリプトが新サーバで実行されない

ゴール

新サーバにて、全てのcronに登録されているスクリプトが正常終了するようにする

トラブルの概要

Linuxディストリビューションにおいて一般的に利用されているタスクスケジューラである cron の実行時に発生する、ディストリビューション間での差異を利用したトラブルです。

一部のLinuxディストリビューションでは、/etc/cron.hourly/, /etc/cron.monthly/, /etc/cron.weekly/のように、ディレクトリ以下にスクリプトを設置するだけで一定の時間間隔でスクリプト群を実行するディレクトリが用意されています。
このディレクトリを実行している実態は /etc/cron.d に設置されていることが多いです。

[vagrant@node1 ~]$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)

[vagrant@node1 ~]$ ls -l /etc/cron.d
合計 8
-rw-r--r--. 1 root root 128  8月  3  2017 0hourly
-rw-------. 1 root root 235  8月  3  2017 sysstat

[vagrant@node1 ~]$ cat /etc/cron.d/0hourly
# Run the hourly jobs
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
01 * * * * root run-parts /etc/cron.hourly

/etc/cron.d/0hourly に、run-parts /etc/cron.hourly というコマンドを実行しています。
この際に実行されている run-parts というコマンドの実装が異なることが、今回の問題におけるキモとなります。

今回の大会の競技時間を考慮した場合、1時間に1回実行されるというシナリオは無用な時間の損失を産んでしまう可能性があったため、疑似的に /etc/cron.d/0minutely というファイルを生成し1分に1回実行されるようにしていました。

run-partsについて

実際に確認してみると、 run-parts というコマンドはディストリビューションによってそもそもファイル形式すら違う事が分かります。

[vagrant@node1 ~]$ cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

[vagrant@node1 ~]$ which run-parts
/usr/bin/run-parts

[vagrant@node1 ~]$ file /usr/bin/run-parts
/usr/bin/run-parts: Bourne-Again shell script, ASCII text executable



vagrant@node2:~$ cat /etc/debian_version
stretch/sid

vagrant@node2:~$ which run-parts
/bin/run-parts

vagrant@node2:~$ file /bin/run-parts
/bin/run-parts: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=53e52d241c66c42300698ceec057edd3417be4b6, stripped

CentOS においてはBash ベースなシェルスクリプトとして実装されており、Debian においては実行可能なバイナリとして実装されていることが分かります。

CentOS におけるシェルスクリプトでは、以下のような記述がありました。

[vagrant@node1 ~]$ head -n 5 /usr/bin/run-parts
#!/bin/bash
# run-parts - concept taken from Debian

# keep going when something fails
set +e

つまり、元々debianutilsに実装されていたrun-partsをシェルスクリプトで実装したものを、CentOSは利用していると考えられます。

この実装時に差異が発生したのが今回のトラブルの原因となります。

今回の問題におけるトラブル

実際には、以下の差異を利用してトラブルを発生させました。

  • スクリプト名に . を含める (例: crawler.sh)
    • Debianでは . が含まれていても実行されますが、CentOSでは実行されません
  • Shebangがスクリプトに存在しない
    • DebianではShebangが存在しなくても拡張子で判別されますが、CentOSでは拡張子を削除するため記載が必要になります

また、今回は移行時に発生するトラブルとして、以下のトラブルも発生させました。

  • 移行先のディストリビューションにコマンドがあっていない
    • 移行先はDebianだったのですが、 yum update というコマンドを実行させていました
  • cronに登録されているスクリプトが移行先サーバに存在しない
    • WebAPIに対してリクエストを送信するスクリプトが移行元にはあるが移行先には配置していませんでした

採点基準

日本語でこの事象を説明しているブログも多く存在しており、cronという比較的利用者も多いプロダクトであることから、入門編と位置づけて出題しました。
そのため、「どこまで気づいているのか」を採点基準に採点を行いました。

まとめ

トラブルシューティングの基本として、「事象の切り分けを行う」という事があります。
実際にトラブルが発生している事象はどのように実行されていて、どのような箇所で実行されているのかを確かめるのがベターと言われています。

今回の回答を見てみると、「実行権限がなかったので付与しました」「内容が誤っていたため修正しました」などの回答が来ていたのですが、今回で言うなればファイル名を変更しない限り実行されていないため、cronを経由したファイルの実行を確認出来ていなかったのではないかと予測します。
実際にはどのような環境で、どのような方法で目の前のコマンドが実行されているのかを確かめるようにするようにしてみるのが重要だと改めて感じました。

なお、今回の記事中で検証のために利用したVagrantfileはこちらとなります。是非検証してみてください。

 /

問題文

障害対策調査課から依頼があった。
我社で運用しているサービスに初歩的なディレクトリトラバーサルの脆弱性が見つかってしまったらしい。

しかし、不幸なことに担当者がバカンス中のため連絡を取ることが出来ない。
このサービスは担当者にバカンス直前に無理やり開発させたため、ソースコードは彼のPCの中のようだ。
ソースコードが無いのでプログラムの修正が出来ない。
だが、担当者が戻るまでサービスを落としたままにするわけにはいかない。

どうにかしてプログラムを修正せずに安全にサービスを動かしてほしい。

制約

  • サービスは80番ポートで動かす
  • 対外疎通無し
  • 新たにパッケージをインストールする等はできない

スタート

ファイルアップローダーがディレクトリトラバーサルの脆弱性を受けてしまう状態

ゴール

ファイルアップローダーがディレクトリトラバーサルの影響を受けずにサービスが動く状態

情報

  • 192.168.1.10:80 でサービスが動く
  • ユーザ: admin
  • パスワード: yasumikure
  • ファイルアップローダのバイナリ: /home/admin/uploader

Webサービスのパス

メソッド パス 動作
GET / アップロードされた画像一覧
GET /upload 画像をアップロードするページ
POST /upload 画像をアップロード

使用するディレクトリ

パス 用途
/var/www/templates/ レンダリングするテンプレート
/var/www/assets/ jsやcssなど
/var/www/images/ アップロードしたイメージの保存場所

サーバ動作確認例

# sshしてサーバを起動
ssh admin@192.168.1.10
sudo /home/admin/uploader

# 手元のブラウザもしくはcurlで 192.168.1.10:80にアクセス

# ディレクトリトラバーサルのサンプル
curl 192.168.1.10:80/upload \
-X POST \
-F "graphic=$(echo 'echo Hacked' | base64)" \
-F "filename=../../hacked.txt"

トラブルの概要

この問題ではディレクトリトラバーサルの脆弱性が発覚したファイルアップローダが用意されています。
これをroot権限で動作させるのはまずいので、どうにかしてある程度安全に動くようにして欲しいというのがこの問題の主旨です。

解説

この問題は「Linux Capability」を知って欲しいという意図で、少々無理やり作りました。
問題を解いていて、思うところがあったかもしれませんがご容赦ください。

さて解説に入ります。まず前提を以下に示します。

  • このファイルアップローダはLinuxで動くELFバイナリとして用意されてる。
  • サービスを動かすポートは80番で固定されているため変更はできない。
  • 80番ポートは、通常は一般ユーザではバインドできず、root権限が必要。
  • ディレクトリトラバーサルのあるアップローダをroot権限で動かすと意図しないファイルが書き換えられてしまう可能性が有ります(そもそもサービス止めろよって話ですが)。

この問題の想定解の方向性は「一般ユーザで80番ポートをバインドしてサービスを動かす」です。
その際に、一般ユーザで80番ポートをバインド可能にするのが「Linux Capability」です。
詳細は省きますが、簡単に説明するとケーパビリティとは「root権限を細分化し、部分的に適用できるようにしたもの」です。
今回はウェルノウンポートを一般ユーザでバイドできるようにするために、cap_net_bind_serviceをアップローダのバイナリに付与します。
こうすることで、このアップローダは一般ユーザで80番ポートをバインドできるようになります。
ちなみに、ケーパビリティを付与できるのはバイナリのみで、スクリプトには付与できません。

解答例

この問題の突破基準は以下の解答、もしくは以下と同等の効果が得られると判断した解答です。
以下はファイルアップローダにケーパビリティを付与し、一般ユーザ(admin)で実行する例です。

sudo setcap cap_net_bind_service=eip /home/admin/uploader
/home/admin/uploader

この解答だけでは、ディレクトリトラバーサルは完全には防ぎきれていませんが、この問題を出した意図は達成されているので良しとしました。
adminユーザのままで実行すると、/home/adminが書き換えられてしまうため、以下のようにするとなお良いです。

sudo --user=nobody /home/admin/uploader

お気づきの方もいると思いますが、この問題はケーパビリティを使わなくても、chrootAppArmorを使うことで解決できます(そのほうが良いケースが…)。
今回はそういった解答で、より堅牢で安全だと判断した解答にはボーナス点を付けさせていただきました。

講評

この問題は15チーム中9チームが基準を突破し、そのうち4チームがケーパビリティを使った解答を送ってくれました。(思ったよりケーパビリティ使ってくれなくてちょっと寂しい…)

先程「ケーパビリティを知ってほしい」なんていいましたが、正直ケーパビリティの実用的な用途ってあまり思いつかないんですよね。
ぱっと思いつくのはcap_dac_overrideを付与した、どこでも覗けるlsとか、なんでも読めるcatぐらいですね。

それでは、問題解説を終わります。

 /

問題文

近年のゲーム市場拡大に感化され我が社でも仮想遊戯開発部が新設された。
新サービスに向けてオンラインゲームを試作し、制作環境での複数人対戦は仕様書通りの動作が確認されている。
しかし、ステージング環境ではなんらかの設定ミスにより動作に支障が生じた。
原因を調べ、仕様書通りに動作するようにしてほしい。
また、ゲームの仕様に脆弱性があれば合わせて報告してほしい。

制約

ゲーム自体のソースコードの改変は禁止。

スタート

ゲーム開始後、ユーザ登録を行ってもmainシーンに遷移しない。

ゴール

仕様通りにゲームがプレイできる。
local portが枯渇する仕様やパフォーマンスを指摘できている。
スコアを無限に増やせる脆弱性等を指摘できている。

解説

この問題は、取引先から仕様書を渡され、仕様通りにオンラインゲームを動作させるというものでした。

トラブルの内容

Webサーバ上では、以下のような現象が発生していました。
– ゲームがスタートしない
– 攻撃ができない・アイテムが取れない
– ランキングが反映されない

これらは、以下に挙げるトラブルが原因でした。

1. Redisの使用できるメモリが足りない

参加者の情報は、Redisサーバで管理されていましたが、設定ミスでmaxmemoryを1にしてしまっていました。
そのため、/etc/redis/redis.conf内のmaxmemoryを1gなどに変更する必要がありました。

2. ufwの開放しているポートが間違っている

ufwをセキュリティを考慮して有効にしていましたが、ゲームで使うポートを開けていないトラブルがありました。
そのため、正しく使うポートのみを解放する必要がありました。

3. 使えるローカルポートの数が制限されている

通常、ネットワーク通信をする側はローカルポートを消費します。使えるローカルポートの範囲はカーネルパラメータで設定することができます。このゲームは、redisにたくさんコネクションを貼るため、sysctlでパラメータをいじったのですが、ip_local_port_rangeの値を間違えて設定していたため、疎通が取れなくなっていました。
そのため、ポートの範囲を広げる必要がありました。

その他

このゲームはできるだけ短い間隔でudpによる通信を行い、その度に新しいコネクションをredisにはる仕様になっていました。
このため、パフォーマンスがどうしても制限されてしまいます。

また、ユーザIDは他のプレイヤーに通知されない仕組みになっていましたが、自分のIDはわかるため高さを偽装しスコアを伸ばす、または任意の座標に攻撃を行うことができる仕様的な脆弱性がありました。

そのため、この2点について言及されていた場合は加点の対象としました。

 /
カテゴリー

ICTSC9 では問題 VM およびライフサーバ等の基盤としてオープンソースのプライベートクラウド基盤である OpenStack を使いました。バージョンは OpenStack Pike です。以下では、今回の OpenStack でどのような構成をとったかを解説します。

続きを読む

 /

クソ上司とはクソな上司のことです。今回のクソ上司は自分が納得しないと話に応じてくれないタイプの、いわば頑固な上司でした。
なぜ彼が生まれたかについては諸説ありますが、「ちょっと特殊な技術を触ってみたら思いのほかいろいろな問題を踏み抜いた」というのが実情のようです。
ちなみに当日「クソ神上司」の名札を付けて歩いていた人物はおそらく無関係でしょう。たぶん。

1問目

問題文

最近Webアプリを動かしているサーバーへの負荷が高かったので、業者に頼んで負荷を分散できる構成にしてもらった。
現在は192.168.21.20で動作しているらしいが、どうやらアプリケーションが不安定のようだ。トラブルを解決するためにはいくつかの情報が必要だが、正当な理由なくサーバーへのアクセスが許可されていない。
幸いにも同じセグメントにあるマシンは使えるので、まずはこの負荷分散の名前がどのようなものか知りたい。
このマシンを用いて、負荷分散の名前を理由とともに上司(運営)に報告すること。

注意事項

必ずclientを使うこと。clientを使わずに回答は不可能である。
動作確認にWebブラウザは使わずにcurlなどで確認すること。使った場合の動作は保証されない。

トラブルの概要

負荷分散の形式がわからない(これはトラブルですか?)

解説

最初のトラブル(?)は負荷分散の形式を特定する問題でした。
ポイントとなるのは注意事項にある「必ずclientを使うこと。clientを使わずに回答は不可能である。」の文言です。
同じセグメントにあるマシンを使わないと解けないということは、少なくともL2に関する何かが絡んでいるというところです。この点でピンときたチームもいるのではないでしょうか。

まずcurlなどで192.168.21.20へリクエストを送ってみると、レスポンスが返ってこないことがあるものの、Webページらしきものが見えます。
ここでtcpdumpを使いながらリクエストとレスポンスを眺めると、取得成功時に行きと帰りでMACアドレスが異なっていることに気づきます。
これはDSR (Direct Server Return) と呼ばれる手法で、レスポンスをリアルサーバから直接返すことでLBを経由せず、負荷をかけないようにすることができます。

よってMACアドレスが異なることをふまえた上でDSRであることが指摘できていれば正解です。

2問目

問題文

DSRであることを上司に伝えると、LB1台、アプリケーションサーバー2台という構成であることがわかった。
最初にも述べたが、ブラウザ (Chrome, Firefox, Safariなど) からアクセスすると他のマシンから一切アプリケーションに繋がらない。
DSRであることがわかったのでLBへのアクセスは許可されたが、まだアプリケーションサーバーへのアクセスは許可されていない。上司によると、パケットキャプチャを見ているとアプリケーションサーバーの片方にしかリクエストが来ていないので、負荷分散についてはLBに問題があると疑ってやまないようだ。
LBの設定を調査して、ブラウザからアクセスしても正常に動作するようにしてほしい。たまにレスポンスが返ってこないのはアプリケーションサーバーの問題だと確信しているが、LBの設定を直さないことには上司がアプリケーションサーバーへのアクセスを許可してくれない。

トラブルの概要

192.168.21.20にブラウザで接続したときにそれ以降のリクエストが届かなくなる

解説

この問題ではLBサーバへのアクセスが与えられます。
ログインして設定をいろいろ見てみると、keepalived+ipvsadmでL2DSRを構築していることがわかります。
また、実際にブラウザで192.168.21.20へアクセスしてみると、そのブラウザは繋がるのに他のクライアントからは一切繋がらなくなるという現象に直面します。
まずipvsadmコマンドでLBの状況を確認してみると、

~$ sudo ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.21.20:80 lc
  -> 192.168.21.71:80                Route   1      1          3
  -> 192.168.21.72:80                Route   1      0          4

192.168.21.71:80に対してActiveConnがずっと1になっていることがわかります。
また、スケジューリングアルゴリズムがlc (Least Connection) であることから残りのリクエストがすべて192.168.21.72:80に転送されていることがわかります。

/etc/keepalived/keepalived.confの中身を見ると、

vrrp_instance VI_1 {
  state MASTER
  interface ens3
  virtual_router_id 51
  priority 100
  nopreempt
  advert_int 1
  virtual_ipaddress {
    192.168.21.20
  }
}

virtual_server_group app_servers {
  192.168.21.20 80
}

virtual_server group app_servers {
  delay_loop 10
  lvs_sched rr
  lvs_method DR
  lb_algo lc
  protocol TCP

  real_server 192.168.21.71 80 {
    TCP_CHECK {
      connect_timeout 10
    }
  }
  real_server 192.168.21.72 80 {
    TCP_CHECK {
      connect_timeout 10
    }
  }
}

となっています。注目すべきはvirtual_server group app_serversの中身で、

lvs_sched rr
lb_algo lc

においてlvs_schedおよびlb_algoは全く同じ意味をもつパラメータです。現在はlb_algoは古いパラメータですが、まだ有効であるためlvs_sched rrが上書きされてしまっています。
このことからもスケジューリングアルゴリズムがlcに設定されていることがわかります。

これらの点から、原因はスケジューリングアルゴリズムがlcであることと、ブラウザがずっとコネクションを保持しているために正常に応答が返ってこないもう片方のサーバ(192.168.21.72)へずっとリクエストが転送されていることを指摘できていれば正解です。

3問目

問題文

LBのスケジューリングを指摘したところ、上司はアプリケーションサーバーの片方に問題があることを認めて両方のサーバーへのアクセスを許可してくれた。
VIP192.168.21.20のアプリケーションが正しく動作するように修正してほしい。
また、セキュリティ上の観点から192.168.21.0/26から直接アプリケーションサーバーへHTTPアクセスができないようにして欲しい。
再起動した時も正常な状態が維持されるようにすること。

トラブルの概要

192.168.21.20へのリクエストが返ってこないことがある
192.168.21.{11,12}へのHTTPリクエストが成功する

解説

3問目は2台のリアルサーバへのアクセスが与えられます。
192.168.21.11(app1)と192.168.21.12(app2)の2台存在しますが、いずれもkeepalivedのヘルスチェックを通っているように、LBからのリクエストは正常に行えるため、まずは問題があるサーバを特定するのがスタート地点です。
どちらのサーバにもimgconvというサービスがsystemdで登録されており、/opt/imgconv/imgconvにあるバイナリを起動してこれが80番で動いていることがわかります。
2問目のようにipvsadmコマンドで確認すると、192.168.21.72側へ振り分けられていないことがわかるので、サーバにログインしてapp2(192.168.21.12@ens3, 192.168.21.72@ens4)側が原因であるとわかります。
適当にDSRやkeepalivedで検索すると設定方法が出てきます。やり方はいくつかありますが、app1にはiptables, カーネルパラメータの設定がされていることがわかります。ただしこれらは永続化されていないため、iptables -Lsysctl -aなどで見つける必要があります。
app1に入っていた設定は以下の通りです。

iptables

*nat
-A PREROUTING -d 192.168.21.20/32 -j REDIRECT

sysctl (カーネルパラメータ)

net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.ens3.rp_filter=0
net.ipv4.conf.ens4.rp_filter=0

iptablesにはVIPへのリクエストをそのまま受け取るための設定が、sysctlにはMACアドレス書き換えに伴ったLinuxのセキュリティ機構を無効化するための設定が書かれています。
これらをapp2も適用するとまずはVIP(192.168.21.20)に対して常にリクエストが返ってくることが確認できます。

次に192.168.21.{11,12}へ直接HTTPリクエストができないようにします。これは単純にiptablesを書くだけで良いです。謝ってtcp/22を閉じて締め出されないようにするのを忘れないでください。

-A INPUT -i ens3 -p tcp --dport 22 -j ACCEPT
-A INPUT -i ens4 -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -j DROP

講評

1問目を正解できたチームは2チームのみで、いずれのチームも2問目も突破していました。DSR自体を知っていないと回答するのは難しかったように思います。
よくある誤答としてはVRRPがありました。VRRPはfirst hopで到達するルータが物理的に複数台ある構成のため、今回の問題とは全く関係がありません。keepalivedがVIPを使うためにVRRPを内部で使用しているため、頻繁に飛んでくるVRRPのパケットに気づいてそれについて答えた競技者がかなり多かったようです。
また、VRRPは負荷分散というよりかは冗長化を目的としています。今回のテーマが冗長化であっただけにちょっと意地悪だったかもしれません。ちなみに今回会場提供いただいたさくらインターネット様のサービス「さくらの専用サーバ」のロードバランサーにはDSR・非DSR構成の選択オプションがあります。意図せずしてわかりにくいヒントができてしまったのですが、気づいた方はいらっしゃいましたか?

 /

どうも、作問者のnasuと言います。

問題文

あるドメイン ict2.local はここ最近なりすまし対策・スパム対策に力を入れている。
そのため、送信ドメイン認証DMARC,SPFとDKIMの両方をpassしないとメールを受信してくれない。
自前に検証用のドメイン( ict1.local )・DNSサーバ・メールサーバを用意し、
送信ドメイン認証を導入して ict2.local にメールが届くように構築をしているのだがエラーが起きてメールが届かないようだ。
諸君にはエラーを解決し、 ict2.local にメールを届くようにしてほしい。

スタート

ict2.local に対してメールが送れない。

ゴール

ict2.local に無事メールが届き自動返信メールの中身を報告出来たらゴール。

情報

参加者が操作出来るサーバとインストールされているパッケージは以下の通りである。

  • 参加者側のドメイン情報: ict1.local
  • メールサーバ
  • postfix
  • mailx
  • opendkim
  • DNSサーバ
  • ssh情報
  • bind
  • 解答先のドメイン情報: ict2.local

トラブルの概要

この問題のトラブルは大きく3つあります。

  • mxレコードが解決されない
  • メールを送るとMXレコードが解決できないというログが/var/log/maillogから確認が出来ます。これはDNSサーバの53番ポートがfirewalldによって閉じられている為です。
  • SPF認証に失敗する
  • ict1.localのゾーンファイルのSPFレコードの書式が間違っている為失敗します。この問題はオンライン予選にも出ました。勉強してきた方はすぐに分かったのではないでしょうか。正しい書式に直してください。
  • dkim認証に失敗する
  • ict1.localのゾーンファイルに記載されている公開鍵が間違っているためdkim認証に失敗します。正しい鍵をゾーンファイルに記載してください。

解説

この問題を簡単に解くカギは/var/log/maillogを読んでいくことです。
メールが届かない原因がmaillogには書かれています。

解答例

  • mxレコードが解決されない
    dnsサーバ
$firewall-cmd --add-service=dns --permanent
$firewall-cmd --reload

別解はiptablesで開ける方法。

  • SPF認証に失敗する
/etc/named/ict1.zone
IN TXT "v=spf1 +ip4:192.168.10.11 ~all"
  • dkim認証に失敗する
  • 解答方法1 あらかじめmail.ict1.localサーバにおいてある正しいキーをゾーンファイルに記載して更新する
  • 解答方法2 新たに公開鍵と秘密鍵を生成してゾーンファイルに記載して更新する

採点基準

  • 自動返信の中身を報告 → 基準点
  • 中身を報告且つトラブル原因への言及 → 満点

講評

15チーム中4チームから解答があり3チームには基準点、1チームには満点を与えました。
どのトラブルもそうですが、ログを確認することを頭に入れておきましょう。

 /

問題文

VXLANでの通信を検証するように依頼された。
異なるサーバ上のVXLANインターフェースがお互いに通信できるようにしてほしいとのことだ。サーバ同士はソフトウェアルータを介してL3の疎通性がある。VXLANのアンダーレイ通信には、マルチキャストルーティングを利用してほしいそうだ。
前任者も設定を行ったようなのだが、上手くいかずに諦めてしまったらしい。どうにか設定を変更して、VXLANインターフェース同士が通信できるようにしてほしい。

制約

VXLANインターフェース間の通信は、マルチキャストルーティングを用いたVXLAN通信でなければならない。

スタート地点

Server 1/2のVXLANインターフェース vxlan42 から Server 2/1のVXLANインターフェース vxlan42ping が通らない。

ゴール地点

Server 1/2のVXLANインターフェース vxlan42 から Server 2/1のVXLANインターフェース vxlan42ping が通る。

トラブルの概要

「VXLANが繋がらない」は、L2延伸技術であるVXLANを用います。VXLANは、パケットをカプセル化することでL3ネットワークを超えてL2ネットワークを構成します。
この問題のトポロジーは以下のようになっています。

2台のVMが異なるL2ネットワークに属しており、VyOSによってルーティングされます。それぞれのVMの中にはVXLAN用のインターフェースがあり、これらは仮想的に同じL2ネットワークにあります。
この図のvxlan42から出たパケットがens3でカプセル化され、もう一方のVMのens3を通ってvxlan42に届き、カプセル化が解除されます。
VMのens3とVyOSによって作られるL3ネットワークをアンダーレイ、vxlan42によって作られるL2ネットワークをオーバーレイと呼びます。
一般に、VXLANでは、アンダーレイでのブロードキャストをオーバーレイでのマルチキャストで実装します。ブロードキャストはARPに必要です。オーバーレイがL3ネットワークなので、マルチキャストルーティングを行う必要があります。

この問題では、vxlan42同士が通信できないというトラブルが起こっています。 .67 の方のVMで以下を実行しても疎通が取れません。

$ ping -I vxlan42 10.0.0.3

解説

この問題で起こっているトラブルには要因が2つあります。
– vxlan42 から送られるパケットの TTL が 1 になっている
– VyOS がマルチキャストルーティングを扱えない

TTLについては、VMのVXLANインターフェースが原因です。VXLANインターフェースにTTLを明示的に設定しない場合、TTLが1のパケットが送信されます。 TTLはルーティングの度にデクリメントされ、0になるとパケットが破棄されてしまいます。そこで、VXLANインターフェースの設定を変更する必要があります。

VXLANはマルチキャストルーティングを用いると述べました。実際には、マルチキャストを用いない例もあるのですが、この問題ではマルチキャストを使うよう制約を設けました。ところが、VyOSの config をどのように設定してもマルチキャストルーティングを行うことができません。そのような設定項目がないからです。この問題では VyOS 1.1.7 を使っていますが、私の知る限りは設定方法がありません。
VyOSがマルチキャストルーティングを行うことができないので、パケットが破棄されてしまいます。
しかし、VyOSはDebianをベースにしたソフトウェアルータなので、様々な外部のパッケージを導入することができます。これにより、マルチキャストルーティングを行うことができるようになります。

解答例

まずはVMのVXLANインターフェースのTTLを増やします。
今回、VMのOSはUbuntu 16.04です。はじめ、/etc/network/interfaces に以下のようにVXLANインターフェースの設定が書いてあります。

auto vxlan42
iface vxlan42 inet manual
    pre-up ip link add vxlan42 type vxlan id 42 group 239.255.255.255 || true
    up ip address add 10.0.0.2/24 dev vxlan42 && ip link set vxlan42 up
    down ip link set vxlan42 down
    post-down ip link del vxlan42 || true

これを下記のように書き換えます。

auto vxlan42
iface vxlan42 inet manual
    pre-up ip link add vxlan42 type vxlan id 42 group 239.255.255.255 ttl 2 || true
    up ip address add 10.0.0.2/24 dev vxlan42 && ip link set vxlan42 up
    down ip link set vxlan42 down
    post-down ip link del vxlan42 || true

追加した項目は2行目の ttl 2 のみです。これで送信するパケットのTTLが設定されます。今回はルータを1台はさむ構成なので、TTLが2以上であれば良いです。

$ sudo service networking restart

以上のコマンドを実行すれば設定が反映されます。

続いて、VyOSがマルチキャストルーティングできるようにします。
これはあくまで一例ですが、以下のようにして、外部のリポジトリを登録します。

$ conf
$ set system package repository squeeze components 'main contrib non-free'
$ set system package repository squeeze distribution 'squeeze'
$ set system package repository squeeze url 'http://archive.debian.org/debian'
$ commit; save

ただし、このままでは以下のコマンドでのパッケージのアップデートに失敗します。

$ sudo aptitude update

これは、DNSサーバが設定されていないためです。

$ vi /etc/resolve.conf
nameserver 8.8.8.8

このように /etc/resolve.conf などを修正すれば、アップデートが実行できるようになります。
そして、マルチキャストルーティングのプロトコルであるPIMを扱うために、PIMDをインストールします。

$ sudo aptitude install pimd

インストールすれば自動的にプロセスが立ち上がり、マルチキャストルーティングが動作するようになります。ただし、インストールしてから動作するまでは少し時間がかかります。

以上の項目を完了すれば、以下のコマンドで疎通が取れるはずです。

$ ping -I vxlan42 10.0.0.3

講評

この問題を完全に解くことができたのは1チームだけでした。

余談

ちなみに、この問題はICTSC 8の運営での経験から思いつきました。ICTSC 8ではVXLANを使うことで、Mと手元機材が同じL2ネットワークにあるように見せました。この際、アンダーレイはOpenStackとJuniper機器で構成しました。

OpenStack では以下の設定を変える必要がありました。

  • VXLANインターフェースのTTL
    • OpenStackの設定で変更することができます
  • VXLANインターフェースのマルチキャストグループ
    • デフォルトではリンクローカルの 224.0.0.0/4 になっているので別のものに変更する
  • VXLANのポート番号
    • Juniperの機器はVXLANのポート番号として4789を使うのですが、Linuxのデフォルトは8742になっています
    • Linuxのカーネルパラメータで変更することができます

これらの経験から、TTLの変更を問題にすることを思いつきました。また、VyOSでVXLANを行うにあたって、マルチキャストルーティングができなさそうなことが検証段階で分かったので、それもトラブルとして加えました。

 /

こんにちは!ICTSC8 問題リーダーの中西です。

大変遅くなりましたが、ICTSC8で出題された全問題の問題解説を公開します!
解けた問題は別解法の確認を、解けなかった問題は次回から解けるようになるために、是非勉強にお役立てください!

 


始まりの国

始まりの国には、様々な種族が住んでいる。エイトもこの国の出身である。
立地からか、外国との交流が盛んで旅人も多い。

永遠の国

エルフは魔法を使って生活を便利にすることが上手な種族である。
エルフの国はたくさんの村から構成され、村を指導する長は村人の尊敬を集めている。

謎の国 ICTSC

この国は未だに多くのことが謎に包まれている。
外国との交流は少なく、内情を知るものはほとんどいない。
一説では、政府が強大な力を持ち、魔法陣を使った交信を厳しく制限しているという。

荒廃の国

かつては栄えた国だったが、長く続いた内乱のせいで今は見る影もない。
治安は悪く、盗賊が人々を悩ませているという。

伝統の国

この国はドワーフを中心に構成されている。
ドワーフは何よりも繋がりを大切にしている種族である。
しかし自分の種族以外の人を冷たい目で見ることがある。

研究の国

この国では研究が盛んであり、教育にも力を入れている。
国の各地に学校があり、見習い魔導師たちが机を並べて勉強している。

ホビットの国

この国には、サーバが得意なホビットがたくさん住んでいる。 ホビットは商売が上手く、この国最大の会社であるホビットカンパニーは他国にもその名を轟かせる。

妖精の国

妖精の国がどこにあるのかは知られていない。しかし、たまに迷い込む者がいるという。妖精は様々なものに姿を変えて、出会ったものを惑わすと伝えられている。

最近のコメント