前言

MikroTik RouterOS 是一套非常强大的路由操作系统,但在日常使用中,总会遇到一些 RouterOS 原生功能不方便处理的需求:使用标准 Linux 命令排查网络、通过 SSH 执行自动化脚本、使用 curl/tcpdump/dig 诊断网络,或者运行轻量级 Python 和 Shell 工具。

RouterOS 7 提供了 Container 功能,可以在支持的硬件上运行 Linux 容器。我决定在两台 MikroTik RB5009 上分别部署 Debian 12,让路由器兼具 RouterOS 网络能力与 Linux 运维能力。

本文记录部署过程、关键配置、遇到的问题及解决方式。

一、部署环境

项目 设备 A 设备 B
型号 RB5009UG+S+ RB5009UPr
操作系统 RouterOS 7 RouterOS 7
CPU 架构 ARM64 ARM64
Linux 系统 Debian 12 Slim Debian 12 Slim
容器名称 debian debian
容器 IP(示例) 10.10.10.254 172.16.16.254
SSH 用户 ops ops
存储方式 USB ext4 USB ext4
远程接入 EasyTier EasyTier

本文以设备 B 为示例,设备 A 只需替换 IP、网关及存储路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
远程 Mac / PC
|
EasyTier VPN
|
MikroTik RB5009
|
+---+--------------------+
| |
RouterOS 7 Debian Container
| |
LAN Bridge SSHD
| |
172.16.16.172 172.16.16.254
|
ops / sudo

Debian 容器有独立 IP,接入 RouterOS LAN Bridge,同网段设备可直接访问 SSH,无需额外端口映射。

二、开启 RouterOS Container 功能

检查设备模式:

1
/system/device-mode/print

确认 container: yes,并检查:

1
/container/print

如果 Container 未启用,需按当前 RouterOS 版本要求启用,并完成设备所要求的物理确认。远程操作前应确保可以现场维护设备。

三、准备 USB 持久化存储

RB5009 内部存储有限,建议将 Linux 根文件系统和镜像层放在 USB ext4 存储上。先检查:

1
/disk/print

本次设备 B 的 USB 挂载路径为 usb2。如果需要格式化,请先核实磁盘没有其他业务数据;格式化会清除数据。创建目录:

1
2
3
4
/file add type=directory name="usb2/containers"
/file add type=directory name="usb2/containers/layers"
/file add type=directory name="usb2/containers/tmp"
/file add type=directory name="usb2/containers/shared"

踩坑 1:RouterOS 不是 Linux Shell

尝试 /file/make-directory 会失败。本次 RouterOS 版本使用 /file add type=directory name="路径" 创建目录。已存在的目录无需重复创建。

四、创建 Debian 独立网络

设备 B 的示例网络:

1
2
3
4
RouterOS LAN IP: 172.16.16.172
LAN Bridge: Lan
Debian IP: 172.16.16.254
Subnet: 172.16.0.0/12

创建 VETH 并接入桥:

1
2
/interface/veth/add name=veth-debian address=172.16.16.254/12 gateway=172.16.16.172
/interface/bridge/port/add bridge=Lan interface=veth-debian

检查:

1
2
/interface/veth/print detail
/interface/bridge/port/print where interface="veth-debian"

容器地址应避开 DHCP 分配池及现有静态设备,先核对 ARP、租约和地址规划。/12 是本次实际网络掩码,不应直接套用到 /24 等其他网络。

五、拉取 Debian 12 ARM64 镜像

配置镜像层和临时目录:

1
/container/config/set layer-dir=usb2/containers/layers tmpdir=usb2/containers/tmp

创建容器(可逐行在 RouterOS CLI 中输入,续行写法需符合当前终端):

1
/container/add remote-image=m.daocloud.io/docker.io/library/debian:12-slim name=debian interface=veth-debian root-dir=usb2/containers/debian-rootfs layer-dir=usb2/containers/layers entrypoint=/bin/sleep cmd=infinity logging=yes start-on-boot=no

这里使用 debian:12-slim,体积较小,后续按需安装软件。

踩坑 2:Docker Hub 拉取超时

本次直接从 Docker Hub 拉取镜像曾超时,改用 m.daocloud.io/docker.io/library/debian:12-slim 成功。镜像加速服务的可用性可能变化,失效时应更换可用来源。

初次运行采用 entrypoint=/bin/sleep cmd=infinity,是为了让容器持续运行,方便进入容器安装 SSH,而不是让尚未配置的 SSH 服务导致容器立即退出。

1
2
3
/container/start [find where name="debian"]
/container/print detail where name="debian"
/container/shell [find where name="debian"]

