72

apt, curl, openssl 之间的那点事

 5 years ago
source link: https://mp.weixin.qq.com/s?srcid=0721ExF7MEYL9YUkrC2oKv5j&%3Bscene=23&%3Bmid=2455770009&%3Bsn=f7b173b9c31ca7721f2bad68e9d8c589&%3Bidx=1&%3B__biz=MzAwOTU4NzM5Ng%3D%3D&%3Bchksm=8cc9ec32bbbe6524e97d2a3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

扫描关注公众号(yudadanwx,虞大胆的叽叽喳喳),了解我的最新文章。

vUbUr2q.jpg!web

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 包安装工具实在太方便了。

首先看看 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

结果见下图:

NNZzmyM.jpg!web

其中有两点重点关注:

  • 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"

输出信息如下图:

JzQfmeA.jpg!web

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

我的书 《深入浅出HTTPS:从原理到实战》 今天当当和京东都超级特价,欢迎扫描购买。

UveiQnJ.png!web

FjyQFbF.png!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK