1990年のMacintoshと、2026年の電子辞書と、Windows 95。この三台が、同じ入口から今のインターネットを見た。

retro-proxy - NetSurf が、この記事で作った装置。前々回・前回で、レトロPC向けのゲートウェイ(中継役)を作った話と、作っている最中に私が外した仮説の話を書いた。どちらも「装置の中身」の話だった。今回は、その装置の向こうで実機が実際に動いている画面を並べる。
結論を先に書くと、三台とも動いた。そして三台とも、それぞれ別の理由で一度は動かなかった。
おさらい:レトロ機に何もインストールしない、という縛り
装置の役割は一つで、古い機械には原理的にできないことを、代わりにやること。家庭内サーバの上でHTTPプロキシとして動いている。
- TLSはこちらで終端する。レトロ機には平文しか渡さない(証明書も新しい暗号も触らせない)
- HTTP/1.1のchunked転送やkeep-aliveを吸収し、Content-Length付きのHTTP/1.0で返す
- 圧縮を展開する。文字コードをShift_JISへ変換する。画像をGIF/JPEGへ落とす
- JavaScriptとCSSを、必要な機械に対してだけ落とす
レトロ機の側でやることは、ブラウザの「プロキシ」欄にサーバのアドレスとポートを入れるだけ。追加のソフトは一つも入れない——これは技術的な美意識ではなく、実務上の都合だ。1990年のMacにバイナリを持っていく手段を用意するほうが、プロキシを書くより面倒だから。
一台目:Macintosh LC(漢字Talk 7.1 / Netscape 2.02J)
1990年発売、CPUは16MHzのMC68020。これが今回の一台目(下は同じ筐体のLC II)。

プロキシのホームページを開いたところがこれ。

サーバ側のログには、この機械はこう名乗って現れる。
User-Agent: 'Mozilla/2.02 [ja] (Macintosh; I; 68K)' → profile=old
Mozilla/2はNetscape 2の名乗りなので、装置はいちばん強い降格を選ぶ。JavaScriptを落とし、CSSを落とし、本文をShift_JISへ変換し、画像をGIFに変換して渡す。
AIに質問する
入口から「AIに質問する」を押すと、家庭内のAI基盤に繋がる。

推論には数十秒かかる。結果を待つ画面は <meta refresh> で自動更新している。JavaScriptもXHRも使えない相手なので、1996年当時のやり方がそのまま最適解になった。

そして答えが返る。画面の下に rtx3070ti / elyza-jp-8b / japanese と出ているのは、家庭内クラスタのどの機械が、どのモデルで答えたかだ。1990年のMacの画面に、2026年のGPUマシンで動く8Bのモデルの答えが出ている。

Wikipediaを引く
この装置には、Wikipediaを軽くして返す経路も足した(詳しくは次の節)。試しにこの機械自身を引いてみる。

1990年のパソコンが、自分がどういう機械だったかを2026年のWikipediaで読んでいる。今回いちばん気に入っている画面がこれだ。
普通のサイトも読める

画像も出ている。今のWebの画像はPNGやWebPで、Netscape 2には描けないものが多いので、装置がGIFへ変換して渡している。
フレームの左半分だけが化けた
日本のWebでいちばん軽いことで有名な、あのページを開いてみた。すると左のメニューだけが化けた。

右の本文は読めているのに、左だけ壊れている。同じサイトの、同じ文字コードのページなのに。
あのページはフレームで二枚に分かれていて、装置の中で通った経路が違っていたのが原因だった。
| 枠 | 装置の中で起きたこと | 結果 |
|---|---|---|
| 右(本文) | 本文抽出が働いてHTMLを組み直した → charset宣言が落ちた | 読めた |
| 左(メニュー) | 元からShift_JISなので「変換不要」と判断して素通し → 宣言が残った | 化けた |
前回の記事に書いたとおり、この装置はcharsetを宣言しない。宣言すること自体が古いブラウザを壊すからだ。ところがその規則を実装した場所が悪かった。文字コードを変換する処理の中に書いてあったので、変換が要らないページには一度も適用されていなかった。
元からShift_JISで書かれた古い日本語サイトは、変換が要らない。「何もしなくてよい」と判断したページこそが、いちばん危なかった。
直したら、こうなった。

