プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

Roundcube のアップデート(1.5.3 -> 1.5.6)と attachment_reminder を有効化

こちらの記事で書いたように、 Roundcube のアップデートをおこなおうと思っています。とりあえず今回は、既存のバージョンである 1.5.3 から現時点の docker image の最新版である 1.5.6 へアップデートします(Roundcube 自体は 1.5.7 が出てるんですが docker image がまだでした)。

この作業を行った際の手順をメモにしておきます。

docker イメージの作成

以前、 Roundcube を立ち上げたときの記事に書いたように、今は Roundcube のコンテナイメージを元に一部設定を追加した docker イメージを作成して使っています。なので、まずはこれを再作成します。

dockerfile を編集します。

FROM roundcube/roundcubemail:1.5.6-apache

RUN apt-get update -y \
    && apt-get install -y git \
    && apt-get install -y sqlite3

RUN set -ex; \
    sed -i "s/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/" /etc/ssl/openssl.cnf \
    ;

COPY ./config.docker.add_imap_conn_options.inc.php /var/roundcube/config/

ベースイメージを Roundcube の 1.5.6 にしています。あと、 git と sqlite3 をインストールしているのは、最後に触れているように 1.6.x 系へのアップデートのテストも兼ねていたためです。1.5系で使うだけなら不要です。

今度はタグを2つつけてビルドします。

docker build — Docker-docs-ja 24.0 ドキュメント

[ユーザ名@NAS名 myroundcube]$ docker build -t myroundcube -t myroundcube:0.2 .
Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM roundcube/roundcubemail:1.5.6-apache
(略)
Successfully tagged myroundcube:latest
Successfully tagged myroundcube:0.2
[ユーザ名@NAS名 myroundcube]$ 

無事できました。

新しいコンテナで起動

docker-compose.yml を次のようにします。

version: '3'

services:
  https-portal:
    image: steveltn/https-portal:1.23.1
    ports:
      - 'xxxx:80'
      - 'xxxx:443'
    restart: always
    volumes:
      - rcmail_ssl_certs:/var/lib/https-portal
    environment:
      DOMAINS: 'xxxx.yyyy.zzzz -> http://roundcubemail:80'
      STAGE: 'production'
      # FORCE_RENEW: 'true'
      CLIENT_MAX_BODY_SIZE: 0
  
  roundcubemail:
    image: myroundcube:0.2
    container_name: myrc
#    restart: unless-stopped
    volumes:
      - rcmail_www:/var/www/html
      - rcmail_sqlite:/var/roundcube/db
#    ports:
#      - 9001:80
    environment:
      - ROUNDCUBEMAIL_DB_TYPE=sqlite
      - ROUNDCUBEMAIL_SKIN=elastic
      - ROUNDCUBEMAIL_DEFAULT_HOST=ssl://サーバー名
      - ROUNDCUBEMAIL_DEFAULT_PORT=993
      - ROUNDCUBEMAIL_SMTP_SERVER=ssl://サーバー名
      - ROUNDCUBEMAIL_SMTP_PORT=465
      - ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE=30M
      - ROUNDCUBEMAIL_PLUGINS=archive,zipdownload,attachment_reminder

volumes:
    rcmail_ssl_certs:
        external: true
    rcmail_www:
        external: true
    rcmail_sqlite:
        external: true

Roundcube のイメージとしてさきほど作成したものを指定します。あと、添付ファイルのつけ忘れプラグイン attachment_reminder は最初から Roundcube に埋め込まれているので、上記で有効なプラグインとして記述するだけで使えるようになるみたいです。あとは、今のアプリケーション(コンテナ)で使っているのと同じボリュームを、上記の docker-compose でも再指定しておくこで、データをそのまま引きつぐようにします

なお、本来は、アップデート作業の前には必ずバックアップを取っておいた方が良いと思います。今回は Roundcube のストレージをバインドマウントからボリュームに変更する作業と同じタイミングで行ったので、バックアップは取得済みでしたので省略しています。

