メールファイルのOS上のタイムスタンプをメールヘッダ内のタイムスタンプに変更するサンプルプログラム

先日書いたiPhoneのメールアプリのタイムスタンプが狂う問題を修正を目的とした、Yuaiho作成のサンプルプログラム(Perlスクリプト)を配布します。サンプルを名乗ってますが、一応Yuaihoが実際に使っているスクリプトです。

配布用にコメントやメッセージ出力は割と手直しはしていますが、アルゴリズム的にはそのままです。


配布先

※免責事項は本記事の下部にあります。
ダウンロード from yuaiho.com
ダウンロード後、拡張子をplなどに変更して、実行権限を与えてください。

年月日時分秒からEpoch秒を求めているため、Timelocalモジュールが必要です。

メールファイルのファイルリスト一覧を標準入力で送り込むと、メールファイルを1つづつ開いて読み込み、Receivedヘッダ、もしくはDateヘッダからタイムスタンプを取得します。


使い方

使い方は下記の一番上の行のように、タイムスタンプが狂ったメールファイルが存在するメールボックスのcurディレクトリから呼ばれることを想定しています。

$ find ./ -type f | /tmp/dateperse.pl --debug --commit
$ ls -1 | /tmp/dateperse.pl --commit --noinfo
$ cat <filelist> | /tmp/dateperse.pl --debug --commit
$ cat <filelist(Abusolute file path)> | /tmp/dateperse.pl --absolute

引数に--commitをつけて実行すると、本当にファイルシステム上のタイムスタンプを書き換えます。--ommit引数がない場合は、タイムスタンプ書き換えは行わず、&#45;&#45;commitで実行する際のコマンドがテキストで表示されます。

引数に--debugをつけるとDEBUG:メッセージが出力され、より詳細な情報が出ます。ただ、私がデバッグ用に使用していたものそのままなので内容は不親切です。

引数に--noinfoを追加するとINFO:メッセージが出ません。--noinfoを追加してもエラー(ERROR:)が出るとエラーメッセージが出力されます。--commitと--noinfoを組み合わせると、エラー発生時以外は何も表示されなくなります。

標準入力から送られてくるファイルリストが絶対パスの場合は引数に--absoluteをつけてください。送られてくるファイルリストは絶対パスとして処理します。送られてくるパスをそのまま開きます。

引数に--absoluteが無い場合は標準入力から送られてくるファイルリストを相対パスとみなします。標準入力から送られて来たファイルリストの頭に、スクリプト実行時のシェルののカレントディレクトリを付け足してからファイルを開きます。

引数に-h --usage --helpを入れるとAboutメッセージと使い方が表示されます。

ファイル内に処理すべきタイムスタンプを含むヘッダが見当たらないファイルは--commitを入れて実行しても時刻変更の処理はされません。

下記は引数なしの出力例です。緑が--commit時に実行されるコマンドです。これがファイル数分出力されます。

$ find ./ -type f | /path_to_app/dateperse.pl
-----
INFO: Executing file "/path_to_maildir/cur/./1486390265.M692487P75574.mail.yuaiho.net,S=1962,W=2000:2,S"
INFO: Header read: 2003-08-02 12:58:24+0900 -> Final destinaiton time: 2003-08-02T12:58:24
/usr/bin/touch -d 2003-08-02T12:58:24 "/path_to_maildir/cur/./1486390265.M692487P75574.mail.yuaiho.net,S=1962,W=2000:2,S" >> /dev/null
-----
※ファイル名は一部架空のものです。

動作の前提となる条件

メールは下記を満たしていることを前提に作っています。下記を満たさないファイルを食わせると、不正確なタイムスタンプが生成されたり、プログラムが落ちたりします。微妙に文字色が違う部分の処理はかなり雑に書かれています。

  • タイムスタンプの年表記は西暦4桁表記であること。
  • タイムスタンプの月表記はJan/Feb/Marのように大文字開始の半角英字3文字であること。
  • タイムスタンプの時刻はhh:mm:ddの0フィル有り24時間制表記であること。
  • Date:はヘッダ内に必ず存在し、そこにはタイムスタンプが必ず書かれていること。
  • Received:ヘッダのセミコロンの後には必ずタイムスタンプが存在すること。
  • 時差表記は+hhmmまたは-hhmmで、hhは0〜19でmmは00から15分刻みであること。
  • タイムスタンプは0以上のEpoch秒の範囲で、かつ実在する有効な日付・時刻で、整数表記であること。
    (つまり2000年08月32日とか、25:05:00とか、13:75:00とか、12:00:00.000はダメです。)
  • ヘッダ内に空行が無いこと。
  • ヘッダと本文の区切りは必ず空行であること。

MUA(Mail User Agent/メーラ)を変更しても問題なく読めるメールであれば、基本的に上記を満たしていると思います。たぶん。


主な仕様

使用可能なヘッダ

採用するタイムスタンプは「Received:ヘッダのみ」「Dateヘッダのみ」「どちらか先に見つかった方」の3つを選べます。「$g_pref_mode_header」で設定します。デフォルトでは「どちらか先に見つかった方」です。

Received:ヘッダのみを参照する場合、参照範囲をヘッダ内に絞る設定があります。絞らないと、Received:ヘッダがヘッダ全体を探しても見つからない場合、本文や添付中に書かれたものを拾う可能性があります。これは「$g_pref_mode_parse_headeronly」で設定できます。デフォルトでは絞っています。

Received:ヘッダは1番上にあるもののみを自動的に拾います。そのファイル内にReceived:で始まる行が1つでもあったか(マッチしたか)を検査してるので、最初のReceived:ヘッダより行頭側にタイムスタンプがあっても反応しません。

タイムスタンプの拾い方はかなり手抜きをしてるので注意が必要です。例えば、Feb 31とか26:58:57とかも拾ってしまいます。

あり得ないタイムスタンプを検知して除外するような機能は実装していません。あり得ないタイムスタンプを拾ってしまうとプログラムがエラーで止まります。

ファイル内に利用可能なタイムスタンプが見つからない場合、そのファイルは何も処理されません。処理されない代わりに「ERROR: File “ファイル名” has no valid hedear.」と表示されて次のファイルを処理します。


時差補正

どちらのヘッダを利用していても、最終的なメールサーバの設置場所の時差を勘案したものとなるよう時差補正をかける処理を入れています。

例えばReceived:なりDate:なりのタイムスタンプに00:00:00+0000(UTC)と書かれているメールは、時刻やタイムゾーン設定が正確なら日本時間では09:00:00に受信してサーバのディスクに書き込まれたことになります。

タイムスタンプの時分秒をそのまま信じると00:00:00ですが、UTCの00:00:00であって日本時間の00:00:00なわけではないので、時差を考慮してサーバ設置場所の正しい時刻(ローカルタイム)に補正する必要があります。

このプログラムは読み込んだタイムスタンプを一旦UTCに戻し、そこからプログラム内で設定した時差を追加することで、サーバ設置場所のローカルクロックの示す時刻になるような処理を入れています。この修正用の時差は時差は「$g_pref_tz_sec」で秒単位で設定できます。

私のサーバはUTC+0900(日本)、にありますのでデフォルトは+0900に補正する設定になってます。

この補正値は任意の時間に設定出来ますが、タイムスタンプの日付や時刻によって補正値を変えるような処理には対応してません。つまりDST(夏時間)には非対応です。DST実施国にお住まいの方は適宜改造してくださいです。

+0900 (JST)のように後ろにタイムゾーンや標準時名とかが付いてる場合もありますが、各国の標準時はたまに変わるのでこのプログラムではカッコ内のタイムゾーン名や標準時名は無視しています。というか、たまに付与されてないし。

ちなみに日本標準時であるJSTは1951年から変わってませんが、例えばここ20年のUTC+9だけ見ても2015年に北朝鮮やロシア(イルクーツク)、モンゴルに異動にあり、UTCとの時差が変更になってます。

余談ですが、古いメールだとGMT+0900とかあったと思います。UTCとGMTは厳密な定義の上では異なる存在ですが、時差を示す場合においては同一のものと考えて差し支えありません。


免責事項

サンプルプログラムの利用・改造・転載は公序良俗に反しない限り自由です。事前・事後の連絡も不要ですが、必ず利用者の自己責任で行なってください。再配布の際はオリジナルのAuther名を残していただけると作者としては嬉しいです。

意図的に有害コードを含むようなことはしておりませんが、意図しない不具合を内包している可能性があります。

Yuaihoが実際に使ったプログラムですが、一般の使用に耐えうるような充分なテストがされてるわけではありません。例外処理などももほとんどされていないか、されていても激甘です。そのため実環境に適用される際はよく検証してからご自身の責任で適用してください。間違いや事故があっても責任は取れません

コードが汚い系の批判は、頂いてもたぶん直さないと思います。

サイドチャネル的に作ったので参考文献は特にありません。

iPhoneのメールアプリのタイムスタンプが狂う問題

iPhoneのメールで表示されるタイムスタンプはDateヘッダではなくエンベロープの到着日

理由は知りませんが、iPhoneのApple純正のメールアプリ(※)に表示されるタイムスタンプは、IMAP4を使ってる場合、メールヘッダのDate:ヘッダの中身では無く所謂エンベロープの到着日を表示しているようです。

※インストール時点で入っているApple公式の青いアイコンのメールアプリのことです。

エンベロープの到着日というのはIMAP4のINTERNALDATEに相当するタイムスタンプです。IMAPサーバにloginコマンドでログイン後、SELECTコマンドでメールボックスを選択して「fetch <メール番号> INTERNALDATE」みたいなコマンドを送りつけると返ってくるタイムスタンプです。

a FETCH 1 INTERNALDATE
* 1 FETCH (INTERNALDATE "18-Mar-2010 01:36:12 +0900")
a OK Fetch completed (0.013 + 0.000 + 0.012 secs).
a FETCH 1 SAVEDATE
* 1 FETCH (SAVEDATE "21-Oct-2022 05:38:12 +0900")
a OK Fetch completed (0.031 + 0.000 + 0.030 secs).

このエンベロープのタイムスタンプは私のメールサーバ(※)の場合、下記に示すようにファイルシステム上で、上記のメールに該当するメールファイルの属性値であるBirthかModified属性のいずれかのタイムスタンプがそのまま入っていました(※※)。ちなみにSAVEDATEコマンドの方はChange属性が入っているみたいです。

$ stat -x 1268843772.*****.mail.yuaiho.net:2,S
  File: "1268843772.*****.mail.yuaiho.net:2,S"
  Size: 654          FileType: Regular File
  Mode: (0600/-rw-------)         Uid: (yuaiho/515)  Gid: (yuaiho/515)
Device: 0,112   Inode: 19423***    Links: 1
Access: Fri Oct 21 05:07:10 2022
Modify: Thu Mar 18 01:36:12 2010
Change: Fri Oct 21 05:38:12 2022
 Birth: Thu Mar 18 01:36:12 2010
※ファイル名の一部(FQDN部分)やInode番号、UID/GIDは架空のものですが、それ以外はオリジナルのデータです。タイムスタンプ変更もこのファイルに関しては変更していません。

※FreeBSD13.1+Postfix3.7.3+Dovecot2.3.19.1。投稿日時点の安定版の最新Versionです。互換モードは無効化。
※※BirthかModified属性のいずれか
: BirthとModifiedのどっちを採用してるかは不明です。freebsd-ufs上ではModifiedもBirthも同じタイムスタンプになるため、どちらを見てるのかわかりません。

まぁ要するにMTA(Mail Transfer Agent)やMRA(Mail Retrieval Agent)の独自DBだったりMaildirだったりのどこかに、エンベロープのタイムスタンプが書かれているファイルが別途存在する、というわけでは無いと言うことです。

他のMTAやMRAの組み合わせまでは存じませんが、少なくともPostfix+Dovecotでは前述の通りです。

MRAはMUAからIMAPコマンドでINTERNALDATE相当の問い合わせを受けると、それに該当するメールファイルのファイルシステムのModified or BirthのタイムスタンプをOSに問い合わせて、その結果をエンベロープのタイムスタンプと(いうことに)して送って来てるだけと言うことです。

iPhoneの純正のメールアプリはこのエンベロープのタイムスタンプ、つまりメールファイルがサーバのファイルシステムに書き込まれた時点のタイムスタンプメール受信日として取り扱っています。


iPhoneのメールのタイムスタンプがおかしい理由

と、いうわけで、ファイルシステム上のメールファイルのModified属性のタイムスタンプが狂うと、iPhone上のメールアプリの受信日もその狂ったタイムスタンプになります。

他のメールソフトで見るとタイムスタンプがそれっぽいものがちゃんと表示されているのに、同じメールをiPhoneで見るとタイムスタンプがおかしい場合、たぶんこれが原因です。他のメールソフトはDate:ヘッダをParseして表示していたりするんですが、iPhoneのメールアプリはDate:ヘッダを使って無いっぽいです。

メールファイルのタイムスタンプが狂う起因ですが、例えばメールサーバのシェルなどでメールファイルを直接操作するときに、tar cfpやcp -pとかの属性保存オプションの使用を忘れて雑にcpやtarをしたりすると、コピー先でメールファイルのタイムスタンプがファイル操作実行時点のものに書き変わってしまいます。

エンベロープのタイムスタンプの実態はさっき説明したように、実態はメールファイルの置いてあるディスク(ファイルシステム)に記録されたModified属性です。

そのため、メールファイルのModifiedのタイムスタンプが変更されるような操作をすると、本当のエンベロープのタイムスタンプが虚空に消えると言うわけです。

そして、そんな正しいModifiedのデータが虚空に消え、”管理者が雑にファイルを操作した日”とかいう利用者からするとわけのわからんタイムスタンプが入ったメールファイルを含むメールボックスをiPhoneのメールアプリから見ると、その謎の日付が表示されることになります。


修正方法

さて、リストアする方法ですが、きちんとタイムスタンプが保存されているバックアップが無いなら基本的にはありません。

しかし、メールヘッダ内にあるタイムスタンプが信用できるか、(信用できるかどうかに関わらず)信用することにするなら、メールヘッダに入ってるタイムスタンプを元にしてModified属性の日付時刻に修正することは出来ます。

使用出来るタイムスタンプが入ったヘッダは2つあり、Received:ヘッダとDate:ヘッダです。

具体的には、Received:ヘッダのうち最も行頭に近いところにあるReceived:ヘッダの末尾に付いてるタイムスタンプと、Date:ヘッダに含まれるタイムスタンプのいずれかです。1つのReceived:ヘッダが複数行渡って書かれている場合、その1つのReceived:ヘッダ全体の末尾に書かれたタイムスタンプを使用します。

後述しますが、どちらのヘッダを使っても信頼性はケースバイケースです。特に昔の牧歌的な時代のタイムスタンプはReceived:ヘッダであっても正直怪しいです。

そしてReceived:ヘッダを使う方法は1つだけ制限があって、MUA(Mail User Agent/メーラ)が送信時に直接IMAPフォルダに書き込んだメール、つまりSentフォルダや送信済フォルダの中身には使用できません。これらのメールはSMTPサーバを経由しておらず、Received:ヘッダがヘッダに付与されていないので、Date:ヘッダしか使用できません。

Received:ヘッダ

もっとも行頭に近い部分にあるReceived:ヘッダは、メールリレーの終着点である自分のサーバが付けるので、送信者側から詐称が難しく、適切な時刻管理がされていればかなり正確なのが期待できます。この「適切な時刻管理がされていれば」と言うのがミソで、本当に正確かは終着点のサーバの管理次第です。

自営SMTPサーバを持ってて、そのSMTPがメールリレーの終点であれば1番上のReceived:ヘッダは自分のサーバが付与したヘッダになります。

エンベロープのタイムスタンプは終点のメールサーバにファイルが書き込まれた時刻です。MTA内部でメールスプールがふん詰まったりしない限り、通常はSMTPでメールを受信したら即座にMaildirのあるディスクに書き込まれますので、ヘッダ上の自分のサーバへの到着日をエンベロープの到着日とみなすのは一定の合理性があります。

まぁ、実際のところファイル属性値はミリ秒まで書かれているらしいんでが、SMTPのヘッダは1秒未満(=ミリ秒)の情報が無いのでミリ秒の情報はヘッダから復元出来ません。

そのため時刻管理が正しく行われているサーバのReceivedヘッダを使って修正したとしても実は若干不正確なんですが、それでも±1秒レベルぐらいの精度では合うので、秒以前に年月日すら合ってないようなわけわからんタイムスタンプに比べれば全然マシです。

仮に終点が自分のサーバでなくても、読み込んで時差補正さえかければまぁそれっぽい時間にはなります。

ただ時刻管理が杜撰なメールサーバでは、下手するとDate:ヘッダより不正確です。私の場合、過去のメール調べてみると2000年代前半のものはDate:ヘッダや先頭のReceived:ヘッダとその1つ前のReceived:ヘッダに乖離があるものが結構ありました。

まぁ2000年代前半(5号機時代)の私のサーバは時刻同期(NTP)の管理が杜撰そのものでした。当時はメインで使ってるマシンぐらいしかまとも時刻同期してませんでしたし、合わせ方もNTPではなくSNTPで気が向いた時にたまに合わせるぐらいでした(※)。

※今のモダンなOSは特に設定してなくても明確に止めない限り、w32tmなりntpdなりchronydなりsystem-timesyncdなりのNTPが動きます。

Real Time Clock Due to oddities of the Macintosh hardware interrupt priority scheme, NetBSD/mac68k keeps very poor time. Under a high interrupt load (e.g. SCSI or serial port activity), a machine can lose several minutes per hour. A consequence of this problem is that attempting to run ntpd is generally rather pointless.

https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.3/mac68k/INSTALL.html#Known%20hardware%20issues%20with%20this%20release

ちなみに私の場合、杜撰な時刻同期管理に加えて、5号機で使ってたNetBSD/mac68kは上記のようにIO処理が重いと時計が狂う仕様らしいので正確な要素が全く見当たりませんね。実際、SNTP (ntpdate)で合わせると毎回1〜2時間ぐらいズレてて修正かかってました。

しっかりしたISPなら大丈夫だと思いますが、時刻管理が杜撰なサーバの古いメールだとReceivedヘッダの時刻は怪しいかもしれません。

たた、終点が自分のサーバなら、仮にそのサーバの時刻同期が杜撰で多少ズレていたとしても、1番上のReceived:ヘッダは「サーバに到着した時のサーバの時刻」が書かれてます。その時にサーバはその時刻だったのは間違いはないので、目を瞑れる程度のズレならスルーするしてしまうのがいいと思います。

前述したように、Received:ヘッダを採用する方式の弱点は、MUAから直接IMAPサーバに書き込まれたメール、つまり「Sentフォルダ」や「送信済メール」の中身には適用出来ません

これらのメールは基本的にReceivedヘッダが1つも無いことが多いのでReceived:ヘッダの時刻を適用する方法では修正出来ません。これらのメールに対してはDate:ヘッダを使う必要があります。

Date:ヘッダ

Date:ヘッダはReceived:ヘッダと異なり、メールファイル内で付いていないということはまず無いというメリットがあります。

ただ、Date:ヘッダは送信者の自己申告も容易に出来ます。つまり詐称しやすいヘッダです。よって、必ずしも信用できる値が入ってるわけではありません。これが最大のデメリットです。

ただ、これは私の主観にはなりますが、明らかにおかしいタイムスタンプが付いているケースはゼロではありませんが、実際のところはほとんど見かけません(※)。

また、Date:ヘッダを受信時刻として扱うMUAの実装もあるので、「管理者がファイル操作した時刻」というメールの中身と無関係なタイムスタンプよりは、Dateヘッダのタイムスタンプを使う方がまだマシとは言えます。

※たぶんですが、Date:ヘッダは明らかに詐称してるものがあるのでiPhoneは Date:ヘッダでなくエンベロープを見てるのだと思います。

基本はReceived:ヘッダから時刻を引っ張ってきて、なんらかの理由でReceived:ヘッダのタイムスタンプが明らかにおかしいか、SentフォルダなどでReceived:ヘッダがない場合はDateから復旧すれば良いと思われます。


修正の流れ

具体的な流れはメールファイルのヘッダから読み込んだReceived:なりDate:なりにあるタイムスタンプをParseして、整形して、時差を修正して、touch -dコマンドの引数として利用可能なYYYY-MM-DDThh:mm:ss形式(例:2000-05-15T21:15:09)にします。Yuaihoの場合はtouch -dの引数に入れる時刻はローカルタイム、つまり時差修整を含む日本時間を指定しています。

ちなみに、Date:ヘッダのタイムスタンプはYuaihoの持ってるメールだけでも下記のように割とバラエティがあってParseするが割と面倒でした。もし自分でコードを書くのであればReceived:ヘッダを使う方が楽だと思います。Receivedヘッダの方がバラエティが少ないです。

1. Fri, 28 Apr 2006 15:44:57 +0900 (JST) ※PostfixのReceivedヘッダ
2. Fri, 18 Jul 2003 17:58:36 +0900 ※よくわからんMTAのReceivedヘッダ
3. Thu, 18 Sep 2003 08:00:00 +0900 (JST) ※Dateヘッダ/Receivedヘッダと同じ
4. 18 Jan 2006 15:24:58 +0900 ※Dateヘッダ/曜日がないパターン
5. Wed, 5 Apr 2017 18:02:17 +0900 (JST) ※Dateヘッダ/日の0フィル無し(こっちが一般的)
6. Mon, 03 Mar 2008 12:01:34 +0900 (JST) ※Dateヘッダ/日の0フィル有り
7. Wed, 25 Jan 2006 01:52:30 +0900 ※Dateヘッダ/タイムゾーン名なし

上記は私の古いメールを漁って、タイムスタンプがどんな表記をしているのか確かめた実物です。上記の1と2はReceived:ヘッダのパターンで、3〜7はDate:ヘッダのパターンです。

具体的には1がPostfix、2が自宅サーバで受信していないメールから持ってきた詳細のわからないMTAです。3〜7はDate:ヘッダから目に付くものを持ってきたものです。

Received:ヘッダはJSTなどのTZ名の有無ぐらいしか差がありませんが、Date:ヘッダは曜日がなかったり、TZ名がなかったり、日にゼロフィルがあるなど意外とバリーションがあるのがわかります。

上記をうまくParseして、YYYY-MM-DDThh:mm:ss形式のタイムスタンプ文字列が出来たら、touchコマンドでメールファイルのModifiedを下記のように書き換えます。コマンドを実行するとメールファイルのファイルシステム上のタイムスタンプが変更されます。

[yuaiho@yuaiho.net cur]$ touch -d 2000-05-15T21:15:09 <メールファイル>

こうするとエンベロープのタイムスタンプ、つまりINTERNAL DATEをメールヘッダから読み込んだタイムスタンプに修正できます。

ファイルシステムのタイムスタンプを書き換え終わったら、シェルで書き換えたcurやnewフォルダの上位にあるのdovecotのキャッシュファイルを消します。具体的には dovecot-uidlist dovecot.index.log dovecot-keywords dovecot.index.cache の4ファイルです。curやnewなどのディレクトリを消さないようにしてください。削除後のDovecotの再起動は不要です。

-rw-------   1 yuaiho  yuaiho     15 Jan 14  2021 dovecot-keywords
-rw-------   1 yuaiho  yuaiho   2109 Sep 26 12:11 dovecot-uidlist
-rw-------   1 yuaiho  yuaiho  13332 Sep 29 11:56 dovecot.index.cache
-rw-------   1 yuaiho  yuaiho   3484 Sep 29 11:56 dovecot.index.log

ここまで終わったら、iPhone上でそのフォルダを読み直せばさっき修整した日付になる筈です。全ファイル読み直すので時間はかかります。

iPhoneのメールのメールボックスのリスト上では修整されたのに、メールを開いた際に出てくる日付が修整されてない場合はiPhoneの「設定」→「メール」→アカウントでそのメールボックスを含むアカウントを消してから、iPhoneを再起動し、アカウントをもう一度登録すると直ります。

アクセス制御リスト(ACL)の勘所

多くのNW機器やFW、OS、サーバソフトウェアにはアクセス制御(機構)が実装されています。

このアクセス制御機構は多くの場合、Allow list(ホワイトリスト)やDeny list(ブラックリスト)あるいはその両方を含むルールリスト、俗にいうACL(Access Control List)をもってて、アクセスして来たクライアントのIPやポートと、ACLに書かれているルールを比較して、OK、NGを判別しています。

1つのACLの実装しか扱ってないと中々気がつかないんですが、実はACLの評価方法は実装毎に異なります

実装毎の具体的な仕様は必要になったらその場で調べればいいんですが、少なくとも「実装ごとに評価方法は違う」と言うことだけは知っておかないと、慣れてない実装でACLを操作した時に嵌ります。

ポイント

新しいシステムのACLを操作するなら下記はの3つは確認した方が良いと思います。特にハマりやすいのが最初の2つです。新しい実装を触る場合は確認しておきましょう。

  • デフォルトの挙動(デフォルトポリシー)
  • マッチ後の挙動(ファーストマッチかラストマッチか)
  • ステートフル型かステートレス型か

