最早被这两个报错折磨,是在接手一批Linux远程桌面维护工作的时候。用户在客户端输入VNC密码,结果界面弹出“Authentication Failure”,要么就是在建立连接前看到一行“Unencrypted connection”警告,很多人看到英文就慌了,直接截图发过来问怎么办。说实话,这两个报错算是VNC登录失败里出现频率最高的两个坑,一个负责告诉你“密码没通过”,一个负责提醒你“链路没加密”。但它们的成因和处理方式完全不一样,不能靠“重启大法”蒙混过关。
这篇文章我打算把这两个报错一次说清楚。无论你是刚接触VNC的小白,还是被远程桌面问题反复折腾的运维,都应该能从里面找到直接能用的解决方案。我会先拆解报错背后的机制,再给一套标准化的修复流程,最后用一次完整实操复盘把步骤串起来。看完之后,你至少能自己定位问题出在哪,而不是每回都对着报错干瞪眼。
1. 先把两个报错看清楚:问题到底出在哪
1.1 Authentication Failure是什么在“认证失败”
VNC的认证机制其实很简单:VNC Server启动后,会读取当前用户家目录下那个用于保存密码哈希的文件,通常是~/.vnc/passwd。VNC客户端连接时,会把输入的密码发过去,Server端比对哈希,一致就放行,不一致就返回认证失败。
这个文件不是手写的,而是通过vncpasswd命令生成。听起来很基础,但问题恰恰容易出在这里。比如你明明用vncpasswd设了密码,但启动服务时用的用户不对,Server读的是另一个用户家目录下的passwd文件,甚至根本读不到;再比如passwd文件权限是644甚至777,某些版本的TigerVNC出于安全策略直接拒绝读取,也会表现为Authentication Failure。还有一种很隐蔽的情况:VNC密码这个历史包袱保留了早年8个字符的上限,如果你输的密码超过8位,部分旧版本只比对前8位,新版本又整个拒绝,两边对不上,认证自然失败。
所以这个报错的本质,是“Server端用来验证密码的那套文件和权限出了问题”,而不是单纯“你密码输错了”。排查的时候,不能只盯着键盘,要去看服务进程跑在哪个用户下、密码文件在不在、权限对不对、日志里有没有额外线索。
1.2 Unencrypted connection到底在警告什么
另一个报错性质就不一样了。VNC协议本身是从上世纪90年代走过来的,早期设计里没有把加密作为默认能力。你输入的密码、屏幕上的内容,在网络里是以明文方式传输的。也就是说,如果中间被人抓包,理论上可以看到你在VNC会话里敲了什么、屏幕上显示了什么。
现在的VNC Viewer客户端越来越“不给面子”,检测到Server端没有启用TLS/SSL加密,就会弹出Unencrypted connection警告。轻的版本还是提示让你确认后继续,严格一点的版本或配置,直接拒绝建立连接。这不是客户端在找茬,而是安全策略在起作用。尤其在公网环境,明文VNC几乎是裸奔,没人愿意把管理员密码从明文链路里传出去。
所以解决思路有两条:要么给Server端配置证书,开启TLS加密,让链路不再裸奔;要么在内网临时环境里,明确关闭或绕过加密检查。但后者要知道自己在干什么,别把明文连接暴露到不可信网络里。
2. 基础环境准备:从安装到第一个可用的VNC会话
2.1 Server端安装与密码文件初始化
在动手解决报错之前,最好先确认一遍基础环境。这里我以最常见的TigerVNC为例,不同发行版的包管理命令略有差异,但逻辑是一样的。
在Debian/Ubuntu系上:
sudo apt update sudo apt install tigervnc-standalone-server tigervnc-common在CentOS/RHEL系上:
sudo yum install tigervnc-server tigervnc-server-minimal如果你用的是麒麟这类国产Linux发行版,操作思路也基本一致,只是包管理器换成yum或dnf,软件源里包名可能有细微差别。我见过有人强行从第三方源塞通用rpm包,结果依赖冲突,反而不如用系统自带源里匹配好的版本。
安装完之后不要急着启动服务,先把密码文件准备好:
mkdir -p ~/.vnc vncpasswd执行vncpasswd后,会提示你输入密码并确认。这里请记住一个关键细节:VNC的传统密码上限是8位,虽然新版做了扩展,但为了兼容性,我建议你设置密码时控制在8位以内。别觉得8位太短不安全,你可以配合限制来源IP、仅内网访问、SSH隧道等策略来兜底,而不是把密码设得又长又臭然后踩了截断的坑。
生成之后检查一下文件:
ls -l ~/.vnc/passwd正常情况下,这个文件的所属用户应该是当前用户,权限是-rw-------。如果不是这样,后续Authentication Failure基本跑不了。
2.2 用systemd托管VNC服务的正确姿势
创建好密码文件后,第二步是把VNC服务交给systemd管理。很多人图省事直接vncserver :1跑一个前台进程,登录一断服务就没了,这在实际使用里非常难受。我的建议是注册成systemd单元,这样开机自启、崩溃重启都好处理。
在systemd里,最简洁的方式是写一个service文件。以下是一个我在Ubuntu上验证过的方案,端口用:1,对应TCP 5901:
[Unit] Description=VNC Server for user After=syslog.target network.target [Service] Type=forking User=myuser Group=myuser WorkingDirectory=/home/myuser ExecStart=/usr/bin/vncserver :1 -localhost no -geometry 1920x1080 -depth 24 ExecStop=/usr/bin/vncserver -kill :1 [Install] WantedBy=multi-user.target把文件放到/etc/systemd/system/vncserver@.service,然后执行:
sudo systemctl daemon-reload sudo systemctl enable --now vncserver@1这里有几个参数务必要理解,不然出了问题都不知道往哪查。-localhost no表示允许非本机连接,如果留成默认的yes,客户端从外部连过来会直接被拒,表现很像“连接超时”或“无法访问”。-geometry指定分辨率,按你远程客户的屏幕尺寸调就行。-depth 24是色彩深度,一般不用动。User和Group必须指向生成密码文件的那个用户,否则Server读不到正确的~/.vnc/passwd。
如果是防火墙开启状态,别忘了放行对应端口:
sudo firewall-cmd --add-port=5901/tcp --permanent sudo firewall-cmd --reloadUbuntu上如果用的是ufw,则是:
sudo ufw allow 5901/tcp到这里,一个最基本的VNC会话应该已经能跑起来了。接下来才是重头戏:把两个报错一个一个拆掉。
3. 逐个击破:Authentication Failure与Unencrypted connection的修复方案
3.1 认证失败的四步排查法
遇到Authentication Failure,我建议按顺序做四件事,基本能覆盖绝大多数原因。
第一步,看服务日志。TigerVNC会把日志写到用户家目录下,形如~/.vnc/主机名:1.log,或者你用systemd托管的话,直接看journal:
journalctl -u vncserver@1 -e日志里经常会直接写明“Authentication failed”,同时也会暴露更底层的问题,比如“unable to open password file”或者“password file has bad permissions”。那句话比客户端弹窗实在多了。
第二步,检查密码文件是否存在、权限是否正确:
ls -l ~/.vnc/passwd如果文件不存在,重新跑一次vncpasswd。如果权限不对,执行:
chmod 600 ~/.vnc/passwd chown myuser:myuser ~/.vnc/passwd注意,这里的myuser必须和启动VNC服务的用户一致。
第三步,确认服务启动用户。很多人会把systemd单元文件里的User写成root,但密码文件是用普通用户生成的。这时候VNC Server会尝试读取root家目录下的passwd文件,读不到就认证失败。最稳妥的做法是:密码文件归哪个用户,服务就跑在哪个用户下。
第四步,验证密码有没有被“截断”或“污染”。VNC密码是存在哈希文件里的,无法反查明文。如果怀疑密码不对,最简单粗暴但有效的方式就是重新vncpasswd,设一个8位以内的密码,再重启服务。这个操作不丢任何桌面配置,放心改。
如果四步走完还报Authentication Failure,还有一个冷门但真实存在的可能:系统里的PAM配置把VNC的认证流程接管了,而VNC Server和PAM对密码的解读方式不一致。这种情况多发生在修改过/etc/pam.d/相关文件的机器上。排查方法是临时把服务改成不经过PAM的认证方式,但这就涉及安全类型调整了,建议在可控环境下验证,别在线上随意改。
3.2 未加密连接的两种正确处理路径
解决Unencrypted connection的正确姿势,取决于你的使用场景。
如果你让VNC暴露在公网,或者跨越不可信网络连接,我的强烈建议是给VNC Server启用TLS加密。TigerVNC支持X509证书加密,生成自签名证书就够用。证书生成的步骤如下:
sudo mkdir -p /etc/pki/tigervnc sudo openssl req -x509 -nodes -newkey rsa:2048 \ -keyout /etc/pki/tigervnc/vnc.key \ -out /etc/pki/tigervnc/vnc.crt \ -days 3650生成过程中,Common Name随便填个IP或域名就行。接下来需要把证书和密钥告诉VNC Server。修改systemd单元,在ExecStart里追加参数,或者更优雅的方式是写入TigerVNC的配置文件/etc/tigervnc/vncserver-config-defaults:
SecurityTypes=X509Vnc X509Cert=/etc/pki/tigervnc/vnc.crt X509Key=/etc/pki/tigervnc/vnc.key然后重启服务:
sudo systemctl daemon-reload sudo systemctl restart vncserver@1配置完成之后,客户端再去连接,会弹出一个证书确认提示,选择信任即可,Unencrypted connection的警告就不会再出现。注意证书路径在不同发行版上可能不太一样,Ubuntu上习惯放到/etc/ssl/下,Debian系的TigerVNC也认这个路径。
如果你的环境纯粹是办公室内网,所有机器都在自己的可控网段,而且你只是想快速解决警告,那可以在Server端把安全类型显式设为VncAuth,客户端连接时检测到使用的是旧的VNC密码认证,虽然仍会提示未加密,但至少不会因为“没有可用安全类型”而直接拒绝连接。也可以从客户端侧调整:在VNC Viewer的连接属性里,把加密方式改为“始终接受未加密连接”的选项。但请务必记住,这个操作只适合可信内网,一上公网,这就等于把密码和屏幕内容都放在透明玻璃上给人看。
还有一个更稳妥的曲线方案:让VNC Server只监听本地回环,然后用SSH隧道转发到本地端口。也就是把-localhost改成yes,然后客户端这样连:
ssh -L 5901:localhost:5901 myuser@服务器IP然后本地VNC Viewer连接localhost:5901。这样VNC协议本身不暴露到网络里,流量全部走SSH加密隧道,安全性和兼容性都很好。我自己的管理机上就经常这么干,既不需要折腾证书,又不用牺牲安全性。
4. 完整实操复盘:把一台Ubuntu服务器从报错修到能稳定连接
4.1 故障现场与初步定位
为了让你看明白整套排查流程,我拿一个真实的故障场景复盘。一台Ubuntu 22.04服务器,用户说VNC连不上,客户端提示Authentication Failure。我登录服务器后,第一步就是看服务状态和日志:
systemctl status vncserver@1 journalctl -u vncserver@1 -e日志里出现了一行关键词:
TigerVNC Server failed to open password file这下基本不用猜了,密码文件路径有问题。我切到服务配置里用的用户,检查~/.vnc/passwd是否存在:
ls -l /home/myuser/.vnc/结果发现.vnc目录存在,但里面没有passwd文件。原来这台机器之前是用root身份装过一次VNC,密码文件生成在/root/.vnc/passwd里,后来systemd单元文件被改成以myuser用户启动,两边对不上,就一路报Authentication Failure。
这种情况在实际维护中非常典型,特别是那种“之前能用、后来不能用了”的机器,多半是有人改过启动用户或重置过系统账户。解决办法很简单:用当前服务用户重新生成密码文件:
sudo -u myuser vncpasswd或者切换到myuser用户再执行,注意家目录和权限。
4.2 修改后的最终配置与启动验证
为了让这台机器以后不再出同类问题,我把systemd单元文件整理成了下面这样,把用户、工作目录、密码文件路径都锁死:
[Unit] Description=VNC Server for myuser After=syslog.target network.target [Service] Type=forking User=myuser Group=myuser WorkingDirectory=/home/myuser ExecStart=/usr/bin/vncserver :1 -localhost no -geometry 1920x1080 -depth 24 -SecurityTypes X509Vnc ExecStop=/usr/bin/vncserver -kill :1 [Install] WantedBy=multi-user.target同时确认证书文件存在:
ls -l /etc/pki/tigervnc/vnc.crt /etc/pki/tigervnc/vnc.key重启服务:
sudo systemctl daemon-reload sudo systemctl restart vncserver@1然后我习惯做三个验证。第一,服务是否处于running状态:
systemctl status vncserver@1第二,端口是否在监听:
ss -tlnp | grep 5901第三,从客户端用VNC Viewer连接服务器的IP:1。这时VNC Viewer会先问证书是否信任,确认之后,文件管理器、终端窗口正常渲染,Authentication Failure和Unencrypted connection都没有再出现。
整个过程中有个容易被忽略的点:如果你之前用旧配置启动过VNC,端口上可能残留了僵死进程。如果ss输出里看到端口被占用但进程PID对不上,先vncserver -kill :1,再确认进程确实没了,最后重启服务。这类“旧进程没杀掉”导致的异常,重启不一定能解决,必须手动清干净。
5. 高频问题速查与我们的避坑记录
5.1 常见问题速查表
我把这些年遇到的VNC问题整理成一张速查表,方便你以后直接对照。
| 现象 | 最可能原因 | 处理方法 |
|---|---|---|
| 客户端提示Authentication Failure | 密码文件缺失或权限不对 | 用启动用户重新执行vncpasswd,chmod 600 |
| 密码明明正确但认证失败 | 服务用户和密码文件用户不一致 | 统一systemd单元里的User和家目录 |
| 提示Unencrypted connection | VNC Server未启用TLS | 配置X509证书,或在可信内网调整安全类型 |
| 客户端能连上但黑屏 | xstartup缺失或没有执行权限 | 创建~/.vnc/xstartup,写入桌面会话,chmod +x |
| 外部无法连接,但本机能连 | -localhost参数为yes,或防火墙拦截 | 改为-localhost no,放行5901端口 |
| 端口被占用,重启无效 | 旧VNC进程残留 | vncserver -kill :1,确认PID消失后再启动 |
| 连接速度极慢,画面卡顿 | 分辨率或色彩深度过高 | 调低-geometry分辨率,用-depth 16 |
| 客户端提示没有可用安全类型 | Server端SecurityTypes配置错误 | 检查vncserver-config-defaults或ExecStart参数 |
表格之外,还有一条:如果你看到网上某个网站提供“VNC激活秘钥”或者“破解版VNC”,我劝你别碰。开源VNC方案本身就不需要激活,TigerVNC、Turbovnc这些项目完全免费。那些所谓的秘钥,轻则让你下载到捆绑广告软件的安装包,重则可能夹带恶意程序。用正规软件源里的包,比什么“破解秘钥”都靠谱。
5.2 几次踩坑之后的经验总结
做了这么多年远程桌面维护,踩过不少坑,有几个经验我觉得比任何命令都值钱。
第一,VNC服务一定要用systemd托管,不要图方便前台运行。不是每次你都有机会登录服务器重新拉起进程的,尤其在远程维护场景下,服务起不来的后果就是你要么求助机房,要么等人工介入。
第二,密码文件权限这种“低级问题”反而是最高频的生产事故。我见过不止一次,运维为了省事,把~/.vnc目录整个chmod -R 777,结果TigerVNC因为安全策略直接拒绝读取密码文件,报Authentication Failure。这类问题藏得很深,因为表面看权限“更开放了”,实际上反而触发保护机制。
第三,Unencrypted connection警告出现时,不要第一反应就是关掉安全选项。先问自己一句:这台VNC服务器部署在什么网段?谁有权限访问?如果答案是“公网”,那无论如何都要上加密。哪怕只是自签名证书,也好过明文裸奔。麻烦一次,受益长期。
第四点也算一个实践技巧:如果有多台服务器需要管理,建议统一端口和分辨率规范。比如所有机器都用:1端口、1920x1080分辨率,密码策略统一。这样维护的时候不会因为“这台是5901那台是5902”而手忙脚乱。人脑的记忆带宽有限,能标准化的东西就别靠记。
最后分享一个小习惯:每次改完VNC配置,我都会在日志里留个标记,执行一次vncserver -list看看当前会话状态,再顺手用客户端连一次。别嫌这一步多余,很多问题就是在改完配置后没做回归验证,等到下个工作日才被用户发现,那就尴尬了。把验证动作固化到操作流程里,比事后懊恼强得多。