この docker-compose.yml を QNAP の Container Station から既存のアプリケーションの再作成で指定してやります。

これでアップデート完了です。

確認

Roundcubeにログインします。左側のメニューから、『このプログラムについて』を表示すると

のようにバージョンが上がっていることがわかります。また、プラグインの一覧に attachment_reminder が入っていることもわかります。

attachment_reminder を使ってみる

せっかく有効にしたので、早速 attachment_reminder を使ってみます。

ログイン後の画面の右側のメニューより、『設定』->『設定』->『メッセージの作成』を選択し、『基本的な設定』のなかにある『添付ファイルのつけ忘れを確認』を有効にします。

これで、保存を押せば設定完了です。

早速、試します。適当なテストメールを作って、本文中に『添付ファイル』と入れておきます。もちろん、添付ファイルはつけていません。この状態で送信ボタンを押すと

おぉ、警告してくれましたね。もちろん、添付ファイルがあれば、警告なしでそのまま送信されます。

なお、下記の記事によれば、添付以外にもいくつかのキーワードで警告してくれるようです。

Roundcubeのプラグイン〜添付ファイル〜 | OSSのデージーネット

これはずいぶんと役立ちそうです。

まとめ

最初は 1.5.3 から一足飛びにいまの最新版の 1.6.7 にアップデートしようと思って作業したのですが、

  • 1.6.x 系にアップデートすると ident_switch 関連で Roundube コンテナのコンソールに warning が表示される( 1.6.3 と 1.6.7 で試した)
  • そのうえ、データベース内の ident_switch テーブルの中身がすべて消えてしまう
  • ident_switch の後続になりそうな identy_switch は Roundcube 1.6 以降に対応(PHP 8 以降が必要)

ということがあり、なかなか一筋縄ではアップデートできなさそうな印象です。なので、これについてはまた改めて作業したいと思います。

とりあえずは 1.5系の最新版にしたので、当面はこれでいいかなと思ってます。

Roundcube を動かしている docker コンテナのストレージ設定を変更

docker のコンテナで動かしている Roundcube ですが、先日メールを送る際に、添付ファイルをつけ忘れるというあるあるをやってしまいました。メールのありがちなミスですね。

で、調べてみると Roundcube のプラグインで添付ファイル忘れを警告してくれるもの( attachment_reminder )があるので、それを導入することにしました。

Roundcubeのプラグイン〜添付ファイル〜 | OSSのデージーネット

せっかくなので、ついでに、 Roundcube のバージョンも上げたいと思います。ということで、その作業に先立ち、まずは Roundcube のコンテナの永続データの持ち方を見直してみようと思いましたので、その際の作業をメモっておきます。

なんで永続データの持ち方を変えるのか

いま動いている Roundcube のコンテナの設定内容を確認してみます。こちらの記事で紹介したように docker-compose.yml は

version: '3'

services:
  https-portal:
    image: steveltn/https-portal:1
    volumes:
      - ./data/ssl_certs:/var/lib/https-portal
    (略)
  
  roundcubemail:
    image: myroundcube:latest
    container_name: myrc
    volumes:
      - ./www:/var/www/html
      - ./db/sqlite:/var/roundcube/db
    (略)

となっており、2つのコンテナで3つのボリューム(厳密にはバインドマウント)を指定しています。

これらは、 QNAP 上のファイルシステムの特定のフォルダを、docker 側に割り当てる方法になっています。実際のデータは、 QNAP 側の Container Station 用のデータ領域下にある application/(アプリケーション名)/ 以下に、 www や data といったフォルダが作られ,、その中に保存されています。

普段だと、コンテナが使っているデータを直接見ることができて、それなりに便利だし、なによりわかりやすいと思います。が、気をつけないといけないのが、

  • QNAP でアプリケーションを削除すると、このフォルダ(アプリケーション名のフォルダ)は消されてしまう

