在 AVR 微控制器上托管网站Hosting a website on an AVR
Maurycy Zysk 演示了如何在 AVR64DD32 微控制器(类似 Arduino Atmega328)上搭建简易网站服务器。该设备配备 8KB RAM、64KB Flash 和 24MHz 单核 CPU,虽资源有限,但仍能运行基本 HTTP 服务,展示了嵌入式系统在极简场景下的可行性。
本期节目是“用8位微控制器做蠢事”:
MCU网站演示(如果发布到HN可能会宕机)
我的“受害者”是AVR64DD32,它与著名的Arduino Atmega328非常相似。 相比旧款Atmega,这些芯片在相同内存下更便宜,仅需一个编程引脚,且外围设备也更完善:
这就是计算机(而且相当宽敞),但它需要一个互联网连接来托管网站。
显而易见的选择是以太网,但即使是最低速版本(10BASE-T)仍能以10兆比特/秒运行。 更糟的是它使用曼彻斯特编码: 零被发送为“10”,一被发送为“01”,因此10兆比特的数据实际上在电线上传输的是20兆比特。
这对AVR来说太快了。 虽然它的处理器可以运行在24MHz,但所有外设和IO引脚最高只能达到12MHz。 (尽管有些其他8位芯片可以做到这一点)
正确的解决方案是从DigiKey购买专用的以太网芯片,但这意味着我要等几周才能完成这个项目。
...而且以太网远非唯一选择:
串行线路互联网协议(RFC 1055)是一个非常古老且简单的通过串行线路运行网络的协议:
在发送数据包之前,用0xC0字节将其封装起来。 如果数据包中包含任何0xC0字节,则将其替换为0xDB 0xDC。 为避免歧义,任何原有的0xDB字节都会被替换为0xDB 0xDD。
这种方案曾广泛用于通过调制解调器连接到互联网: 老式拨号调制解调器只需在电话线上建立串行链路,至于计算机如何处理则由计算机自行决定。
...这也是为什么SLIP至今仍在现代Linux中受支持的原因:
# Just a normal USB to Serial adapter
stty -F /dev/ttyUSB0 115200 raw cs8
slattach -m -F -L -p slip /dev/ttyUSB0
# ... and now it's a network interface微控制器端的硬件极其简单:
它无需外部元件即可工作,但我想要一些指示灯,以及一个防呆二极管——以防我 inevitably 接反电源。
因为它只消耗几毫瓦功率,所以完全可以从串口适配器的5伏轨直接供电: 只用一根线真是太方便了。
现在它有了一个互联网连接,但这几乎算不上是一个真正的服务器。
为了让我的网页能到达你的电脑,它必须经过数十个不同的网络。
为此,每个数据包都包含一个IP头部: 40字节的内容包括源地址和目标地址,以及其他我不太关心的信息。
这个协议曾经复杂得多,具有像分片这样的功能,需要大量内存才能正确处理,但我不必担心: 每个现代操作系统都会禁用分片,而IPv6更是彻底移除了这一特性。
这使得实现变得非常简单: 只需交换接收到的数据包中的源与目标地址,就能生成响应的头部(并重置TTL计数器)。
另一个协议TCP则困难得多: 实现它要求微控制器跟踪连接状态、定期重传丢失的数据包,并处理大量边缘情况。
我花了几天时间才让自定义实现正常工作,目前仍有几个bug。
至于HTTP的实现,我没有做: 服务器总是向客户端返回一个硬编码的“响应”。 只要网站上只有一个URL,这样就没问题。
[视频:页面加载过程。详见web或files目录下的loading.mp4]
好了,但如果我想和朋友分享呢? 遗憾的是,要做到这一点,它需要一个公开可路由的IPv4地址。 这些地址不仅昂贵(数量有限),而且我在家里也搞不到好的互联网连接。
(不,Starlink 并不好用)
我确实有一台拥有公网可路由地址的机器, 但它位于赫尔辛基附近的数据中心: 我需要一条非常长的串口线……
Linux 还支持另一件很酷的事——WireGuard,它能在互联网上创建一个虚拟网络链路。 即使其中一台机器位于(CG)NAT 或其他网络障碍之后,也能正常工作。
问题解决了:
让 Linux 路由器通过 VPS 连接以获得正常的互联网访问?
……但 MCU 仍然没有自己的 IP 地址: 我可以把 VPS 的地址转发给它,但这会破坏我的正常网站。
相反,我设置了服务器,将 /mcu 路径下的所有请求代理到本地地址块中的服务器。 这意味着访客不会直接连接到 MCU 的 TCP/IP 栈…… 不过话说回来,这和 Vape Server 用的是同样的配置,也没人抱怨过。
(这也让通过发送 SYN 包来攻击稍微难一点, 但 DDoS 一个实际上是通过拨号方式连接的服务器,其实也不太难)
相关:
需要完整排版与评论请前往来源站点阅读。