Nginx

在 Nginx 上測試 SSL 性能

  • August 4, 2014

我正在使用庫存 OpenSSL 在 CentOS 6 x86_64 上執行 nginx 1.0.0。以下是 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 speed -engine 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 的情況下測試了用於 AES 的 openssl,數字是:

[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 是否對 AES-256 使用 EVP 或者是否值得在沒有 asm 的情況下針對 openssl 編譯 nginx 的正確方法是什麼?

我知道每個新連接都需要 RSA 解密來交換密鑰,所以這是應該考慮的瓶頸,但是ssl_session_cache 共享多少會影響 SSL 會話重用,並且像 ab、siege 或類似的工具可以模擬真實流量 ssl 流量?

我調查的內容可能對您有所幫助。英特爾有一篇文章: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。

引用自:https://serverfault.com/questions/291821