Nginx 配置 ECC RSA 双证书

Config Nginx for parallel ECC and RSA Certificate

先决条件

Nginx 1.11.0 以上

OpenSSL 1.0.2 以上

申请证书

首先申请 ECC 证书,这个不多说,很多方法都可以,大部分 CA 现在也都可以签署。生成 CSR 的命令是:

openssl ecparam -out 证书名.key -name prime256v1 -genkey && openssl req -new -key 证书名.key -nodes -out 证书名.csr

拿到证书之后,还是像之前一样将中级 CA 拼接在证书后面,得到给 Nginx 使用的 domain-cert.crt

配置 Nginx

首先是将两个证书链都加入 Nginx 的配置文件:

ssl_certificate     example.com.rsa.crt;
ssl_certificate_key example.com.rsa.key;

ssl_certificate     example.com.ecdsa.crt;
ssl_certificate_key example.com.ecdsa.key;

如果要使用 CT 的话有两种方法:

1. 将两个证书的 CT 信息放到同一目录,并做如下设置:

ssl_ct on;
ssl_ct_static_scts /path/to/sct/dir;

这样 Nginx CT 模块会自动在这个目录下查找相应证书的 CT 信息并发送

2. 可以单独配置每个证书的 CT 文件:

ssl_ct on;

ssl_certificate example.com.rsa.crt;
ssl_certificate_key example.com.rsa.key;
ssl_ct_static_scts xample.com.rsa.scts;

ssl_certificate example.com.ecdsa.crt;
ssl_certificate_key example.com.ecdsa.key;
ssl_ct_static_scts example.com.ecdsa.scts;

然后问题来了。很多盆友这么配置之后可能发现用 Chrome 之类的明明支持 ECC 的浏览器却并没有用 ECC 证书。这是为什么呢?

问题就出在  ssl_ciphers  这个配置项上面。

如果我们用各种网上推荐的配置,需要注意顺序问题。以 Cloud Flare 的配置为例:

#https://github.com/cloudflare/sslconfig/blob/master/conf
ssl_protocols               TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers                 EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers   on;

注意到这里面的算法都是优先使用 RSA 的,所以服务器和浏览器协商出来的一定是 RSA ,这就导致 Nginx 会自动发送 RSA 证书链给浏览器。

这里可以用 openssl 验证一下:

# openssl ciphers -V 'EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5' | column -t
0xC0,0x2F  -  ECDHE-RSA-AES128-GCM-SHA256    TLSv1.2  Kx=ECDH  Au=RSA    Enc=AESGCM(128)  Mac=AEAD
0xC0,0x2B  -  ECDHE-ECDSA-AES128-GCM-SHA256  TLSv1.2  Kx=ECDH  Au=ECDSA  Enc=AESGCM(128)  Mac=AEAD
0xC0,0x27  -  ECDHE-RSA-AES128-SHA256        TLSv1.2  Kx=ECDH  Au=RSA    Enc=AES(128)     Mac=SHA256
0xC0,0x23  -  ECDHE-ECDSA-AES128-SHA256      TLSv1.2  Kx=ECDH  Au=ECDSA  Enc=AES(128)     Mac=SHA256
0xC0,0x13  -  ECDHE-RSA-AES128-SHA           SSLv3    Kx=ECDH  Au=RSA    Enc=AES(128)     Mac=SHA1
0xC0,0x09  -  ECDHE-ECDSA-AES128-SHA         SSLv3    Kx=ECDH  Au=ECDSA  Enc=AES(128)     Mac=SHA1
0x00,0x9C  -  AES128-GCM-SHA256              TLSv1.2  Kx=RSA   Au=RSA    Enc=AESGCM(128)  Mac=AEAD
0x00,0x3C  -  AES128-SHA256                  TLSv1.2  Kx=RSA   Au=RSA    Enc=AES(128)     Mac=SHA256
0x00,0x2F  -  AES128-SHA                     SSLv3    Kx=RSA   Au=RSA    Enc=AES(128)     Mac=SHA1
0xC0,0x30  -  ECDHE-RSA-AES256-GCM-SHA384    TLSv1.2  Kx=ECDH  Au=RSA    Enc=AESGCM(256)  Mac=AEAD
0xC0,0x2C  -  ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2  Kx=ECDH  Au=ECDSA  Enc=AESGCM(256)  Mac=AEAD
0xC0,0x28  -  ECDHE-RSA-AES256-SHA384        TLSv1.2  Kx=ECDH  Au=RSA    Enc=AES(256)     Mac=SHA384
0xC0,0x24  -  ECDHE-ECDSA-AES256-SHA384      TLSv1.2  Kx=ECDH  Au=ECDSA  Enc=AES(256)     Mac=SHA384
0xC0,0x14  -  ECDHE-RSA-AES256-SHA           SSLv3    Kx=ECDH  Au=RSA    Enc=AES(256)     Mac=SHA1
0xC0,0x0A  -  ECDHE-ECDSA-AES256-SHA         SSLv3    Kx=ECDH  Au=ECDSA  Enc=AES(256)     Mac=SHA1
0x00,0x9D  -  AES256-GCM-SHA384              TLSv1.2  Kx=RSA   Au=RSA    Enc=AESGCM(256)  Mac=AEAD
0x00,0x3D  -  AES256-SHA256                  TLSv1.2  Kx=RSA   Au=RSA    Enc=AES(256)     Mac=SHA256
0x00,0x35  -  AES256-SHA                     SSLv3    Kx=RSA   Au=RSA    Enc=AES(256)     Mac=SHA1
0xC0,0x12  -  ECDHE-RSA-DES-CBC3-SHA         SSLv3    Kx=ECDH  Au=RSA    Enc=3DES(168)    Mac=SHA1
0xC0,0x08  -  ECDHE-ECDSA-DES-CBC3-SHA       SSLv3    Kx=ECDH  Au=ECDSA  Enc=3DES(168)    Mac=SHA1
0x00,0x0A  -  DES-CBC3-SHA                   SSLv3    Kx=RSA   Au=RSA    Enc=3DES(168)    Mac=SHA1