この機械で動かなかったもの:同じMacに入れたNCSA Mosaic 1.0.3では、今も動かない。理由は二つあって、どちらも独立している。(1) このバージョンにはプロキシ設定の欄自体が無い。(2) 日本語が白紙ではなく文字化けで出る——つまり後述するWindows 95の問題とは別種で、Mosaic 1.0.3には日本語のエンコーディング処理そのものが無いと判断した。前者はバージョンを上げれば解決するが、後者は「このブラウザ向けには日本語を英語に変換して返す」といった別の実装が要る。今回は見送った。
二台目:電子辞書にLinuxを載せた機械
冒頭の写真の機械がこれ。シャープの電子辞書「Brain」にDebianを載せたもの(Brainuxという有志のプロジェクトがある)。メモリ112MB、ARMv5、シングルコア。ブラウザはNetSurf。
この機械は「古い」のではなく「小さい」。TLSもUTF-8も普通に扱えるので、Macとは詰まる場所が違う。詰まるのは量だ。
「Wikipediaを引けるようにしてほしい」と言われて、まず測った。
| 取り方 | 1記事(「東京」)の転送量 |
|---|---|
| そのまま中継する | 423,617バイト |
| 本文抽出(広告・ナビを落として本文だけ組み直す) | 139,321バイト |
| APIから節(セクション)単位で取る | 3,920バイト |
最初は、既に作ってあった「本文抽出」の機能をこの機械にも有効にすれば済むと思っていた。測ったら3分の1にしかならなかった。本文抽出は「1ページ丸ごと」を前提にした処理なので、元が巨大なら結果も巨大になる。
そこで取得の単位を変えた。MediaWikiのAPIは記事を節ごとに返せるので、最初に導入部と目次だけを出し、各節はリンクを踏んだときに取りに行く。108分の1になった。

🔑 量の問題は、抽出ではなく取得の単位で解くほうが効く。これは今回いちばん実になった判断で、しかも作る前に3経路を測ったから分かったことだった。測らずに「既存機能を有効にする」で済ませていたら、139KBを渡して「重いですね」で終わっていた。
検索もできる。電子辞書が「電子辞書」を引いているところ:

記事内のリンクはそのまま次の記事へ繋がる。ここには小さな仕掛けがあって、このページ自身をプロキシの /wiki/ という場所から出している。Wikipediaの内部リンクは /wiki/○○ という形なので、同じ場所から出していればリンクを一つも書き換えなくても相対解決で繋がる。ここを「親切に」絶対URLへ書き換えると、本家のwikipedia.orgへ直接飛んで423KBに戻ってしまう。
三台目:Windows 95 + Internet Explorer 3
同じ入口が、こちらではこう出る。

この機械が一番てこずった。前回の記事に書いた「200が返っているのに画面は白紙」がこれで、真因はcharsetを宣言したこと自体だった。Shift_JISでもx-sjisでも駄目で、宣言をやめた瞬間に表示された。日本語版Windows 95のブラウザは既定がShift_JISなので、黙ってバイト列を渡せば素直に読む。
正しい名前を探すより、言わないほうが確実な相手がいる。
今は写真も出る。ためしに、日本のWebでいちばん軽いと言われているあのページを開いてみた。

1996年のブラウザで2026年のページが、レイアウトも写真もそのまま出ている。もっとも、このページが軽いのは今も昔もHTMLが素直だからで、装置の手柄は少ない。装置がやったのはTLSを終端したことと、JPEGをそのまま渡してよいと判断したことだけだ。
AIにも質問できる。