という点です(QNAP でというのがポイントです)。

今回調べて初めて知ったのですが、 docker の場合、起動したコンテナに対して、元にしたイメージを最新版に更新するには、一度コンテナを削除して再度立ち上げる必要がある、という挙動になるそうです。ちなみに、 QNAP の Container Station には再作成というのがありますが、やってることは一度削除して同じ名前で作っているだけですので、本質的には同じですね。

となると、せっかくデータを残したいと思って、わざわざフォルダを指定しているのに、QNAP でコンテナを作り直すと、そこのデータが消えてしまうことになります(もっとも、アプリケーション名の外部のフォルダを最初から指定しておけば、消えることはないですけどね)。

ということで、QNAP 上でコンテナ(アプリケーション)を消しても、消えてしまわないように、永続データを持ち方を変更することにします(一応書いておくと、 QNAP 上から操作しないのであれば不要な作業になります)。

データの保存方法

docker でのデータの保存方法を調べてみると、下記のドキュメントにあるように3つ存在するようです。

Docker でのデータ管理 — Docker-docs-ja 24.0 ドキュメント

しかし、 tmpfs マウントはメモリ上にしか作られないので、ホスト側にファイルを作るものとしては、バインドマウントとボリュームになります。ボリュームにも、名前付きボリュームと匿名ボリュームがあるそうです。今回は、 docker が管理する名前付きボリュームを使ってみようと思います。

ちなみに、ネットを調べていると、この『ボリューム』という用語が、上記のドキュメントにある docker が管理する領域を利用する方法を指す場合と、バインドマウントを含めてホストとファイルを共有する方法という2つの意味で使われているため、なかなかややこしいですね。

永続化したいデータを名前付きボリュームへ移動

ということで、バインドマウントではなく、名前付きボリュームを作成して、そちらにデータを持たせるようにします。今回は名前付きボリュームが、既に動かしているアプリケーションのデータを移行する移行先になるため、手作業で名前付きボリュームを作りたいと思います。

名前付きボリュームの作成

作業前の名前付きボリュームはこんな感じになってました。

[ユーザ名@NAS名 ~]$ docker volume ls
DRIVER    VOLUME NAME
local     2f40159df0420ac580e90daf4ab80d6d7e6254702ccdc2dee6e1c919fe4e38ca
local     89150fae22bbd638b52d990488969696fedf86e9c9c82b51c3e5980634f21bdf
local     186999773b4d354046bcefbfcfc9fad5fb034ecf97d21a0eddde94e92c4cf710
local     c30c7cc6ef15fe2f9ace1a799d4afa1a0e1935eb0ebcb745f87e48aa261e9cfe
local     wp_db_data
local     wp_www
[ユーザ名@NAS名 ~]$ 

まずは、名前付きボリュームを作ります。今回の Roundcube アプリケーションでは3つのボリュームを使っているので、3つ作ります。

[ユーザ名@NAS名 ~]$ docker volume create rcmail_ssl_certs
rcmail_ssl_certs
[ユーザ名@NAS名 ~]$ docker volume create rcmail_www
rcmail_www
[ユーザ名@NAS名 ~]$ docker volume create rcmail_sqlite
rcmail_sqlite
[ユーザ名@NAS名 ~]$ docker volume ls
DRIVER    VOLUME NAME
local     2f40159df0420ac580e90daf4ab80d6d7e6254702ccdc2dee6e1c919fe4e38ca
local     89150fae22bbd638b52d990488969696fedf86e9c9c82b51c3e5980634f21bdf
local     186999773b4d354046bcefbfcfc9fad5fb034ecf97d21a0eddde94e92c4cf710
local     c30c7cc6ef15fe2f9ace1a799d4afa1a0e1935eb0ebcb745f87e48aa261e9cfe
local     rcmail_sqlite
local     rcmail_ssl_certs
local     rcmail_www
local     wp_db_data
local     wp_www
[ユーザ名@NAS名 ~]$ 