デフォルトの挙動(デフォルトポリシー)

デフォルトの挙動とは「ACL内で明示したルールにマッチしなかったもの」に対する扱いです。例えば、下記のようなACLのところに10.0.5.15のIPが来た場合ですね。

192.168.0.0/24 → 不許可
172.16.0.0/12 → 許可

たまに勘違いしてる方がいるんですが、「ACLにルールを書いてない=暗黙のDeny(Block)」とは限りません。そう言う実装もありますが、全てではありません。

例えばLinuxで使われてるiptablesやnftables、FreeBSDのipfやpfのデフォルト設定は「暗黙のAllow (Permit)」です。ブロードバンドルータの簡易的なFirewall(FW)もデフォルトはAllowだったりします。Apache HTTPdなんかは自分で定義したOrderで、デフォルトのポリシーがAllowかDenyかが決まります。

まぁ、こんな感じでデフォルトAllowの実装は意外とあります。

デフォルトの動作についてちゃんと確認しとかないと、Allow List(ホワイトリスト)で作ったつもりのFirewallが、Default Allowの所為でガバガバになってて、全くアクセス制御されてなかった。とか言う事故に繋がります。

ちなみに、nftablesやiptablesに関してはデフォルトポリシーをDENYやREJECTに変更出来ます。BSDのpfやipfilterもたぶんできると思いますが知りません。


評価後の挙動(ファーストマッチかラストマッチか)

評価後の挙動とはマッチしたあとどうなるかと言うことですね。言い換えるとファーストマッチ型かラストマッチ型ということです。

下記の例で192.168.0.1のIPアドレスを持つクライアントがアクセスして来た時にどうなるかを考えます。

192.168.0.0/24 → 不許可
172.16.0.0/12 → 許可
192.168.0.1/32 → 許可
※DefaultはDenyとします。

ここで、「192.168.0.1は192.168.0.0/24に含まれるからブロックされる」と解釈するのは早計です。実装や書き方に依存しますので、もちろん正しいこともありますが常に正解とは限りません。

ルールにマッチするとACLの評価が終わって、その後ろに書かれてるリストは無視する実装だと上記の「192.168.0.1は192.168.0.0/24に含まれるからブロックされる」という解釈は正解です。

しかし、一度マッチしても評価が止まらず、最後までリストを舐めて、最後にマッチした条件(ここでは192.168.0.1/32の部分)で許可される実装もあります。中には行末に明示的に書いおいたDefault denyがマッチして結局ブロックされる場合もあります。

これも実装に依存します。特に主流らしい主流も無い気がしますし、BSD PFやipfilterのように、実装によってはルール毎(行毎)に当該行以降の評価をやめる/続けるを制御出来るものをあります。

例えばBSD PFは下記の上の行のようにquickを入れない場合はマッチしても評価が終わらず次の行が評価されます。下側のようにquickを入れるとルールマッチした時点でルールの評価が終了し、後ろのルール群は評価されません(無視されます)。

pass in log proto tcp from 172.16.0.1 any to any port 25
block in log quick proto tcp from 172.16.0.0/12 any to any port 25

※上記の場合172.16.0.1からSMTPへのアクセスはブロックされます。

許可した筈なのに許可されない、ブロックしたはずなのにブロックされてないというケースは、(その製品等にバクが無いなら)この評価の継続性やデフォルトの挙動をちゃんと把握してないか、認識を誤ってます。


ステートフル型かステートレス型か

ネットワーク通信はほぼ全てが双方向ですので、サーバであれば入ってくる方だけでは無く、出ていく通信も許可する必要があります。

例えばIPが192.168.5.15のメールサーバ(SMTPサーバ)で、Source 172.16.0.1:5555⇨Destination 192.168.5.15:25という通信が発生した際に、逆方向の通信、つまりサーバから見てSource 192.168.5.15:25⇨Destination 172.16.0.1:5555の通信を、Inbound通信のSourceやDestinaionを見て自動的に許可するのがステートフル型、そういういいい感じの許可をステートレス型のFWです。かなり雑な説明ですが。

どちらかを採用してるかは実装によりますし、ステートフル型でもあってもステートフルに許可する設定が入ってないと機能しないことがあります。例えばnftablesだと「ct state established related accept」みたいなワードを入れてあげないステートフルに動作しません。

ステートフル型はコネクションテーブルを管理する都合上、必要なメモリや処理量がステートレスより重くなりがちで、CPUやメモリをそれなりにリッチに必要とします。そのため、CPUやメモリがリーンな組込系のシステムでは、ステートレス型のアクセス制御機構を採用していることがあります。

ステートフル型はテーブルを持ってるので逆方向の通信は通信終了かタイムアウトまでは許可されます。逆に、ステートレス型は明示的に逆方向の通信を許可しないと通信が出来ません。

ステートレス型は所謂許可された通信の戻りの通信かどうかを見ていませんので。そのためステーレス側のACLにDefault Denyみたいなの強力なブロック性能を持つルールをステートフル型のノリで入れると、外に向けて提供していたサービスがブロックされて止まったり、目の前のコンソールが固まることがあるので注意が必要です。

ただ、サーバの場合、設計者や運用者によってはOutboundがガバガバの場合なケースがあります。こう言う場合はあまり気にすることはありませんが、Outbound側もより適切にフィルタリングしたい場合は注意が必要になります。

その他の勘所

そのほかにYuaihoが思うACLのハマりを紹介します。

IP重複の可否

これはnftablesなんかが該当するんですが、ACL内部でIP重複を認めない実装もあります。実装にもよりますが、host単位(/32や/128)だけはなく、レンジとして重複してるのもダメな実装もあり、例えば下記のようなルールはnftコマンドで同一セットに入れることはできません。

192.168.0.0/24
192.168.0.1/32

一方、nftablesの前世代にあたるiptablesはIP・IPレンジの重複を許容しています。

そのため雑に作ってて重複管理なんかしていないiptablesの中身を、何も考えずにnftablesに移植してくるとハマります。

どうなるかというと、リストの後ろ側で重複してるものが弾かれて、nftの再起動に失敗するなどしてハマります。というか、私はハマりました

ブロックポリシー・Denyポリシー

ブロックポリシー/DenyポリシーというのはルールなどによってDenyされた時、その後Denyされた通信をどう始末するかです。

よくあるのはDROP(静かにパケット破棄して無視する)するかREJECT(拒絶した旨の応答を返す)するかですね。

REJECTはIP FWだとTCP RST等を返したり、Webサーバ等のアプリケーションの場合は403(Forbidden)のような拒絶を示す応答を返したりすることです。

DROPとREJECTのどちらかが良いかは考え方次第で、結局は自分が何を良しとするかです。これについては他のサイトに説明を譲りますが、いずれにしても下記の3要素は考慮したほうが良いです。

1つめはルータやFWなどのOSの前段でもACLを用いてパケットフィルタリングをしてる場合、前段にあるルータやFWと、後段のOSのIP FWのDenyの挙動は合わせた方がいいです。

前段と後段でDenyの挙動を変えると、「特定のポート以外はREJECTで何か返ってくるのに、特定のポートは何も返ってこない」みたいに挙動になります。

これそのポートには何らかのサービスがあることを暗示することに繋がります。これは管理用のSSH等、隠蔽したいサービスやポートを開いている場合は適切ではありません。

2つめはIP FWでDROPを行うとクライアントがTCP SYN等を再送してくることがあります。FWでSYNの時点でログ出力する設定をしてると、DROPの場合この再送によってログの行数が無駄に増えます。大体2〜3回再送してくるので、これに伴ってDROPログも2〜3倍無駄にに増えます。

体感的な傾向では、攻撃観点ではIP FWの場合はREJECTにしてTCP RST送っておくと即座に諦めてくれることが多いです。ただ、REJECTされてもめげないIPはちょくちょくいます。まじでクソですね。またアプリケーションが行うREJECT場合、REJET(Webなら403 Forbidden等)を出しても諦めてくれるのは期待薄です。

ちなみに、YuaihoはIP FWではDROP派です。上記は一見REJECTを推してますが、Yuaihoが所有する機材はDROPしてることの方が圧倒的に多いです。

3つ目はアプリケーションの場合、DROPを返すと何も方法を与えないことができますが、REJECT応答を返すとそのサービスが稼働してること自体はわかってしまいます。ここでバナー隠蔽などの設定が漏れていると、OSやソフトウェアバージョンなどもわかってしまうことがあります。

最後に

ACLはこんな感じで実装ごとに動作挙動が異なります。

某C社の「暗黙のDeny」は結構有名ですが、「暗黙のDeny」は別にACLの標準仕様でもデファクトスタンダードでもありません。これまで見てきたように、本当に実装ごとに違いますし、なんなら暗黙のAllowも普通にあります。

初めて触れるアクセス制御機構を設定するときは、少なくとも「デフォルトの挙動」「マッチ後の挙動」ぐらいは確認しないとガバガバACLを作る可能性があります。事故った時にシャレにならないことになる方は特に注意しましょう・・・。

大学共通テストの規模は実は日本最大級

センター試験の後継の共通テストの出願が始まったみたいです。50万人ぐらい受けるみたいです。

私はこの手の試験を受けたことあるんですがまぁトラウマ級に嫌いですね。まぁそれはいいとして、記事をよく見ると未だにペーパー使ってるんですね。何か宗教上の理由でもあるんでしょうかね。令和になって4年も経つのに不思議です。


大学入学共通テストは1開催あたりで計算すると約50万人/回という日本最大級の受験者数を誇る試験です。ここ(資格部)に各資格の受験者数の統計がありますが、50万人/回超に達する試験は英検と漢検だけです。規模としては漢検が日本最大と言ってもいいのでは?と思います。

英検は1開催に日程が7日とかアホほどあるので、日程あたりでは数は少なくなりますね。TOEIC全体では260万人と多いのですが、この試験は年8回あるので平均的に分散していると仮定すると1開催だと30万人前後です。それでも結構多いですけどね。同様の理由で運転免許試験も1開催あたりの人数は少ないと思われます。

ちなみに国家試験では情報処理試験の2022年春がおよそ167,000 [人](情報処理推進機構)、宅建の2021年度が256,000 [人](不動産ニュース)です(申込者基準、1000未満端数切り捨て)。

宅建は今の所年1回実施ですので、数の規模としては(運転免許試験や)IPAが多いですが、1回あたりの人数は宅建が多いことがわかりますね。5chに資格板というのがあるのですが、盛り上がりが大きい試験もやはりこの2つかなと思います。

ちなみに(2013年のセンター試験の国語で出題されスピンスピンで一躍有名になった)牧野信一の「地球儀」は青空文で全文を読みましたが、残念ながら私にはスピンスピンも含めて一体何が面白いのかいまいちわかりませんでした。この作品では自己満足のために高速回転させるという、作品のタイトルになっている割には雑に扱われてる地球儀ですが、実は今でも製造には手間のかかる贅沢な逸品(YouTube)です。

拠点間OpenVPNはNGN経由で繋ぐと結構速い

 Yuaihoは実家と自宅の両方にPCやネットワークを持っていて、NGN経由のVPNで(ほぼ)常時接続されています。ほぼと言うのはVPNルータはただのLinuxマシンなのでyumとかでOSのメンテナンスした後にリブートかけると切れます。

 VPNで拠点感同士を接続してるNWは昔は実家も自宅もOCN経由でしたが、まだOCNにUpload 30GB制限があった時代に1TBぐらい転送したら怒られたので、2010年代終わりぐらいからNGNで接続しています。今のOCNは転送制限が廃止されているので制限無く垂れ流せますが戻る気はありません。

 まぁ、実際はNGNに行き着く前に、転送制限が無くて安いISPを色々使ってみたのですが、速度に難がありました。色々試してみて、結局NGN経由ならISP不要で維持費がかからないのでNGNに落ち着きました。

 どことは言いませんが、ひどいISPは夜間がADSLより遅くて「これが噂に効く光ナローバンドか…実在するんだな」と思ったことがあります。


 NGNはフレッツユーザであれば漏れなく接続されてます。そして実はNTT東日本管内or西日本管内であれば(IPv6さえわかれば)、ノード同士を直結出来ます。しかも現時点ではNGN内は事実上、帯域制限も転送量制限も無くて流し放題です。

 ただ、NGNはNTT東とNTT西では分断されてますので、東京に実家があって、大阪に自宅があるのでそれをNGNだけでつなぐというのは無理です。

 しかし両拠点がNTT東日本内、またはNTT西日本内であれば両拠点にIPv6オプションつけるだけでノード間をIPv6で接続できます。両拠点のIPv6オプションさえつけとけばそれ以外の申請は不要です。


 このオプションは月額は無料なんですが、フレッツスクエアというIPv4で繋ぐのが結構難しい所経由で申請しないと、(つまり電話などで申し込むと)申請手数料が2,000円ぐらいかかると言う曲者です。

ISP契約は不要ですが以下の制限はありますね。
・NGN網内はIPv6しか使えません。
・IPv6のISP契約がないとNGNだけではIPoEでIPv6でインターネットには接続できない(※)。
※IPoEで出来ないという意味であってPPPoEでIPv6のインターネット接続はできます。

NGNのIPv6はルータが適切に設定されていれば、ルータのWAN側を繋ぐだけで/64がICMPv6 RAで降ってきます。降ってくるIPv6のブロックサイズは電話などの契約してるオプションによっても変わるみたいですが、ほぼ素の契約だと/64が降ってきます。

/64の場合、左側64bitは契約変えるとか引っ越すとかが無い限りほぼ固定です。私も数年変わってません。ユーザが任意に設定できるのは右側64bitのみです。ちなみに<自分に割り当てられた/64>::fffeがNGN側のGWっぽいです。

IPv6の右側の生成はIPv6を使う機器次第ですが、面倒なら機器側で固定してしまうか、SoftEtherで有名な登遊大氏がNGNで使えるDynamic DNSを作られてる(i.open.ad.jp)ので、そちらを使うのも一手です。NGN内のフルリゾルバでも引けますし、Pingで更新できて便利です。


VPNは私の場合、OpenVPNを使っていて拠点同士はL3接続しています。実家側をサーバにしています。

OpenVPNは少なくともトンネル掘る側(WAN側)はIPv6に対応していますので、今までIPv4で接続していたのであればOpenVPNクライアント側のOpenVPNのremoteをIPv6アドレスに書き換えれば、IPv4からそのまま移行可能です。ただ、WAN側をIPv6のTCPで繋ぐ場合は「proto tcp-client」にしないとダメ(proto tcpではダメ)っぽいです。

OpenVPN同士がIPv6で、各拠点のLAN内はIPv4 Onlyでも特に問題なく繋がります。WAN側がIPv6でもちゃんとPeer to PeerのGWはIPv4ですし、向こうの拠点のIPv4で接続出来ます。

NGN経由だとIPoEになりますので、フレッツ接続時とはMTU/MSSが異なります。IPoEは1,500 [Byte]ですが、フレッツはIPv4の場合1,454 [Byte]前後なので基本的にフレッツ接続時よりもMTUやMSSや大きくなります。チューニングされてる場合は見直すと速度が出るかもしれません。

OpenVPNのMTUやMSSの設定は私も色々勉強して、『IPヘッダーが入るから4 or 20 [Byte]引いて〜』みたいに計算してチューニングやりましたが、(24時間帯域いっぱいまで送受信する必要があるとかでなければ)ぶっちゃけOpenVPNによる自動決定が1番楽で、速度も十分です。

1バイト単位でカリカリに詰めてチューンしても、PONなりマンション内のスイッチなり、自分のNWなりの同時接続者の使用帯域変動の方が大きくてまともな効果測定が出来ません。そのため、24時間帯域をいっぱいいっぱい使って最大限効率的に送受信したいとかの需要がないなら、カリカリに詰めるのを頑張るよりも利用者少ない深夜に送る方が断然速いです。

NGN網はセキュリティのことをガン無視なら向こうの拠点のIPv6打ち込めば直結出来ますが、私は一応暗号化しておきたいのでOpenVPNを入れています。OpenVPNのオーバーヘッドは正確に計算したわけではありませんが大体8〜9%です。まぁ小さくはないですね。Wire Guardにしたらどうなんだろう?とは思います。

この方法は応用すると距離による遅延を気にしないなら、実家だけISP契約しておいて、自分はNGN VPN経由で実家のISP使うとかも出来ます。LAN内のDefault GWを全部VPNルータに向けてしまえばいいんですね。通過するノードの経路設定を正しく行う必要はありますが。


NGN網内が素通りできるのはNTTはあまり表立っては言っていませんが、レンタル可能なHGWのマニュアルを見るそういう通信が出来そうだというがちゃんと書かれてます。