会看到第一个选择就是使用 RSA,而不是椭圆曲线 ECDSA。

再来验证一下 Mozilla 给出的配置:

# openssl ciphers -V 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS' | column -t 
0xC0,0x2B  -  ECDHE-ECDSA-AES128-GCM-SHA256  TLSv1.2  Kx=ECDH  Au=ECDSA  Enc=AESGCM(128)  Mac=AEAD
0xC0,0x2F  -  ECDHE-RSA-AES128-GCM-SHA256    TLSv1.2  Kx=ECDH  Au=RSA    Enc=AESGCM(128)  Mac=AEAD
0xC0,0x2C  -  ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2  Kx=ECDH  Au=ECDSA  Enc=AESGCM(256)  Mac=AEAD
0xC0,0x30  -  ECDHE-RSA-AES256-GCM-SHA384    TLSv1.2  Kx=ECDH  Au=RSA    Enc=AESGCM(256)  Mac=AEAD
0x00,0x9E  -  DHE-RSA-AES128-GCM-SHA256      TLSv1.2  Kx=DH    Au=RSA    Enc=AESGCM(128)  Mac=AEAD
0x00,0x9F  -  DHE-RSA-AES256-GCM-SHA384      TLSv1.2  Kx=DH    Au=RSA    Enc=AESGCM(256)  Mac=AEAD
0xC0,0x23  -  ECDHE-ECDSA-AES128-SHA256      TLSv1.2  Kx=ECDH  Au=ECDSA  Enc=AES(128)     Mac=SHA256
0xC0,0x27  -  ECDHE-RSA-AES128-SHA256        TLSv1.2  Kx=ECDH  Au=RSA    Enc=AES(128)     Mac=SHA256
0xC0,0x09  -  ECDHE-ECDSA-AES128-SHA         SSLv3    Kx=ECDH  Au=ECDSA  Enc=AES(128)     Mac=SHA1
0xC0,0x28  -  ECDHE-RSA-AES256-SHA384        TLSv1.2  Kx=ECDH  Au=RSA    Enc=AES(256)     Mac=SHA384
0xC0,0x13  -  ECDHE-RSA-AES128-SHA           SSLv3    Kx=ECDH  Au=RSA    Enc=AES(128)     Mac=SHA1
0xC0,0x24  -  ECDHE-ECDSA-AES256-SHA384      TLSv1.2  Kx=ECDH  Au=ECDSA  Enc=AES(256)     Mac=SHA384
0xC0,0x0A  -  ECDHE-ECDSA-AES256-SHA         SSLv3    Kx=ECDH  Au=ECDSA  Enc=AES(256)     Mac=SHA1
0xC0,0x14  -  ECDHE-RSA-AES256-SHA           SSLv3    Kx=ECDH  Au=RSA    Enc=AES(256)     Mac=SHA1
0x00,0x67  -  DHE-RSA-AES128-SHA256          TLSv1.2  Kx=DH    Au=RSA    Enc=AES(128)     Mac=SHA256
0x00,0x33  -  DHE-RSA-AES128-SHA             SSLv3    Kx=DH    Au=RSA    Enc=AES(128)     Mac=SHA1
0x00,0x6B  -  DHE-RSA-AES256-SHA256          TLSv1.2  Kx=DH    Au=RSA    Enc=AES(256)     Mac=SHA256
0x00,0x39  -  DHE-RSA-AES256-SHA             SSLv3    Kx=DH    Au=RSA    Enc=AES(256)     Mac=SHA1
0xC0,0x08  -  ECDHE-ECDSA-DES-CBC3-SHA       SSLv3    Kx=ECDH  Au=ECDSA  Enc=3DES(168)    Mac=SHA1
0xC0,0x12  -  ECDHE-RSA-DES-CBC3-SHA         SSLv3    Kx=ECDH  Au=RSA    Enc=3DES(168)    Mac=SHA1
0x00,0x16  -  EDH-RSA-DES-CBC3-SHA           SSLv3    Kx=DH    Au=RSA    Enc=3DES(168)    Mac=SHA1
0x00,0x9C  -  AES128-GCM-SHA256              TLSv1.2  Kx=RSA   Au=RSA    Enc=AESGCM(128)  Mac=AEAD
0x00,0x9D  -  AES256-GCM-SHA384              TLSv1.2  Kx=RSA   Au=RSA    Enc=AESGCM(256)  Mac=AEAD
0x00,0x3C  -  AES128-SHA256                  TLSv1.2  Kx=RSA   Au=RSA    Enc=AES(128)     Mac=SHA256
0x00,0x3D  -  AES256-SHA256                  TLSv1.2  Kx=RSA   Au=RSA    Enc=AES(256)     Mac=SHA256
0x00,0x2F  -  AES128-SHA                     SSLv3    Kx=RSA   Au=RSA    Enc=AES(128)     Mac=SHA1
0x00,0x35  -  AES256-SHA                     SSLv3    Kx=RSA   Au=RSA    Enc=AES(256)     Mac=SHA1
0x00,0x0A  -  DES-CBC3-SHA                   SSLv3    Kx=RSA   Au=RSA    Enc=3DES(168)    Mac=SHA1