データの移行作業

次に、今のバインドマウントにあるデータを作成した名前付きボリュームに移行させます。念のため、一度アプリケーションを停止させ、作業前にアプリケーションフォルダ以下にあるデータのバックアップを取っておきます。

バックアップが取れたら、次にデータを名前付きボリュームにコピーします。名前付きボリュームへデータをコピーするには、一時的な作業用のコンテナを立ち上げて、それに対してファイルをコピーするのが一番簡単で確実なようです。

一時的な作業用コンテナは busybox を利用しています。立ち上げ時に -v で名前付きボリュームをコンテナ内のフォルダにマウントしておきます。

[ユーザ名@NAS名 アプリケーション名]$ ls
data/  db/  docker-compose.resource.yml  docker-compose.yml  qnap.json  www/
[ユーザ名@NAS名 アプリケーション名]$ 
[ユーザ名@NAS名 アプリケーション名]$ docker run -d --name tmp_container -v rcmail_ssl_certs:/data busybox tail -F /dev/null
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
ec562eabd705: Pull complete 
Digest: sha256:9ae97d36d26566ff84e8893c64a6dc4fe8ca6d1144bf5b87b2b85a32def253c7
Status: Downloaded newer image for busybox:latest
c764efa16e97b60f0e23d8a807db5405855123b3b88efdcf8a7bffaec5e8315c
[ユーザ名@NAS名 アプリケーション名]$ 

ここで tail -F /dev/null を指定しておくことで、なにもせず停止もしないコンテナを立ち上げることができます。なお、今回は始めて busybox を使ったのでイメージのダウンロードとかも行われました。

コンテナ(tmp_container)が起動したら docker cp でファイルをコピーします。

[ユーザ名@NAS名 アプリケーション名]$ docker cp data/ssl_certs/. tmp_container:/data/
ERRO[0000] Can't add file /(フルパス)/(アプリケーション名)/data/ssl_certs/default_server/default_server.key to tar: open /(フルパス)/(アプリケーション名)/data/ssl_certs/default_server/default_server.key: permission denied 
ERRO[0000] Can't add file /(フルパス)/(アプリケーション名)/data/ssl_certs/dhparam.pem to tar: archive/tar: missed writing 1704 bytes 
(略)
Error response from daemon: Error processing tar file(exit status 1): unexpected EOF
[ユーザ名@NAS名 アプリケーション名]$ 

これでうまくいくはんずだったんですが、証明書関係のファイルについてはコピー時にパーミッションで怒られてしまいました。なので、sudoをつけて再実行してみます。

[ユーザ名@NAS名 アプリケーション名]$ sudo docker cp data/ssl_certs/. tmp_container:/data/
Password: 
[ユーザ名@NAS名 アプリケーション名]$ 

問題なくコピーできました。作業が終われば、このコンテナは削除しておきます。

[ユーザ名@NAS名 アプリケーション名]$ docker stop tmp_container
tmp_container
[ユーザ名@NAS名 アプリケーション名]$ docker rm tmp_container
tmp_container
[ユーザ名@NAS名 アプリケーション名]$ 

同様に、他の2つの名前付きボリュームにもコピーしておきます

