MariaDB Connector/C 3.0 新特性 – 第一部分:SSL
新的 SSL 替代方案
MariaDB Connector/C 之前版本的 SSL 连接基于 OpenSSL 库。但由于 OpenSSL heartbleed 漏洞、许可问题以及对不同传输层缺乏支持,我们决定添加对替代 SSL 实现的支持。
因此 Connector/C 3.0 不仅可以使用 OpenSSL,还可以使用
- GnuTLS (http://www.gnutls.org)
- SChannel (仅限 Windows)
在 Windows 上,Connector/C 3.0 默认使用 SChannel,并且不需要任何外部 SSL 库。
目前,SSL 实现必须在编译 Connector/C 时选择。可以通过将 WITH_SSL cmake 变量设置为 OPENSSL、GNUTLS、SCHANNEL 或 OFF 来实现,其中 OFF 表示完全没有 SSL 支持。
如果未指定 WITH_SSL,Connector/C 将在 Windows 上使用 SChannel,在其他地方使用 OpenSSL。
示例
cmake . -DWITH_SSL=GNUTLS
Connector/C 之前版本中使用的 CMake 参数 WITH_OPENSSL=ON/OFF 已不再支持。
mariadb_get_info() API 函数返回 MariaDB Connector/C 正在使用的 SSL 库类型
const char *library; mariadb_get_info(mysql, MARIADB_CONNECTION_SSL_LIBRARY, (void *)&library); printf("SSL library: %s\n", library);
安全性
防止 MTM 攻击
身份(而非加密)是加密协议中最重要的一部分。如果并非与您想要通信的对象进行通信,最强的加密也毫无价值——仅仅因为数据被加密并不意味着它不能被窥探。
为了防止中间人攻击(MTM),MariaDB Connector/C 和 MariaDB 服务器包中的 libmysql 都提供了检查服务器发送给客户端证书中的通用名(CN)的选项。
客户端根据客户端用于连接服务器的主机名验证 CN
my_bool verify= 1; mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify);
然而,验证主机名可能不够安全
- 客户端验证程序仅根据证书的 CN 条目验证主机名,但不验证一个或多个 SAN(Subject Alternative Name)条目,这使得在故障转移环境中使用 SSL 变得困难。
- 除了使用 GnuTLS 的情况,目前尚不支持带通配符的主机名验证
- 过去,未经审计的证书被反复签发,尤其是一些经销商,这些证书被用于攻击。
因此,主机名验证并非 100% 的保护。
指纹验证
除了主机名验证之外,MariaDB Connector/C 3.0 还提供了一种额外的验证方法:检查服务器证书的指纹。指纹是一串短字节序列,用于识别较长(公共)密钥。可以通过对密钥应用加密哈希函数来创建指纹。MariaDB Connector/C 仅支持 SHA1 哈希函数。
创建指纹
1) OpenSSL
openssl x509 -in server-cert.pem -sha1 -fingerprint -noout SHA1 Fingerprint=3A:07:9E:1A:14:AD:32:69:53:A5:D2:80:F9:96:B9:3D:77:2A:5B:EA
2) GnuTLS
certtool -i --infile=server-cert.pem
Look for SHA1 fingerprint in output:
Other Information:
SHA1 fingerprint:
3a079e1a14ad326953a5d280f996b93d772a5bea
验证指纹
要验证服务器证书的指纹,您可以指定单个指纹或包含多个指纹的文件。指纹需要以十六进制格式指定,不包含冒号。
mysql_options(mysql, MARIADB_OPT_SSL_FP, "3a079e1a14ad326953a5d280f996b93d772a5bea");
或
mysql_options(mysql, MARIADB_OPT_SSL_FP_LIST, "./fingerprint.list");
传输层安全 (TLS)
正如 Sergei Golubchik 在之前的一篇博客文章 MariaDB 中的 SSL 状态 中所写,较新的 MariaDB 服务器版本(> 5.5.41 和 > 10.0.15)现在支持较新的安全标准 TLSv_1.1,并且更推荐使用 TLS_v_1.2(根据 PCI DSS v_3.1 的要求)。
在 Connector/C 的 3.0 版本中,我们现在也添加了对 TLSv_1.1 和 TLSv_1.2 的支持。MariaDB Server 和 Connector/C 都提供一个选项来确定正在使用的 TLS 版本。
服务器
MariaDB [(none)]> show session status like 'ssl_version'; +---------------+---------+ | Variable_name | Value | +---------------+---------+ | Ssl_version | TLSv1.2 | +---------------+---------+
客户端
const char *tls_version; mariadb_get_info(mysql, MARIADB_CONNECTION_SSL_VERSION, (void *)&tls_version); printf("Ssl_version: %s\n", tls_version);
密码保护的私钥
通常私钥会使用一个密码短语进行加密,以防止丢失(?)。
密码短语保护的密钥为了安全起见是推荐的,但在 MariaDB Connector/C 3.0 之前的版本中通常不切实际,因为密码短语保护的密钥只能在手动输入密码短语后才能使用
./my_test --ssl-ca=ca-cert.pem --ssl-key=client-key-enc.pem --ssl-cert=client-cert.pem Enter PEM pass phrase:
使用 MariaDB Connector/C 3.0,如果密码短语
在建立连接之前已指定
mysql_options(mysql, MARIADB_OPT_SSL_PASSPHRASE, "4_l0ng3r_P4ssphr4s3_is_much_b3tt3r_th4n_4_sh0rter_0ne");
注意
MariaDB Connector/C 3.0 是一个 Alpha 版本。通常这意味着除了标记为功能请求的错误外,没有已知的严重错误,但我们认为它需要进一步的测试和开发才能称之为稳定版本。