news 2026/7/28 12:04:06

Ubuntu 22.04编译支持国密SSL与HTTP/2的Curl完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu 22.04编译支持国密SSL与HTTP/2的Curl完整指南

1. 项目概述与核心价值

最近在做一个需要对接国内某金融系统接口的项目,对方明确要求通信链路必须支持国密SSL(GM/T 0024-2014)协议,同时为了性能考虑,还希望启用HTTP/2。我手头的主力开发环境是Ubuntu 22.04 LTS,系统自带的Curl版本虽然功能强大,但默认并不支持国密算法。网上搜了一圈,发现现成的、同时支持国密和HTTP/2的Curl二进制包几乎没有,即便有,版本和依赖库也可能不匹配,在生成环境部署时容易埋坑。于是,我决定从源码开始,手动编译一个“定制版”的Curl。

这个“从零编译”的过程,远不止是简单的./configure && make。它涉及到几个关键组件的协同:首先是Curl本身,它是我们最终要得到的工具;其次是国密SSL的实现库,我选择了国内开源且活跃的“铜锁”(Tongsuo,原BabaSSL);最后是HTTP/2的支持库nghttp2。整个过程就像搭积木,你需要确保每一块“积木”(库)都正确编译、链接,并且彼此兼容。最终,我成功在Ubuntu 22.04上编译出了同时支持国密套件(如ECC-SM2-SM4-CBC-SM3)和HTTP/2协议的Curl。这篇文章,我就把完整的配置、编译步骤、踩过的坑以及验证方法,毫无保留地分享出来。无论你是开发、运维还是安全工程师,只要你有在Linux环境下构建支持国密标准工具链的需求,这篇指南都能帮你省下大量摸索的时间。

2. 编译环境准备与依赖梳理

工欲善其事,必先利其器。在动手编译之前,我们需要一个干净、可靠的编译环境,并安装所有必要的依赖。Ubuntu 22.04本身是一个很稳定的基础,但我们仍需进行一些准备。

2.1 系统更新与基础工具安装

首先,确保你的系统是最新的。打开终端,执行以下命令更新软件包列表并升级现有软件。这一步能避免一些因基础库版本过旧导致的编译问题。

sudo apt update sudo apt upgrade -y

接下来,安装编译所需的“工具链”和基础开发包。这包括编译器(gcc/g++)、构建工具(make、cmake)、版本控制(git)以及一些通用的开发库。

sudo apt install -y build-essential git cmake autoconf libtool pkg-config

注意build-essential这个元包非常重要,它包含了gcc, g++, make, libc-dev等核心编译工具。缺少它,后续的./configure步骤大概率会失败。

2.2 编译铜锁(Tongsuo)的专项依赖

铜锁SSL库的编译有自己特定的依赖要求。它需要Perl来生成一些配置文件,并且依赖于zlib库进行压缩。

sudo apt install -y perl zlib1g-dev

这里特别强调一下zlib1g-devzlib1g是运行时库,而zlib1g-dev包含了开发所需的头文件(.h)和静态库(.a)。如果只安装了zlib1g,在编译链接阶段会报错找不到zlib.h

2.3 编译nghttp2的专项依赖

nghttp2库的依赖相对简单,但有一个容易忽略的点:它需要libc-ares-devlibev-dev来支持更高效的异步DNS解析和事件循环,这对于高性能HTTP/2客户端很重要。

sudo apt install -y libc-ares-dev libev-dev

2.4 为Curl编译准备额外依赖

虽然Curl的依赖很多可以通过后续的./configure脚本自动检测并提示,但提前安装好可以避免反复配置的麻烦。我们主要需要SSL库(这里我们将用自己编译的铜锁)、zlib以及idn(国际化域名)的支持。

sudo apt install -y zlib1g-dev libidn2-dev

你可能注意到,我们并没有安装libssl-dev。这是因为我们将使用自己编译的铜锁库来替代系统自带的OpenSSL。如果系统已安装libssl-dev,原则上不会冲突,但为了纯净和避免链接混淆,我们选择不安装,并在后续配置中明确指定铜锁的路径。

至此,所有必要的依赖已经安装完毕。你可以通过gcc --versioncmake --version等命令验证工具是否就绪。

3. 铜锁SSL(Tongsuo)库的编译与安装

铜锁是整个环节的基石,它为Curl提供了国密算法的能力。我们选择从GitHub拉取最新的稳定代码进行编译。

3.1 获取源代码与配置