[ユーザ名@NAS名 アプリケーション名]$ docker run -d --name tmp_container -v rcmail_www:/data busybox tail -F /dev/null
af2454e5010061c4d4fae5ff27d8ac7245a78716f3e8a72abf94b078b2ab3e28
[ユーザ名@NAS名 アプリケーション名]$ docker cp www/. tmp_container:/data/
[ユーザ名@NAS名 アプリケーション名]$ docker stop tmp_container
tmp_container
[ユーザ名@NAS名 アプリケーション名]$ docker rm tmp_container
tmp_container
[ユーザ名@NAS名 アプリケーション名]$ 
[ユーザ名@NAS名 アプリケーション名]$ docker run -d --name tmp_container -v rcmail_sqlite:/data busybox tail -F /dev/null
e5326f49e14e4a2847611ed41c4d796181a975d8cd2414defe69adf6fe0e544e
[ユーザ名@NAS名 アプリケーション名]$ docker cp db/sqlite/. tmp_container:/data/
[ユーザ名@NAS名 アプリケーション名]$ docker stop tmp_container
tmp_container
[ユーザ名@NAS名 アプリケーション名]$ docker rm tmp_container
tmp_container
[ユーザ名@NAS名 アプリケーション名]$ 

なお、バインドマウントの data と db については、そのサブフォルダをコピーしている点、ご注意ください。

アプリケーションの再起動

ここまでできたら、docker-compose.yml を変更して、名前付きボリュームを使って起動するようにしてみます。

コンテナイメージにタグ付け

その前に、いまのコンテナイメージにタグ付けを行っておきます。この後 Roundcube のアップデートなどをやり始めると、コンテナイメージをいろいろと変更することになるので、現状動作しているイメージを見失わないようにするためです。

【Docker】イメージ名とタグ名を変更する方法 | エンジニアの眠れない夜

まずは、対象となるイメージのイメージ ID を調べます。

[ユーザ名@NAS名 アプリケーション名]$ docker images
REPOSITORY                  TAG                         IMAGE ID       CREATED         SIZE
myroundcube                 latest                      664cbf63c985   10 months ago   596MB
[ユーザ名@NAS名 アプリケーション名]$ 

イメージIDがわかりましたのでタグをつけます。

[ユーザ名@NAS名 アプリケーション名]$ docker tag 664cbf63c985 myroundcube:0.1

タグが変わったことを確認します。

[ユーザ名@NAS名 アプリケーション名]$ docker images
REPOSITORY                  TAG                         IMAGE ID       CREATED         SIZE
myroundcube                 0.1                         664cbf63c985   10 months ago   596MB
myroundcube                 latest                      664cbf63c985   10 months ago   596MB
[ユーザ名@NAS名 アプリケーション名]$ 

無事変わったというか、タグが増えてますね。

アプリケーションの起動

QNAP の Container Station から『アプリケーション』を選択し、いま動いているアプリケーションを選びます。歯車アイコンをクリックし、『再作成』を選びます。

docker-compose.yml を入力する画面が表示されるので、下記のようにします。

version: '3'

services:
  https-portal:
    image: steveltn/https-portal:1.23.1
    ports:
      - 'xxxx:80'
      - 'yyyy:443'
    restart: always
    volumes:
      - rcmail_ssl_certs:/var/lib/https-portal
    environment:
      DOMAINS: 'xxxx.yyyy.zzzz -> http://roundcubemail:80'
      STAGE: 'production'
      # FORCE_RENEW: 'true'
      CLIENT_MAX_BODY_SIZE: 0
  
  roundcubemail:
    image: myroundcube:0.1
    container_name: myrc
#    restart: unless-stopped
    volumes:
      - rcmail_www:/var/www/html
      - rcmail_sqlite:/var/roundcube/db
#    ports:
#      - 9001:80
    environment:
      - ROUNDCUBEMAIL_DB_TYPE=sqlite
      - ROUNDCUBEMAIL_SKIN=elastic
      - ROUNDCUBEMAIL_DEFAULT_HOST=ssl://メールサーバー名
      - ROUNDCUBEMAIL_DEFAULT_PORT=ポート番号
      - ROUNDCUBEMAIL_SMTP_SERVER=ssl://メールサーバー名
      - ROUNDCUBEMAIL_SMTP_PORT=ポート番号
      - ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE=30M

volumes:
    rcmail_ssl_certs:
        external: true
    rcmail_www:
        external: true
    rcmail_sqlite:
        external: true

