尝试使用官方的server demo和client demo程序
https://wiki.openssl.org/index.php/Main_Page
- server程序在 https://wiki.openssl.org/index.php/Simple_TLS_Server
- Client程序在https://wiki.openssl.org/index.php/SSL/TLS_Client
- 证书尝试使用Chromium QUIC Toy教程中,使用./generate-certs.sh 脚本生成的证书
在Quic Toy的使用过程中, Server使用的证书和密钥文件为:
--certificate_file=./leaf_cert.pem --key_file=./leaf_cert.pkcs8
而且需要讲根证书添加到系统可信域内:
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n <certificate nickname> -i <certificate filename> - 将Simple_TLS_Server.c放入到Ubuntu系统里编译:gcc Simple_TLS_Server.c -o tls_server
编译出错,找不到一系列符号:
/tmp/cc7arh7v.o: In function `init_openssl':
Simple_TLS_Server.c:(.text+0xbf): undefined reference to `SSL_load_error_strings'
Simple_TLS_Server.c:(.text+0xc4): undefined reference to `SSL_library_init'
/tmp/cc7arh7v.o: In function `cleanup_openssl':
Simple_TLS_Server.c:(.text+0xd0): undefined reference to `EVP_cleanup'
/tmp/cc7arh7v.o: In function `create_context':
Simple_TLS_Server.c:(.text+0xe0): undefined reference to `SSLv23_server_method'
Simple_TLS_Server.c:(.text+0xf0): undefined reference to `SSL_CTX_new'
Simple_TLS_Server.c:(.text+0x114): undefined reference to `ERR_print_errors_fp'
/tmp/cc7arh7v.o: In function `configure_context':
Simple_TLS_Server.c:(.text+0x14b): undefined reference to `SSL_CTX_ctrl'
Simple_TLS_Server.c:(.text+0x161): undefined reference to `SSL_CTX_use_certificate_file'
Simple_TLS_Server.c:(.text+0x174): undefined reference to `ERR_print_errors_fp'
Simple_TLS_Server.c:(.text+0x194): undefined reference to `SSL_CTX_use_PrivateKey_file'
Simple_TLS_Server.c:(.text+0x1a7): undefined reference to `ERR_print_errors_fp'
/tmp/cc7arh7v.o: In function `main':
Simple_TLS_Server.c:(.text+0x246): undefined reference to `SSL_new'
Simple_TLS_Server.c:(.text+0x25b): undefined reference to `SSL_set_fd'
Simple_TLS_Server.c:(.text+0x267): undefined reference to `SSL_accept'
Simple_TLS_Server.c:(.text+0x27a): undefined reference to `ERR_print_errors_fp'
Simple_TLS_Server.c:(.text+0x29d): undefined reference to `SSL_write'
Simple_TLS_Server.c:(.text+0x2a9): undefined reference to `SSL_free'
增加编译选项-lssl : gcc Simple_TLS_Server.c -lssl -o tls_server
/usr/bin/ld: /tmp/cc5pFn01.o: undefined reference to symbol 'EVP_cleanup@@OPENSSL_1.0.0'
//lib/x86_64-linux-gnu/libcrypto.so.1.0.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
还剩下一个,再增加编译选项: -lcrypto
编译通过。
-
配置密钥
从Chromium Quic中拷贝证书到当前目录,重命名leaf_cert.pem为cert.pem。、,leaf_cert.key为key.pem
需要注意的是,我在Quic Toy中使用的是./leaf_cert.pkcs8,但是这里用的是leaf_cert.key,如果使用leaf_cert.pkcs.8会报错。启动./tls_server
-
使用openssl的s_client功能测试tls_server
先查看一下openssl s_client功能说明# openssl s_client help
-host 选项用于指定地址,-port选项用于指定端口
尝试连接:
openssl s_client -host 127.0.0.1 -port 4433
```
root@ubuntu:~/chromium/src# openssl s_client -host 127.0.0.1 -port 4433
CONNECTED(00000003)
。。。。。此处省略大量细节
test
read:errno=0
```
前面证书校验好像出错,但是仍然完成了握手过程,收到了来自server的"test"响应。
抓包展示如下:
![image.png](https://img.haomeiwen.com/i1939047/c2d5fbbd4e2525b2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 使用Client demo访问tls server
https://wiki.openssl.org/index.php/SSL/TLS_Client
这个Client程序使用BIO方式访问一个网页,里面讲解了各个接口的作用。代码在最后的download章节可以下载到。
将下载的压缩文件包Openssl-bio-fetch.tar.gz中的代码openssl-bio-fetch.c与openssl-bio-fetch.h以及Makefile拷贝到Ubuntu机器。
修改Makefile中ssl与crypto的链接:
OPENSSL_LDFLAGS = -Bstatic $(OPENSSL_LIBDIR)/libssl.a $(OPENSSL_LIBDIR)/libcrypto.a
为如下:
OPENSSL_LDFLAGS = -Bstatic -lssl -lcrypto
执行Make:
```
root@ubuntu:/home/zengyi/data/openssl# make
cc -g3 -ggdb -O0 -DDEBUG=1 -std=c99 -Wall -Wextra -Wconversion -Wformat -Wformat=2 -Wformat-security -Wno-deprecated-declarations -Wno-unused-function -I/usr/local/ssl/macosx-x64/include openssl-bio-fetch.c -o openssl-bio-fetch.exe -Bstatic -lssl -lcrypto
In file included from openssl-bio-fetch.c:2:0:
openssl-bio-fetch.h: In function ‘InstallDebugTrapHandler’:
openssl-bio-fetch.h:65:22: error: storage size of ‘new_handler’ isn’t known
struct sigaction new_handler, old_handler;
^
openssl-bio-fetch.h:65:35: error: storage size of ‘old_handler’ isn’t known
struct sigaction new_handler, old_handler;
^
openssl-bio-fetch.h:70:15: warning: implicit declaration of function ‘sigaction’ [-Wimplicit-function-declaration]
ret = sigaction (SIGTRAP, NULL, &old_handler);
^
openssl-bio-fetch.h:83:15: warning: implicit declaration of function ‘sigemptyset’ [-Wimplicit-function-declaration]
ret = sigemptyset (&new_handler.sa_mask);
^
openssl-bio-fetch.h:65:35: warning: unused variable ‘old_handler’ [-Wunused-variable]
struct sigaction new_handler, old_handler;
^
openssl-bio-fetch.h:65:22: warning: unused variable ‘new_handler’ [-Wunused-variable]
struct sigaction new_handler, old_handler;
^
Makefile:31: recipe for target 'openssl-bio-fetch.exe' failed
make: *** [openssl-bio-fetch.exe] Error 1
```
struct sigaction类型找不到定义,是因为编译选项中使用-std=c99选项导致。
sigaction属于Posix.1-2001中新增的接口,c99标准中还未启用,因此会报错。修改方式可以是将sigaction使用更普遍的signal类型替换,或者去掉c99标准,或者去掉DEBUG宏,disable掉相关信号处理函数。
我们去掉C99标准选项。
修改Makefile,去掉std=c99选项,重新编译成功。
由于Client程序硬编码访问的是www.example.org,需要将其修改为127.0.0.1,端口修改为4433。
运行client,连接server握手
root@ubuntu:/home/zengyi/data/openssl# ./openssl-bio-fetch.exe
Warning: thread locking is not implemented
Assertion: openssl-bio-fetch.c: function main, line 115
No such file or directory
verify_callback (depth=0)(preverify=0)
Issuer (cn): QUIC Server Root CA
Subject (cn): 127.0.0.1
Subject (san): www.example.org
Subject (san): mail.example.org
Subject (san): mail.example.com
Unknown GENERAL_NAME type: 7
Error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
verify_callback (depth=0)(preverify=0)
Issuer (cn): QUIC Server Root CA
Subject (cn): 127.0.0.1
Subject (san): www.example.org
Subject (san): mail.example.org
Subject (san): mail.example.com
Unknown GENERAL_NAME type: 7
Error = 21
Assertion: openssl-bio-fetch.c: function main, line 268
SSL_get_verify_results failed: 21 (0x15)
看起来是证书验证失败了。
去掉client中关于verify callback的注册:
注释掉 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);一行
root@ubuntu:/home/zengyi/data/openssl# ./openssl-bio-fetch.exe
Warning: thread locking is not implemented
Assertion: openssl-bio-fetch.c: function main, line 115
No such file or directory
Assertion: openssl-bio-fetch.c: function main, line 268
SSL lib
把代码中整个step 1的部分全部注释掉(250 - 275行)。
root@ubuntu:/home/zengyi/data/openssl# ./openssl-bio-fetch.exe
Warning: thread locking is not implemented
Assertion: openssl-bio-fetch.c: function main, line 115
No such file or directory
Fetching: /cgi-bin/randbyte?nbytes=32&format=h
test
嗯,测试成功!
-
更新OpenSSL库
目前我Ubuntu上的OpenSSL库版本比较低,不支持TLS1.3.root@ubuntu:~/openssl/openssl-1.1.1c# openssl version OpenSSL 1.0.2g 1 Mar 2016 root@ubuntu:~/openssl/openssl-1.1.1c# openssl ciphers -v 'ALL:COMPLEMENTOFALL' | grep TLSv1.3 root@ubuntu:~/openssl/openssl-1.1.1c#
下载最新OpenSSL版本,从官网上的值目前最新的稳定版本是1.1.1系列。我下载了openssl-1.1.1c.tar.gz,链接地址:https://www.openssl.org/source/openssl-1.1.1c.tar.gz
放到Ubuntu上解压。
根据Cookbook介绍按部就班,为了不影响现有OpenSSL库,配置好前缀。
./config --prefix=/usr/local/openssl-1.1.1c --openssldir=/usr/local/openssl-1.1.1c enable-ec_nistp_64_gcc_128
make depend
make
sudo make install
先看一下效果:root@ubuntu:~/openssl/openssl-1.1.1c# cd /usr/local/openssl-1.1.1c/ root@ubuntu:/usr/local/openssl-1.1.1c# ./bin/openssl version root@ubuntu:/usr/local/openssl-1.1.1c/bin# ./openssl version ./openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
报错找不到libssl.so.1.1,先临时配置一下环境变量:
root@ubuntu:/usr/local/openssl-1.1.1c# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./lib root@ubuntu:/usr/local/openssl-1.1.1c# ./bin/openssl version OpenSSL 1.1.1c 28 May 2019
版本是正确的,再看一下加密套件支持情况:
root@ubuntu:/usr/local/openssl-1.1.1c# ./bin/openssl ciphers -v 'ALL:COMPLEMENTOFALL' | grep TLSv1.3 TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
将新版本的openssl配置到系统。
移除原有OpenSSL版本(先搜索查看原有的ssl库在哪些地方,然后对应配置一下):mv /usr/bin/openssl /usr/bin/openssl.1.0.2g
ln -s /usr/local/openssl-1.1.1c/bin/openssl /usr/bin/openssl
mv /usr/include/openssl/ /usr/include/openssl.1.0.2g
ln -s /usr/local/openssl-1.1.1c/include/openssl /usr/include/openssl
rm -rf /usr/lib/x86_64-linux-gnu/libssl.so
ln -s /usr/local/openssl-1.1.1c/lib/libssl.so.1.1 /usr/lib/x86_64-linux-gnu/libssl.so
rm /usr/lib/x86_64-linux-gnu/libcrypt.so
ln -s /usr/local/openssl-1.1.1c/lib/libcrypto.so.1.1 /usr/lib/x86_64-linux-gnu/libcrypt.so
cp /usr/local/openssl-1.1.1c/lib/libssl.so.1.1 /lib/x86_64-linux-gnu/
cp /usr/local/openssl-1.1.1c/lib/libcrypto.so.1.1 /lib/x86_64-linux-gnu/
mv /usr/lib/x86_64-linux-gnu/libssl.a /usr/lib/x86_64-linux-gnu/libssl.a.1.0.2g
cp /usr/local/openssl-1.1.1c/lib/libssl.a /usr/lib/x86_64-linux-gnu/
mv /usr/lib/x86_64-linux-gnu/libcrypto.a /usr/lib/x86_64-linux-gnu/libcrypto.a.1.0.2g
cp /usr/local/openssl-1.1.1c/lib/libcrypto.a /usr/lib/x86_64-linux-gnu/
cp /usr/local/openssl-1.1.1c/lib/libssl.so.1.1 /usr/lib/i386-linux-gnu/
cp /usr/local/openssl-1.1.1c/lib/libssl.so.1.1 /lib/i386-linux-gnu/
cp /usr/local/openssl-1.1.1c/lib/libcrypto.so.1.1 /lib/i386-linux-gnu/
cp /usr/local/openssl-1.1.1c/lib/libcrypto.so.1.1 /usr/lib/i386-linux-gnu/
rm -rf /usr/lib/i386-linux-gnu/libcrypto.so
ln -s /lib/i386-linux-gnu/libcrypto.so.1.1 /usr/lib/i386-linux-gnu/libcrypto.so
rm -rf /usr/lib/x86_64-linux-gnu/libcrypto.so
ln -s /lib/x86_64-linux-gnu/libcrypto.so.1.1 /usr/lib/x86_64-linux-gnu/libcrypto.so
rm -rf /usr/lib/i386-linux-gnu/libssl.so
ln -s /lib/i386-linux-gnu/libssl.so.1.1 /usr/lib/i386-linux-gnu/libssl.so在一个新的Shell中运行,openssl版本已经更新
root@ubuntu:~/chromium/src# openssl version OpenSSL 1.1.1c 28 May 2019 root@ubuntu:~/chromium/src# openssl ciphers -v 'ALL:COMPLEMENTOFALL' | grep TLSv1.3 TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
重新编译Server和Client,出现大量错误:DEPRECATEDIN_1_1_0等符号找不到定义。
这个符号是在opensslconf.in.h中定义的,在Make的时候会自动生成为opensslconf.h(竟然这样的骚操作,本地代码上根本看不到这个opensslconf.h)。但是即使这样,系统的openssconf.h也已经正常被生成,应该不会有问题。搜索一下系统,发现还有其他的目录下存在这个文件,需要替换掉。
存在opensslconf.h的目录有:/usr/include/x86_64-linux-gnu/openssl/,/usr/include/i386-linux-gnu/openssl/
替换为最新的文件解决问题。重新编译server和client,发现有一些函数已经处于未定义状态:
root@ubuntu:/home/zengyi/data/openssl# gcc Simple_TLS_Server.c -lssl -lcrypto -o tls_server /tmp/ccssBesj.o: In function `init_openssl': Simple_TLS_Server.c:(.text+0xbf): undefined reference to `SSL_load_error_strings' Simple_TLS_Server.c:(.text+0xc4): undefined reference to `SSL_library_init' /tmp/ccssBesj.o: In function `cleanup_openssl': Simple_TLS_Server.c:(.text+0xd0): undefined reference to `EVP_cleanup' /tmp/ccssBesj.o: In function `create_context': Simple_TLS_Server.c:(.text+0xe0): undefined reference to `SSLv23_server_method' collect2: error: ld returned 1 exit status
查看源码,发现这些函数确实已经废弃,版本号小于1.0.1才有用:
# if OPENSSL_API_COMPAT < 0x10100000L # define SSL_load_error_strings() \ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL) # endif
从SSL_library_init()手册看,SSL_load_error_strings()与SSL_library_init(),EVP_Cleanup()接口已经被OPENSSL_init_ssl()替代。SSLv23_server_method()接口已经被TLS_server_method()接口替代,TLS_server_method()接口已经摒弃了具体的协议约束。
The SSL_library_init() and OpenSSL_add_ssl_algorithms() functions were deprecated in OpenSSL 1.1.0 by OPENSSL_init_ssl().
Calling this function will explicitly initialise BOTH libcrypto and libssl.
The OpenSSL_add_all_algorithms(), OpenSSL_add_all_ciphers(), OpenSSL_add_all_digests(), and EVP_cleanup(), functions were deprecated in OpenSSL 1.1.0 by OPENSSL_init_crypto().
SSLv23_method(), SSLv23_server_method() and SSLv23_client_method() were deprecated and the preferred TLS_method(), TLS_server_method() and TLS_client_method() functions were introduced in OpenSSL 1.1.0.
All version-specific methods were deprecated in OpenSSL 1.1.0.int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
将SSL_load_error_strings();OpenSSL_add_ssl_algorithms();函数替换为OPENSSL_init_ssl,将 EVP_cleanup()注释掉,将SSLv23_server_method();修改为TLS_server_method()。编译成功!
运行tls_server
运行 openssl s_client
可以看到使用了TLSv1.3握手!
抓包如下:
image.png
网友评论