SSD Nodes Learn
指南 Matt Connor作者: Matt Connor · 更新于 2026-07-19

在 Ubuntu 24.04 上安装并加固 Webmin

在 Ubuntu 24.04 上安装 Webmin,然后将其锁定:使用 SSH 隧道或 IP 白名单访问,配置真实的 Let's Encrypt 证书、双因素认证,并用 Fail2ban 保护 10000 端口。

您将搭建什么

Webmin 是一个网页控制面板,它为整台 Linux 服务器提供了浏览器前端,涵盖用户、软件包、cron 任务、防火墙、Apache、BIND、磁盘以及上百个其他模块,通过 HTTPS 在 10000 端口访问。安装本身只有三条命令,大约一分钟即可完成。本指南把大部分篇幅花在后半部分,原因在于 Webmin 是以 root 身份登录的,root 能做的事它都能做。一个完全开放或未经认证的 Webmin 不是「需要管理的风险」,而是一次带着登录页面的彻底服务器沦陷。所以用十分钟把它装好,然后把这一小时余下的时间用来确保只有您能访问到它。

前置条件与一句实话提醒

一台全新的 Ubuntu 24.04 KVM VPS,拥有 root 或一个 sudo 用户即可。Webmin 是用 Perl 写的,很轻量,1 GB 内存绰绰有余,空闲时占用远低于四分之一 GB。它通过自带的 Web 服务器(miniserv.pl)监听 TCP 10000 端口,而不是 Apache 或 nginx,所以不需要先安装其他任何东西。

开始之前有两件事要决定。第一,用于登录的账户:Webmin 通过 PAM 对 Unix 账户进行认证,所以您以 rootsudo 组中的某个用户身份登录,用的是该账户的 Unix 密码。云镜像通常只允许密钥登录,默认用户没有设置密码,而 Webmin 无法登录一个没有密码的账户。请先用 sudo passwd youruser 设置密码,否则无论您输入什么,登录都会失败。

第二,也就是那句提醒:不要简单地把 10000 端口开放到互联网上然后就撒手不管。现在就决定您将通过 SSH 隧道(推荐,不暴露任何东西)访问 Webmin,还是将其限制到您自己的 IP。这一个决定会影响下面的每一步,所以在动防火墙之前,请把两种方案都读一遍。

从官方仓库安装 Webmin

Webmin 发布了一个签名的 apt 仓库。安装脚本会添加该仓库及其 GPG 签名密钥,这样今后运行 apt upgrade 时就会像其他软件包一样拉取 Webmin,您获得的是经过认证的更新,而不是一个下载后永远不会自我打补丁的 .deb

curl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh
sudo sh webmin-setup-repo.sh

脚本会打印出它将要做的事情,并询问 Setup repository? (y/N),请回答 y。完成后,安装该软件包。--install-recommends 参数会拉取常用的 Perl 和 SSL 模块依赖,这样个别模块以后就不会因为缺少库而出错。

sudo apt-get install --install-recommends webmin

Webmin 曾经重命名过这个脚本,较旧的指南引用的是 setup-repos.sh,所以如果这个原始 URL 返回 404,请直接从 webmin.com/download 获取当前的一行命令,而不要固定某个名字。一次正确的安装会以类似这样的一行结束:Webmin install complete. You can now login to https://your-host:10000/ as root。服务已启用并正在运行,配置位于 /etc/webmin 下,请求记录到 /var/webmin/miniserv.log,失败的登录进入 syslog,在 Ubuntu 24.04 上就是 systemd 日志。

在打开浏览器之前,先确认它确实已启动并在监听:

sudo systemctl status webmin --no-pager
sudo ss -tlnp | grep 10000

您想看到 active (running) 状态,以及一行显示 miniserv.pl 绑定在 0.0.0.0:10000 上;一旦您走下面的隧道方案,这个地址会变成 127.0.0.1:10000。如果 ss 在 10000 上什么都没显示,说明 Webmin 没有启动,在继续之前请查看 journalctl -u webmin -n 50

首次登录,以及证书警告

用浏览器访问 https://YOUR_SERVER_IP:10000。在一台全新的机器上会发生两件事。

如果 ufw 处于启用状态(Ubuntu 自家的服务器镜像默认它是关闭的,但许多供应商会预先启用它),页面根本不会加载,这在下面的故障模式里有涉及。如果端口是开放的,浏览器会抛出一个整页拦截:「您的连接不是私密连接」,在 Chrome 中带有代码 NET::ERR_CERT_AUTHORITY_INVALID,在 Firefox 中则是 SEC_ERROR_UNKNOWN_ISSUER /「警告:潜在的安全风险」。这是预期之中的,不是被入侵了。Webmin 在安装时生成了一个自签名证书(/etc/webmin/miniserv.pem),由于没有任何证书颁发机构为它背书,浏览器拒绝默默信任它。连接仍然是加密的,只是没有得到担保。暂时点击通过(高级,然后继续访问),我们会在后面正式替换掉这个证书。