IPv6セキュリティのレベル (初期値: 標準)
IPv6セキュリティのレベルを設定します。
「標準」
NTT東日本のフレッツ 光ネクスト網内で折り返す通信(NTT東日本との契約により可能となるもの)を許容します。
「高度」
NTT東日本のフレッツ 光ネクスト網内で折り返す通信(NTT東日本との契約により可能となるもの)を拒否します。
※セキュリティレベルを「高度」に設定し、NTT東日本のフレッツ 光ネクスト網内で折り返す通信(NTT東日本との契約により可能となるもの)を行う場合には、個別に通信を許容するパケットフィルタルールを設定の上、ご利用ください。 

PR-500KI / RS-500KI / RT-500KI 機能詳細ガイド NTT東日本, 2022.09.03閲覧

このマニュアルを初めてみた当時はカッコ内のNTT東日本との契約云々の文言は無かった気がしますが、これは言い換えると「NGN網内では、あなたのサブネット外から入ってくる通信が出来ますよー」ってことなんですよね。で、やってみたら出来たと言うわけです。

まぁ、この「IPv6セキュリティのレベル」の設定、「高度」にしても効いてるのか知らないですけどね。見た感じAtermと同じ、NECAT/NECPF製だと思いますが、このメーカのこの画面が出る似たような機種は/64だとNGNにLayer 2接続してLAN内にIPv6ばら撒きませんでしたっけ?って感じです。

私はL2接続されるのが嫌でOpenWrtを使って、NGNに繋ぐルータにNDP/RA Relay modeを入れて接続してしてるですが、NTTのこのHGWの場合、この設定を「高度」にするとNDP/RA Relayモードになるんですかね?まぁ、私はこのHGWは持ってなくて、ONU/VDSLから先は自前の設備なので知らないですけど。

これが出来るのはフレッツだけの話です。auひかりとかNURO光とか、CATV系はNGN網を通らず、ISPに直結なのでこの技は無理です。

 

USB Type-C Dock(非Thunderbolt/PD/GbE/USB3.xポート/4k60Hz)の勘所

先月36号機(モバイルノート)を買ったんですが、USB Type CがThunderbolt非対応だったので、非ThunderboltのType C Dockを2メーカほど買って試していました。なんとなく選び方の勘所がわかった気がするので書きたいと思います。

私の要件はこんな感じです。

  1. HDMIで4K 60Hzで表示できること。
  2. Gigabit Ethernet(GbE)が搭載されていて1Gbps(実効950Mbps)が出ること。
  3. USB3.0が搭載されててその速度が出ること。
  4. DockでPDで受電して、PCに送電できること。

上記の1〜3要件を満たすDockを買うのに、書かれている、または外観上必要があるのは下記のI〜IIIです。

  • I. 4K 60Hz対応が明記されている。
  • II. PC側でのType C + Display Port(以下、DP)1.4対応が必須と書かれている。
  • III. USB3.0以上の端子が搭載されている。

当然ですが出力する側のPCが4k 60Hz、DP 1.4以上(1.3でもOK、1.2はNG)に対応していることや、モニタがHDMI2.0/4k 60Hzに対応していること、LANが1Gbpsでリンク可能などの周辺機器が対応OKなのが前提です。

理由は後述しますが、私と同じ要件のDockを購入される予定なら上記のI~IIIはすべて対応しているのが重要です。

1番目の4k 60Hzの要件ですが、4k 30Hzしか対応してないDockは値段に関わらず普通にあります。しかも、この記事書いている時点では4k 60Hz対応より値段の高い4k 30Hz迄対応のType-C Dockも普通に売ってます。

そのため「4K対応」とだけ書いてあって、肝心の対応周波数書いていないType-C Dockは、4k 60Hzが必須なら買わない方が無難です。

4番目の要件のPDの部分は、PD対応書いてあればまず大丈夫です。ただ、PD受電用のType-CポートがPD専用か、それともUSBポートとしての機能もあるかはDockの機種次第です。

PDは2つトラップがあって「DockにType CがついてるけどPD受電不可」と、「PCからの受電では動作しない(PD挿して外部給電しないととまともに動かない)」という罠がある製品もあります。

DellのDA-300なんかは前者です。1万円近くしたのになかなかのクソ仕様です。後継のDA-310はPD受電できるらしいですが。ちなみに、このDA-300を36号機(hp)に繋いだら普通に画面出ませんでした

あと、PD受電そのものが付いていないDockもあります。購入前によく確認が必要です。


さて、Type-C Dockのモニタ出力部分はほぼ全ての機種がDPをHDMIに変換しています。つまりUSB Type-C の Alternate modeを使って映像データをDisplay Portで送信しています。

これはDisplay port Alternate modeという仕組みを使用しています。

HDMI Alternate mode自体はある(Impress PC Watch)ようですが、HDMIは必要な芯線数(差動ペア数)多いですし1.4までしか対応していないようで、DP変換でいけるならDP変換で良くね?って感じはしますね。対応が遅れたのが普及していない理由とも言われますが、先に出ててもDPに抜かされたと思います。

ナントカ Alternate modeというのはホスト側とデバイス側が交渉(Negotiation)して、お互い合意が取れたら通常はUSB3.xに使用する信号線の一部に、USB信号以外のデータを流してしまおうという規格です。

Thunderbolt(以下、TB)やDPをUSB Type-Cで接続できるのはこの規格があるからです。それぞれ、Thunderbolt Alternate modeやDisplay Port alternate modeなどと呼ばれます。まぁ、PCでは事実上ThunderboltとDisplay PortのAlternate modeの2規格しかありませんが。

Alternate modeには両端USB Type C〜USB Type CのUSBケーブルが必要で、Type Cコネクタのピンの全結線が必要です。つまり両端がType CでもUSB2.0までしか対応しないケーブルや、USB3.2対応でも片端がType C以外のケーブルはAlternate modeには対応しません。Type A〜Type CケーブルのType A部分をType C変換してもAlternate modeでは動作しません。。

これはUSB2.0のType C〜Type Cケーブルや、片端がType C以外のケーブルにはAlternate modeで高速伝送可能な信号線が無いか、充分に入ってないからですね。

USB Power Delivery(PD)も両端Type Cが必須ですが、PDはAlternate modeとは別枠ですのでPD単体ならUSB2.0のType C〜Type CでもOKです。ただ、Type A〜Type Cのコネクタ形状を変換して無理やりUSB Type C〜USB Type Cにしてもダメです。

両端がネイティブでType C対応が必要なのはAlternate modeもPDも同じです。PDは高速伝送可能なペアは必要ありませんが、Type AやType Bなどの端子はPDに必要なCC1/CC2端子が無いから変換ではダメなんですね。


Fig01. USB Type C Receptacle ピンアサイン

さて、そのなんちゃらAlternate modeではUSB Type-Cが必須ですが、そのUSB Type-Cのピンアサインはフル結線だとFig01のようになっていて、USB以外の通信に転用できるのは5対10線、高速4レーン+低速1レーンの合計5レーンです(※1)。

  • (高速用)A2/A3 TX1 (TXp1/TXn1)
  • (高速用)B10/B11 RX1 (RXn1/RXp1)
  • (高速用)A10/A11 TX2 (TXn2/TXp2)
  • (高速用)B2/B3 RX2 (RXp2/RXn2)
  • (低速用)A8/B8 SBU1/SBU2

※この記事でいう1レーンは差動ペア1つのことを指します。PCIeやUSBで言う1レーンは差動ペア2つ(TX1/RX1の1セット)で1レーンと呼びますが、DPは差動ペア1つを1レーンと呼んでるっぽいです。ここでは特記がない限りDP側に併せて差動ペア1つを1レーンと呼ぶことにします。

A2とかB2というはUSB Type Cの端子番号です。高速用・高速レーンとは数Gbps以上の高速なデータ転送レートに対応します。TXnとかRXnはSSTXnとかSSRXn(n=1,2、SSはSuper Speedの略)とも表記されます。ちなみにAlternate modeではRXの差動対でデータを送ったりと元の端子のデータ送受信の方向に関係なく使えます。

要件の2と3にある「Gigabit Ethernet(GbE)が搭載されていて1Gbps(実効950Mbps)が出ること。」と「USB3.0が搭載されててその速度が出ること。」は実は同じ内容で、Type C Dockで1Gbps以上出すには内部的にはUSB3.0以上(〜USB3 Gen2x1、以下USB3.x)で接続されている必要があります。GbEがUSB2.0接続されていると1Gbpsなんて出ませんからね。

Fig02. 内部的な接続(USB Tree Viewで表示)

Fig2.はちゃんと1Gbps出るEthernetポートを積んだDockで、上記のようにType-C Dockの内部にはUSB3.xハブのコントローラ(Fig02では汎用Super Speed USBハブ)があって、配下のPort4にGigabit Ethernetがぶら下がってます。ちゃんとSuper Speedでリンクされてるいるのがわかります。ちなみに、このDockはSD/MicroSDのカードリーダがついていてPort1にマウントされています。

Dockに普通のUSB3.xのType Aポートもある場合、そのポートもその内部のUSB3ハブにぶら下がっています。Fig02のDockの場合、Port2とPort3がそれです。ちなみに機種によってはPD受電のType CコネクタもこのUSB3.xハブにぶら下がっていたりしますがこのDockにはありません。

このようにDockがUSB3.xのハブの機能を持つにはType Cの4+1レーンからUSB3.xに必要な通信線割り当てないといけません。USB3.xはx1規格の場合(つまりUSB3.2 Gen 1×2とかUSB3.2 Gen2x2ではない場合)、高速レーン(高速用の差動ペア)が2レーン必要(※1)です。
つまり、TX1/RX1/TX2/RX2の高速4レーンのうち高速2レーンをUSB3.0通信に割り当てる必要があります。ちなみにUSB2.0部分はAlternateでは通常転用できない(※2)のと、Alternate云々に関係なくあるので考慮から除外します。

※1: 繰り返しですが、実際はUSB規格ではこの作動ペア2レーンのことを1レーンと呼びます。USB3.2 Gen2x2のx2というのはこの差動ペア4レーン全部(USB規格上は2レーンと呼称)を使って実現しています。
※2: 半分嘘で、一部のスマホなどで使われているらしいAudio Alternate modeではUSB2.0のポートを転用しています。もちろんUSBの機能は失われます。ただ、PCでは(Alternateで頑張らなくてもUSB2.0部分にUSB Audio繋げばいいだけなので)使ってないと思います。

Fig03. USB3.xにTX1, RX1を割り当てた場合のピンアサイン

ここではUSB3.xに左側のTX1/RX1(SSRX1, SSTX1)を割り当てたと仮定すると、残ったレーンは下記の3レーンです。つまり映像信号は高速2レーンと低速1レーンの合わせて3レーン以下で送らないといけません。

  • (高速用)A10/A11 TX2
  • (高速用)B2/B3 RX2
  • (低速用)A8/B8 SBU1/2

先ほど、Type C DockのHDMIはDPからの変換と言いました。DPはHDCPなどの映像本体以外の信号のやりとり用として映像転送とは別に信号線が1レーン分必要です。DPではAUX+/AUX-というピン名でアサインされています。Display port Alternate modeではこれにSBU1/SBU2を割り当てます。

Fig04. DPのAux+/Aux-
Wikipedia Display Portの項より引用。2022.08.28閲覧

残ったType Cのレーンは下記の高速レーンが2つです。

  • (高速用)A10/A11 TX2
  • (高速用)B2/B3 RX2

ところで、4K 60Hz、色深度RGB10bit(計30bit)、HDRがない場合のDisplay Portのデータ転送レートは15.68 [Gbps]です。またDisplay Portの1レーンあたりの速度はDisplay Portのバージョンによって異なっており、Wikipediaでは下記の通りとなっています。

Fig05. Display Portの転送速度
Wikipedia Display Portの項より引用。2022.08.28閲覧

DP自体は最大4レーンですので、4k 60Hzに必要な15.68 [Gbps]をType Cで実現するには下記のどちらかで実現する必要があります。
I. DP1.2で4レーン(5.4Gbps x 4レーン)
II. DP1.3 or DP1.4以上で2レーン(8.1Gbps x 2レーン)
※この記事書いた時点ではDisplay Alternate modeで対応するのはDP1.4までです。またUSB4は除きます。

Fig.06 – IのDisplay Port 1.2で4レーン使う場合のピンアサイン例
VESA – DisplayPort(TM) Alternate Mode on USB-C(R) P.23, USB.org, 2022.08.28閲覧
Fig.07 – IIのDisplay Port 1.4で2レーン使う場合(典型的なUSB3.x/HDMI搭載のDock例)
VESA – DisplayPort(TM) Alternate Mode on USB-C(R) P.22, USB.org, 2022.08.28閲覧

私の要件満たすType C Dockの場合、結論としてはIIです。

Fig.07を見るとType Cの高速4レーンのうち、2レーンをすでにUSB3.xに使われています。残った高速2レーンで4k 60Hzに必要な15.68 [Gbps]を出そうとしたらDP1.3 or DP1.4(8.1 [Gbps] per Lane)が必須です。DP1.2(5.4 [Gbps] per lane)だと2レーンでは10.8Gbpsしか出ないので4k 60Hzを出すには帯域が不足です。

まぁ、そもそもUSBポートを持ってるType C Dockで4k 60Hzを出すには、現状、下記の2通りしかやり方がありません。

  1. Display Port 1.2で、USBポートを非実装か実装してもUSB2.0にして、高速4レーンを全部DPに回す(USB3.0は妥協する)。→Fig06のパターン
  2. Display Port 1.4で、高速4レーンのうち2レーンだけをDisplay Port Alternate modeに回して、残った高速2レーンをUSB3.0に回す。→Fig07のパターン

DP 1.2でも4k 60Hzの出力は可能です。ただ、DP1.2で4k 60Hzを出力しようとすると、高速レーンを4レーン全部使わないと帯域が足りません。そのためType C DockでPC本体側、もしくはType C Dock側のいずれかがDP1.2にしか対応しない場合、Dock側の(Thunderboltがない限りは)USBポートは2.0にしかなりません

DP1.2までしかDockが対応していないのに、Dockが「USB3.xが絶対必要!」とネゴシエーションで譲らないなら、映像に関してはDP1.2 x2レーンで接続されます。

DP1.2 x2レーンの最大解像度は4kだと30Hz迄なので、必然的にDockの4k 30Hzまでの対応になります。4k 30Hzは7.73 [Gbps]なので、4k 30HzまでであればDisplay Port 1.2でも高速2レーン(10.8 [Gbps])で伝送可能です。


別の見方をするとUSB3.0ポートがあるのに4k60Hz対応と謳われていなかったり、DP1.4が必要と書かれていない場合は、書き忘れで無ければ下記の可能性があります。

A. 4k 30Hzまでしか対応してない。
B. 4k 60HzにするとUSBが2.0になる。
C. ポートの見た目はUSB3.0だが、内部結線はUSB2.0(詐欺)
D. ちゃんとDP1.4で4k 60Hzに対応しているが、Thunderbolt以外での使用を考えていない。

Cの詐欺パターンで無ければ、4k 60Hz非対応として流通してるType-C DockはAがほとんどだと思います。

AとBはDisplay Port 1.2までしか対応していないパターンですね。

Aは、4k 30Hzまでであれば前述の様にDisplay Port 1.2でも高速2レーンで伝送できるので、4k 30HzとUSB3.0で同時成立させてるパターンです。この記事書いている時点ではこのパターンの製品が多いです。

BはDPでType Cの高速レーン使い切ってて、USB3.xに高速レーンを振る気が無いか、割り振れないパターンですね。ヨドなどの国内市販品でBのパターンは私が調べた限りではありませんでした。

ただ、どことは言いませんが、4k 60Hz対応と書かれてるのに、中のDP/HDMI変換チップのチップ名が書かれてて、そのチップベンダのページ見るとがDP1.2まで対応という中華のType C Dock製品を尼で見たことあります。買ったわけでは無いので動作の真偽の程は謎ですが注意が必要です。

ちなみにDockではなく単なるType-C〜HDMI変換の場合、USBポートがそもそも不要なのでDP1.2で4k 60HzをFig06のパターンで実現している製品も多分にあると思います。

ThunderboltはThudnerboltというプロトコル(実際はPCI Express)でDPもUSBもペイロードとして送受信して、それをPC側やデバイス側で解きます。Thuderbolt自体は4+1レーン全部使い切りますが、あくまでThunderbolt通信であって、DPやUSB3.xはそのThunderbolt通信の上に乗るようなになるのでDPとUSB3.xは併存可能です(※)。

※この説明はThunderbolt対応のUSB Type CにThunderbolt対応機器を接続して、Thuderbolt modeで使う場合の説明です。

Windows Updateで降ってくるIntel Display Driver 27.20.100.9415(2022/07/11)は動作が怪しい。

8月度のWindows Update(以下、WUD)に混じって降ってきた「Intel Corporation – Display – 27.20.100.9415」ですが23号機のIntel UHD Graphics 750では動作が怪しいです(クラッシュしてる)。
※正確には8月度のWUDではなく私の場合は2022.08.07に降ってきてます。