在这份配置中可以看到,每种套件中使用椭圆曲线部分都被排在了 RSA 前面,所以能尽量协商出支持椭圆曲线的算法。

或者我们还可以更激进一些:

# openssl ciphers -V 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK' | column -t
0xC0,0x2B  -  ECDHE-ECDSA-AES128-GCM-SHA256  TLSv1.2  Kx=ECDH        Au=ECDSA  Enc=AESGCM(128)    Mac=AEAD
0xC0,0x2C  -  ECDHE-ECDSA-AES256-GCM-SHA384  TLSv1.2  Kx=ECDH        Au=ECDSA  Enc=AESGCM(256)    Mac=AEAD
0xC0,0x23  -  ECDHE-ECDSA-AES128-SHA256      TLSv1.2  Kx=ECDH        Au=ECDSA  Enc=AES(128)       Mac=SHA256
0xC0,0x09  -  ECDHE-ECDSA-AES128-SHA         SSLv3    Kx=ECDH        Au=ECDSA  Enc=AES(128)       Mac=SHA1
0xC0,0x24  -  ECDHE-ECDSA-AES256-SHA384      TLSv1.2  Kx=ECDH        Au=ECDSA  Enc=AES(256)       Mac=SHA384
0xC0,0x0A  -  ECDHE-ECDSA-AES256-SHA         SSLv3    Kx=ECDH        Au=ECDSA  Enc=AES(256)       Mac=SHA1
0xC0,0x2F  -  ECDHE-RSA-AES128-GCM-SHA256    TLSv1.2  Kx=ECDH        Au=RSA    Enc=AESGCM(128)    Mac=AEAD
0xC0,0x30  -  ECDHE-RSA-AES256-GCM-SHA384    TLSv1.2  Kx=ECDH        Au=RSA    Enc=AESGCM(256)    Mac=AEAD
0x00,0x9E  -  DHE-RSA-AES128-GCM-SHA256      TLSv1.2  Kx=DH          Au=RSA    Enc=AESGCM(128)    Mac=AEAD
0x00,0xA2  -  DHE-DSS-AES128-GCM-SHA256      TLSv1.2  Kx=DH          Au=DSS    Enc=AESGCM(128)    Mac=AEAD
0x00,0xA3  -  DHE-DSS-AES256-GCM-SHA384      TLSv1.2  Kx=DH          Au=DSS    Enc=AESGCM(256)    Mac=AEAD
0x00,0x9F  -  DHE-RSA-AES256-GCM-SHA384      TLSv1.2  Kx=DH          Au=RSA    Enc=AESGCM(256)    Mac=AEAD
0xC0,0x27  -  ECDHE-RSA-AES128-SHA256        TLSv1.2  Kx=ECDH        Au=RSA    Enc=AES(128)       Mac=SHA256
0xC0,0x13  -  ECDHE-RSA-AES128-SHA           SSLv3    Kx=ECDH        Au=RSA    Enc=AES(128)       Mac=SHA1
0xC0,0x28  -  ECDHE-RSA-AES256-SHA384        TLSv1.2  Kx=ECDH        Au=RSA    Enc=AES(256)       Mac=SHA384
0xC0,0x14  -  ECDHE-RSA-AES256-SHA           SSLv3    Kx=ECDH        Au=RSA    Enc=AES(256)       Mac=SHA1
0x00,0x67  -  DHE-RSA-AES128-SHA256          TLSv1.2  Kx=DH          Au=RSA    Enc=AES(128)       Mac=SHA256
0x00,0x33  -  DHE-RSA-AES128-SHA             SSLv3    Kx=DH          Au=RSA    Enc=AES(128)       Mac=SHA1
0x00,0x40  -  DHE-DSS-AES128-SHA256          TLSv1.2  Kx=DH          Au=DSS    Enc=AES(128)       Mac=SHA256
0x00,0x6B  -  DHE-RSA-AES256-SHA256          TLSv1.2  Kx=DH          Au=RSA    Enc=AES(256)       Mac=SHA256
0x00,0x38  -  DHE-DSS-AES256-SHA             SSLv3    Kx=DH          Au=DSS    Enc=AES(256)       Mac=SHA1
0x00,0x39  -  DHE-RSA-AES256-SHA             SSLv3    Kx=DH          Au=RSA    Enc=AES(256)       Mac=SHA1
0x00,0x9C  -  AES128-GCM-SHA256              TLSv1.2  Kx=RSA         Au=RSA    Enc=AESGCM(128)    Mac=AEAD
0x00,0x9D  -  AES256-GCM-SHA384              TLSv1.2  Kx=RSA         Au=RSA    Enc=AESGCM(256)    Mac=AEAD
0x00,0x3C  -  AES128-SHA256                  TLSv1.2  Kx=RSA         Au=RSA    Enc=AES(128)       Mac=SHA256
0x00,0x3D  -  AES256-SHA256                  TLSv1.2  Kx=RSA         Au=RSA    Enc=AES(256)       Mac=SHA256
0x00,0x2F  -  AES128-SHA                     SSLv3    Kx=RSA         Au=RSA    Enc=AES(128)       Mac=SHA1
0x00,0x35  -  AES256-SHA                     SSLv3    Kx=RSA         Au=RSA    Enc=AES(256)       Mac=SHA1
0x00,0x6A  -  DHE-DSS-AES256-SHA256          TLSv1.2  Kx=DH          Au=DSS    Enc=AES(256)       Mac=SHA256
0xC0,0x32  -  ECDH-RSA-AES256-GCM-SHA384     TLSv1.2  Kx=ECDH/RSA    Au=ECDH   Enc=AESGCM(256)    Mac=AEAD
0xC0,0x2E  -  ECDH-ECDSA-AES256-GCM-SHA384   TLSv1.2  Kx=ECDH/ECDSA  Au=ECDH   Enc=AESGCM(256)    Mac=AEAD
0xC0,0x2A  -  ECDH-RSA-AES256-SHA384         TLSv1.2  Kx=ECDH/RSA    Au=ECDH   Enc=AES(256)       Mac=SHA384
0xC0,0x26  -  ECDH-ECDSA-AES256-SHA384       TLSv1.2  Kx=ECDH/ECDSA  Au=ECDH   Enc=AES(256)       Mac=SHA384
0xC0,0x0F  -  ECDH-RSA-AES256-SHA            SSLv3    Kx=ECDH/RSA    Au=ECDH   Enc=AES(256)       Mac=SHA1
0xC0,0x05  -  ECDH-ECDSA-AES256-SHA          SSLv3    Kx=ECDH/ECDSA  Au=ECDH   Enc=AES(256)       Mac=SHA1
0x00,0x32  -  DHE-DSS-AES128-SHA             SSLv3    Kx=DH          Au=DSS    Enc=AES(128)       Mac=SHA1
0xC0,0x31  -  ECDH-RSA-AES128-GCM-SHA256     TLSv1.2  Kx=ECDH/RSA    Au=ECDH   Enc=AESGCM(128)    Mac=AEAD
0xC0,0x2D  -  ECDH-ECDSA-AES128-GCM-SHA256   TLSv1.2  Kx=ECDH/ECDSA  Au=ECDH   Enc=AESGCM(128)    Mac=AEAD
0xC0,0x29  -  ECDH-RSA-AES128-SHA256         TLSv1.2  Kx=ECDH/RSA    Au=ECDH   Enc=AES(128)       Mac=SHA256
0xC0,0x25  -  ECDH-ECDSA-AES128-SHA256       TLSv1.2  Kx=ECDH/ECDSA  Au=ECDH   Enc=AES(128)       Mac=SHA256
0xC0,0x0E  -  ECDH-RSA-AES128-SHA            SSLv3    Kx=ECDH/RSA    Au=ECDH   Enc=AES(128)       Mac=SHA1
0xC0,0x04  -  ECDH-ECDSA-AES128-SHA          SSLv3    Kx=ECDH/ECDSA  Au=ECDH   Enc=AES(128)       Mac=SHA1
0x00,0x88  -  DHE-RSA-CAMELLIA256-SHA        SSLv3    Kx=DH          Au=RSA    Enc=Camellia(256)  Mac=SHA1
0x00,0x87  -  DHE-DSS-CAMELLIA256-SHA        SSLv3    Kx=DH          Au=DSS    Enc=Camellia(256)  Mac=SHA1
0x00,0x84  -  CAMELLIA256-SHA                SSLv3    Kx=RSA         Au=RSA    Enc=Camellia(256)  Mac=SHA1
0x00,0x45  -  DHE-RSA-CAMELLIA128-SHA        SSLv3    Kx=DH          Au=RSA    Enc=Camellia(128)  Mac=SHA1
0x00,0x44  -  DHE-DSS-CAMELLIA128-SHA        SSLv3    Kx=DH          Au=DSS    Enc=Camellia(128)  Mac=SHA1
0x00,0x41  -  CAMELLIA128-SHA                SSLv3    Kx=RSA         Au=RSA    Enc=Camellia(128)  Mac=SHA1