在 Debian 内检查:

1
2
cat /etc/os-release
uname -m

预期系统为 Debian 12,架构为 aarch64。

六、为 Debian 配置文件共享目录

本文配套的完整部署包:rb5009-debian-kit-v1.1.1.zip。解压后包含两台设备对应的 RouterOS 准备脚本、Debian 初始化脚本 02-debian-bootstrap.sh、RouterOS 收尾脚本和详细 README。

SSH 尚未安装时,不能直接用 SCP 上传初始化脚本。可以使用 RouterOS Container 挂载共享目录:

1
2
3
4
/container/mounts/add list=debian-shared src=usb2/containers/shared dst=/mnt/shared
/container/stop [find where name="debian"]
/container/set [find where name="debian"] mountlists=debian-shared
/container/start [find where name="debian"]

进入 Debian 验证:

1
/container/shell [find where name="debian"]
1
ls -lah /mnt/shared

通过 WinBox Files 将部署包中的 02-debian-bootstrap.sh 上传至 usb2/containers/shared/,在 Debian 中即可通过 /mnt/shared/ 访问。先检查脚本内容,再执行:

1
bash /mnt/shared/02-debian-bootstrap.sh

踩坑 3:Mounts 使用 list=,不是 name=

本次 RouterOS 版本的 /container/mounts/add 不接受 name=,需要使用 list=。可在 CLI 输入 /container/mounts/add 后查看支持的参数;关联容器时使用 mountlists=。

七、安装 SSH 和运维工具

在 Debian root Shell 中:

1
2
3
4
5
apt-get update
apt-get install -y \
openssh-server sudo ca-certificates curl wget \
iproute2 iputils-ping dnsutils net-tools procps \
tcpdump traceroute vim-tiny less

本次安装了约 65 个软件包及依赖。安装时可能看到:

1
2
invoke-rc.d: could not determine current runlevel
invoke-rc.d: policy-rc.d denied execution of start.

这并不意味着安装失败。容器中没有运行完整的 systemd 服务管理环境,后面直接运行 sshd 即可。

八、创建 SSH 运维用户并配置 sudo

不建议使用 root 直接远程登录。创建 ops 用户(若已存在则跳过 useradd):

1
2
3
id ops >/dev/null 2>&1 || useradd -m -s /bin/bash ops
usermod -aG sudo ops
passwd ops

建立独立 sudo 授权文件:

1
2
3
4
printf 'ops ALL=(ALL:ALL) ALL\n' > /etc/sudoers.d/90-ops
chown root:root /etc/sudoers.d/90-ops
chmod 440 /etc/sudoers.d/90-ops
visudo -cf /etc/sudoers.d/90-ops

sudo whoami 出现 [sudo] password for ops: 是正常现象,输入 ops 密码后应输出 root。建议保留密码验证,不必默认配置 NOPASSWD。

九、配置 SSH 公钥认证

Mac 上查看已有公钥:

1
cat ~/.ssh/id_rsa.pub

如果没有密钥,可生成 Ed25519 密钥:

1
ssh-keygen -t ed25519

在 Debian 中写入公钥(不要上传私钥):

1
2
3
4
5
6
7
8
mkdir -p /home/ops/.ssh
cat > /home/ops/.ssh/authorized_keys <<'KEY'
替换为自己完整的 SSH 公钥
KEY
chown -R ops:ops /home/ops/.ssh
chmod 700 /home/ops/.ssh
chmod 600 /home/ops/.ssh/authorized_keys
chmod go-w /home/ops

踩坑 4:公钥正确仍然报 Permission denied (publickey)

第一台 RB5009 曾因 .ssh 目录和 authorized_keys 权限不正确导致公钥认证失败。目录应为 700,授权文件应为 600,所有者应为 ops,且用户主目录不能被其他用户随意写入。

十、配置并测试 SSH 服务

在 Debian 中创建配置文件:

1
2
3
4
5
6
7
cat > /etc/ssh/sshd_config.d/99-ops.conf <<'EOF_SSH'
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication yes
KbdInteractiveAuthentication no
AllowUsers ops
EOF_SSH

初始化阶段暂时保留密码认证,公钥登录验证成功后建议将 PasswordAuthentication 改为 no,并重新加载 SSH 服务。关闭前务必在第二个终端确认公钥可用,避免锁死远程访问。

检查配置并启动:

1
2
3
4
5
6
mkdir -p /run/sshd
chown root:root /run/sshd
chmod 755 /run/sshd
/usr/sbin/sshd -t
/usr/sbin/sshd
ss -lntp | grep ':22'

Mac 上连接:

1
ssh ops@172.16.16.254

登录后验证:

1
sudo whoami

输出 root 即表示 sudo 授权正常。

十一、让 SSH 随容器自动启动

RouterOS Container 不应依赖完整的 systemd,使用前台 sshd 作为容器主进程即可。

在 Debian 中创建启动脚本:

1
2
3
4
5
6
7
8
9
cat > /usr/local/bin/start-sshd.sh <<'EOF_SSHD'
#!/bin/sh
set -eu
mkdir -p /run/sshd
chown root:root /run/sshd
chmod 755 /run/sshd
exec /usr/sbin/sshd -D -e
EOF_SSHD
chmod 755 /usr/local/bin/start-sshd.sh

踩坑 5:sshd 启动后立即退出

第一台设备曾因 /run/sshd 所有权异常导致 SSH 服务启动失败。启动脚本显式设置目录所有者及权限,再通过 exec /usr/sbin/sshd -D -e 将 sshd 作为容器前台主进程,避免后台守护进程退出导致容器停止。

十二、配置 RouterOS 开机自启

确认 SSH 已能正常登录后,回到 RouterOS:

1
2
3
4
/container/stop [find where name="debian"]
/container/set [find where name="debian"] entrypoint=/usr/local/bin/start-sshd.sh cmd="" start-on-boot=yes
/container/start [find where name="debian"]
/container/print detail where name="debian"

确认容器状态为 RUNNING,从 Mac 再次连接:

1
ssh ops@172.16.16.254

两台 RB5009 都已通过容器重启后的 SSH 登录验证。

十三、通过 EasyTier 实现异地访问

不建议将 SSH 22 端口直接映射到公网。本次设备已部署 EasyTier,可以进一步通过对应节点发布 Debian 的单主机子网路由:

1
2
设备 A:10.10.10.254/32
设备 B:172.16.16.254/32

需要验证 EasyTier 节点在线、远端路由下发、RouterOS 转发/防火墙放行,以及 Debian 回程路径。配置子网代理不等于远程访问已经成功,应在非局域网环境中实际测试:

1
ssh ops@172.16.16.254

十四、日常维护

SSH 登录:

1
ssh ops@172.16.16.254

上传文件或目录:

1
2
scp ./test.sh ops@172.16.16.254:/home/ops/
scp -r ./scripts ops@172.16.16.254:/home/ops/

更新软件:

1
2
sudo apt-get update
sudo apt-get upgrade

网络诊断:

1
2
3
4
5
ip addr
ip route
sudo ss -lntp
dig debian.org
sudo tcpdump -i eth0 -nn

RouterOS 检查容器状态:

1
/container/print detail where name="debian"

备份 RouterOS 配置:

1
/export file=rb5009-container-config

导出文件可能包含网络拓扑、账号或其他敏感信息,请妥善保存,不要直接发布到公开仓库。

十五、部署经验总结

问题 原因 解决方式
Docker Hub 拉取超时 镜像源网络访问受限 使用可访问的镜像加速源
创建目录失败 RouterOS CLI 语法与 Linux 不同 /file add type=directory
Mount 参数错误 使用了不支持的 name= 改用 list=
SSH 安装后未启动 容器没有传统服务管理环境 直接启动 sshd
公钥认证失败 .ssh 权限错误 修正所有者及权限
SSH 启动失败 /run/sshd 权限异常 启动前修正目录权限
重启后 SSH 不运行 sshd 不是容器主进程 使用自定义 entrypoint
sudo 要求密码 sudo 的正常安全机制 输入 ops 用户密码

RouterOS Container 最重要的原则:不要把它当作完整的 Linux 虚拟机,而要把它当作运行在 RouterOS 上的轻量 Linux 服务环境。

不依赖完整 systemd,让主要服务以前台运行;将根文件系统放在外部存储,使用独立 VETH 网络和 SSH 运维入口,避免直接暴露公网管理端口。

十六、结语

两台 MikroTik RB5009 现在都拥有独立的 Debian 12 ARM64 运维环境。RouterOS 继续负责路由、交换、防火墙和网络连接,Debian 承担 Shell 脚本、网络诊断及轻量自动化任务。

这套方案的价值不只是“在路由器上多运行一个 Linux”,而是让网络设备拥有一个标准化、可脚本化、可远程维护的运维入口。

未来还可以扩展 Python 网络检测、链路质量采集、自动化故障诊断,以及通过 EasyTier 统一管理多台路由器。RB5009 毕竟是路由器,CPU、内存和 USB 存储性能有边界,生产环境应优先保证 RouterOS 核心转发能力。

让路由器专注于网络,让 Debian 专注于工具。