apt,curl,openssl之间的那点事

Curl 可以说是非常流行的一个客户端网络请求工具,充分理解了 Curl,相当于熟练掌握了 HTTP/HTTPS 协议(也包括其他的应用层协议,比如 FTP、IMAP 等等)。

一旦将 Curl 和 HTTPS 协议联系在一起,对于初学者来说,必然会思考以下几个问题:

  • Curl 是如何完成 HTTPS 协议交互的?
  • Curl 是基于 OpenSSL、Nss,还是其他密码学库实现的 HTTPS 功能?
  • 和浏览器一样,Curl 为校验证书,其依赖的根证书库位置在哪儿?
  • 使用包安装(apt或yum)和源代码安装 Curl 有什么区别?

在我写的书《深入浅出HTTPS:从原理到实战》也描述了 Curl 和 HTTPS 的交互,但由于各方面原因,讲解的不是特别深入,所以打算写几篇相关的文章解释这些问题,这篇文章主要基于 Ubuntu(14.4 版本) 的 apt 包安装工具讲解 Curl 和 HTTPS 相关知识,如何你对 apt 包安装工具不熟悉,也可以借此篇文章学习。

在 Ubuntu 下,为支持 HTTPS 协议,Curl 安装的时候默认使用的是 OpenSSL 密码库;在 CentOS 下,Curl 安装的时候默认使用的是 NSS 密码库。

首先看看 curl 依赖于哪些包,执行如下命令:

$ apt-cache depends  curl

输出如下:

curl
  依赖: libc6
  依赖: libcurl3
  依赖: zlib1g
  冲突: curl:i386

依赖最重要的包就是 libcurl3,执行如下命令,看看 libcurl3 依赖什么包:

$ apt-cache depends  libcurl3

输出如下:

libcurl3
  依赖: libc6
  依赖: libgssapi-krb5-2
  依赖: libidn11
  依赖: libldap-2.4-2
  依赖: librtmp0

并没有看到 OpenSSL 的影子,难道 libcurl3 没有包含 OpenSSL 相关库?

再仔细阅读 libcurl3 包的说明,执行下列命令:

$ apt-cache show libcurl3

结果见下图:

apt,curl,openssl之间的那点事_第1张图片
libcurl3

其中有两点重点关注:

  • Recommends: ca-certificates,推荐安装 ca-certificates 包,非常有用,后续我会专门描述。
  • SSL support is provided by OpenSSL,说明 libcurl3 的 SSL 功能确实由 OpenSSL 提供。

那么为什么从 libcurl3 包中看不到 OpenSSL 的影子呢?让我们拿出 ldd 大法,执行下列命令:

ldd /usr/bin/curl | grep ssl  

关键输出如下:

libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007fd25e60a000)

原来是 libcurl3 静态绑定了 libssl.so.1.1,这个包是 OpenSSL 提供的吗?通过两种方法验证。

(1)查看包依赖关系

$ apt-cache depends openssl 

输出:

openssl
  依赖: libc6
  依赖: libssl1.0.0
  建议: ca-certificates
  冲突: openssl:i386

可以看出 openssl 也依赖 libssl1.0.0。

同时 libssl1.0.0 也提供给 libcurl3,可以执行下列命令进行确认:

$ apt-cache rdepends  libssl1.0.0 | grep curl 
  libcurl3

(2)通过 curl-config

这个工具非常有用,官方介绍如下:

curl-config - Get information about a libcurl installation

也就是说,通过 apt 包安装 curl 虽然简单,但失去了解细节的乐趣(比如无法知晓编译了那些具体参数),而 curl-config 工具可以让你了解内幕。

如果机器没有该工具,可以使用下列命令安装:

$ apt-get install libcurl4-openssl-dev  
$ dpkg -L libcurl4-openssl-dev 

然后重点观察 apt 安装采用的 configure,执行如下命令:

$ curl-config --configure

输出如下:

 '--build=x86_64-linux-gnu' '--prefix=/usr' '--includedir=/usr/include' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--sysconfdir=/etc' '--localstatedir=/var' '--libdir=/usr/lib/x86_64-linux-gnu' '--libexecdir=/usr/lib/x86_64-linux-gnu' '--disable-maintainer-mode' '--disable-dependency-tracking' '--disable-symbol-hiding' '--enable-versioned-symbols' '--enable-threaded-resolver' '--with-lber-lib=lber' '--with-gssapi=/usr' '--with-ca-path=/etc/ssl/certs' 'build_alias=x86_64-linux-gnu' 'CFLAGS=-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security' 'LDFLAGS=-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,--as-needed' 'CPPFLAGS=-D_FORTIFY_SOURCE=2'

--with-ca-path 这个参数可以重点关注,curl 在校验服务器证书的时候,会使用该目录下的根证书库文件,在 Ubuntu 中,/etc/ssl/certs 是 OpenSSL 库配置的根证书库(是不是很想改为 NSS 可信任根证书库?后续文章我会描述)。

上述命令并没有 ssl 包相关信息,可以执行下列命令查看静态编译的库:

$ curl-config  --static-libs

输出如下:

/usr/lib/x86_64-linux-gnu/libcurl.a -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,--as-needed -lidn -lrtmp -lssl -lcrypto -lssl -lcrypto -Wl,-Bsymbolic-functions -Wl,-z,relro -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -llber -llber -lldap -lz

如果你没有安装 Curl,执行一条命令就能完成(前提你安装了 OpenSSL,Ubuntu 默认会安装):

$ apt-get install curl

看看 Curl 安装后的信息,执行如下命令:

$ curl -V

输出信息如下:

curl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.1.0g zlib/1.2.8 nghttp2/1.31.0-DEV
Release-Date: 2018-01-24
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy 

可见 curl 基于 libcurl/7.58.0 和 OpenSSL/1.1.0g。

然后再执行下 curl https 请求命令:

$ curl -v "https://www.baidu.com"

输出信息如下图:

apt,curl,openssl之间的那点事_第2张图片
curl -v

重点关注的细节是 curl 使用的可信任根证书库 CAfile: /etc/ssl/certs/ca-certificates.crt。后续会重点讲解 Curl 使用的根证书库。


我最近写了一本书《深入浅出HTTPS:从原理到实战》,欢迎去各大电商购买,也欢迎关注我的公众号(yudadanwx,虞大胆的叽叽喳喳),了解我最新的博文和本书。

apt,curl,openssl之间的那点事_第3张图片
公众号二维码

你可能感兴趣的:(apt,curl,openssl之间的那点事)