先日のIntel MEの件は、WUDで降ってくるIntel MEより新しいバージョンを当ててやると、WUDで降ってくるバージョンを無視して新しいするようですが、このIntel UHD Graphics 750に関しては後から入れられた方を優先するようです。

Fig1. より新しい31.0.101.3222を入れているのにWindows Updateでは古いバージョンが落ちてくる。
Fig2. Windows Updateが終わると古いバージョンが使われてしまう。

画面は構成が似てて使用するドライバも同じ35号機のIntel UHD Graphics 730ものです。Fig1.のようにこのアップデートより前に最新の31.0.101.3222(Intel)を入れてあったのですが、Windows Updateでは古いバージョン(27.20.100.9415)が降ってきてましたし、Fig2のようにWUD当てたら普通に古いのが使われました。

Fig2のようにでWUDで古いドライバが有効化されても、古いドライバ自体はプリザーブされてますので、もしより新しいドライバを入れてるのであれば、上のFig2.の「ドライバを元に戻す」を選択するとFig3のような「ドライバー パッケージを戻す」の画面が出てくるので、理由を適当に選べば戻せます。

Fig3. ドライバを戻す画面

上のFig2.の「ドライバを元に戻す」のボタンがグレーアウトで押せない場合、面倒ですがIntelの公式ドライバで一度上書きしてから、一旦WUDを受け入れた上で、上記ステップでdevmgmt.msc (デバイスマネージャ)上から「ドライバを元に戻す」で元に戻してください。

Windowsのドライバはたまにハズレドライバが落ちてくるので、安定重視ならGPOで禁止してもいいと思います。ただ、ドライバも脆弱性が出ることがあるので、更新しないのが最善かと言われると微妙なところです。

終戦記念日@2022

終戦記念日ですね。終戦から77年です。
最近は終戦から年数経ちすぎて、教育現場では祖父母に戦争体験をヒアリングして来いって宿題出すと、「私(祖父母)も戦後生まれだからそんなの知らん」って言われるみたいです。

この戦争体験のヒアリングは悲惨さを話してもらうことを主眼にしてるようですが、地域や話者の立場で結構異なるようで、私自身はあまり悲惨な話は聞きませんでした。話さなかっただけの可能性もありますが。

ちなみに私もこの手の宿題を出された記憶があります。理由は忘れましたが何故かスルーして出しませんでした。たぶん纏めるの面倒だったか、発表の日になってやってないことを思い出したかのどっちかだったような気がします。私に当てないで、って思ってたら授業終わってましたw。


今年は行ってないので知りませんが、終戦記念日に靖国神社の最寄駅の九段下駅に行くと、終戦記念日でカーキーの戦時中の国民服や軍服のコスプレした人がウロウロしてることがあってなかなか怖いです。

靖国と言えば、毎年のように閣僚が参拝していますね。私は参拝自体は私費で参拝する分には個人の自由の範疇だと思ってます。自分で稼いだ金をどう使うかは当人の勝手ですしね。公費でやると政教分離の原則に反するとは思いますが。

余談ですが、靖国神社に合祀されているA級戦犯のA級っていうのは学校のクラス分けやオペアンプと同じ単なる分類で、A級だからやばい、高い、というわけでは無いみたいですね。私は合祀の話題はあまり興味ありませんが「へー」とは思いました。

2022年07月度のWindows Updateに含まれるIntel MEはRocket Lake上での動作が怪しい

Windows Updateは8月度が出ていますが、7月度の問題が解消できたのでようやくメインマシンに入れることができました。

Yuaihoは23号機(Z590+Rocket Lake)をメインに使っているのですが、2022年07月に含まれるWindows Updateをを当てたらBSoDが頻発するようになりました。

怪しそうなのを探してみると7月度のWindows Updateに含まれる「Intel – Software Component – 2130.1.15.0」を入れたせいっぽいです。Yuaihoの環境では、ですが。

「Intel – Software Component – 2130.1.15.0」の中身はSkylake以降用のIntel Management Engine(Intel)のようです。

Windows10はパッチを選り好みして入れる方法が事実上ないので(Blacklist化は出来るが面倒なので)、より新しいドライバを入れてからWindows Updateを当てると「Intel – Software Component – 2130.1.15.0」自体はインストールされるもののドライバ自体は新しい方を利用するようです。

Fig1. devmgmt.msc(デバイスマネージャ)

ドライバのバージョンは「devmgmt.msc」の「システム デバイス」の「Intel(R) Management Engine Interface #1」の「ドライバ」タブで確認できます。

Fig2. Intel(R) Management Engine Interface #1のプロパティ

なんかIntelのWebサイトのものと若干違う気がしますが、2130.1.15.0ではないっぽいので細けぇこたぁいいんだよってことで気にしないことにしました。一応、この方法でIntel Managementを更新したら、安定して動作するようになりました。

ちなみに、Fig.2の「ドライバーの更新」で強制的に別のバージョンを使用させることもできるようです。ただ、ネットの記事を読んだだけで試したことがないので本当にできるかは知りません。

割と危なかった秋葉原通り魔事件

 2008年にあった秋葉原通り魔事件の犯人(加藤智大死刑囚)の死刑が今日執行されたみたいですね(産経新聞)。色々ある方もいると思いますが、犯人がこの世からいなくなり一旦幕引きという感じでしょうか。

 この先はまぁ昔話です。

 この事件があったのは2008年06月08日の日曜日です。私は当時15号機を建造中でした。15号機のパーツ一式自体は同年06月04日に秋葉原で買ったですが、稼働前のチェックでmemtestとMHDD(※1)の試験がパスせず、建造が遅れていました。

※1: MHDDとは不良セクタの検査用ソフトで、HDDの全セクタを走査して各セクタ(ブロック?)の読み込み時間を収集するソフトです。50[ms]以上がモリモリ出ると不良品か寿命です。最近というか、AFTになった頃辺りからはこの試験やってないです。

 まぁ、要はメモリとHDDが不良品だったんですね。不良品は交換してもらわないといけないので、この事件があった06月08日に秋葉原に行く予定を立ててました。06月07日は土曜日でしたが色々予定があって行くことが出来ませんでした。

 この当時はよく一緒に秋葉原に行っていた友人(※2)がいて、特に理由がなければなければ06月08日の大体11時ぐらいに集合して一緒に行く予定でした。まぁ、後述のせいで約束してませんでしたが。

※2: ちなみに12号機を一緒に組んだ友人と同一人物。

 で、その秋葉行く予定ですが、前日の06月07日に飲み過ぎてしまって、残念な感じに潰れてしまいました。なんとか家に辿り着いて目が覚めたら、すでに事件が起きたあとの13時過ぎでした。

 目が覚めて『なんか携帯に着信とメールがやったら多いな。誰か亡くなったのかな?』と寝ぼけながら確認すると、心配した親や友人からの大量の着信でした。
 最初はよくわかりませんでしたが、上記の友人から「秋葉原で大変なことになってるよ」って言われてネットか何かで確認したら、秋葉原で通り魔事件があったことを知り、大量に着信があった理由を把握しました。

 まぁ、要するに前日酔いつぶれていなければ時間的にほぼ間違いなく事件に巻き込まれてたってことですね。危なかったです。まぁ前日のは潰れたと言うか実際は酔い潰されたというのが正しいんですが、結果的には助かりましたね。
 ぶっちゃけベンチで寝てた時は死ぬかと思いましたが、道路か担架の上で死ぬかと思ってたor死んでた可能性があるよりは全然マシだったと言うことですね。

 そして、その事件があった時間帯は二日酔いで寝てた(事実上音信不通になっていた)ので事件に巻き込まれてないかとめちゃくちゃ心配されました。親に会うと「あの時はすごく心配したんだぞ。」って今でも言われます。

 後日談というか余談ですが、15号機の建造は急いでいたので、この事件発生後、事件は見なかったことにして、その当日に前述の友人と秋葉原行って不良品パーツを交換しました。

 事件日に交換されたパーツというと何かいわく付きな感じがしなくもありませんが、特に問題なく試験はパスし、15号機は無事06月14日に落成しました。現役だった約8年間も特に大きな問題もなく2016年の引退まで普通に安定稼働してました。まぁCPUがVIA C7なんで遅かったですが。

 そして、事件の後に当日秋葉原に行ったことを聞いた私の父が「事件後に行くなんて何考えてるんだ!」と激おこ憤慨丸だった、と後に母に聞かされました。