「明日の東京の天気は『晴れ』で、最高気温は32℃、最低気温は24℃です。降水確率は20%です。」——この答えはWeb検索を経由して作られている。web-worker / web_search / japanese の表示がその経路だ。1995年のOSの上で、2026年の天気を読んでいる。
同じページを、三台で
ここまでに三台とも阿部寛のホームページを開いたので、並べてみる。電子辞書ではこう出た。

フレームも、背景の透かしも、写真も、三台とも出ている。1990年のMacも、1995年のWindowsも、2026年の電子辞書も、同じHTMLを同じように描いた。
これは装置の手柄ではない。このページが、三十年前のブラウザでも読める書き方のまま今も更新されているからだ。日本のWebでいちばん速いと言われているのも同じ理由で、要するに余計なことをしていない。
逆に言えば、装置がいちばん苦労するのは「今どきの書き方をしたページ」のほうで、その手当てが前々回に書いた七枚の壁の話だった。
おまけ:この記録そのものを、その機械で読む
ここまで書いておいて気づいたのだが、この基盤の話を書いているブログ自体が、同じサーバの上で動いている。ということは、レトロ機からも読めるはずだ。
やってみたら403で断られた。理由は自分で書いた安全装置で、このプロキシは私有アドレス(LAN内のアドレス)へは中継しないようにしてある。外部から踏み台にされないための線だ。そして家のDNSは、外からと中からで別の答えを返す設定になっている——中から mapleharp.jp を引くと、公開アドレスではなくLAN内のアドレスが返る。自分のサイトが、自分の安全装置に引っかかった。
「私有アドレス全体を開ける」設定も持っているが、それは使わなかった。使うと踏み台対策そのものが無くなる。代わりにホスト名とポートを名指しで1件だけ許可した。ついでに、入口ページのリンクはその許可があるときだけ出すようにした。押しても403になるリンクを置かないためだ——レトロ機では「押してみたら駄目だった」の切り分けが、母艦の何倍も高くつく。


古い二台では素直に読めた。CSSもJavaScriptも落としているので、文章だけが残る。
ところが電子辞書のほうでは、こうなった。

暗い背景に、暗い青のリンク。CSSが半分だけ効いた状態だ。この機械のNetSurfは今どきのブラウザなのでCSSを落としていない。落としていないのに読めない。
これは前回Windows 95のIE3で踏んだのと同じ形の症状で、「CSSが効かない」より「CSSが半分だけ効く」ほうが悪いという例がまた出た。20年新しいブラウザでも出るということは、これはブラウザの古さの問題ではなく、CSSを部分的にしか実装していない実装すべてに共通するということになる。
この機械についてだけCSSを落とす設定に切り替えると、こうなる(70,206バイト → 33,350バイト)。