首先,找一个合适的目录,克隆铜锁的仓库。我习惯在/usr/local/src下操作,方便管理。

cd /usr/local/src sudo git clone https://github.com/Tongsuo-Project/Tongsuo.git cd Tongsuo

在编译之前,建议切换到某个稳定版本的分支或标签,而不是直接使用master分支,以保证稳定性。你可以通过git tag查看版本列表。例如,我选择8.3.0版本。

git checkout 8.3.0

接下来是配置环节。铜锁提供了类似OpenSSL的config脚本。我们需要启用国密特性(enable-gmssl),并指定安装路径(--prefix)。将其安装到/usr/local/tongsuo是一个清晰的选择,与系统自带的OpenSSL(通常在/usr)隔离。

./config --prefix=/usr/local/tongsuo enable-gmssl shared

参数解析

  • --prefix=/usr/local/tongsuo:指定安装目录。编译后的库文件、头文件都会安装在此路径下。
  • enable-gmssl关键参数。启用国密算法支持。没有这个,编译出的库就不支持SM2、SM3、SM4等算法。
  • shared:生成动态链接库(.so文件)。这样编译出的Curl可以动态链接铜锁,便于后续更新。

3.2 编译、测试与安装

配置完成后,使用make进行编译。-j$(nproc)参数可以利用你CPU的所有核心并行编译,显著加快速度。

make -j$(nproc)

编译过程可能需要几分钟,取决于你的机器性能。编译完成后,强烈建议运行测试套件,确保编译的库在基础功能上是正常的。

make test

如果测试全部通过,就可以安装了。安装命令会将编译好的库和头文件复制到之前--prefix指定的目录(/usr/local/tongsuo)中。

sudo make install

3.3 配置系统动态链接器

安装完成后,我们需要让系统知道这个新库的位置。编辑动态链接器的配置文件:

sudo bash -c "echo '/usr/local/tongsuo/lib' > /etc/ld.so.conf.d/tongsuo.conf"

然后更新动态链接库的缓存:

sudo ldconfig

现在,你可以验证铜锁库是否安装成功并支持国密:

/usr/local/tongsuo/bin/openssl version /usr/local/tongsuo/bin/openssl ciphers -v | grep -i sm

第一条命令应输出类似“Tongsuo 8.3.0”的信息。第二条命令会列出所有密码套件,你应该能看到包含SM2SM4SM3的国密套件,例如ECC-SM2-WITH-SM4-SM3

实操心得make test这一步不要省略。我曾有一次跳过了测试,编译安装都顺利,但后来Curl链接时出现奇怪的符号错误,回溯发现是铜锁编译时某个模块未正确生成。运行测试能提前发现大部分基础问题。

4. nghttp2库的编译与安装

nghttp2是HTTP/2协议的C语言实现库,Curl通过它来支持HTTP/2。我们同样从源码编译,以获得与当前系统环境的最佳兼容性。

4.1 获取与编译nghttp2

nghttp2的编译过程比较标准。首先从其官方发布页面获取稳定版源码包,或者使用git克隆。这里以发布包为例(版本号请替换为最新稳定版):

cd /usr/local/src sudo wget https://github.com/nghttp2/nghttp2/releases/download/v1.55.1/nghttp2-1.55.1.tar.gz sudo tar -xzf nghttp2-1.55.1.tar.gz cd nghttp2-1.55.1

然后执行标准的自动化编译安装流程。--prefix指定安装路径,--enable-lib-only表示只编译库文件(不编译客户端、服务器等可执行程序),因为我们只需要它的库来支持Curl。

./configure --prefix=/usr/local/nghttp2 --enable-lib-only make -j$(nproc) sudo make install

同样,安装后需要更新链接库缓存:

sudo bash -c "echo '/usr/local/nghttp2/lib' > /etc/ld.so.conf.d/nghttp2.conf" sudo ldconfig

4.2 验证nghttp2库安装

可以通过检查pkg-config文件来验证nghttp2的安装是否被系统识别:

pkg-config --cflags --libs libnghttp2

如果安装正确,这条命令会输出包含-I/usr/local/nghttp2/include-L/usr/local/nghttp2/lib的编译链接标志。

5. Curl的编译与集成配置

前面所有的准备工作,都是为了这一步:编译一个同时链接铜锁和nghttp2的Curl。

5.1 获取Curl源码并配置

前往Curl官网下载最新稳定版源码,或者使用git。这里以下载包为例:

