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