root 或您的 sudo 用户及其 Unix 密码登录,您就会进入「系统信息」仪表板。这里一个常见的失误是输入了 http:// 而不是 https://。miniserv 会在该端口以纯文本回应普通 HTTP 请求,内容正是 「This web server is running in SSL mode. Try the URL https://...」,修复方法就是把地址栏里的 http 改成 https

安全决策:您将如何访问 Webmin?

现在到了关键部分。一个等同于 root 的面板不应该暴露在开放的互联网上,回应地球上每一个扫描器的登录尝试。您有两个站得住脚的选择,按优先顺序排列。

方案 B 中的 SSH 隧道是更好的那个,因为它完全不暴露任何东西。方案 A 中的 IP 白名单,如果您的地址是静态的,也可以接受。两者都不做,恰恰是整份指南要防止的错误。如果比起这两种方式,您更愿意通过私有网络访问 Webmin,那就把这台机器放到一个自建的 WireGuard VPN后面,并把 Webmin 绑定到隧道地址而不是公网地址上。

方案 A:将 Webmin 限制到您的 IP

在面板中,打开 Webmin,然后 Webmin Configuration,然后 IP Access Control。选择 「Only allow from listed addresses」 并输入您的公网 IP,您可以在自己的笔记本上运行 curl ifconfig.me 来查到它。保存。Webmin 会把这个写入 /etc/webmin/miniserv.conf 中的 allow= 行并重启自身。

陷阱在于:如果您家里的 IP 是动态的会变化,或者您把地址敲错了,就会把自己锁在外面。浏览器随后会显示 「Access denied for <your IP> 而没有登录表单,也没有任何网页途径能回去。您得从服务器控制台通过 SSH 或供应商的 VNC 来修复它:

sudo nano /etc/webmin/miniserv.conf
# find the line that begins  allow=
# correct your IP, or delete the whole line to allow all again
sudo systemctl restart webmin

删除 allow= 行会恢复完全开放的访问,所以只在需要恢复时才这么做,然后立即设置一个正确的值。

方案 B:绑定到 localhost 并通过 SSH 建立隧道(推荐)

比任何白名单都更好的做法,是根本不在公网接口上监听。告诉 miniserv 只绑定到回环地址,然后通过一条您本就信任的加密 SSH 隧道来访问它。

编辑 /etc/webmin/miniserv.conf,添加或修改一行:

bind=127.0.0.1

sudo systemctl restart webmin 重启。现在 Webmin 从互联网上已无法访问,对 10000 端口的扫描什么也找不到,而前面那条 ss 检查现在会显示它绑定在 127.0.0.1:10000 上。在您的笔记本上,打开一条隧道:

ssh -L 10000:localhost:10000 youruser@YOUR_SERVER_IP

让那个会话保持打开,然后访问 https://localhost:10000。流量在 SSH 内部传输,而 SSH 已经由您的密钥认证并加密,所以您在这里可以放心接受那个自签名证书,真正的保护是由 SSH 层完成的。关闭 SSH 会话,Webmin 就消失了。没有要加白名单的东西,没有暴露的东西,也没有额外要加固的服务。

如果您设置了 bind=127.0.0.1 却忘了建隧道,远程访问就会直接停止,这是功能在正常工作,而不是故障。恢复方式与方案 A 相同:从控制台移除 bind 行或设为 bind=0.0.0.0,然后重启。这和您访问一台在 tmux 中运行 Claude Code 的远程开发机时会用的隧道习惯是一样的,一条 SSH 会话,一切私密,公网接口上没有多余的东西在监听。

用真实证书替换自签名证书

如果您确实在方案 A 下把 Webmin 暴露在某个主机名上,那就用一张真实的 Let's Encrypt 证书除掉浏览器警告。您需要一个 DNS 名称,比如 panel.example.com,它有一条 A 记录指向服务器,并且在验证期间有某个东西响应 80 端口上的 HTTP 质询。

Webmin 内置了这个功能:Webmin,然后 Webmin Configuration,然后 SSL Encryption,然后 Let's Encrypt 标签页。输入主机名,把「website root directory」指向一个在 80 端口上为该域名提供服务的路径,然后请求。Webmin 会获取证书,替您更新 miniserv.conf 中的 certfile=keyfile= 行,并在过期前自动续期。刷新页面,那把锁就干净了。