cd /usr/local/src sudo wget https://curl.se/download/curl-8.6.0.tar.gz sudo tar -xzf curl-8.6.0.tar.gz cd curl-8.6.0

接下来是最关键的./configure步骤。我们需要通过参数明确告诉Curl:

  1. 使用我们编译的铜锁,而不是系统OpenSSL。
  2. 启用nghttp2支持。
  3. 安装到独立目录,避免覆盖系统自带的curl。
./configure --prefix=/usr/local/curl-gmssl \ --with-openssl=/usr/local/tongsuo \ --with-nghttp2=/usr/local/nghttp2 \ --with-zlib \ --with-libidn2 \ --enable-http \ --enable-https \ --enable-ipv6 \ --disable-shared \ --enable-static \ --without-libssh2 \ --without-librtmp

关键配置参数深度解析

  • --prefix=/usr/local/curl-gmssl:指定Curl的安装路径。这样编译出来的curl会独立安装在/usr/local/curl-gmssl下,与/usr/bin/curl互不干扰。
  • --with-openssl=/usr/local/tongsuo核心参数。指示Curl使用位于/usr/local/tongsuo的铜锁库。Curl的配置脚本会在这个路径下寻找include/openssllib目录。
  • --with-nghttp2=/usr/local/nghttp2:指示Curl使用我们编译的nghttp2库来支持HTTP/2。
  • --with-zlib--with-libidn2:启用压缩和国际化域名支持。
  • --disable-shared --enable-static:这里我选择编译成静态链接的Curl。这意味着铜锁和nghttp2的代码会被直接打包进最终的curl可执行文件里。这样做的好处是生成的是一个独立的、不依赖特定库版本的单文件,分发和部署极其方便。缺点是文件体积会稍大。如果你希望动态链接,可以去掉这两个参数,但需要确保运行环境也有对应版本的铜锁和nghttp2动态库。
  • --without-libssh2--without-librtmp:禁用我们不需要的SCP/SFTP和RTMP协议支持,让编译更专注,减少不必要的依赖。

5.2 编译与安装静态版Curl

配置成功后,就可以开始编译了。

make -j$(nproc)

编译完成后,进行安装:

sudo make install

安装完成后,我们编译的curl可执行文件位于/usr/local/curl-gmssl/bin/curl

5.3 创建便捷使用方式

为了方便使用,可以创建一个软链接到/usr/local/bin,或者直接将该路径加入PATH环境变量。

sudo ln -sf /usr/local/curl-gmssl/bin/curl /usr/local/bin/curl-gm

现在,你就可以在终端里直接使用curl-gm命令来调用我们定制编译的版本了。

6. 功能验证与性能测试

编译安装完成,必须进行全面验证,确保国密SSL和HTTP/2功能都正常工作。

6.1 基础版本与功能检查

首先,检查curl的版本和编译时启用的功能:

curl-gm --version

在输出信息中,你需要重点关注以下几行:

  • Features里应该包含httpsHTTP2
  • Protocols里应该包含httphttps
  • 最重要的是SSL信息,应该显示为TongsuoBabaSSL,并且后面有版本号,而不是系统的OpenSSL

6.2 国密SSL连接测试

测试国密功能,需要一个支持国密算法的服务器。你可以自己搭建一个测试服务,或者使用一些公开的国密测试站点(请注意使用合规的测试环境)。这里以假设你有一个支持国密的服务器gmtest.example.com:443为例。

测试命令:

curl-gm -v --ciphers 'ECC-SM2-SM4-CBC-SM3' --tlsv1.2 https://gmtest.example.com

参数解析与结果判断:

  • -v:输出详细过程,便于调试。
  • --ciphers 'ECC-SM2-SM4-CBC-SM3'关键参数。强制curl使用指定的国密密码套件进行协商。如果服务器不支持此套件,握手会失败。
  • --tlsv1.2:指定TLS 1.2协议。国密算法通常运行在TLS 1.2及以上版本。
  • -v的详细输出中,你需要寻找:
    1. * SSL connection using TLSv1.2 / ECC-SM2-SM4-CBC-SM3这样一行,这明确表示使用了国密套件。
    2. 整个握手过程没有报错,最终成功获取到响应内容(哪怕是404或主页HTML)。

6.3 HTTP/2协议测试

测试HTTP/2相对简单,可以使用支持HTTP/2的知名公共服务,比如Cloudflare或谷歌。

curl-gm -v --http2 https://www.cloudflare.com/ -o /dev/null

