linux服务器上openvpn服务器性能加速计划[2012] 回首页

目标:在千M网卡上,openvpn服务器使用aes-256-cbc算法,优化其性能至900M/秒。
PS:这样标的的一台专业加密通讯的网关设备通常30万一台。
选择一台服务器主板加若干Intel千兆网卡来做这件事,成本仅1~2万

尝试开发进展:
1.硬件环境准备
    我的MAC air的CPU型号是i5-2557m,带有intel AES-Ni指令集。
    具体验证如下:
    在linux虚拟机中
    通过cat /proc/cpuinfo | grep aes
    发现处理器支持aes,而且这个指令集被带入到linux虚拟机中。

    如果要买新的服务器做开发用,mac mini(2013)是个不错的选择:支持到16G内存,耗能平均11W,Ivy Bridge处理器,两颗1T硬盘,OS X lion服务版。
    http://www.apple.com.cn/mac-mini/server/
    http://www.apple.com/mac-mini/server/

2.linux内核
检查模块是否加载:
$ /sbin/modinfo aesni_intel
filename:       /lib/modules/3.2.11-merry/kernel/arch/x86/crypto/aesni-intel.ko
alias:          aes
license:        GPL
description:    Rijndael (AES) Cipher Algorithm, Intel AES-NI instructions optimized
depends:        cryptd,aes-x86_64
vermagic:       3.2.11-merry SMP mod_unload modversions 

检查加密方法是否支持:
$ grep module /proc/crypto | sort -u
module       : aesni_intel
module       : aes_x86_64
module       : arc4
module       : kernel

3.openssl
检查openssl是否支持该方法:
$ openssl engine
(aesni) Intel AES-NI engine
(dynamic) Dynamic engine loading support

---------------------------------------------------------------------------------
方法讨论:
一、openvpn官方以及网上,对openvpn加速和性能调优的方法有下面几种:
====
  1.调整NIC的MTU
  2.openssl和Intel® AES-NI相结合。
  3.SSL硬件加速

二、基于openvpn的局限性:
====
  1.openvpn只能用到CPU单核,其它CPU核心空闲
  2.openvpn是单进程,受载能力有限
有人在源码上做了二次开发:
  1.改进tun设备驱动,使多个openvpn服务/进程捆绑于一个tun设备上。
  2.使用openvpn的tap方式,并将多个tap和一个ethernet桥接
  3.将多个openvpn服务绑在不同的CPU核心,并为之做一个负载均衡前端。

三、我的方案:
====
  1.建立单核CPU的虚拟机,在其中将openvpn服务调至最优,并统计资源。
  2.建立多个上述虚拟机,基于同一个只读盘启动,加载不同的网络配置,并分配不同的CPU,共享宿主机上证书和客户端配置。
    (但是这个方案似乎用不上硬件加速卡和一些CPU指令集)

---------------------------------------------------------------------------------
参考文献和引用地址:

(1).修改openvpn相关:
====
摘要>>><<<隐藏
1.动手写一个OpenVPN的wrapper来优化OpenVPN性能 http://blog.csdn.net/dog250/article/details/7294234 简单的多进程OpenVPN前端控制程序 http://blog.csdn.net/dog250/article/details/8045209 桥接多进程OpenVPN虚拟网卡解决多处理问题 http://blog.csdn.net/dog250/article/details/8045217 2.OpenVPN性能-多OpenVPN共享一个虚拟网卡 http://blog.csdn.net/dog250/article/details/6938412 3.OpenVPN性能-OpenVPN的第一个瓶颈在tun驱动 http://blog.csdn.net/dog250/article/details/6300347 4.OpenVPN性能-OpenVPN的第二个瓶颈在ssl加解密 http://blog.csdn.net/dog250/article/details/6300348 5.返璞归真的OpenVPN的p2p模式 http://blog.csdn.net/dog250/article/details/7484119 6.关于OpenVPN文章的目录 http://blog.csdn.net/dog250/article/details/6990814 (2).SSL加速相关: ==== 1. Intel® AES New Instructions (Intel® AES-NI) http://www.intel.com/content/www/us/en/architecture-and-technology/advanced-encryption-standard--aes-/data-protection-aes-general-technology.html Intel® AES-NI Performance Testing on Linux/Java Stack http://software.intel.com/en-us/articles/intel-aes-ni-performance-testing-on-linuxjava-stack/ 2. Optimizing performance on gigabit networks https://community.openvpn.net/openvpn/wiki/Gigabit_Networks_Linux OpenVPNのスループットと最適化 http://yamatamemo.blogspot.com/2012/01/openvpn-1.html Intel® Advanced Encryption Standard Instructions (AES-NI) http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-instructions-aes-ni/ Intel AES-NI For Ubuntu Home Encryption http://www.phoronix.com/scan.php?page=article&item=ubuntu_aesni_intel&num=1 摘要: The performance improvement expected with the use of AES-NI would depend on the applications and how much of the application time is spent in encryption and decryption. At the algorithm level, using AES-NI can provide significant speedup of AES. For non-parallel modes of AES operation such as CBC-encrypt AES-NI can provide a 2-3 fold gain in performance over a completely software approach. For parallelizable modes such as CBC-decrypt and CTR, AES-NI can provide a 10x improvement over software solutions. 3. OpenVPNのスループット http://yamatamemo.blogspot.com/2011/05/openvpn.html 摘要>>><<<隐藏
詳細は上記サイトを参照していただくとして、要は「いい性能のPCを使ってGigabit上でOpenVPNをつないでみて、どこまでスループットを上げられるか実験してみよう!」ということです。OSはサーバー、クライアントともLinuxです。以下、結果を簡単にまとめるとこんな感じ(すべて計測値はiperfによるもので、プロトコルはUDPを使用しています)。 標準設定(MTUやFragmentなどをいじらない&CipherはBlowfish)のOpenVPNスループットで156Mbps。Cipherをaes-256-cbcに変更すると 126Mbps。今回のPCのスペックでは標準のままで100Mbpsは超えます。この速度で十分というケースもありそうですね。 OpenVPNでMTUの設定値を大きくし、フラグメントを無効にするとスループットが上昇する。たとえばMTUを9000にすると 370Mbps、24000では 466Mbps、48000では 510Mbps。この値が最大で、これ以上MTUを増やすと速度は低下していく。 Cipherをaes-256にすると、MTUとスループットの相関性は低くなる(MTUを上げてもちょっとしかスループットが上がらない)。こんな大きいMTU設定したことない…。 AES-NIを使用すると速度がかなり向上する(当然、CipherをAESにしないと効果はありません)。たとえば、AES256でAES-NIを使用すると、MTUが9000なら 249Mbps→410Mbps に、24000なら 259Mbps→540Mbps に、48000では 247Mbps→585Mbps に上がります。これは相当なパワーアップですね。 OpenVPNの暗号化と署名を無効にした場合、 930Mbps というスループットに。Gigabitの範囲であればユーザー空間とカーネル空間の分離はパフォーマンスにそれほど影響せず(この結果によれば7%程度)、やはりOpenSSLによる暗号化と署名の処理がスループットに大きく影響することがわかる。 結論として、MTUサイズを大きくして、フラグメントを無効にすればスループットは大きく向上する、とのこと。ただし、当たり前ですが、MTUの設定値にネットワークの品質は密接に関わっていますので、ネットワーク構成に応じて設定する必要がありますね。
4.程序中如何启用openssl的AES-NI ? http://www.udpwork.com/item/7855.html 摘要>>><<<隐藏
昨天我贴了一个测试报告,openssl在启用了AES-NI后,做AES加解密的时候,效率有8-9倍的提升。但是当我自己写了一个程序去测试的时候,结果却并非如此。 首先,openssl有两套接口,一套EVP的(与具体算法无关),一套较低level的,针对特定算法的。 EVP的例子如下: EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); ENGINE_load_builtin_engines(); ENGINE* engine=ENGINE_by_id("aesni"); if(engine==NULL){ printf("aesni not found\n"); } EVP_EncryptInit_ex(&ctx,EVP_aes_128_cbc(),engine,test_key_128,test_init_vector); int out; EVP_CipherUpdate(&ctx,output,&out, test_plain_text, inputlen); 需要特别说明的是:在openssl 1.0.0中,新添了一个叫做aesni的engine,只有当你指定了使用这个engine的时候,才会使用CPU的AES指令。但是到了openssl 1.0.1 之后,这个engine被去除掉了,变成运行期自动监测是否使用AESNI。1.0.1版本中EVP_aes_128_cbc()这个函数的实现如下: extern unsigned int OPENSSL_ia32cap_P[2]; #define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32))) const EVP_CIPHER *EVP_aes_128_cbc(void) { return AESNI_CAPABLE?&aesni_128_cbc:&aes_128_cbc; } 除了EVP,还有一套低级接口如下: int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc); 这些函数都是没有文档没有注释的。与这3个函数类似的,还有一套aesni_set_encrypt_key、aesni_set_decrypt_key、aesni_cbc_encrypt函数。但是这几个函数并 不在安装后的头文件中。但是没有关系,可以自己声明一下然后用: extern "C"{ int aesni_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); int aesni_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); void aesni_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc); } 然后我这还有一个函数,用来监测CPU是否支持AES-Ni: #ifndef __linux__ #include #else static void __cpuid(unsigned int where[4], unsigned int leaf) { asm volatile("cpuid":"=a"(*where),"=b"(*(where+1)), "=c"(*(where+2)),"=d"(*(where+3)):"a"(leaf)); return; } #endif #define AES_INSTRCTIONS_CPUID_BIT (1<<25) bool check_for_aes_instructions() { #ifdef __linux__ unsigned int cpuid_results[4]; #else int cpuid_results[4]; #endif __cpuid(cpuid_results,0); if (cpuid_results[0] < 1) return false; /* * MSB LSB * EBX = 'u' 'n' 'e' 'G' * EDX = 'I' 'e' 'n' 'i' * ECX = 'l' 'e' 't' 'n' */ if (memcmp((unsigned char *)&cpuid_results[1], "Genu", 4) != 0 || memcmp((unsigned char *)&cpuid_results[3], "ineI", 4) != 0 || memcmp((unsigned char *)&cpuid_results[2], "ntel", 4) != 0) return false; __cpuid(cpuid_results,1); if (cpuid_results[2] & AES_INSTRCTIONS_CPUID_BIT) return true; return false; }
6.nCipher SSL 卸载卡 (nCipher nfast ultra BN1200 ssl offload card) http://net.yesky.com/193/2455193.shtml http://baike.baidu.com/link?url=BgJa2GPcTqwV4woXnlyoXIpXE0K5m2BRvKS_dmrew9BPhys9zNyT3IwxEwV3fQVEqfBJ-4yXkOXsJX_D2hAP_a 7.在PowerEdge 服务器上使用SSL加速适配器 http://www1.ap.dell.com/content/topics/topic.aspx/ap/topics/power/zhcn/ps4q01_broadcom?c=cn&l=zh&cs=cnlca1 8.深信服应用交付助服务器实现SSL压力卸载 http://news.zol.com.cn/303/3034868.html (3).其它参考: ==== openssl速度测试 openssl speed -evp aes-128-cbc openssl speed -evp aes-256-cbc