在 Nginx 上测试 SSL 性能

在 Nginx 上测试 SSL 性能

我在 CentOS 6 x86_64 上运行 nginx 1.0.0,使用原装 OpenSSL。以下是 openssl 基准测试的结果。

sh# openssl speed aes-256-cbc
OpenSSL 1.0.0-fips 29 Mar 2010
built on: Sat Jun 25 04:58:15 BST 2011
options:bn(64,64) md2(int) rc4(1x,char) des(idx,cisc,16,int) aes(partial) blowfish(idx) 
compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN 
-DHAVE_DLFCN_H -DKRB5_MIT -m64 -DL_ENDIAN -DTERMIO -Wall -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 
-fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -Wa,--noexecstack 
-DMD32_REG_T=int -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM 
-DMD5_ASM -DAES_ASM -DWHIRLPOOL_ASM
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
aes-256 cbc      51869.80k    54173.06k    54835.11k    54890.84k    55206.96k

AES-NI 引擎已启用(我使用的是 Xeon E5620 @ 2.40GHz x 2):

sh# openssl engine -t
(aesni) Intel AES-NI engine
     [ available ]

我也使用得到了相同的结果openssl 速度-引擎 aesni aes-256-cbc

但是当我使用 EVP 时:

sh# openssl speed -evp aes-256-cbc
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
aes-256-cbc     403447.23k   420048.47k   424418.65k   425523.88k   426726.49k

因此性能提升非常显著。我发现了关于过时的 openssl 程序集Simon 测试了没有使用 ASM 的 openssl 的 AES 结果如下:

[openssl-1.0.0d]# OPENSSL_CONF=apps/openssl.cnf util/opensslwrap.sh speed aes-256-cbc
OpenSSL 1.0.0d 8 Feb 2011
options:bn(64,64) rc4(1x,char) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx) 
compiler: gcc -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H 
-m64 -DL_ENDIAN -DTERMIO -O3 -Wall -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 
-DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DWHIRLPOOL_ASM
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
aes-256 cbc     107854.91k   111229.18k   112361.56k   112501.08k   112536.23k

我还没有设法在 1.0.0d 上构建 aesni 引擎来查看差异。并且使用英特尔的 IPP需要修补 openssl 的技能。

我的问题是:

测试 nginx 是否正在使用 EVP 进行 AES-256 的正确方法是什么,或者是否值得在没有 AES asm 的情况下针对 openssl 编译 nginx?

我知道每个新连接都需要 RSA 解密来交换密钥,所以这是应该考虑的瓶颈,但有多少ssl_session_cache 共享是否会影响 SSL 会话重用,并且 ab、siege 或类似工具是否可以模拟真实的 SSL 流量?

答案1

我调查过的内容可能对你有帮助。英特尔有一篇文章:https://software.intel.com/sites/default/files/open-ssl-performance-paper.pdf

他们使用 apache 进行测试,并表示他们没有调整 apache 的任何配置。我认为 Nginx 也一样。

我使用 gdb 进行追溯,结果如下:

(gdb) bt
#0  0x00000000004dcd50 in aesni_init_key ()
#1  0x00000000004d8dff in EVP_CipherInit_ex ()
#2  0x0000000000494c5a in ssl3_send_newsession_ticket ()
#3  0x00000000004997e8 in ssl3_accept ()
#4  0x00000000004281af in ngx_ssl_handshake (c=0x7ffff7fad1c0) at src/event/ngx_event_openssl.c:996
#5  0x0000000000428571 in ngx_ssl_handshake_handler (ev=0x8c3770) at src/event/ngx_event_openssl.c:1144
#6  0x0000000000424467 in ngx_epoll_process_events (cycle=0x89b9d0, timer=<value optimized out>, flags=<value optimized out>)
    at src/event/modules/ngx_epoll_module.c:691
#7  0x000000000041bd43 in ngx_process_events_and_timers (cycle=0x89b9d0) at src/event/ngx_event.c:248
#8  0x0000000000421de8 in ngx_single_process_cycle (cycle=0x89b9d0) at src/os/unix/ngx_process_cycle.c:315
#9  0x000000000040519c in main (argc=<value optimized out>, argv=<value optimized out>) at src/core/nginx.c:404

EVP_CipherInit_ex 使用 ctx->cipher->init(ctx,key,iv,enc) 来启动 aesni_init_key()。具体定义在 openssl/crypto/evp/e_aes.c

 #define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aesni_##keylen##_##mode = { \
    nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
    flags|EVP_CIPH_##MODE##_MODE,   \
    aesni_init_key,         \
    aesni_##mode##_cipher,      \
    NULL,               \
    sizeof(EVP_AES_KEY),        \
    NULL,NULL,NULL,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
    nid##_##keylen##_##nmode,blocksize, \
    keylen/8,ivlen, \
    flags|EVP_CIPH_##MODE##_MODE,   \
    aes_init_key,           \
    aes_##mode##_cipher,        \
    NULL,               \
    sizeof(EVP_AES_KEY),        \
    NULL,NULL,NULL,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }

AESNI_CAPABLE 确定启用哪个函数,aes_init_key 还是 aes_init_key。这在编译时完成。您可以找到更多详细信息这里

如果您的 openssl evp 接口启用了 AESNI,Nginx 也会使用它。因此对于您的情况,我认为 nginx 默认使用 AESNI。

答案2

我对你的 EVP 问题没有任何答案,但就 SSL 会话缓存而言,答案是“它有很大帮助”。我最近为 nginx 编写了一个补丁,使用 memcached 在集群之间实现 SSL 会话缓存,我发现 SSL 会话缓存有相当大的好处——你节省了几次往返(从用户的角度来看,这是很重要的,因为他们可以更快地获取页面),并且 CPU 使用率也得到了适度的改善(尽管现代服务器很少受到 CPU 限制,所以这通常不是问题)。

测试您是否正在使用 SSL 会话缓存很容易:

gnutls-cli -V -r HOSTNAME |grep 'Session ID'

但进行测试以查看它对“实际流量”有多大影响非常困难,因为“实际流量”非常复杂。考虑到配置更改的风险很低,我建议收集一些好的统计数据(基于您想要改进的内容),然后在生产中启用它并再次测量以查看您的指标是否有所改善。

相关内容