可以看到在这份配置中,我几乎将所有的支持椭圆曲线的套件都提到了最前面,来加大协商出支持椭圆曲线算法的套件的可能性。

综上,推荐的配置如下:

ssl_ciphers 'EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5';
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';

三者任选其一即可。

 

参考:

https://imququ.com/post/ecc-certificate.html

https://www.zeroling.com/nginx-kai-qi-https-shuang-zheng-shu-zhi-nan/

https://n4l.pw/nginx-dual-certificates.html

https://imququ.com/post/certificate-transparency.html

https://seryo.net/use-ecc-algorithms-issued-a-certificate-request-file.Seryo

Ubuntu 14.04 安装 Ejbca (Install Ejbca on Ubuntu 14.04)

[warning]首先,如果不是万不得已,请不要使用 EJBCA,请不要阅读本文章!这个软件真的不是正常人可以驾驭的!如果只是个人兴趣(比如我就是装着好玩),那么请千万不要尝试使用 EJBCA!非常蛋疼!千万不要用!而且这玩意的搭建特别看脸,说不定啥时候就成功了。本文的成功方法并无法复制。[/warning]

这个玩意毕竟是一个商业软件的社区免费版,功能先不说,Bug一定是比商业版多一大堆的。而且官方给的文档也基本都很老了,并且不全,大部分你遇到的问题官方文档都不会说的。官方文档似乎最喜欢教你怎么配置,当然反正按照那个配一样成功不了。。。官方这么做当然另一个目的就是卖收费服务,不然免费的随便配置下就成功了谁还买呢。。。

