一次tls握手失败导致的vnc不可用

序言

直接从我的个人博客 cv过来的。 看看我的个人博客喵,看看我的个人博客谢谢喵. 也因为是从博客cv过来的,图床用的是自己的,如果访问有影响的话,我在复制图片过来。

前言

使用 guacd 连接高版本 vnc 服务遇见了失败

检验 vnc 服务器输出

可见tls握手失败。

这里我们优先质疑是 centos 的问题,因为它的本机openssl 版本为:1.0.2k

查看支持的加密套件库,甚至看不到tls1.3 ,而且还有 ssl3.0

实验中定位,实验中解决

笔者计划:

  • 升级 centos openssl 库 查看是否可以
  • 若不行,升级 guacd 编译机器重新编译guacd 验证是否可行

笔者先给出最终的方法,具体的解决过程将在后续逐渐给出:

  • 运行机器 openssl 肯定需要升级
  • Guacd 也需要在升级了openssl 的情况下编译
  • Guacd 的 vnc 服务依赖 libvncserver 实现,因而 libvnvserver 也需要在编译机器重新编译

同时需要考虑到安装包的问题,所以这里的 openssl 与 libvncserver 的升级方案,都需要做rpm包

所以我们最终需要的是

  • Openssl 新版本 rpm
  • 指向了 新 openssl 的 libvncserver 的rpm
  • 指向了 新libvncserver 的guacd

Openssl rpm 构建

笔者先是参考了一篇文章与一个github仓库:

CentOS7制作rpm包升级OpenSSL

Build latest OpenSSL binary for CentOS

构建过程为:

安装依赖

shell 复制代码
yum install rpm-build rpmlint rpmdevtools -y
yum install gcc gcc-c++ make perl perl-WWW-Curl -y

构建文件夹

mkdir -p /root/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

移动包到目标下

cp openssl-1.1.1w.tar.gz ~/rpmbuild/SOURCES/

创建 spec

vi ~/rpmbuild/SPECS/openssl.spec 填写内容:

spec 复制代码
Summary: OpenSSL 1.1.1w for redhat
Name: openssl
Version: %{?version}%{!?version:1.1.1w}
Release: 1%{?dist}
Obsoletes: %{name} <= %{version}
Provides: %{name} = %{version}
URL: https://www.openssl.org/
License: GPLv2+

Source: https://www.openssl.org/source/%{name}-%{version}.tar.gz 
 
BuildRequires: make gcc perl perl-WWW-Curl
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
%global openssldir /usr/local/openssl1.1.1w
 
%description
OpenSSL RPM for version 1.1.1w on redhat
 
%package devel
Summary: Development files for programs which will use the openssl library
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
 
%description devel
OpenSSL RPM for version 1.1.1w on redhat (development package)
 
%prep
%setup -q
 
%build
./config --prefix=%{openssldir} --openssldir=%{openssldir}
make -j4
 
%install
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%make_install
 
mkdir -p %{buildroot}%{_bindir}
mkdir -p %{buildroot}%{_libdir}
ln -sf %{openssldir}/lib/libssl.so.1.1 %{buildroot}%{_libdir}
ln -sf %{openssldir}/lib/libcrypto.so.1.1 %{buildroot}%{_libdir}
ln -sf %{openssldir}/bin/openssl %{buildroot}%{_bindir}
 
%clean
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
 
%files
%{openssldir}
%defattr(-,root,root)
/usr/bin/openssl
/usr/lib64/libcrypto.so.1.1
/usr/lib64/libssl.so.1.1
 
