/

問題文

以下のメールがあなたのもとへ届いた。しかし、どうやらこのメールの中にはサーバの設定が間違っているために期待していた配送が行われなかったものがあるようだ。該当するメールとその理由を答えてほしい。(複数回答可)

https://drive.google.com/drive/folders/1h0Ro8lMD3EYBwqE5jZKAa9F7TtZcKjlu?usp=sharing

トラブルの概要

  • メールサーバのドメイン設定が間違っているためにドメイン詐称状態になっている。
  • DNSサーバに登録されているSPFレコードの記法が間違っている。
  • DNSサーバにDKIMレコードが登録されていない。

解説・解答例

配布されているメールのヘッダから判断します。

mail2.txt より、Received: from mx2.prob2019-q1.ictsc.net (mx5.prob2019-q1.ictsc.net [103.202.216.3]) から 次のことが把握できます。

  • メールを転送した 103.202.216.3 のサーバから逆引きできるドメインが mx5.prob2019-q1.ictsc.net である。
  • ヘッダには mx2.prob2019-q1.ictsc.net が送信元として記述されている

mail3 .txtより、spf=softfail (ictsc.net: domain of transitioning ... から SPFに何らかの問題があることを把握できます。
ここで、実際に送信元のドメインに登録されているSPFレコードを確認してみます。

$ dig mx3.prob2019-q1.ictsc.net txt

; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> mx3.prob2019-q1.ictsc.net txt
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24853
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;mx3.prob2019-q1.ictsc.net.     IN      TXT

;; ANSWER SECTION:
mx3.prob2019-q1.ictsc.net. 299  IN      TXT     "v=spf1 ipv4:103.202.216.33/32  ~all"

;; Query time: 77 msec
;; SERVER: 192.168.10.1#53(192.168.10.1)
;; WHEN: Sat Aug 10 20:11:56 JST 2019
;; MSG SIZE  rcvd: 99

結果から "v=spf1 ipv4:103.202.216.33/32 ~all" というTXTレコードが登録されていることがわかりますが、正しい書式は "v=spf1 ip4:103.202.216.33/32 ~all" であり、期待通りの設定がされていないことがわかります。

mail4.txtより、dkim=neutral (invalid public key) ... から DKIMの公開鍵の設定に何らかの不備があることが確認できます。
DKIM-Signature からセレクタがdefaultであることを把握し、実際に送信元ドメインに登録されているDKIMレコードを確認します。

$ dig default._domainkey.mx4.prob2019-q1.ictsc.net

; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> default._domainkey.mx4.prob2019-q1.ictsc.net
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 61834
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;default._domainkey.mx4.prob2019-q1.ictsc.net. IN A

;; AUTHORITY SECTION:
ictsc.net.              1799    IN      SOA     desi.ns.cloudflare.com. dns.cloudflare.com. 2031710084 10000 2400 604800 3600

;; Query time: 107 msec
;; SERVER: 192.168.10.1#53(192.168.10.1)
;; WHEN: Sat Aug 10 20:18:54 JST 2019
;; MSG SIZE  rcvd: 135

結果より、DKIMレコードが設定されていないことが確認できます。参考として、他のすべてのメール・送信元ドメインにはすべてDKIMレコードが以下のように設定されています。

$ dig default._domainkey.mx3.prob2019-q1.ictsc.net txt

; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> default._domainkey.mx3.prob2019-q1.ictsc.net txt
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33765
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;default._domainkey.mx3.prob2019-q1.ictsc.net. IN TXT

;; ANSWER SECTION:
default._domainkey.mx3.prob2019-q1.ictsc.net. 299 IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0og8YgAH1Uo/bS+WShCsdCg+7UTlw9GvvfxVcLdBAzlU0cjZqmGRj6FqoI0yWafcVN3L7G78zXqL0zGllFmBP19IJjGryFRmVKvjTofK6bSs0o4bfZvNowy9UAAQcuwLNgNdAw2QNsMe4RfbQhhdbAaTTMwrwV0YqCx0hIsMG6QIDAQAB"

;; Query time: 62 msec
;; SERVER: 192.168.10.1#53(192.168.10.1)
;; WHEN: Sat Aug 10 20:19:47 JST 2019
;; MSG SIZE  rcvd: 320

採点基準

mail2 について

  • 送信元ドメインと逆引きドメインが間違っていることを指摘する (10%)
  • 解決方法について記述する (10%)

mail3 について

  • SPFに言及している (10%)
  • SPFのレコードの 書式 に問題があることについて言及している (20%)
  • 正しいSPFレコードを提示する (10%)

mail4 について

  • DKIMに言及している。 (10%)
  • DKIMレコードが登録されていないことに言及する。(20%)
  • 登録するべきDKIMレコードについて言及する。(10%)
 /

問題文

あなたは新しくルーターを購入しました。そして、新しく購入したルーターを自分の部屋に設置しました。

新しいルーターは、元々家にあったルーターの配下に接続されています。(2重ルーターの状態です。)

新しく購入したルーターに自分のPCを接続しましたが、なぜかInternetと通信ができません。

外部Internetと通信ができる状態にしてください。

条件

  • 設定を変更できる機材は新しいルーターのみ。

ゴール

  • 新しく購入したルーターの配下のPCが8.8.8.8とのping疎通確認が成功する。

各マシンの説明

情報

  • 各マシンへの接続はVNCから可能です。

ルーター1

既に設置されていたルーターで本ルーターに接続された機器は外部ネットワークと通信が可能。

ルーター2

  • IPアドレス: 192.168.0.102
  • ユーザー: admin
  • パスワード: password

新しく購入したルーターで本問題で設定変更ができる。初期状態でDHCPの設定のみ行われている。

※ルーター2はルーター1と異なるネットワークアドレスを配布します。

ubuntu

  • IPアドレス: 192.168.0.103
  • ユーザー: admin
  • パスワード: password

ルーター2に接続されているマシンでIPアドレスは持っているが外部との通信ができない。

構成

トラブルの概要

  • 新しく購入したルーター(ルーター2)の配下から外部に通信ができない。

解説・解答例

ルーター1は、Ubuntuに配布されているローカルアドレスをテーブルにもっていません。

そのため、Ubuntuのアドレスをルータ1に知らせてあげる必要があります。

方法は2つあります。

  1. 静的ルートをルーター1に記述する。
  2. ルータ2にNATの設定を行い、ルータ1が知っているアドレスに変換する。

    本問題の場合、ルータ1へのアクセスができないため、

    2のSNATが解法になります。

従って、ルーター2にSNATの設定をすることでルーター1はUbuntuへの経路を

理解できるため、疎通確認することができます。

コマンド

set nat source rule 1 outbound-interface eth1
set nat source rule 1 source address 192.168.2.0/24
set nat source rule 1 translation address masquerade

採点基準

原因の説明ができて5割。natを書いて疎通確認ができれば5割。

  • 原因の説明
    • ルーター1は、Ubuntuに配布されているローカルアドレスをテーブルにもっていない
    • natしてないから。
  • 疎通確認ができる
    • SNATを記述する。(設定の差分を記述できていたらOK)

参考

 /

問題文


Webアプリケーションからドメインが異なるAPIにリクエストを発行する際には、クロスオリジンについて注意する必要があります。
CORS (Cross-Origin Resource Sharing) に関する以下の問いについて、それぞれ適切な選択肢を選んでください。

問1

https://example.com と同じOriginを選んで下さい。

問2

app.ictsc で動いているアプリケーションから api.ictsc へ以下のような fetch() を実行したところ、CORSのエラーで正常に動きませんでした。 api.ictsc に設定する必要があるHTTP response headerをすべて選んでください。

fetch({
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  "body": JSON.stringify(data)
})
  • Access-Control-Allow-Origin
  • Access-Control-Allow-Headers
  • Access-Control-Allow-Methods

問3

選択肢に示すHTTPメソッドのうち、いかなる場合においてもpreflight requestが行われるものを選んでください。

  • GET
  • POST
  • HEAD
  • DELETE

問4

preflight requestについて示した文章のうち、正しいものを全て選んでください。

  • リクエスト元のドメインとリクエスト先のドメインが同じ場合は、いかなる場合においてもpreflight requestは行われない。
  • クロスオリジンで独自HTTPメソッド TEST を発行するためには、Access-Control-Allow-Methods* を追加することで必ず正しく動く。
  • preflight requestに対する応答は、Access-Control-Allow-* ヘッダの内容が正しいHTTP responseであれば他の内容はなんでもよい。
  • Access-Control-Allow-Origin* を設定しておけば、他のヘッダが適切である限りいかなる場合でも動作する。

解説

問1

ポート番号、プロトコル(HTTP か HTTPS か)、ホストが一致するときのみ同一のOriginとなります。したがって https://example.com/hoge のみが正解です。

参考: https://developer.mozilla.org/ja/docs/Glossary/Origin

問2

問題文中の fetch では https://api.ictschttps://app.ictsc から POST リクエストが実行されます。これはホストが異なるため、異なるOriginへのリクエストになるので、応答の HTTP ヘッダに Access-Control-Allow-Origin が必要です。

リクエストには Content-Type ヘッダが含まれており、その値が application/json になっています。Content-Type が以下の3つの値以外のときは、実際のリクエストの前に preflight request が発行されます。

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

preflight request は OPTIONSメソッドで行われ、サーバ側の許可するメソッドやヘッダが応答の HTTP ヘッダ内の情報として返されます。問題文のように Content-Type: application/json のリクエストを送る場合は、サーバ側で prefilght request への応答の HTTP ヘッダに Access-Control-Allow-Headers: Content-Type と設定しておく必要があります。

一方で、メソッドがGET, HEAD, POST の場合は preflight request への応答の HTTP ヘッダに Access-Control-Allow-Methods をつける必要はありません。

したがって、設定するべきヘッダは Access-Control-Allow-OriginAccess-Control-Allow-Headers となります。

参考: https://developer.mozilla.org/ja/docs/Web/HTTP/CORS#Preflighted_requests

問3

preflight request の概要については問2の解説で説明したとおりです。メソッドが以下に挙げるものの場合は、必ず preflight request が発行されます。

  • PUT
  • DELETE
  • CONNECT
  • OPTIONS
  • TRACE
  • PATCH

したがって正解は DELETE となります。

問4

リクエスト元のドメインとリクエスト先のドメインが同じ場合は、いかなる場合においてもpreflight requestは行われない。

ドメインが同じであってもOriginが同じであるとは限りません。ポート番号やプロトコルが異なる場合は異なるOriginとなります。Originが異なる場合、特定の条件を満たせばpreflight requestが行われるため、この文章は間違っています。

クロスオリジンで独自HTTPメソッド TEST を発行するためには、Access-Control-Allow-Methods* を追加することで必ず正しく動く。

Access-Control-Allow-Methods: * と設定した場合の独自メソッドの動作は実装に依存しています。Ubuntu 18.0.4 上で Python3.6.8 の Bottle v0.12.17 によりHTTPサーバをhttp://localhost:8090, http://localhost:8080に立てて、前者から後者に JavaScript の fetch でリクエストを送って検証しました。Chromium 76.0.3809 で TESTリクエストを行ってみると成功しますが、FireFox 68.0.1 では失敗しました。 したがって、「必ず正しく動く」とするこの文章は間違っています。

参考: https://developer.mozilla.org/ja/docs/Web/HTTP/CORS/Errors/CORSMethodNotFound

preflight requestに対する応答は、Access-Control-Allow-* ヘッダの内容が正しいHTTP responseであれば他の内容はなんでもよい。

preflight request に対する応答のステータスコードが200番台でない場合、リクエストを送ることができません。上記と同様の検証環境で、preflight requestに対するHTTP responseのステータスコードを404にするとPOSTリクエストが飛ばないことを確かめられました。したがってこの文章は間違っています。

参考: https://fetch.spec.whatwg.org/#cors-preflight-fetch

Access-Control-Allow-Origin* を設定しておけば、他のヘッダが適切である限りいかなる場合でも動作する。

リクエストにCookieなどのリクエスト情報が含まれている場合、Access-Control-Allow-Origin: *というワイルドカードの指定ではなく、具体的なOriginの指定が必要です。したがって、「いかなる場合でも動作する」とするこの文章は間違っています。

参考: https://developer.mozilla.org/ja/docs/Web/HTTP/CORS#Requests_with_credentials

以上より、全ての文が間違っているので、何も選択しないのが正解です。

 /

ICTSC2019 の一次予選に参加してくださった皆さん、お疲れ様でした。一次予選で出題した問題の解説記事をテーマ別にまとめました。これらのテーマの問題は、二次予選、本選でも出題される予定ですので解説記事を参考に対策していただければと思います。

コンテナ

コンテナが作れない

監視できない!

ウェブ

APIが飛ばないんですけど…

メール

メールは届いてるけど…

トンネリング

OpenVPNが急に繋がらなくなった!

パケットフィルタ

郷に入っては郷に従え

SSHできなくなっちゃった

ルーティング

接続が不安定になっちゃった

外に出れません・・。

IPv6

VyOSの設定が吹き飛んだ!

データベース

ストアドプロシージャってやつでなんとかして!!!!

 /

問題文

あなたはA社に今年入社した新入社員です。
A社は人手不足でAさんの他に上司のBさんしか情報システム部門にいません。
ある日突然Bさんが人事のCさんに、「簡単に指定のデータを取り出せるようにしてほしい」と言われました。
ですが、Bさんは次の日からバカンスに行く予定があったため、あなたに任せて出国してしまいました。
Bさんの代わりにCさんを助けてあげてください。

問1(q01)

  • 性別名が”男”の従業員のみを取得してください。
  • カラムは(employee_id, name, birthday, sex_name)を表示してください。

問2(q02)

  • 性別名が”女”で年齢が女性従業員の平均年齢以上の従業員のみを取得してください。
  • カラムは(employee_id, name, age, sex_name)を表示してください。
  • age(年齢)に関してはbirthdayから求めて答えてください。

問3(q03)

  • 部署も権限もすでに決まっている(NULL以外である)従業員のデータのみを取得してください。
  • カラムは(employee_id,name,age,department_name,permit_name)
  • age(年齢)に関してはbirthdayから求めて答えてください。

条件

Employees以外のテーブル内にあるカラム”〇〇_id”は今後内容が変更されることがあるので注意すること。

ゴール

問1,2,3で指定したデータを取得するクエリを、q01,q02,q03という名前でストアドプロシージャとして登録する。

情報

問題サーバー

  • IPアドレス: 192.168.0.1
  • ユーザー: admin
  • パスワード: 6pfmqje365Ed
  • DBユーザー: root
  • DBパスワード: 無し

解説・解答例

解説

 この問題は指定されたデータのみをストアドプロシージャを利用してCall (小問id)で簡単に呼び出せるようにしてあげるというものでした。
なので、最初に必要なデータを取得するためのクエリを用意しないといけません。
用意する際は以下の点に気をつけなければいけません。

  • 問1(q01)
    • 性別名が男なので、sexテーブルのsex_nameと一致してなければいけない
      • JOIN句を用いてsexテーブルとEmployeesテーブルを結合したあとにWhere句を用いてsex_nameのレコードのみを抽出する。
  • 問2(q02)
    • ageを求めるためにbirthdayから変換しないといけない
      • 現在の日付誕生日の差を取り、その年数を求めることで年齢を求められる
  • 問3(q03)
    • q02と同様にagebirthdayから求めないといけない
    • Join句を2回用いていなければいけない。
      • 順番はDepartmentsテーブルからでもPermitテーブルからのどちらからでも問題ない
  • 共通
    • クエリの内容でWHERE句とHAVING句を混同するなど動作が未定義な用法をしている場合は減点対象になっている

ここまでで用意したクエリをそれぞれプロシージャとして保存しなければいけませんでした。
クエリの最初にCREATE PROCEDURE [小問id]()をつけて実行することでそのクエリを保存することができます。
ここまでの作業を行ったうえでCall [小問id]();を実行することで簡単に指定したデータを取り出せるようになります。

解答例

問1(q01)

CREATE PROCEDURE q01() SELECT employee_id, name, birthday, sex_name FROM Employees LEFT OUTER JOIN Sex ON Employees.sex_id = Sex.sex_id WHERE sex_name = "男";

問2(q02)

CREATE PROCEDURE q02() SELECT employee_id, name, TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age, sex_name FROM Employees LEFT OUTER JOIN Sex ON Employees.sex_id = Sex.sex_id WHERE sex_name= "女" AND TIMESTAMPDIFF(YEAR, birthday, CURDATE())&gt;= (SELECT AVG(TIMESTAMPDIFF(YEAR, birthday, CURDATE())) FROM Employees LEFT OUTER JOIN Sex ON Employees.sex_id = Sex.sex_id WHERE sex_name="女");

問3(q03)

CREATE PROCEDURE q03() SELECT employee_id,name,TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age,department_name,permit_name FROM Employees AS Emp JOIN Departments AS Dep ON Emp.department_id=Dep.department_id JOIN Permit AS Per ON Emp.permit_id=Per.permit_id;

講評

 今回は一次予選で最近出題が少なかったデータベースの問題ということで、どちらかというとオペレーションの簡略化とミス防止、ストアド・プロシージャという機能を知っているかということを意識して作問しました。
 問1~3まで通して、ストアドプロシージャという機能を使えるかということを中心に、問題文の条件にも書いてあるようにテーブル内のデータの増減や変更などに耐えられるクエリがかけているかということを中心に採点を行いました。
 今回の解答を見ている中で惜しいミスがいくつかあり、例えばsex_id=0など、Employeesテーブル以外のsex_idとsex_nameが今後変化することがあるかもしれないのに抽出条件に書いてしまっている解答が多く見られました。
また、解答では正答を書いているにも関わらず問題環境でオペレーションを行っていないチームが多数ありました。
こちらについては、問題の本質について理解しているということで各小問50%減点で採点をさせていただきました。
減点の理由としては問題の本質について理解していても、オペレーションの時間を他の問題に費やせていたかもしれないという考えからです。
 今回、採点をした感想としては上位層はかなり高い割合で問題を完答しており、DBの基本的なところがしっかり理解していそうだなと感じました。
今回出題した機能は、SQLの入門書の最後の方に出てくるかどうかという機能でした。
ストアドプロシージャ以外にもMySQLやMariaDBには様々な機能が備わっているのでぜひ調べて見てください!