ICTSC2025 本戦 問題解説: [5023] 今夜のIRC

問題文

概要

[22:10:45] * wind ([email protected]) has joined #home-lan
[22:10:50] <wind> ついに建ててしまったな
[22:11:05] <~wave> お家ネットワークでIRC始めた
[22:11:20] <wind> わろた 時代錯誤も甚だしいな
[22:11:45] <~wave> あ、なんかお前のIP 10.0.0.2 だけど
[22:12:02] <wind> そういうお前も 10.0.0.2。
[22:12:15] <~wave> ほんとうだ、なんでだろう
[22:12:40] <~wave> あと新しいマシンいれたけど
[22:12:55] <~wave> なんかうまくlinkしてくれない
[22:13:10] <wind> ドキュメント読んだか?

制約

  • 各ホスト 5023-sv1, 5023-sv2 で、 docker stack を用いて、 InspIRCd が TLS モードで起動している
    • stack 名は irc, service 名は irc_inspircd
    • コンテナの image は InspIRCd
    • ローカルの認証局(step-ca)が環境に存在しており、 5023-ca が担っている
      • 各ホストマシンは、その認証局を信頼するよう設定済みである
    • 証明書は acme.sh を用いて発行済で、service に secret として組み込まれている
    • 証明書について、その有効期間が本日もつならば、十分であるとしてよい
  • ホスト名 vespertilio.irc.internal, myotis.irc.internal それぞれは 各マシンの /etc/hosts に登録されており、それぞれ 10.200.1.1, 10.200.1.2 が割り当てられている
    • 10.200.1.1, 10.200.1.25023-sv1, 5023-sv2 がそれぞれ持っている
  • ホスト名 ca.internal は 各マシンの /etc/hosts に登録されており、10.200.1.100 が割り当てられており、 それは 5023-ca が持っている
  • IRCクライアントとサーバーの接続およびサーバー間リンクでは、TLSを使用すること

初期状態

  • 5023-h1 から weechat を起動し vespertilio.irc.internal につないだうえで
    • サーバが認識する当該クライアントの接続元アドレスが 10.200.1.200 ではない
    • /links と打って myotis.irc.internal との link が確認できない
  • 5023-h1 から weechat を起動し myotis.irc.internal につないだうえで
    • サーバが認識する当該クライアントの接続元アドレスが 10.200.1.200 ではない
    • /links と打って vespertilio.irc.internal との link が確認できない

終了状態

  • 5023-h1 から weechat を起動して vespertilio.irc.internal につないだうえで
    • サーバが認識する当該クライアントの接続元アドレスが 10.200.1.200 である
    • /links と打って myotis.irc.internal との link が確認できる
  • 5023-h1 から weechat を起動して myotis.irc.internal につないだうえで
    • サーバが認識する当該クライアントの接続元アドレスが 10.200.1.200 である
    • /links と打って vespertilio.irc.internal との link が確認できる
  • 上記の状態が永続化されている
    • 特に docker service update --force irc_inspircd などによって container が再作成されても、終了状態が維持される

接続情報

ホスト名 IPアドレス ユーザ パスワード
5023-sv1 192.168.23.1 user ictsc2025
5023-sv2 192.168.23.2 user ictsc2025
5023-ca 192.168.23.3 user ictsc2025
5023-h1 192.168.23.4 user ictsc2025

解説

証明書の有効期限が切れている

acme.sh を使って、証明書を再作成する。

acme.sh --install-cert -d vespertilio.irc.internal \
  --key-file /srv/inspircd/tls/key.pem \
  --fullchain-file /srv/inspircd/tls/fullchain.pem
acme.sh --install-cert -d myotis.irc.internal \
  --key-file /srv/inspircd/tls/key.pem \
  --fullchain-file /srv/inspircd/tls/fullchain.pem

有効期限は1日だが、制約は満たしているので問題ない。

送信元が10.0.0.2になる問題

docker ingressを介さず、直接hostから受けるようにする。

stack.yml の ports の項目を以下に変更

    ports:
      - target: 6697
        published: 6697
        protocol: tcp
        mode: host
      - target: 7001
        published: 7001
        protocol: tcp
        mode: host

これによって NAT されないので、送信元の IP アドレスが観測できるようになる。

linkが立ち上がらない問題

環境変数による設定がうまくいかないため、代わりに conf を作成し流し込む。
今回は mount を用いる。

すべての stack.yml

    volumes:
      - /srv/inspircd/conf/conf.d:/inspircd/conf.d:ro

LINK 系の環境変数は消しているとより丁寧である。

sv1 の /srv/inspircd/conf/conf.d/links.conf

<link name="myotis.irc.internal"
      ipaddr="10.200.1.2"
      port="7001"
      sendpass="vesp-to-myo"
      recvpass="myo-to-vesp"
      sslprofile="main">

sv2 の /srv/inspircd/conf/conf.d/links.conf

<link name="vespertilio.irc.internal"
      ipaddr="10.200.1.1"
      port="7001"
      sendpass="myo-to-vesp"
      recvpass="vesp-to-myo"
      sslprofile="main">

<autoconnect period="30s"
             server="vespertilio.irc.internal">
  • sslprofile の名前は既存設定から探す
  • ipaddr は直打ちが前提で、そうでないと container 上で名前解決をする必要があり、地獄を見る
docker stack rm irc
docker stack deploy -c stack.yml irc

で container が再作成されても、設定が維持されることを確認する。

採点基準

300点

  • 証明書を作成し直した(加点なし)
  • 接続元が 10.200.1.200 と認識された 50点
  • linkが成立した 250点

講評

Internet Relay Chat と呼ばれる、古き良きプロトコルを使用した、「今の時代に IRC !?」としたかった問題でした。
15チーム中9チーム満点で、おそらく初見、もしくはほとんど触ったことないであろうプロトコルをその場で解決したのでしょうか。拍手👏

……と言っても、この問題の本筋は IRC はあまり関係ないというオチでした。
見掛け倒しな問題になってしまってすみません。

解法についてですが、どのチームも作問者が想定していた解答ではありませんでした。
7000番ポートを開いたり(本当は7000は plain text な link で使うべき)、同一 Docker Swarm 内で link 張ったり(独立したホスト同士で繋げてほしかった)、設定の生成スクリプトを直に変更したりなど……。
わざと制約は緩くして、好きに解いていただきたいと思っていましたが、正直、IRC の自由度の高さをナメていました。

ところで今の時代に IRC はどうなんでしょうか……。
個人を認証するのに外部のサービスが必要って時点で、今の時代には合わないものになっているかなぁ……。

雑記

vespertilio は ヒナコウモリ属、myotis は ホオヒゲコウモリ属である。(それぞれのリンクは、その属の代表的な種)

これらは、とあるゲームで知ったので組み込んでみた。
この問題のタイトルも、そのゲーム関連が由来である。