在详细输出中,寻找* Using HTTP2, server supports multi-use* Connection state changed (HTTP/2 confirmed)这样的行,这确认了连接成功升级到了HTTP/2。

6.4 综合性能与兼容性验证

你可以编写一个简单的脚本来同时测试两种特性。例如,先使用HTTP/2从公共站点下载一个小文件,再尝试向国密测试服务器发起一个POST请求。

# 测试HTTP/2下载 echo “测试HTTP/2:” curl-gm --http2 -s -w “HTTP版本: %{http_version}, 耗时: %{time_total}s\n” https://http2.golang.org/serverpush -o /dev/null # 测试国密HTTPS请求 (假设为GET请求) echo -e “\n测试国密SSL:” curl-gm -v --ciphers ‘ECC-SM2-SM4-CBC-SM3’ --tlsv1.2 -s -w “SSL协议: %{ssl_verify_result}, 密码套件: %{cipher}\n” https://gmtest.example.com 2>&1 | grep -E “(SSL connection|HTTP/2|error)”

7. 常见问题排查与解决方案实录

编译过程很少一帆风顺,以下是我在多次实践中遇到的典型问题及其解决方法。

7.1 配置阶段错误

问题1:configure: error: Could not find libnghttp2

  • 原因./configure脚本在默认路径或指定路径下找不到nghttp2的开发文件(libnghttp2.songhttp2.h)。
  • 解决
    1. 确认--with-nghttp2=/usr/local/nghttp2路径是否正确。
    2. 确认/usr/local/nghttp2/lib/pkgconfig目录是否存在libnghttp2.pc文件。如果没有,可能是nghttp2安装失败。
    3. 设置PKG_CONFIG_PATH环境变量,帮助configure找到它:export PKG_CONFIG_PATH=/usr/local/nghttp2/lib/pkgconfig:$PKG_CONFIG_PATH,然后重新运行./configure

问题2:configure: error: OpenSSL libraries not found

  • 原因:找不到指定的铜锁(OpenSSL兼容)库。
  • 解决
    1. 检查--with-openssl=/usr/local/tongsuo路径。确保/usr/local/tongsuo/lib下有libssl.solibcrypto.so等文件。
    2. 执行sudo ldconfig更新库缓存。
    3. 同样可以尝试设置PKG_CONFIG_PATHexport PKG_CONFIG_PATH=/usr/local/tongsuo/lib/pkgconfig:$PKG_CONFIG_PATH

7.2 编译阶段错误

问题3:fatal error: openssl/ssl.h: No such file or directory

  • 原因:编译器找不到OpenSSL的头文件。虽然我们指定了路径,但可能静态链接时需要显式指定头文件路径。
  • 解决:这通常发生在复杂的编译环境中。一个稳妥的方法是,在configure之前,临时设置CPPFLAGSLDFLAGS环境变量:
    export CPPFLAGS=“-I/usr/local/tongsuo/include -I/usr/local/nghttp2/include” export LDFLAGS=“-L/usr/local/tongsuo/lib -L/usr/local/nghttp2/lib” ./configure ... (其他参数不变)
    这显式地告诉了编译器头文件和库文件的搜索路径。

