一次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,等待他们修复了

相关推荐
晚椰子树31 分钟前
Scala的数据类型
开发语言·后端·scala
安然无虞1 小时前
31天Python入门——第13天:文件操作
开发语言·后端·爬虫·python
Bruce_Liuxiaowei7 小时前
基于Flask的智能天气助手系统设计
后端·python·flask
时光不负追梦人9 小时前
谈谈对spring IOC的理解,原理和实现
java·后端·spring
Asthenia041210 小时前
面试场景题:设计微信朋友圈后端-从接口到数据库的实现
后端
南屿欣风10 小时前
Go 语言中使用 Swagger 生成 API 文档及常见问题解决
开发语言·后端·golang
Asthenia041210 小时前
场景题:设计微信的双向好友添加/建群逻辑
后端
Asthenia041210 小时前
外键是个啥?为什么我要加它?——从面试复盘聊聊数据库设计
后端
程序饲养员11 小时前
Kafka新版本重大更新,发布4.0!!
后端·kafka·消息队列