一个实话实说的小麻烦:Webmin 自己的服务器运行在 10000 而不是 80 端口上,所以 http-01 质询需要一个真正的 Web 服务器(Apache 或 nginx)在 80 端口上为 panel.example.com 响应,或者改用基于 DNS 的验证。在一台只跑 Webmin、80 端口上什么都没有的机器上,请求会以验证错误失败,直到您给 Let's Encrypt 一个能访问到质询文件的途径。其中的机制(DNS 记录、80 端口质询和续期)和为任何一个网站签发证书是一样的。如果您想了解这方面的背景,用 Certbot 和 nginx 申请 Let's Encrypt TLS 证书的指南详细讲解了验证流程和 DNS 设置。如果您走的是 SSH 隧道方案,可以完全跳过本节:自签名证书在 SSH 后面就够用了,而为 panel.example.com 签发的真实证书,反正在您访问 https://localhost:10000 时只会产生一个名称不匹配的警告。

开启双因素认证

对一个 root 面板来说,单靠密码是薄弱的保护,所以加上第二重因素。打开 Webmin,然后 Webmin Configuration,然后 Two-Factor Authentication。选择 Google Authenticator 提供方,那是标准的 TOTP,所以它能配合 Authy、1Password 或任何验证器应用工作,然后保存。Webmin 会安装它需要的那个小 Perl 模块(Authen::OATH 加一个二维码生成器)并启用该功能;单单这一步还不能保护任何账户。

接着每个账户各自登记自己的设备。启用 2FA 后,打开 Webmin,然后 Webmin Users,选中账户,选择 Enable Two-Factor For User,Webmin 会显示一个二维码;用应用扫描它,并输入一个生成的验证码来确认。从那以后,登录会在密码之后要求那个六位数令牌。请在退出登录之前完成登记,如果要求了 2FA 而您的账户从未扫描过验证码,您仍然可以从控制台清除这个要求,但先登记好会省心得多。

添加 Fail2ban 以封禁暴力破解登录

即便是一个受限的登录端点,也应该惩罚反复的失败。Webmin 会以 webmin[12345]: Invalid login as root from 10.0.0.9 这样的形式把失败登录报告给 syslog,对于一个连 Unix 账户都不是的用户名则是 Non-existent login as ...;在 Ubuntu 24.04 上这些行会进入 systemd 日志,因为原始镜像没有 /var/log/auth.log。Fail2ban 自带一个现成的 webmin-auth 过滤器,恰好匹配这两行,而下面的 jail 自身设置了 backend = systemd,所以它不需要自定义正则或日志路径。

创建 /etc/fail2ban/jail.d/webmin.local

[webmin-auth]
enabled  = true
port     = 10000
filter   = webmin-auth
backend  = systemd
maxretry = 4
bantime  = 1h

sudo systemctl restart fail2ban 重新加载,然后确认 jail 已生效:

sudo fail2ban-client status webmin-auth

您应该看到列出的 jail,起始的封禁计数为零(在 journal 后端下没有 File list: 这一行)。要端到端地验证接线是否正确,可以从另一个网络故意失败登录几次,然后重新运行状态命令,看着 Currently banned 往上涨。如果它始终不涨,请确认您测试所用的地址不在 Fail2ban 的 ignoreip 里,并在服务器上运行 journalctl SYSLOG_IDENTIFIER=webmin 来确认那些 Invalid login 行确实被写入了。如果这台机器上还没安装 Fail2ban,在 Ubuntu 24.04 上为 SSH 配置 Fail2ban 的指南讲解了安装以及您应该与这个 jail 一起运行的 SSH jail。

限制每个 Webmin 用户能触及的范围

不是每个需要用面板的人都需要对所有东西拥有 root 权限。在 Webmin,然后 Webmin Users 下,创建额外的 Webmin 登录账户,并只授予每个账户它需要的模块,比如一个只看得到 cron 和文件系统模块的备份操作员。编辑一个用户会显示每个模块的清单;取消勾选某一项会把它从该用户的菜单里移除,并封锁底层的 URL。这就是纵深防御:当 Users 模块不在其列表里时,即便一个被盗的低权限 Webmin 会话也无法改写 /etc/shadow

保持 Webmin 更新

因为您是从 apt 仓库安装的,sudo apt update && sudo apt upgrade 会连同系统其余部分一起拉取新的 Webmin 版本。请及时打补丁,控制面板是热门的攻击目标。Webmin 也可以从 Webmin,然后 Webmin Configuration,然后 Upgrade Webmin 自我更新,但在 Ubuntu 上 apt 这条路更干净,因为它能让版本与您其他的包管理保持一致。不要把这当成可选项:过去好几个 Webmin 的 CVE 都是远程代码执行漏洞,而「已打补丁」和「已被攻破」之间唯一的区别,就是管理员运行升级的速度有多快。

故障模式,以及您会看到的字符串