以前のものと比較して

  • バインドマウントではなく、ボリュームを指定した
  • アプリケーションのイメージのタグをバージョン番号まで含めて指定した

という点が主に異なる点になります。

入力が終わったら、『更新』ボタンを押します。

しばらく待つと、既存のアプリケーション(およびコンテナ)の削除が行われ、続いて作成が行われます。なお、画面上の進捗表示がうまく更新されないことがあるようで、しばらく待っても変化がないような場合は、 ContainerStation 自体を一度閉じてから再度開くと進展がある場合があります。

エラー等がなく無事に起動したら完了です。 あとは、 Roundcube にログインして、問題なく動作するか確認しておきます。特に問題もなく無事に動いていました。

まとめ

これで、永続データを(狭義の)ボリュームに移行できたので、次は Roundcube 自体のアップデートを行ってみたいと思います。

DNS のワイルドカードレコードについて

先日、DNSのワイルドカードレコードを設定しているネームサーバーで、 TXT レコードを追加したら、一部のサブドメインでアクセスできないという事態になりました。

これ、調べてみると、 DNS のワイルドカードレコードを使っている時に起こるもののようです。

blog.future.ad.jp

知りませんでした・・・。ということで、知識としては上記の記事で事足りるのですが、改めて自分でも手を動かしていろいろと確認したので、それらをメモっておきます。

DNS のワイルドカードレコードとは

ホスト名のところに、ワイルドカード『*』を使うことによって、いちいちサブドメインを指定しなくても、該当レコードを引くことができる機能とのことです。例えば、

test.mori-soft.com     IN A 192.168.0.1
*.test.mori-soft.com   IN A 192.168.0.2

のようにしていれば、 sample.test.mori-soft.com も mail.test.mori-soft.com も 192.168.0.2 に解決できるというものです。これは便利ですね。

詳しくは、下記なども参照してください。

ワイルドカードドメインの挙動について #dns - Qiita

どの種類のレコードに使うことができるのかは、ネームサーバーによって微妙に異なっているようです( RFC 見れば仕様としてわかるんでしょうが、ま面倒なので端折ります)。いくつかの会社さんを眺めてみると、たいていは、

  • A
  • AAAA
  • MX
  • CNAME

あたりは問題なく使えるっぽいです。ほかの種類のレコードはネームサーバーによってまちまちっぽいです。

例えば、お名前.com ならこちらのページに記載があります。ただ、私も使っているさくらインターネットの場合は、残念ながらワイルドカードレコードについての記述は見つけられませんでした(が、後述するように少なくとも CNAME では使えました)。

実験

ワイルドカードレコードについて勉強するのはこれぐらいにして、早速実験してみます。実験は、自分のドメインの mori-soft.com を使ってやります(さくらインターネットのネームサーバーで管理しています)。

なお、さくらインターネットの場合、ワイルドカードレコードの記述が無かったので最初ワイルドカードレコードが使えるかわかりませんでしたが、下記のページ

ドメインコントロールパネルについて知りたい | さくらのサポート情報

の使える文字のところに、アスタリスクが入っていたので、多分使えるだろうなとアテをつけ、サポートに聞いてみたところ、使えるとのことでした。よかった、よかった。

準備

さくらインターネットの『会員メニュー』から『ドメインコントロールパネル』を開きます。自分のドメイン mori-soft.com のゾーン情報の編集を使って、

  • エントリ名: *.test
  • タイプ: CNAME
  • 値: www.mori-soft.com.

という感じでワイルドカードレコードを追加しておきます。

レコードを保存して、しばらくたってから、ワイルドカードレコードが正しく動いていることを確認します。

mor@DESKTOP-DE7IL4F:~$ dig a.test.mori-soft.com

; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> a.test.mori-soft.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3957
;; flags: qr rd ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;a.test.mori-soft.com.          IN      A