问题4:链接错误,提示undefined reference tonghttp2_session_callbacks_new‘`等

  • 原因:链接器找不到nghttp2的库函数。在静态编译时,库的链接顺序很重要。
  • 解决:确保Curl的configure命令中--with-nghttp2参数正确。如果问题依旧,可以尝试在configure后,手动编辑生成的Makefile,在LIBS变量中确保-lnghttp2出现在依赖它的库之后(通常靠后即可)。但更建议清理后,用上一条的CPPFLAGSLDFLAGS方法重新配置编译。

7.3 运行时错误

问题5:运行curl-gm时提示error while loading shared libraries: libtongsuo.so.3: cannot open shared object file

  • 原因:如果你编译的是动态链接的curl,运行时系统找不到铜锁的动态库。
  • 解决
    1. 确认已执行sudo ldconfig
    2. 检查/etc/ld.so.conf.d/tongsuo.conf文件是否存在且内容正确。
    3. 可以临时指定库路径:LD_LIBRARY_PATH=/usr/local/tongsuo/lib:$LD_LIBRARY_PATH curl-gm ...。但永久方案还是ldconfig

问题6:国密握手失败,提示no ciphers availablesslv3 alert handshake failure

  • 原因
    1. 服务器不支持你指定的国密套件ECC-SM2-SM4-CBC-SM3
    2. 客户端(curl)虽然支持该套件,但铜锁库在编译时某些国密算法未正确启用。
    3. 证书问题。国密连接通常需要使用SM2证书。
  • 解决
    1. 先用/usr/local/tongsuo/bin/openssl ciphers -v | grep SM确认本地支持的国密套件列表。
    2. 尝试不指定--ciphers,让curl和服务器自动协商,看是否能协商出国密套件(在-v输出中查看Cipher行)。
    3. 确认服务器端确实配置并启用了国密SSL。
    4. 检查是否使用了正确的SM2证书和私钥。

7.4 静态编译与动态编译的选择建议

这是我踩过的一个大坑。最初我编译了动态链接版本,部署到另一台机器时,因为库版本依赖问题跑不起来。

  • 静态编译(--enable-static --disable-shared

    • 优点:生成单一可执行文件,依赖全部打包进去,移植性极强。拷贝到任何同架构的Linux机器上都能运行。
    • 缺点:文件体积大(可能十几MB);如果库有安全更新,需要重新编译整个curl。
    • 适用场景:需要分发给多个环境、在隔离网络部署、或作为容器镜像的一部分。
  • 动态编译(默认或--enable-shared

    • 优点:文件小;库可以单独升级。
    • 缺点:部署时需要确保目标机器上有对应版本的铜锁和nghttp2等库。
    • 适用场景:在固定环境或可通过包管理统一管理依赖的环境中使用。

我的选择:对于这种定制化程度高、用于特定需求(国密)的工具,我强烈推荐静态编译。一次编译,处处运行,避免了部署时的依赖地狱。文件体积的增大在当今存储环境下是可以接受的代价。本文的配置示例也正是采用了静态编译。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/28 12:00:28

AI编程助手深度解析:从Codex到Claude Code,如何选择与高效使用

最近在技术社区和开发者社群里,经常看到“小龙虾”、“Codex”、“Claude Code”这些词被大家挂在嘴边。对于刚接触编程或者AI辅助开发的新手来说,这些名词可能既熟悉又陌生,感觉大家都在用,但具体是什么、怎么用、有什么区别,却一头雾水。 本文将从零开始,为你彻底讲清…

作者头像 李华
网站建设 2026/7/28 12:00:11

Transformer架构在机器翻译中的实现与优化

1. 机器翻译项目概述 "耿直哥深度学习"系列的第10.9期聚焦机器翻译的代码实现,这个看似简单的标题背后,实际上包含了一个完整的自然语言处理(NLP)工作流。作为深度学习领域最具挑战性的任务之一,机器翻译要求我们同时处理序列建模、…

作者头像 李华
网站建设 2026/7/28 11:59:30

08-Skill系统入门-让Agent学会你的工作方式

08 Skill系统入门——让Agent学会你的工作方式 开场故事:一次意外的"教学" 阿杰是 Hermes 的重度用户。有天他接到了一个复杂任务——把公司的一套微服务从 Docker Compose 迁移到 Kubernetes。涉及十几个服务、ConfigMap、Secrets、Ingress 配置,以前他做这种事…

作者头像 李华
网站建设 2026/7/28 11:57:32

从SQL注入到UDF提权:Kioptrix Level 4靶场完整渗透实战解析

1. 项目概述与核心目标 最近在复盘一些经典的渗透测试靶场,Kioptrix Level 4(也叫Kioptrix 2014)是绕不开的一个。这个靶场之所以经典,不仅仅是因为它模拟了一个相对完整的攻击链,更因为它将Web应用漏洞(SQ…

作者头像 李华
网站建设 2026/7/28 11:56:30

物联网设备硬件级安全防护与SE050应用实践

1. 为什么物联网设备需要硬件级安全防护在智能家居和工业物联网项目中,开发者常常面临一个两难选择:既要保证设备通信安全,又要控制硬件成本。传统方案通常采用软件加密算法,比如在MCU上运行TLS协议栈,但这种方案存在三…

作者头像 李华
网站建设 2026/7/28 11:56:27

DSPE-Biotin生物素化磷脂的特性与应用解析

1. 项目概述:DSPE-Biotin的生物素化磷脂特性 DSPE-Biotin(1,2-distearoyl-sn-glycero-3-phosphoethanolamine-N-[biotinyl(polyethylene glycol)-2000])是一种将生物素分子通过PEG连接臂共价修饰到磷脂上的功能化材料。这种结构设计使得它同时…

作者头像 李华