8ビットマイクロコントローラでWebサイトをホスティングする
(maurycyz.com)- AVR64DD32 という8ビットMCUだけでWebサイトをホスティングしており、24MHz CPU・8KB RAM・64KB Flashという小さな環境で動作する
- Ethernet 信号を直接生成するには、10BASE-Tですらこの環境には速すぎるため、LinuxがサポートするSLIPを使ってUSB-Serialリンクをネットワークインターフェースのように利用する
- SLIP はパケットを
0xC0で囲み、特殊バイトをエスケープする単純な方式なので、MCUと現代のLinuxをつなぐのに適している - IPはフラグメンテーション無効化のおかげで単純になったが、TCP実装 は接続状態・再送・例外処理が必要で数日かかり、まだバグも残っている
- 外部アクセスはVPS・WireGuard・プロキシで
/mcuリクエストだけを転送する迂回構成で、公開IPv4のコストと IPv6の不在 が主要な制約として明らかになった
8ビットAVRでWebサイトをホスティングした構成
- AVR64DD32 はArduinoで知られるAtmega328に近い8ビットAVR系MCUで、同じメモリ基準ならより安価で、単一のプログラミングピンとより優れた周辺機能を備える
- 最大 24MHz の単一8ビットAVRコア
- 8KB静的RAM、64KB Flash、256バイトEEPROM
- 1.8〜5.5Vの電圧範囲、$1〜$2の価格帯
- MCUだけでインターネットに直接接続するには Ethernet 信号を作る必要があるが、最も遅い10BASE-Tでもこの環境には速すぎる
- 10BASE-Tは10Mbit/sで動作し、Manchesterエンコーディングのため実際の回線上では20Mbitになる
- AVR64DD32のCPUは24MHzまで可能だが、周辺機器とIOピンは12MHzクロックが上限のため、直接信号を生成するのは難しい
- 専用のEthernetチップを使う方法が定石だが、プロジェクト完成のために数週間待つ必要があった
- 代替として SLIP(Serial Line Internet Protocol, RFC 1055) を使い、シリアルリンク上にネットワークを載せる
- パケットの前後を
0xC0バイトで囲む - パケット内の
0xC0は0xDB 0xDCに、既存の0xDBは0xDB 0xDDに置き換えて曖昧さを避ける - 過去のダイヤルアップモデムが電話回線上にシリアルリンクを作り、その上でコンピュータがネットワーク処理をしていた方式につながっている
- 現代のLinuxもSLIPをサポートしており、USB-Serialアダプタをネットワークインターフェースにできる
- 使用例は
stty -F /dev/ttyUSB0 115200 raw cs8,slattach -m -F -L -p slip /dev/ttyUSB0のような形
- パケットの前後を
- MCU側のハードウェアは単純で、外部部品なしでも動作する
プロトコル実装と公開アクセスの処理
- IP実装 は現代環境の制約のおかげで単純化される
- Webページがユーザーのコンピュータに届くには、パケットが複数のネットワークを通過する必要があり、各パケットには送信元と宛先アドレスなどを含む40バイトのIPヘッダが必要になる
- 以前のIPはパケットフラグメンテーションのような機能のため、正しく処理するには多くのメモリが必要だった
- 現代のOSはフラグメンテーションを無効化しており、IPv6はフラグメンテーションを廃止しているため、自前で処理する必要がない
- 受信したパケットの送信元と宛先を入れ替え、TTLカウンタをリセットすれば応答ヘッダを作れる
- TCP実装 は接続状態の追跡、失われたパケットの再送、さまざまな例外処理が必要で、はるかに難しい
- カスタムTCP実装が十分に動くようになるまで数日かかり、まだいくつかのバグが残っている
- HTTPは別途実装せず、サーバーが常にハードコードされた「応答」をクライアントに送る
- URLが1つしかないサイトなら、この方式で十分に動作する
- 読み込みの様子は Video 3 で見られる
- 外部アクセスには 公開ルーティング可能なIPv4アドレス が必要だが、コストと自宅インターネット接続の品質が障害になる
- 公開ルーティング可能なアドレスを持つマシンは、Helsinki近郊のデータセンターにあるVPSである
- LinuxのWireGuardでインターネット上に仮想ネットワークリンクを作り、片側がCGNATの背後にあっても動作するようにする
- LinuxルーターボックスがVPSに接続され、より適切なインターネット接続を得る構成になる
- MCUには依然として独自の公開IPがないため、VPSアドレスへのすべてのリクエストを転送すると既存のWebサイトが壊れてしまう
- その代わり、サーバーが
/mcu配下のリクエストだけをローカルアドレスブロックを使ってMCUサーバーへプロキシするよう構成した - 訪問者がMCUのTCP/IPスタックに直接接続する構造ではないが、Vape Server と同じ方式である
- SYNパケットで壊すのは多少難しくなるが、実質的にはダイヤルアップに近い接続上のサーバーなのでDDoSには脆弱である
- その代わり、サーバーが
- IPv6の不在 が、この迂回構成全体の根本原因として残っている
- IPv6は30年間存在しているが、それでもなお大半の人はアクセスできない状態にある
- /mcu: MCUでホスティングされているページ
- http://ewaste.fka.wtf/: 廃棄物の中から取り出した32ビットMCUでホスティングされているVape Server
- https://lcamtuf.substack.com/p/psa-if-youre-a-fan-of-atmega-try: AVR Dxラインについてのlcamtufの記事
1件のコメント
Hacker Newsのコメント
25年以上前、最小のWebサーバーを作る見せびらかし競争があった: https://web.archive.org/web/20000815063022/http://www-ccs.cs...
ACE1101マイクロコントローラを使った人が「優勝」したが、元記事は見つからず、こんなものもある: https://conceptlab.com/fly/
ハエの上のWebサーバーだった
コードを切り詰める作業は本当に楽しく、pingを外したらビットバンギングI2CとEEPROMへのUDPアップロードを入れる余地ができ、それでもまだ1024バイト未満だった
AVR DD、EA、EBシリーズは好きだが、Microchipの最近のチップ投入はAVRファンには少し不安に見える: https://www.microchip.com/en-us/products/microcontrollers/32...
PIC32 CMは、イベントシステム、MVIO、5V動作などAVR DDの機能の大半を備えつつ、より大きく標準的なARM 32ビットM0+コアを提供している
そのせいでAVR DDはやや旧式になったようにも思えて不安になる。AVR EAとAVR EBには16倍のプログラマブルゲインを持つ12ビットADCがあり、ノイズは多少あるものの約50マイクロボルトまで感度があり、ものすごく優秀なADC/電流センサーなので安泰にも見える
逆に、これがAVR系をさらに人気にする可能性もある。ピン互換のARM32 Cortex M0+があることが、AVRプラットフォーム上に作る可能性を高めるのか下げるのか気になる
個人的にはペリフェラルが最も重要だと思う。AVR DDのほうが消費電力は低いかもしれず、とくに1.8V動作ではそうだろうが、それで十分かは分からない
プロジェクト自体はとても興味深く、AVR DDはとにかく素晴らしいチップなので、実際に使われているのを見るのはうれしい
10BASE-Tは10メガビット/秒で動作し、マンチェスター符号化のため線路上では20メガビットになるが、AVR EBにはx2 PLLタイマーがあるので、長く取り組めばマンチェスター符号化を出力できるかもしれない
LUT、UARTペリフェラル、PLLで引き上げたタイマー回路を組み合わせれば高速マンチェスター符号化を押し出せそうだが、20Mbitまで行けるかはもう少し考える必要がある
Cortex-M0路線をいじっているのは、Dxの次の8ビットプラットフォーム世代を引き続き開発したくないというサインかもしれない。同じ機能を別のCPUコアに持っていくなら、それはそれで構わないと思う
ページ上でHTMLがリアルタイムにストリーミングされてくるのが見えて良い。昔のダイヤルアップ時代に画像が上から下へゆっくり描かれていった感じを思い出す
そっちではFTPで、後にはNapsterで、1回の接続で曲を何曲も落とせた
タイトルを見たとき最初に思ったのは「組み込み/IoT機器ではああいうことをたくさんやっているのに」だった
10/100 Ethernet内蔵8051の例がある: https://www.asix.com.tw/public/index.php/en/product/Microcon...
2つの点が面白かった。1つ目は、ここのwww.cには入っていないRFC 1055の2025年正誤表があること。その正誤表はデコードアルゴリズムをどう変えるべきかをかなり説得力を持って示しており、このケースではリンクの反対側が実際にLinuxだ
2つ目は、次の行き先はたぶんRFC 1144だろうということ
ENC28J60 + PIC18の組み合わせは、20年前にMicrochipがよく配布していたデモでまさにこういうことをしていた構成だった
プロキシがページの**server:**ヘッダーを上書きしていないのが気に入った
昔、Arduino Megaで似たようなものを作ったことがある。クライアントが多くの仕事をしてくれるのでかなりもっともらしく見せられるのが驚きで、コントローラはただuSDカードからコンテンツを配信していただけだった