至于官方的 Quick Start,直接无视吧。如果你按照官方的 Quick Start 成功的把服务搭起来了,那我只能佩服你了。。。反正我一开始一直遵照官方的教程死活也没有成功过一次。直到我找到一篇第三方的教程,才终于成功了一次。原教程地址:http://ejbcacentos.blogspot.hk/2014/04/how-to-install-ejbca-611-on-centos-65.html 因为是全英文的而且需要科学上网来访问,所以我在这里参考这篇教程把我配置的过程写一下。如果按照教程配置不成功请不要提问!我也不知道为什么!我自己配十次能成功一次就很开心了!


介绍

EJBCA 是一个用 Java 编写的可以在网页上完成所有操作的全功能 CA 服务器,只要是 CA 应该支持的功能这个软件全都支持。但是!这个软件的安装完全不像官方说的那么简单!如果你只是想玩玩,建议直接下载官方的虚拟机镜像玩吧。

准备

首先要安装相关依赖。因为我在后端数据库的选择上使用的是 Mysql,所以我需要装这么些东西:
sudo apt-get install openjdk-7-jdk ant ant-optional unzip ntp mysql-server libmysql-java
那篇教程里说 Java 7 会有问题,实际上似乎已经修复了,所以可以直接用。源里 ant 的版本是 1.8.2,满足最低的版本要求,所以也可以直接用,不用下载最新的。libmysql-java 是 Java 连接 Mysql 数据库所需要的必须的组建,因为我使用 Mysql 作为后端,所以需要安装。然后防火墙什么的就不管他了,建议你在确定配置成功的情况下再去搞别的,不然纯属浪费时间。。。

配置 Mysql

mysql 主要是要更改一下默认的编码,确保一直使用 UTF-8 作为编码方式,防止乱码。在 my.cnf 中加入这一段:
#UTF-8
character-set-server=utf8
collation-server=utf8_unicode_ci
init-connect='SET NAMES utf8'
#character-set-client = utf8

然后使用 root 账号登陆,新建数据库和账号:
service mysqld start
mysql_secure_installation
mysql -u root -p
create database ejbcadb;
grant all privileges on ejbcadb.* to 'ejbcadbuser'@'localhost' identified by 'password';
flush privileges;
exit

然后确认一下你刚刚创建的账号可以正常的访问数据库:
mysql -u ejbcadbuser -p
use ejbcadb;
show grants for ejbcadbuser@localhost;
exit

创建用户

建议不要直接使用 root 用户来安装 EJBCA,而是分配专门的账户。所以我们使用 adduser ejbca 添加一个用户。然后执行 su – ejbca,切换到 ejbca 用户下操作。

下载 Ejbca 和 Jboss

wget http://download.jboss.org/jbossas/7.1/jboss-as-7.1.1.Final/jboss-as-7.1.1.Final.zip
wget http://downloads.sourceforge.net/project/ejbca/ejbca6/ejbca_6_2_0/ejbca_ce_6_2_0.zip
unzip *.zip
ln -s ejbca_ca_6_2_0 ejbca
ln -s jboss-as-7.1.1.Final jboss

配置 Jboss

cd /opt/jboss/modules/sun/jdk/main
vi module.xml

在适当位置添加下面几行:(注释不要加进去)
### Start module.xml Delta ###

### End module.xml Delta ###