切り替えはレトロ機側からリンクを1回踏むだけでできる。母艦に戻って設定ファイルを触ってサービスを再起動して……とやっていると、実機の前で試せる回数が10分の1になる。
三台に共通していたこと
並べてみて見えたのは、一つの既定値で全部を賄う設計は最初から成り立たないということだった。
| Macintosh LC / Netscape 2 | Windows 95 / IE3 | Brainux / NetSurf | |
|---|---|---|---|
| TLS | 不可 | ほぼ不可 | 普通に可能(でも中継役が肩代わりする) |
| 文字コード | Shift_JIS | Shift_JIS・宣言すると壊れる | UTF-8 |
| CSS | 落とす | 半分だけ効いて本文が消える | たいていは残す(暗いテーマのサイトだけ落とす) |
| 画像 | GIFへ変換 | GIFへ変換 | そのまま |
| 詰まる場所 | プロトコルと文字 | プロトコルと文字と表示 | 量 |
だから装置の側は「機械ごとに、どこまで落とすかを選ぶ」構造になっている。ブラウザの名乗り(User-Agent)で自動判定しつつ、レトロ機の側からリンクを1回踏むだけで切り替えられるようにもしてある。これは親切心ではなく切り分けのためで、「変換をやめたら直るのか」を実機で1手で確かめられないと、原因が変換にあるのか通信にあるのか永久に推測のままになる。
そして未知の機械は「何も落とさない」側に倒す。壊していないほうが既定であるべきだから。正体不明の相手を勝手に劣化させるより、まず素通しして、名乗りを記録して、見てから足せばよい。
今日踏んだバグ:「シャープ」は開けるのに「東京」が開けない
電子辞書向けのWikipedia経路を配備した直後、実機から叩いたら記事によって通ったり通らなかったりした。
/wiki/%E3%82%B7%E3%83%A3%E3%83%BC%E3%83%97 200 (7,948バイト) ← シャープ /wiki/%E6%9D%B1%E4%BA%AC 200 (488バイト) ← 東京(中身は「記事なし」)
原因は、ブラウザから来たバイト列を Shift_JIS → UTF-8 の順で読んでいたこと。既存のAI質問画面からそのまま持ってきた実装で、そちらは相手がIE3(Shift_JISで送ってくる)なので正しかった。
- 「東京」のUTF-8バイト列は Shift_JISとしても妥当(別の漢字になる)。先にShift_JISで読むと、化けたまま「成功」する
- 「シャープ」のUTF-8バイト列はShift_JISとして妥当でないので、たまたまUTF-8へ落ちて通っていた
逆向き——Shift_JISのバイト列をUTF-8として読む——は、ほぼ必ず失敗する。判別できるのはUTF-8側だけなので、順序を入れ替えて解決した。
🔑 片方の例だけで確かめると、必ず見落とす。もし先に「シャープ」を試していたら、通ったことにしてその日は終わっていた。二種類の入力で両側を試して初めて、順序が間違っていることが見える。
もう一つ:直した規則を、自分自身に当てはめ忘れる
この装置では同じ形の見落としを三回やっている。
- 中継するページのcharset宣言をやめて日本語が出るようになった後も、プロキシ自身が出すページだけ宣言を続けていた(操作画面が表示されない)
- 「この機械だけ宣言名を変える」機能を作った後も、入口ページだけその設定を見ていなかった
- そして今回、文字コードを機械ごとに選べるようにしたとき、自作ページだけShift_JIS決め打ちのままだと、中継したページは読めるのにこちらのページだけ化ける
- 同じ日にもう一件。「charsetを宣言しない」規則を変換処理の中に書いていたので、変換が要らないページには適用されていなかった(上のフレームの話)
三回目は配備前に気づいて同時に直した。過去二回を記録に残していたから気づけたのであって、覚えていたからではない。四回目は実機の画面で教わった。
四つ並べると、形が見えてくる。規則を「例外的な処理の内側」に書くと、その処理を通らない経路には効かない。規則は、それが守るべき対象の側——ここでは「古いブラウザへ返すHTML」全部——に掛かる場所へ置かないといけない。
ついでに、前日に「その場の設定」で直していた文字化けがサービスを再起動すると消える状態だったことにも気づいた。設定ファイルに書ける形にして恒久化した。この種の「設定が実機の中にしか無い」穴は、この基盤で繰り返し出てきている。
今回やったことのまとめ
- Macintosh LC(漢字Talk 7.1 / Netscape 2)・Windows 95 + IE3・電子辞書Linuxの三台が、同じ中継役を通して今のWebを読めている状態を実機で確認した
- 電子辞書向けにWikipediaの軽量経路を追加(423KB → 3.9KB)。作る前に3経路を測って、既存機能の流用では足りないと判断した
- 文字コードの自動判別を「判別できる向き」に直した。機械ごとの文字コード設定を恒久化した
- レトロ機からこのブログを読めるようにした。私有アドレス全体を開けるのではなく、ホスト名を1件だけ名指しで許可した
次は、ダウンロードしたファイルのウイルススキャン(古いOSには対策ソフトが無いので、これも中継役が肩代わりする)を考えている。対象をWindows 95/98だけでなく、XP以降の「今どきのマルウェアが実際に動いてしまう」世代まで広げたいと思っている。