「您的连接不是私密连接」/ NET::ERR_CERT_AUTHORITY_INVALID 在第一次加载时出现。原因:Webmin 在安装时生成的自签名证书没有受信任的颁发者。这不是攻击,通道是加密的,只是没有得到担保。修复:暂时穿过这个警告,然后签发一张真实的 Let's Encrypt 证书,或者如果您通过 SSH 隧道访问 Webmin,就永久接受它。

「This web server is running in SSL mode. Try the URL https://...」 您输入的是 http://server:10000。miniserv 在该端口上只讲 TLS,并用纯文本告诉您这一点。修复:把地址栏里的 http 改成 https

页面超时——ERR_CONNECTION_TIMED_OUT /「无法访问此网站」。 请求根本没到达 Webmin。在 Ubuntu 上这几乎总是 ufw 在丢弃 10000 端口。用 sudo ufw status 确认;如果 10000 没有列出,要么用 sudo ufw allow 10000/tcp 打开它,要么更好地保持它关闭,改用方案 B 的 SSH 隧道。注意区别:超时 意味着防火墙在默默丢包,而 ERR_CONNECTION_REFUSED 则意味着端口可达但 Webmin 没在运行,此时应检查 sudo systemctl status webmin

「Access denied for <your IP>。」 您在方案 A 下设置了 IP Access Control,而您当前的地址不在允许列表上,可能是动态 IP 变了,或者是打错了。没有从浏览器回去的途径。从控制台修复:编辑 /etc/webmin/miniserv.conf 中的 allow= 行,改正或删除它,然后运行 sudo systemctl restart webmin

「Login failed. Please try again.」而您确信凭据是对的。 该账户没有 Unix 密码,这在只允许密钥登录的云镜像上是常态。Webmin 通过 PAM 对 Unix 密码进行认证,而该用户并不存在这个密码。修复:在服务器上运行 sudo passwd youruser,然后登录。如果 /var/webmin/miniserv.log 显示 Non-existent login as ...,说明您输入的用户名根本不是一个 Unix 账户。

要管理超过一两台服务器,自动化比在每台机器上装一个控制面板更能扩展:您的第一个 Ansible playbook就是从那里开始的。

FAQ

把 Webmin 暴露在公网上安全吗?

把一个面向互联网的 Webmin 当作一个带登录页面的 root shell 来对待,因为它就是这么回事。它只有在层层防护下才 足够 安全:一张真实证书、双因素认证、Fail2ban,再加上一个严格的 IP 白名单,或者更好地,完全不做公网暴露。风险最低的做法是把 Webmin 绑定到 127.0.0.1 并通过 SSH 隧道访问,这样 10000 端口在开放的互联网上不回应任何人。

怎么去掉 Webmin 的证书警告?

这个警告(NET::ERR_CERT_AUTHORITY_INVALID)出现是因为 Webmin 自带一张自签名证书。请从 Webmin、Webmin Configuration、SSL Encryption、Let's Encrypt 里签发一张真实的证书,用一个指向服务器、并有某个东西为验证提供 80 端口质询的 DNS 名称。如果您只会通过 SSH 隧道访问 localhost 上的 Webmin,这个警告是无害的,SSH 已经加密并认证了连接,您可以放心接受那个自签名证书。

我怎么把 Webmin 限制到只有我的 IP 地址?

进入 Webmin、Webmin Configuration、IP Access Control,选择「Only allow from listed addresses」,并输入您用 curl ifconfig.me 查到的公网 IP。Webmin 会把它存进 /etc/webmin/miniserv.confallow= 行里。当心动态的家庭 IP:如果它变了,您就被锁在外面,必须从服务器控制台修复那条 allow= 行,所以实际上一个静态地址或 SSH 隧道方案更可靠。

为什么密码是对的登录还是失败?

Webmin 通过 PAM 对您的 Unix 密码进行认证,而云镜像通常只允许密钥登录,默认账户没有设置密码,所以 PAM 没有可匹配的东西,登录就被拒绝了。在服务器上运行 sudo passwd youruser 设置一个,然后登录。如果 /var/webmin/miniserv.log 里出现 Non-existent login as ... 这一行,则说明这个用户名本身不是一个真实的 Unix 账户。

和纯 SSH 相比,Webmin 有什么用?

Webmin 是一个便于发现和使用的便利层。它对于浏览日志文件、管理用户和 cron、编辑防火墙规则,以及在不用记住每条命令的情况下查看磁盘和服务状态,确实很有用,对偶尔操作的管理员或技能水平不一的团队来说很方便。纯 SSH 更快、可脚本化,日常工作暴露的攻击面也小得多。许多管理员两者都用:日常操作用 SSH,偶尔需要点点点的活儿就用绑定到 localhost、藏在隧道后面的 Webmin。