安装 Mysql 连接组件

cd ~
mkdir -p jboss/modules/com/mysql/main/
ln -s /usr/share/java/mysql.jar
vi module.xml

新建 module.xml 文件,写入如下内容:
### Start module.xml ###










### End module.xml ###
现在可以启动 Jboss 了。打开一个新的终端或者使用 screen 执行 ~/jboss/bin/standalone.sh。日志会写入 ~/jboss/standalone/log/
如果你看到这样的日志,说明 Jboss 应该是启动成功了:
22:51:40,482 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-2) Starting Coyote HTTP/1.1 on http--127.0.0.1-8080
22:51:40,688 INFO [org.jboss.as.remoting] (MSC service thread 1-3) JBAS017100: Listening on /127.0.0.1:4447
22:51:40,690 INFO [org.jboss.as.remoting] (MSC service thread 1-2) JBAS017100: Listening on /127.0.0.1:9999
22:51:40,699 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-3) JBAS015012: Started FileSystemDeploymentService for directory /opt/jboss/standalone/deployments
22:51:40,773 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
22:51:40,774 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: JBoss AS 7.1.1.Final "Brontes" started in 1528ms - Started 130 of 204 services (74 services are passive or on-demand)

接下来给 Jboss 添加 Mysql 连接器:
cd ~/jboss/bin
sh jboss-cli.sh
connect
/subsystem=datasources/jdbc-driver=com.mysql.jdbc.Driver:add(driver-name=com.mysql.jdbc.Driver,driver-module-name=com.mysql,driver-xa-datasource-class-name=com.mysql.jdbc.jdbc.jdbc2.optional.MysqlXADataSource)
:reload
exit

这句话在 ~/jboss/standalone/configuration/standalone.xml 中定义了 Mysql Driver ,然后重启 Jboss。
接下来修改 Jboss 的配置文件,删掉自带的 h2 数据库:
### Start standalone.xml Delta ###

删除这一段:


jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
h2

sa sa

还有这一段:


org.h2.jdbcx.JdbcDataSource

### End standalone.xml Delta ###
好了!现在可以开始配置 Ejbca 了。

配置 Ejbca

Ejbca 的配置文件在这个文件夹里:
~/ejbca/conf/
默认配置文件都以 .sample 结尾。需要修改的话删除 .sample 然后进行相应的修改即可。
cd ~/ejbca/conf
cp certstore.properties.sample certstore.properties
cp cesecore.properties.sample cesecore.properties
cp crlstore.properties.sample crlstore.properties
cp database.properties.sample database.properties
cp ejbca.properties.sample ejbca.properties
cp install.properties.sample install.properties
cp mail.properties.sample mail.properties
cp web.properties.sample web.properties

接下来是要改的配置。这里只放出需要修改的行:
certstore.properties

### Start certstore.properties ###

certstore.enabled=true

certstore.contextroot=/certificates

### End certstore.properties ###

cesecore.properties

### Start cesecore.properties ###

ca.toolateexpiredate=80000000

securityeventsaudit.implementation.X=org.cesecore.audit.impl.log4j.Log4jDevice
securityeventsaudit.implementation.X=org.cesecore.audit.impl.integrityprotected.IntegrityProtectedDevice

securityeventsaudit.implementation.0=org.cesecore.audit.impl.log4j.Log4jDevice
securityeventsaudit.implementation.1=org.cesecore.audit.impl.integrityprotected.IntegrityProtectedDevice
securityeventsaudit.exporter.1=org.cesecore.audit.impl.AuditExporterXml

### End cesecore.properties ###

crlstore.properties

### Start crlstore.properties ###

crlstore.enabled=true
crlstore.contextroot=/crls

### End crlstore.properties ###

database.properties

### Start database.properties ###

datasource.jndi-name=EjbcaDS

database.name=mysql

database.url=jdbc:mysql://127.0.0.1:3306/ejbcadb?characterEncoding=UTF-8
database.driver=com.mysql.jdbc.Driver

database.username=ejbcadbuser

# Change this to your mysql user password:
database.password=pumpkin

### End database.properties ###

ejbca.properties

### Start ejbca.properties ###

appserver.home=/home/ejbca/jboss
appserver.type=jboss

ejbca.productionmode=false

approval.defaultrequestvalidity=28800
approval.defaultapprovalvalidity=28800

healthcheck.amountfreemem=32
healthcheck.dbquery=Select 1 From CertificateData where fingerprint='XX'
healthcheck.authorizedips=127.0.0.1
healthcheck.catokensigntest=true
healthcheck.publisherconnections=true
healthcheck.okmessage=ALLOK
healthcheck.sendservererror=true

ejbca.passwordlogrounds=8

### End ejbca.properties ###

install.properties

### Start install.properties ###

ca.name=mgmtca
ca.dn=CN=mgmtca,O=Your Company,C=US
ca.tokentype=soft
ca.tokenpassword=null

ca.keyspec=4096

ca.keytype=RSA

ca.signaturealgorithm=SHA256WithRSA

ca.validity=3652
ca.policy=null
ca.certificateprofile=ROOTCA

