我应该如何升级到 TLS 1.2?
为了满足技术要求,使用 OpenSSL 1.0.1 或 1.0.2 就足够了。两者都提供 TLS 1.2,并且都提供 SHA-256。 (还有其他隐藏的实现,例如 OpenSSL 1.0.0 不提供 EC 设备的完整补充和 TLS 1.2 密码套件的完整补充,但 1.0.1 和 1.0.2 提供)。
在您使用 OpenSSL 的 C 代码中,您需要为 SSL 上下文或会话执行所有操作:
/* Useless return value ??? */
SSL_library_init();
const SSL_METHOD* method = SSLv23_method();
if(NULL == method) handleFailure();
SSL_CTX* ctx = SSL_CTX_new(method);
if(ctx == NULL) handleFailure();
/* Cannot fail ??? */
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | \
SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);
对于类似 Apache 的服务器配置,请使用以下内容(我的包括 +TLSv1 +TLSv1.1):
# From my CentOS production server
SSLProtocol -all +TLSv1.2
您也应该倾向于加密套件。为此,在 C 代码中:
const char CIHPHER_LIST[] = "HIGH:!aNULL:!RC4:!MD5"
/* Ensure at least one cipher suite is added, which indicates non-failure */
int rc = SSL_CTX_set_cipher_list(ctx, CIHPHER_LIST);
if(!(rc >= 1)) handleFailure();
在类似 Apache 的配置文件中:
# From my CentOS production server
SSLCipherSuite HIGH:!aNULL:!MD5:!RC4
如果您想避免 RSA 密钥传输(TLS 1.3 正在删除它),那么:
SSLCipherSuite HIGH:!aNULL:!MD5:!RC4:!kRSA
删除 RSA 密钥传输后,您几乎只剩下临时密钥交换协议(PSK 和 SRP 等模密码套件)。
如果您想明确使用临时密钥交换,那么您将需要kEECDH:kECDHE:kDHE:kEDH:!aNULL 之类的东西。有关详细信息,请参阅 openssl ciphers(1) 手册页。
我在字里行间阅读,但 TLS 1.2 要求可能与经过身份验证的加密以及 GCM 等操作模式有关。为此,请再次使用openssl ciphers(1):
$ openssl ciphers -v 'HIGH:!aNULL' | grep GCM
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
DHE-DSS-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=DSS Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDH-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
ECDH-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
AES256-GCM-SHA384 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD
DHE-DSS-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=DSS Enc=AESGCM(128) Mac=AEAD
DHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD
ECDH-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
ECDH-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
AES128-GCM-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(128) Mac=AEAD
或者:
$ openssl ciphers -v 'HIGH:!aNULL' | grep GCM | grep -v "Kx=RSA" | cut -d " " -f 1
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES256-GCM-SHA384
DHE-DSS-AES256-GCM-SHA384
DHE-RSA-AES256-GCM-SHA384
ECDH-RSA-AES256-GCM-SHA384
ECDH-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES128-GCM-SHA256
DHE-DSS-AES128-GCM-SHA256
DHE-RSA-AES128-GCM-SHA256
ECDH-RSA-AES128-GCM-SHA256
ECDH-ECDSA-AES128-GCM-SHA256
您可以执行以下操作,而不是指定HIGH:!aNULL:!MD5:!RC4:!kRSA:
const char CIPHER_LIST[] =
"ECDHE-RSA-AES256-GCM-SHA384:"
"ECDHE-ECDSA-AES256-GCM-SHA384:"
"DHE-DSS-AES256-GCM-SHA384:"
"DHE-RSA-AES256-GCM-SHA384:"
"ECDH-RSA-AES256-GCM-SHA384:"
"ECDH-ECDSA-AES256-GCM-SHA384:"
"ECDHE-RSA-AES128-GCM-SHA256:"
"ECDHE-ECDSA-AES128-GCM-SHA256:"
"DHE-DSS-AES128-GCM-SHA256:"
"DHE-RSA-AES128-GCM-SHA256:"
"ECDH-RSA-AES128-GCM-SHA256:"
"ECDH-ECDSA-AES128-GCM-SHA256:"
/* Ensure at least one cipher suite is added, which indicates non-failure */
int rc = SSL_CTX_set_cipher_list(ctx, CIPHER_LIST);
if(!(rc >= 1)) handleFailure();
如果您查看 AES256-GCM-SHA384 密码套件,您会看到使用密钥传输 (Kx=RSA),因此您可能希望避免使用它,即使它是 TLS 1.2。这就是grep -v 的原因。
为了完整起见,Au=RSA 很好。这只是意味着服务器仅使用其 RSA 密钥进行签名。而在实践中,Au=DSS 很少使用,因此如果没有 DSS 密钥,OpenSSL 将删除密码套件。
现在,困难可能在于获得提供最新 OpenSSL 1.0.2 的发行版并且提供长期支持。我的 CentOS 机器不提供它,所以我必须从源代码构建它,然后在玩那些愚蠢的 r-path 游戏时重新构建依赖于 OpenSSL 的每个库或程序。
在你的情况下,它看起来像 Apache、PHP、Drupal、MySQL、phpAdmin(当安全性受到关注时,真的有人使用它吗:)和朋友。