前言 #
相信很多人都听过“上古时期”拨号连接时的“猫叫”。当时人们还在使用电话线上网,速率最高只有57.6Kbps。“多图杀猫”这一俚语也是从那一时期生成出来。
前些日子在网上冲浪时,看到 b 站某些 up 主使用了电话交换机和实体调制解调器(猫),让 Windows 11 实现了拨号上网,甚至实现了双机互联和超级终端功能。当时我在构思,有没有一种可能,不使用物理硬件,只使用软件模拟这些功能实现双机互联和拨号上网呢?
还真让我发现了这样一个开源软件:atduck
atduck 模拟了一个 Hayes 兼容的调制解调器。
部署 atduck #
2019 年有一篇博客详细记录了使用atduck进行拨号上网的步骤。
ATduck 本身安装简单,但是它依赖 Perl 的 IO-Pty 模块,以及 Slirp 软件。Slirp 可以在一个 TTY 上模拟一个 SLIP 或者 PPP 协议的服务端,ATduck 本身只实现了 Modem 的部分,联网部分都交由 Slirp。
但是由于显而易见的原因,Slirp 已经很少用到了。Arch Linux 的软件源里根本没有,甚至连 AUR 里都没有。根据 Wikipedia 的 Slirp 页面显示,Slirp 的部分维护交由 Debian 维护者进行。
里面有他使用的Dockerfile:
RUN PKG_INSTALL(git slirp perl libio-pty-perl tini) \
&& git clone https://github.com/nandhp/atduck.git \
&& ln -sf /usr/bin/slirp /atduck/slirp-nandhp-patch \
&& PKG_UNINSTALL(git) \
&& FINAL_CLEANUP()
WORKDIR /atduck
ENTRYPOINT ["tini", "/atduck/atduck", "--", "-l", "0.0.0.0:5555"]或者直接使用他的镜像:xddxdd/atduck
如果你使用 Virtualbox, 那你就可以直接参照博客说明添加串口并使用了。
但是针对 VMware 虚拟机而言,这个 Dockerfile 是不能使用的:一方面,它指定 atduck 监听在 TCP 端口上,而 VMware 只支持使用 Unix Socket 通信串口。所以我们需要稍微修改一下:
方式一:直接修改现有镜像启动命令
FROM xddxdd/atduck
ENTRYPOINT ["tini","/atduck/atduck","--","-l","/tmp/modem"]方式二:直接将DockerFile里的ENTRYPOINT修改为ENTRYPOINT ["tini","/atduck/atduck","--","-l","/tmp/modem"]。
RUN PKG_INSTALL(git slirp perl libio-pty-perl tini) \
&& git clone https://github.com/nandhp/atduck.git \
&& ln -sf /usr/bin/slirp /atduck/slirp-nandhp-patch \
&& PKG_UNINSTALL(git) \
&& FINAL_CLEANUP()
WORKDIR /atduck
ENTRYPOINT ["tini","/atduck/atduck","--","-l","/tmp/modem"]然后编译即可运行。
docker build -t atduck1 . 可以直接使用 docker compose:
services:
atduck:
image: atduck1 # 改成你自己编译的镜像名称
container_name: atduck
restart: always
volumes:
- /tmp:/tmp # 如果你使用的是如我所示的 Unix Socket 就加上。否则如原博客所示,加端口监听即可实现拨号上网 #
我们这里使用 VMware。
依照上一节中 ENTRYPOINT 的指令标识,我们在/tmp/modem的位置创建了一个 Unix Socket。
不过首先,需要设置一下它的权限,且每次启动 atduck docker 时都要设置,不然身为普通用户权限的 VMware 无法读写该 Socket,会报权限不足。
注意! 如果你不是首次启动 atduck 容器, 请务必先删除 /tmp/modem 后再启动,否则可能会出现无法监听的问题。
sudo rm /tmp/modem # 这两条指令必须在启动容器之后执行,username是你的用户名
sudo chown username /tmp/modem
sudo chgrp username /tmp/modem然后,在我们需要拨号上网的虚拟机设置中添加一个串口设备:

按图中设置,选择使用 socket(named pipe),并设置 From Client to An Application。

启动虚拟机,在“控制面板->打印机和其他硬件->电话和调制解调器选项”中安装调制解调器( Windows XP 下可以直接安装标准 56000bps 调制解调器,Windows 2000 下需要安装 Hayes 的调制解调器)

添加一个新的拨号连接,使用新建连接向导:
- 选择 连接到 Internet
- 选择 手动设置我的连接
- 选择 用拨号调制解调器连接
- 输入连接名,随意输入,这个名字就是你的连接名字
- 输入电话号码:5555 参照这里
- 留空用户名和密码,无需输入
- 你可以选择添加一个快捷方式
然后就创建完毕了,可以进行连接了,享受网上冲浪吧少年!

选什么电话号码? #
按照 atduck 使用说明的 DIALING PLAN:
The following dialing plan is configured by default.
5550 Connect to a shell on the host
5555 SLiRP (PPP mode)
5556 SLiRP (SLIP mode)
6xxx Call another emulated modem by serial number. For example, dialing 6006 will connect you to the modem with serial number 6. To determine your modem’s serial number use AT+GSN. Note that serial numbers are not fixed between sessions.
我们可以得知,如果想实现拨号上网,需要虚拟机拨 5555 或 5556,我们选择 Windows 默认使用的 PPP 模式,即5555。
实现双机互联 #
既然拨号连接都成功了,那自然需要体验一下和朋友煲电话粥传送“大文件”的快乐了~
我们需要用到超级终端,Windows 3.1 到 Windows XP 下的原版镜像都有这个东西,一般在附件-通讯中可以找到。
我们使用一台 Windows 2000 的虚拟机和我们的 Windows XP 进行互联。
我们需要让一个 atduck 实例同时监听两个 Unix Socket ,可以修改ENTRYPOINT如下:
ENTRYPOINT ["tini","/atduck/atduck","--","-l","/tmp/modem","-l","/tmp/modem2k"]/tmp/modem2k 就是我们 Windows 2000 虚拟机将要使用的 Socket。
新开一个终端,依然像我们上面所说的,处理好权限问题。
打开 Windows 2000 虚拟机,安装好调制解调器。
根据选什么电话号码:
6xxx Call another emulated modem by serial number. For example, dialing 6006 will connect you to the modem with serial number 6. To determine your modem’s serial number use AT+GSN. Note that serial numbers are not fixed between sessions.
我们知道如果想要双机互联,需要拨6xxx。那么到底该拨多少呢?
我们需要 putty 直接进行串口通信,去网上下载 putty 0.61 版本,可以在 Windows 2000 和 Windows XP 上运行。
打开 putty,选择连接 Serial 连接到COM1
点击连接,输入AT+GSN:
如果你使用docker logs -f atduck查看就可以看到 atduck 的AT指令日志,可以实时查看你的交互。

看到图中回复2, 说明该电脑的电话号码是6002。
我们打开超级终端,等候拨入:

打开 Windows 2000, 拨 6002,注意不要带区号:

然后…就连上了

使用传送功能发个“大文件”吧:

最后 #
这个程序还可以玩更多的东西,但我没怎么试过,所以我也只能写这么多了。