### End install.properties ###

mail.properties

### Start mail.properties ###

mail.jndi-name=java:/EjbcaMail
mail.user=ejbca
mail.password=honeybunny
mail.smtp.host=localhost
mail.smtp.port=25
#mail.smtp.auth=false
#mail.smtp.starttls.enable=false
mail.from=ejbca@yourcompany.net
#mail.debug=false
mail.contentencoding=UTF-8

### End mail.properties ###

web.properties

### Start web.properties ###

superadmin.cn=superadmin
superadmin.dn=CN=${superadmin.cn},O=Your Company,C=US

superadmin.batch=true

httpsserver.hostname=rootca.yourdomain.net
httpsserver.dn=CN=${httpsserver.hostname},O=Your Company,C=US

httpserver.pubhttp=8080

httpserver.pubhttps=8442

httpserver.privhttps=8443
#httpserver.external.privhttps=443

#httpserver.external.fqdn=
#httpserver.external.fqdn=${httpsserver.hostname}

#httpsserver.bindaddress.pubhttp=0.0.0.0
#httpsserver.bindaddress.pubhttps=0.0.0.0
#httpsserver.bindaddress.privhttps=0.0.0.0

web.contentencoding=UTF-8

web.selfreg.enabled=false
web.selfreg.defaultcerttype=1
web.selfreg.certtypes.1.description=User certificate
web.selfreg.certtypes.1.eeprofile=user
web.selfreg.certtypes.1.certprofile=user
web.renewalenabled=false
web.errorpage.notification=An exception has occurred.
web.errorpage.stacktrace=true

web.log.adminremoteip=true

### End web.properties ###
好了!下面可以开始尝试编译了。
cd ~/ejbca
ant deploy

部署的过程中可能会出这么几个问题:
06:05:16,848 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 1) JBAS014612: Operation ("composite") failed - address: ([]): java.lang.IllegalArgumentException

06:05:39,477 ERROR [org.hibernate.internal.util.xml.ErrorLogger] (MSC service thread 1-4) HHH000196: Error parsing XML (21) : cvc-complex-type.3.1: Value '1.0' of attribute 'version' of element 'entity-mappings' is not valid with respect to the corresponding attribute use. Attribute 'version' has a fixed value of '2.0'.

15:29:58,915 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (MSC service thread 1-2) JSF1051: Service entry 'org.jboss.as.web.deployment.jsf.JsfInjectionProvider' does not extend DiscoverableInjectionProvider. Entry will be ignored.
这些问题可以直接无视,这是因为 Jboss 的 Bug。当然,这些问题可能会导致部署失败。那就多试几次吧。。。
如果你在 Jboss 的日志中看到了这个,说明你可能部署成功了:
01:38:38,724 INFO [org.jboss.as] (MSC service thread 1-1) JBAS015874: JBoss AS 7.1.1.Final "Brontes" started in 7761ms - Started 2855 of 2968 services (111 services are passive or on-demand)
01:38:38,769 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "ejbca.ear"

顺便一说,部署的过程中你会看到大量的:
appserver.error.message:
[echo] jndi.properties.file: /home/ejbca/ejbca_ce_6_2_0/conf/jndi.properties.jboss7

没关系,这个我可以确定是完全正常,丝毫不影响后续的。。。

接下来重启 Jboss ,到之前打开的另一个终端或者 screen , Ctrl+C 结束掉 Jboss ,然后重新启动。
之后,回到 ~/ejbca ,执行 ant install
当你看到:

[echo] Initializing CA with 'mgmtCA' 'CN=mgmtca,O=Your Company,C=US' 'soft'

说明你的配置文件没有问题了,至于各种证书和存储库能不能正常生成,还是看脸。

如果你在终端看到 ant 返回 BUILD SUCCESS ,并且重启 Jboss 后能看到这样的日志,恭喜你,配置成功了!
06:20:59,482 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /${app.name}/publicweb/status
06:20:59,484 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/publicweb/apply
06:20:59,491 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/publicweb/webdist
06:20:59,506 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/publicweb
06:20:59,516 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/publicweb/healthcheck
06:20:59,521 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/clearcache
06:20:59,521 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/ejbcaws
06:20:59,571 INFO [org.jboss.web] (MSC service thread 1-4) JBAS018210: Registering web context: /ejbca
06:20:59,727 INFO [org.jboss.web] (MSC service thread 1-1) JBAS018210: Registering web context: /crls
06:20:59,728 INFO [org.jboss.web] (MSC service thread 1-2) JBAS018210: Registering web context: /certificates
06:21:00,141 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/adminweb
06:21:16,576 INFO [org.jboss.web] (MSC service thread 1-1) JBAS018210: Registering web context: /ejbca/doc

WSDL published to: file:/opt/jboss-as-7.1.1.Final/standalone/data/wsdl/ejbca.ear/ejbca-ws-ejb.jar/EjbcaWSService.wsdl

接下来从服务器上将 superadmin.p12 拷贝出来,导入浏览器,就可以访问管理页面了!