;; ANSWER SECTION:
a.test.mori-soft.com.   0       IN      CNAME   www.mori-soft.com.
www.mori-soft.com.      0       IN      CNAME   nervous-morse-2798ce.netlify.com.
nervous-morse-2798ce.netlify.com. 0 IN  A       52.74.166.77
nervous-morse-2798ce.netlify.com. 0 IN  A       46.137.195.11

;; Query time: 59 msec
;; SERVER: 172.31.224.1#53(172.31.224.1) (UDP)
;; WHEN: Thu May 16 13:25:17 JST 2024
;; MSG SIZE  rcvd: 216

mor@DESKTOP-DE7IL4F:~$

別の b.test.mori-soft.com も試します。

mor@DESKTOP-DE7IL4F:~$ dig b.test.mori-soft.com

; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> b.test.mori-soft.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55787
;; flags: qr rd ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;b.test.mori-soft.com.          IN      A

;; ANSWER SECTION:
b.test.mori-soft.com.   0       IN      CNAME   www.mori-soft.com.
www.mori-soft.com.      0       IN      CNAME   nervous-morse-2798ce.netlify.com.
nervous-morse-2798ce.netlify.com. 0 IN  A       52.74.166.77
nervous-morse-2798ce.netlify.com. 0 IN  A       13.251.96.10

;; Query time: 19 msec
;; SERVER: 172.31.224.1#53(172.31.224.1) (UDP)
;; WHEN: Thu May 16 13:59:55 JST 2024
;; MSG SIZE  rcvd: 216

mor@DESKTOP-DE7IL4F:~$

どちらも、 www.mori-soft.com が CNAME として得られ(さらに、それが CNAME になっていて最終的に、 netlify でホストしてるアドレスになっ)ています。ワイルドカードがちゃんと動作してますね。

TXT レコードの追加

次に、不具合を再現するために、ゾーン情報を編集します。

  • エントリ名: default.a.test
  • タイプ: TXT
  • 値: wildcard test

という感じで、 TXT レコードを追加します。

すると今度は、 a.test.mori-soft.com に対しては

mor@DESKTOP-DE7IL4F:~$ dig a.test.mori-soft.com

; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> a.test.mori-soft.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55223
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;a.test.mori-soft.com.          IN      A

;; AUTHORITY SECTION:
mori-soft.com.          3600    IN      SOA     master.dns.ne.jp. tech.sakura.ad.jp. 2024051603 3600 900 3600000 3600

;; Query time: 19 msec
;; SERVER: 172.31.224.1#53(172.31.224.1) (UDP)
;; WHEN: Thu May 16 14:03:08 JST 2024
;; MSG SIZE  rcvd: 116

mor@DESKTOP-DE7IL4F:~$

となり、名前の解決をすることができなくなります(ANSWER セクションが 0 件)。ですが、もちろん、 default.a.test.mori-soft.com の TXT レコードに対しては

mor@DESKTOP-DE7IL4F:~$ dig default.a.test.mori-soft.com txt

; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> default.a.test.mori-soft.com txt
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46278
;; flags: qr rd ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;default.a.test.mori-soft.com.  IN      TXT

;; ANSWER SECTION:
default.a.test.mori-soft.com. 0 IN      TXT     "wildcard test"

;; Query time: 59 msec
;; SERVER: 172.31.224.1#53(172.31.224.1) (UDP)
;; WHEN: Thu May 16 14:03:50 JST 2024
;; MSG SIZE  rcvd: 100

mor@DESKTOP-DE7IL4F:~$

のように DNS レコードを引くことができます。

また、 b.test.mori-soft.com に対しては

mor@DESKTOP-DE7IL4F:~$ dig b.test.mori-soft.com

; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> b.test.mori-soft.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38340
;; flags: qr rd ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;b.test.mori-soft.com.          IN      A