%files devel
%{openssldir}/include/*
%defattr(-,root,root)
 
%post -p /sbin/ldconfig
 
%postun -p /sbin/ldconfig

执行构建

rpmbuild -D "version 1.1.1w" -ba openssl.spec

这里可以看到,选择了将openssl 安装到了自定义文件夹下,而不是默认文件夹,这是因为直接替换的情况下,centos有很多依赖 1.0.2 libs 与 devel 的组件,会导致系统崩溃。

那么第一步,openssl 的 rpm 包就好了

这里做验证:

rpm -ivh --force --nodeps xxx.rpm 安装完成后查看,可见已经在运行 openssl 1.1.1w

并且执行 openssl ciphers -v 也可以看到已经支持了tls1.3

但是这里运行,guacd 还是连接失败,从日志可以定位到仍然在使用 openssl 1.0.2 k,所以需要重新编译guacd

编译guacd

编译guacd 基本与原本的没有区别,只是对 configure 做了增加 改为了 ./configure --prefix=/custom/server

--with-init-dir=/custom/server

--disable-kubernetes --enable-shared

CPPFLAGS="-I/usr/local/openssl1.1.1w/include"

LDFLAGS="-L/usr/local/openssl1.1.1w/lib"

--with-openssl=/usr/local/openssl1.1.1w 但是这个版本还是不可用。 当时还没有考虑好c的编译依赖等情况,只是单程的在想,是不是 libvncserver 需要重新编译? 于是我也编译了libvncserver

Libvncserver

使用如下 cmake 进行配置,之后make&& make install cmake -DCMAKE_C_FLAGS="-I/usr/local/openssl1.1.1w/include"

-DCMAKE_CXX_FLAGS="-I/usr/local/openssl1.1.1w/include"

-DCMAKE_EXE_LINKER_FLAGS="-L/usr/local/openssl1.1.1w/lib"

-DCMAKE_SHARED_LINKER_FLAGS="-L/usr/local/openssl1.1.1w/lib"

-DOPENSSL_ROOT_DIR=/usr/local/openssl1.1.1w

-DOPENSSL_LIBRARIES=/usr/local/openssl1.1.1w/lib

-DOPENSSL_INCLUDE_DIR=/usr/local/openssl1.1.1w/include

-DCMAKE_INSTALL_PREFIX=/opt/libvnc

..

弯路子

然后再次进行了 guacd 编译。但是还是不行。这时想起了同事之前说过的链接。于是去ldd 看了下 guacd

可以看到,引用了 libssl1.1 但是还有老版本的 10.而vnc 的链接居然没有。

到了这一步,笔者走了一个弯路子,认为是不是只要我将guacd对libssl 10.so的全部依赖组件都升级成1.1.1w的就可以了。 甚至开始去做,比如从 guacd 的编译日志中看到了

于是开始去做 openldap 的升级。 当然,这些操作是不必要的,所以这里忽略不记了。

直到最后,在一个 StackOverflow Does Apache Guacamole support VNC Connection with GNUTLS? 中有人提及了一个论坛 或者说邮件

Guacd 的 vnc 连接方式完全取决于 libvncclient 。 而libvncclient 组件是 libvncserver 的一部分。 所以又回到了之前的问题上面了,libvncserver 为什么没有启用 新的 openssl。 或者说,为什么 guacd 没有使用新的 libvncserver。

这里回到 guacd 没有 vnc 依赖的问题。在同事帮助下,得知 guacd 的这几个协议是动态加载的,所以主程序没有依赖是正常的,它们在

可以看到,它引用的 vnc 不是我们重新编译的,而是旧的。那么这里破案了。

Guacd -> 老libvnc -> openssl 1.0.2k

所以我们将 guacd 重新指向新的libvnc就好了,这里学习 openssl 的方法,将libvnc 也安装到了一个独立文件夹

Libvncserver rpm

考虑到前文已经给出了一个rpm的全过程,所以这里只写spec

ini 复制代码
Name:           libvncserver
Version:        0.9.15
Release:        1%{?dist}
Summary:        A library for creating VNC servers and clients

License:        GPLv2+
URL:            https://github.com/LibVNC/libvncserver
Source0:        libvncserver-LibVNCServer-%{version}.tar.gz

BuildRequires:  gcc, make, cmake
Requires:       glibc

%description
LibVNCServer is a library that makes it easy to implement VNC server or client functionality.

%prep
%setup -q -n libvncserver-LibVNCServer-%{version}

%build
# 使用 CMake 构建,添加你的编译选项
mkdir -p build
cd build
cmake -DCMAKE_C_FLAGS="-I/usr/local/openssl1.1.1w/include" \
      -DCMAKE_CXX_FLAGS="-I/usr/local/openssl1.1.1w/include" \
      -DCMAKE_EXE_LINKER_FLAGS="-L/usr/local/openssl1.1.1w/lib" \
      -DCMAKE_SHARED_LINKER_FLAGS="-L/usr/local/openssl1.1.1w/lib" \
      -DOPENSSL_ROOT_DIR=/usr/local/openssl1.1.1w \
      -DOPENSSL_LIBRARIES=/usr/local/openssl1.1.1w/lib \
      -DOPENSSL_INCLUDE_DIR=/usr/local/openssl1.1.1w/include \
      -DCMAKE_INSTALL_PREFIX=/opt/libvnc \
      ..
make %{?_smp_mflags}

%install
# 安装到指定目录
rm -rf $RPM_BUILD_ROOT
cd build
make install DESTDIR=$RPM_BUILD_ROOT

%files
/opt/libvnc/include
/opt/libvnc/lib64

%changelog
* Tue Feb 18 2025 y1nhui <[email protected]> - 0.9.15-1
- Initial RPM release

可以看到,我将libvnc 安装到了 /opt/libvnc 文件夹下

之后就是重新编译 guacd

新 guacd

shell 复制代码
./configure --prefix=/custom/server \
            --with-init-dir=/custom/server \
            --disable-kubernetes \
            --enable-shared \
            CPPFLAGS="-I/usr/local/openssl1.1.1w/include -I/opt/libvnc/include" \
            LDFLAGS="-L/usr/local/openssl1.1.1w/lib -L/opt/libvnc/lib64/ -Wl,-rpath=/opt/libvnc/lib64"

补充了 libvnc,可以看到 指向了

这个版本的guacd 也确实可以连接了

这里如果有眼尖的读者,或许可以看到日志中有一个告警。这是一个坑,后续会谈到

新的问题

看上去一切ok了,但是在实际测试中发现了新的问题。只是可以连上去了,一操作就要崩溃 同时有一个偶现日志:

去除对 gcrypt 的依赖

这时候还是有些迷茫的,先一步步来吧。 上面我也提到了有个告警的坑

Libgcrypt 告警。但是这是 gnutls 的加解密库,openssl 并不依赖它。 笔者就在想,是不是 guacd 有类似 https 连接的一种省略方法,前期握手的时候使用非对称加密,彻底连接后使用对称加密来减少性能开销,而这一步正好用了 libgcrypt

于是继续走弯路,想要升这里,不过幸好看到了 libvncserver 的官方issue

这里提到了 关闭 ssl,开启gcrypt 的方法,那笔者反过来,关闭 gnutls 与 gcrypt 开启tls就好了

所以改成了这样。

shell 复制代码
cmake -DCMAKE_C_FLAGS="-I/usr/local/openssl1.1.1w/include" \
      -DCMAKE_CXX_FLAGS="-I/usr/local/openssl1.1.1w/include" \
      -DCMAKE_EXE_LINKER_FLAGS="-L/usr/local/openssl1.1.1w/lib" \
      -DCMAKE_SHARED_LINKER_FLAGS="-L/usr/local/openssl1.1.1w/lib" \
      -DOPENSSL_ROOT_DIR=/usr/local/openssl1.1.1w \
      -DOPENSSL_LIBRARIES=/usr/local/openssl1.1.1w/lib \
      -DOPENSSL_INCLUDE_DIR=/usr/local/openssl1.1.1w/include \
      -DCMAKE_INSTALL_PREFIX=/opt/libvnc \
      -DWITH_GNUTLS=OFF \
      -DWITH_OPENSSL=ON \
      -DWITH_FFMPEG=OFF \
      -DWITH_GCRYPT=OFF \
      ..

到这一步 gcrypt 的依赖就去除了,直接将rpm 换上去看看。

回退 libvncserver 版本

但是问题仍然存在,这时候就想照猫画虎,用一下 gdb 调试,不过看到了一个issue,他也遇到了类似的崩溃问题,但是说 使用 -f 启用就一切ok,所以我也是试了试

/custom/server/sbin/guacd -p /var/run/guacd.pid -f

然后开始运维,还是会出错,但是看到了更详细的日志

这一步笔者其实没有办法了,只是在收集的时候,发现其他环境的libvnserver 都是 0.9.14,只有这里,因为是我手动编译的,所以是更新的 0.9.15 所以我干脆重新替换了一下,使用0.9.14

然后好了。。。。

具体的问题到底是什么也不知道了,笔者只给 libvncserver 官方提了个issue,等待他们修复了

相关推荐
源码云商2 小时前
基于Spring Boot + Vue的母婴商城系统( 前后端分离)
java·spring boot·后端
还听珊瑚海吗6 小时前
基于SpringBoot的抽奖系统测试报告
java·spring boot·后端
你怎么知道我是队长8 小时前
Go语言标识符
后端·golang
sco528212 小时前
SpringBoot 自动装配原理 & 自定义一个 starter
java·spring boot·后端
海风极客13 小时前
《Go小技巧&易错点100例》第三十三篇
开发语言·后端·golang
养军博客13 小时前
Spring boot 简单开发接口
java·spring boot·后端
计算机学姐15 小时前
基于SpringBoot的在线教育管理系统
java·vue.js·spring boot·后端·mysql·spring·mybatis
有梦想的攻城狮16 小时前
spring中的@Value注解详解
java·后端·spring·value注解
编程乐趣17 小时前
基于.Net Core开发的GraphQL开源项目
后端·.netcore·graphql
阿乾之铭17 小时前
Spring Boot 中的重试机制
java·spring boot·后端