解决 ODBC Driver 18 for SQL Server SSL 证书验证失败错误
问题描述
在使用 ODBC Driver 18 for SQL Server 连接 SQL Server 数据库时,可能会出现以下 SSL 证书验证错误:
[Microsoft][ODBC Driver 18 for SQL Server]SSL Provider: [error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:self signed certificate]
这个错误通常出现在以下环境中:
- Ubuntu 20.04 或更高版本
- PHP 7.4 FPM 与 nginx
- OpenSSL 1.1.1f 或更新版本
- SQL Server 2012 或更高版本
错误原因是 ODBC Driver 18 默认要求进行严格的 SSL 证书验证,而当服务器使用自签名证书或证书链不完整时,验证会失败。
解决方案
方法一:在连接字符串中添加信任服务器证书选项(推荐)
这是最直接且常用的解决方案,通过在连接字符串中添加 TrustServerCertificate=yes
参数来跳过证书验证。
$sql_info = array(
'UID' => 'your_sql_user',
'PWD' => 'your_password',
'Database' => 'your_DB_name',
'TrustServerCertificate' => 1,
);
sqlsrv_connect('your_host_or_ip', $sql_info);
conn_str = f'DRIVER=ODBC Driver 18 for SQL Server;SERVER={server};DATABASE={database};UID={username};PWD={password};TrustServerCertificate=yes'
Dim conStr As String = "Driver={ODBC Driver 18 for SQL Server};Server=your_servername;Database=your_databasename;Uid=your_username;Pwd=your_password;TrustServerCertificate=yes;"
安全提示
TrustServerCertificate=yes
会跳过 SSL 证书验证,降低了连接的安全性。仅应在开发环境或可信的内部网络中使用。生产环境应使用有效的 SSL 证书。
方法二:禁用加密连接
如果安全性不是首要考虑因素(如在开发环境),可以完全禁用加密:
conn_str = f'DRIVER=ODBC Driver 18 for SQL Server;SERVER={server};DATABASE={database};UID={username};PWD={password};Encrypt=no'
'trust_server_certificate' => 'true',
'encrypt' => 'false'
方法三:调整 OpenSSL 安全级别
在某些 Linux 发行版上,可能需要降低 OpenSSL 的安全级别:
sudo nano /etc/ssl/openssl.cnf
找到或添加以下配置:
[system_default_sect]
CipherString = DEFAULT:@SECLEVEL=0
注意
降低安全级别会增加系统安全性风险,请谨慎操作并仅在必要时使用此方法。
方法四:使用 SQLCMD 命令行工具
对于命令行操作,可以使用 -C
参数来信任服务器证书:
sqlcmd -S localhost -U sa -P 'YourPassword' -C
或者尝试使用 IP 地址而非主机名:
sqlcmd -S 127.0.0.1 -U sa -P 'YourPassword' -C
方法五:框架特定配置
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '1433'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'trust_server_certificate' => 'true'
]
DATABASES['source'] = {
'ENGINE': 'mssql',
'NAME': 'db_name',
'USER': 'db_user',
'PASSWORD': 'db_pass',
'HOST': 'db_host',
'OPTIONS': {
'driver': 'ODBC Driver 18 for SQL Server',
'extra_params': "TrustServerCertificate=yes"
},
}
engine = sqlalchemy.create_engine(
conn_string,
connect_args = {
"TrustServerCertificate": "yes"
}, echo=False)
根本原因分析
ODBC Driver 18 引入了更严格的 SSL/TLS 安全要求:
- 默认启用加密连接
- 默认要求验证服务器证书
- 对自签名证书和证书链不完整的情况更加敏感
这与早期版本的驱动程序行为不同,早期版本可能默认不验证证书或使用较宽松的安全设置。
最佳实践建议
- 生产环境:应使用有效的 SSL 证书而非自签名证书
- 开发环境:可使用
TrustServerCertificate=yes
但应意识到安全风险 - 连接字符串:始终明确指定加密和证书信任选项,避免依赖默认设置
- 驱动程序:确保使用正确版本的 ODBC 驱动程序,Linux 和 Windows 上的驱动程序名称可能不同
环境检查
确认你的环境配置:
# 检查 OpenSSL 版本
openssl version
# 测试与 SQL Server 的 SSL 连接
openssl s_client -connect your_server_ip:1433 -tls1
# 查看已安装的 ODBC 驱动程序
odbcinst -q -d
总结
ODBC Driver 18 的 SSL 证书验证错误通常可通过以下方式解决:
- 在连接字符串中添加
TrustServerCertificate=yes
- 或禁用加密
Encrypt=no
(仅限开发环境) - 根据使用的框架进行相应配置
选择解决方案时应权衡安全需求和开发便利性,生产环境强烈建议使用有效的 SSL 证书而非绕过验证。