;; ANSWER SECTION:
b.test.mori-soft.com.   0       IN      CNAME   www.mori-soft.com.
www.mori-soft.com.      0       IN      CNAME   nervous-morse-2798ce.netlify.com.
nervous-morse-2798ce.netlify.com. 0 IN  A       13.251.96.10
nervous-morse-2798ce.netlify.com. 0 IN  A       13.215.144.61

;; Query time: 19 msec
;; SERVER: 172.31.224.1#53(172.31.224.1) (UDP)
;; WHEN: Thu May 16 14:04:21 JST 2024
;; MSG SIZE  rcvd: 216

mor@DESKTOP-DE7IL4F:~$

のように、変わらずDNSレコードを引くことができます。

理由

ワイルドカードレコードがある場合の名前解決方法ですが、JPNIC のこちらの記事にある

具体的には、問い合わせクラスが一致し、問い合わせドメイン名との完全一致がなく、 問い合わせドメイン名と最も近い一致がワイルドカードである場合、システムは、 ワイルドカードにあるリソースレコードが問い合わせドメイン名であるとみなして、 問い合わせドメイン名と一致するリソースレコードのセットをその場で合成します。

という方法のようです。

なので、*.test.mori-soft.com というワイルドカードレコードに対して、 a.test.mori-soft.com を問い合わせても、 default.a.test.mori-soft.com のレコードが存在するので、ワイルドカードには該当しない、となっているようです。この時の判定では、レコードの種類は問題になっていないのがポイントですね。

解決方法

解決方法は最初に紹介した記事にもあった

  • エントリ名: a.test
  • タイプ: CNAME
  • 値: www.mori-soft.com.

のように、a.test.mori-soft.com の A レコードを追加しておくというものになります。こうすれば、 a.test.mori-soft.com の問い合わせに対しては、完全に一致するこのレコードがあるので、問題なくアドレスが解決できます。

実際、

mor@DESKTOP-DE7IL4F:~$ dig a.test.mori-soft.com

; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> a.test.mori-soft.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16112
;; flags: qr rd ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;a.test.mori-soft.com.          IN      A

;; ANSWER SECTION:
a.test.mori-soft.com.   0       IN      CNAME   www.mori-soft.com.
www.mori-soft.com.      0       IN      CNAME   nervous-morse-2798ce.netlify.com.
nervous-morse-2798ce.netlify.com. 0 IN  A       13.215.144.61
nervous-morse-2798ce.netlify.com. 0 IN  A       52.74.166.77

;; Query time: 79 msec
;; SERVER: 172.31.224.1#53(172.31.224.1) (UDP)
;; WHEN: Thu May 16 15:06:29 JST 2024
;; MSG SIZE  rcvd: 216

mor@DESKTOP-DE7IL4F:~$

のように解決できるようになりました。

なお、この場合、 sub.a.test.mori-soft.com に対してもワイルドカードレコードが適用されないので、DNSで問い合わせしても、

mor@DESKTOP-DE7IL4F:~$ dig sub.a.test.mori-soft.com

; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> sub.a.test.mori-soft.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 503
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;sub.a.test.mori-soft.com.      IN      A

;; AUTHORITY SECTION:
mori-soft.com.          1882    IN      SOA     master.dns.ne.jp. tech.sakura.ad.jp. 2024051604 3600 900 3600000 3600

;; Query time: 0 msec
;; SERVER: 172.31.224.1#53(172.31.224.1) (UDP)
;; WHEN: Thu May 16 15:06:58 JST 2024
;; MSG SIZE  rcvd: 120

mor@DESKTOP-DE7IL4F:~$

のように NXDOMAIN が返ってきます(これは、 a.test.mori-soft.com のレコード追加前も後も同じです)。なお、sub.b.test.mori-soft.com は問題なくひけます。

まとめ

最初に書いた現象を再現することができました。ワイルドカードレコード、便利だなと思っていたんですが、ちょっと気を付けないとはまるかもしれませんね。