使用通过程序集内置到 Microsoft.Net 的 Microsoft.Net v4.0 SqlClient 连接System.Data.SqlClient
,特定机器无法连接到特定的一组服务器。尝试连接时,会引发以下错误:
System.Data.SqlClient.SqlException (0x80131904): 与服务器建立连接成功,但是在登录过程中出现错误。(提供者:SSL Provider,错误:0 - 现有连接被远程主机强行关闭。)---> System.ComponentModel.Win32Exception (0x80004005):现有连接被远程主机强行关闭 在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException 异常,布尔 breakConnection,Action`1 wrapCloseInAction) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,布尔调用者HasConnectionLock,布尔异步关闭) 在 System.Data.SqlClient.TdsParserStateObject.SNIWritePacket(SNIHandle 句柄,SNIPacket 数据包,UInt32& sniError,布尔 canAccumulate,布尔调用者HasConnectionLock) 在 System.Data.SqlClient.TdsParserStateObject.WriteSni(布尔值 canAccumulate) 在 System.Data.SqlClient.TdsParserStateObject.WritePacket(字节flushMode,布尔canAccumulate) 在 System.Data.SqlClient.TdsParser.TdsLogin(SqlLogin rec) 在 System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo,字符串 newPassword,SecureString newSecurePassword,布尔型 ignoreSniOpenTimeout,TimeoutTimer 超时,布尔型 withFailover) 在 System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo,字符串 newPassword,SecureString newSecurePassword,布尔重定向用户实例,SqlConnectionString 连接选项,SqlCredential 凭据,TimeoutTimer 超时) 在 System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer 超时,SqlConnectionString 连接选项,SqlCredential 凭据,字符串 newPassword,SecureString newSecurePassword,布尔重定向用户实例) 在 System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity 标识,SqlConnectionString connectionOptions,SqlCredential 凭据,对象 providerInfo,String newPassword,SecureString newSecurePassword,Boolean redirectedUserInstance,SqlConnectionString userConnectionOptions) 在 System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions 选项,DbConnectionPoolKey poolKey,对象 poolGroupProviderInfo,DbConnectionPool 池,DbConnection owningConnection,DbConnectionOptions userOptions) 在 System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection,DbConnectionPoolGroup poolGroup,DbConnectionOptions userOptions) 在 System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection,TaskCompletionSource`1 重试,DbConnectionOptions userOptions,DbConnectionInternal& 连接) 在 System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection,DbConnectionFactory connectionFactory,TaskCompletionSource`1 重试,DbConnectionOptions userOptions) 在 System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 重试) 在 System.Data.SqlClient.SqlConnection.Open() 在 ConsoleApplication1.Module1.Main()
我可以使用相同的二进制文件从其他机器连接到相同的目标服务器而不会出现问题。如果我针对 Microsoft.Net v2.0 重新编译二进制文件,我也可以从有问题的服务器连接。
目标服务器配置为审核失败的登录,但是由于此问题,SQL Server 错误日志中没有记录任何失败 -如果我使用无效的 SQL Server 登录名登录,我可能会导致审核条目,以确保审核正常工作.
我用来测试这个问题的代码是:
Module Module1
Sub Main()
Dim bUseSSL As Boolean = False
If My.Application.CommandLineArgs.Contains("/SSL") Then
bUseSSL = True
End If
If bUseSSL Then
Console.WriteLine("Encryption enabled")
Else
Console.WriteLine("Encryption disabled")
End If
Dim cb As New Data.SqlClient.SqlConnectionStringBuilder
cb.ApplicationName = "SqlClientTest"
cb.DataSource = "<server_name_here>"
cb.IntegratedSecurity = True
cb.Encrypt = bUseSSL
'cb.TrustServerCertificate = True
cb.NetworkLibrary = "dbmssocn"
Try
Using sqlconnection As New System.Data.SqlClient.SqlConnection(cb.ConnectionString)
Try
sqlconnection.Open()
Console.WriteLine("Connected to " & cb.DataSource)
Dim sqlcommand As New System.Data.SqlClient.SqlCommand("SELECT @@SERVERNAME;", sqlconnection)
Dim sqlreader As System.Data.SqlClient.SqlDataReader = sqlcommand.ExecuteReader
While sqlreader.Read
Console.WriteLine(sqlreader.GetString(0))
End While
sqlreader.Close()
Catch ex As Exception
Console.WriteLine(cb.ConnectionString)
Console.WriteLine("")
Console.WriteLine(ex.ToString)
End Try
Console.WriteLine("Press 'q' to quit.")
Dim cki As ConsoleKeyInfo = Console.ReadKey
While cki.KeyChar.ToString.ToLower <> "q"
cki = Console.ReadKey
End While
End Using
Catch ex As Exception
Console.WriteLine(cb.ConnectionString)
Console.WriteLine("")
Console.WriteLine(ex.ToString)
End Try
End Sub
End Module
无论加密设置如何,无论设置如何,都会记录相同的失败TrustServerCertificate
。
即使我通过连接字符串将其禁用,某些东西似乎也在强制这台机器上的 .Net SqlClient v4.0 使用 SSL。
任何想法要检查什么?
安装 Microsoft .Net Framework 4.6.2 版可在我们的环境中解决此问题,并且似乎与此 Microsoft Docs .Net Framework 4.6 迁移指南中提出的问题有关。
所有受影响的计算机都具有 .Net Framework 版本 4.5 或 4.5.1,并通过 vsocklib.dll 具有 VMware vSockets DGRAM 和 vSockets STREAM Base Service Providers,用于宣传非 IFS 合规性。
为什么仅在尝试连接到某些 SQL Server 2016 实例时才会出现此问题仍然是一个悬而未决的问题。