当然,按照我的经验,看到这里的人 99% 都是要被坑的,你应该是无法正常安装的。如果没成功的话,不要灰心,多试几次。我将上述过程整整重新执行了一天,才最终装好一个。然后因为要修改一些配置,又挂了。所以说,这玩意能不碰就不碰,我已经在开头警告过了。。。

[优惠]SSL支持通配符证书 2.5刀/年

产品简介:

SSL Certificates – AlphaSSL (Standard/Wildcard)
SSL Brand: AlphaSSL
Alpha SSL is powered by GlobalSign, the International Certification Authority with its own highly trusted root CA certificates.
Validation Type: Domain Validation
Issuance: 20 Minutes
Encryption: 256bit
Reissue Fee: Free

支持通配符*,即绑定了*.imlonghao.com后,aa.imlonghao.com,bb.imlonghao.com,均可以使用此SSL证书!

根据评论,该优惠码是经常性,即续费同价!
购买地址:https://billing.centriohost.com/cart.php?a=add&pid=21

促销代码: LET2SSL

使用方法:

在Promo code处填入优惠码,认证即可获得优惠

 

 

ssl_1

 

sl_2

Kloxo面板后台SSL证书替换

最近在自己的服务器上搭建Kloxo面板造福大众,然后遇到了一点问题,就是Kloxo面板的后台7777端口访问的时候总是会提示证书是由不受信任的颁发机构颁发。做完一个重度强迫症患者(误),这是绝对不能忍的!

但是找来找去一直没有发现相关的文章。看了大家对不常用的东西一点都不在乎= =|||于是只好自己动手。

首先在你的命令行中输入:

ps -aux|grep kloxo.httpd

然后你会看到类似这样的显示:

lxlabs   16186  0.0  0.2   7256  3544 ?        S    04:07   0:01 /usr/local/lxlabs/ext/lxlighttpd/sbin/kloxo.httpd -f /usr/local/lxlabs/kloxo/file/lighttpd.conf
root     24325  0.0  0.0   3188   796 pts/0    S+   17:26   0:00 grep kloxo.httpd

其中/usr/local/lxlabs/kloxo/file/lighttpd.conf就是Kloxo控制面板的Lighttpd配置文件。(找到它真不容易啊。。。在Apache那绕了一个小时的弯,突然灵光一闪看了下进程列表然后哭了。。。这货居然用的是独立的一套Lighttpd。。。)

打开拉到最下方,能看到:

$SERVER["socket"] == ":7777" {
        server.document-root = "/usr/local/lxlabs/kloxo/httpdocs/"
        ssl.engine = "enable"
        ssl.pemfile             = "/usr/local/lxlabs/kloxo/etc/program.pem"
        ssl.ca-file             = "/usr/local/lxlabs/kloxo/etc/program.ca"
        ssl.use-sslv2 = "disable"
 }

其中ssl.pemfile和ssl.ca-file就是我们需要修改的内容所指的文件就是我们要修改的内容。这里指向的是Kloxo自带的一个证书文件。现在我们修改这两项,将其指定到我们自己的证书文件。注意,ssl.pemfile我之所以没用ssl.crt是因为Lighttpd需要的证书文件比较特殊,是把Key私钥直接附加在crt证书后面生成的。为了不破坏原式证书,我起了一个不一样的名字来区分。 现在我们找到这两个program.pem和program.ca并将其替换成我们自己的证书。

接下来以StartSSL的免费SSL证书为例,说明这两个文件如何生成。

首先,我们从StartSSL拿到的证书文件包括:

ca.pem
ssl.crt
ssl.key
sub.class1.server.ca.pem

四个文件。其中ssl.key是预先解密好的私钥文件。当然不解密应该也可以,但是每次启动服务的时候都需要输入私钥密码,非常麻烦。

首先我们生成program.pem:

cat ssl.crt ssl.key > program.pem

这个ssl_key.crt就是我们最终需要的文件,即ssl.pemfile

然后生成ca-certs.crt:

cat sub.class1.server.ca.pem ca.pem > program.ca

此时生成的文件就是我们需要的文件。

然后将两个文件替换掉原来的文件,把Lighttpd重启一下,再访问就能看到效果了。

刚刚给Blog上了StartSSL的SSL证书

因为更换主机的缘故,在Dropbox里面翻我原来的备份,无意中找到了之前在StartSSL申请的账号的证书,遂导入登陆之。惊喜发现自己的账号还能用,于是决定给我的域名申请一免费的SSL证书。按照官方的提示先对域名进行验证,之后就顺利申请到了证书。

拿到证书后正在忧桑不知道怎么安装,发现StartSSL官方有教程,于是按照指示下载了根证书之后顺利安装。

在这帮他做下宣传吧。StartSSL的证书确实是不错的,而且是免费的SSL证书。不过可惜免费的只能绑定一个子域名,但是一般也够用了。

不过StartSSL的账号可是真难申请。。。如果有想要申请他家的免费SSL证书的话欢迎跟我联系。留言就好。我可以用我的账户帮你申请一个一年的免费证书。