SqlClient: Unable to connect to SQL Server using "localhost" as the server name

When trying to connect to SQL Server running in a Docker container in WSL I am unable to connect using localhost as the server name. I can, however, connect using 127.0.0.1 or ::1.

The application is a .NET 7.0.7 application using Microsoft.Data.SqlClient.dll version 5.0.2 as part of Microsoft.EntityFrameworkCore.SqlServer 7.0.8.

This connection string doesn’t work:

Server=tcp:localhost,1433;Initial Catalog=dbname;Persist Security Info=False;User ID=sa;Password=password;Encrypt=False;TrustServerCertificate=False;Connection Timeout=30;MultipleActiveResultSets=True

This connection string does:

Server=tcp:::1,1433;Initial Catalog=dbname;Persist Security Info=False;User ID=sa;Password=password;Encrypt=False;TrustServerCertificate=False;Connection Timeout=30;MultipleActiveResultSets=True

As does this one:

Server=tcp:127.0.0.1,1433;Initial Catalog=dbname;Persist Security Info=False;User ID=sa;Password=password;Encrypt=False;TrustServerCertificate=False;Connection Timeout=30;MultipleActiveResultSets=True

This is the exception detail:

Microsoft.Data.SqlClient.SqlException
  HResult=0x80131904
  Message=A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - No connection could be made because the target machine actively refused it.)
  Source=Core Microsoft SqlClient Data Provider
  StackTrace:
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, SqlConnectionString connectionOptions, Boolean withFailover)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransientFaultHandling, String accessToken, DbConnectionPool pool)
   at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
   at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.OpenDbConnection(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.<>c__DisplayClass18_0.<Exists>b__0(DateTime giveUp)
   at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.<>c__DisplayClass12_0`2.<Execute>b__0(DbContext _, TState s)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Execute[TState,TResult](IExecutionStrategy strategy, TState state, Func`2 operation, Func`2 verifySucceeded)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists(Boolean retryOnNotExists)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.Exists()
   at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade)
   at Program.<Main>$(String[] args) in C:\Development\Xenon7\Xenon.Administration\Program.cs:line 109

Inner Exception 1:
Win32Exception: No connection could be made because the target machine actively refused it.

From WSL, I can see that it’s listening on the correct ports:

Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:1433            0.0.0.0:*               LISTEN
tcp6       0      0 :::1433                 :::*                    LISTEN

From Windows I can see the same:

Active Connections

  Proto  Local Address          Foreign Address        State
  TCP    127.0.0.1:1433         0.0.0.0:0              LISTENING
  TCP    [::1]:1433             [::]:0                 LISTENING

This is also confirmed by checking Resource Monitor, which shows wslrelay.exe listening on port 1433 on both “1Pv6 loopback” and “IPv4 loopback” and lists the Firewall Status as “Allowed, not restricted”.

In WSL (i.e. not from inside the docker container), running sudo nc 0.0.0.0 1433 -l and sudo nc :: 1433 -l shows connection attempts when using 127.0.0.1 or ::1 as the server address (as expected), but using localhost doesn’t show any network activity.

Using tcpdump in WSL doesn’t show any traffic when attempting to connect using localhost.

I also experience the same issue using SSMS and sqlcmd.

From SSMS, I can connect using 127.0.0.1 or ::1, but cannot connect using localhost.

Here is the error:

===================================

Cannot connect to localhost.

===================================

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - The wait operation timed out.) (Framework Microsoft SqlClient Data Provider)

------------------------------
For help, click: https://docs.microsoft.com/sql/relational-databases/errors-events/mssqlserver-258-database-engine-error

------------------------------
Error Number: 258
Severity: 20
State: 0


------------------------------
Program Location:

   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean withFailover, Boolean isFirstTransparentAttempt, SqlAuthenticationMethod authType, String certificate, ServerCertificateValidationCallback serverCallback, ClientCertificateRetrievalCallback clientCallback, Boolean useOriginalAddressInfo, Boolean disableTnir)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover, Boolean isFirstTransparentAttempt, Boolean disableTnir)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance)
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, ServerCertificateValidationCallback serverCallback, ClientCertificateRetrievalCallback clientCallback, DbConnectionPool pool, String accessToken, SqlClientOriginalNetworkAddressInfo originalNetworkAddressInfo, Boolean applyTransientFaultHandling)
   at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides)
   at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides)
   at Microsoft.Data.SqlClient.SqlConnection.Open()
   at Microsoft.SqlServer.Management.SqlStudio.Explorer.ObjectExplorerService.ValidateConnection(UIConnectionInfo ci, IServerType server)
   at Microsoft.SqlServer.Management.UI.ConnectionDlg.Connector.ConnectionThreadUser()

===================================

The wait operation timed out

By default, SSMS attempts to use the Named Pipes Provider when trying to connect with localhost specified as the Server name. Changing to localhost,1433 or setting the Network protocol to TCP/IP (from default) in the connection Options / Connection Properties tab, shows it trying to use the TCP Provider (as expected), with the same results.

It appears that localhost is not being resolved in any SQL application.

Other applications, however, are able to connect (from Windows) using localhost to applications running in Docker, including MySQL, Apache, etc. In these instances, localhost is resolving to ::1, as does ping when run from a Command Prompt.

For what it’s worth, this used to work on a previous machine using Windows 10 and WSL2, so I’m not sure if this is a Windows issue, or a Microsoft SQL Data Provider issue, which may have also been a different version at the time.

In summary:

  • It doesn’t appear to be a mssql-docker issue, because connecting via 127.0.0.1 or ::1 works, and it appears that WSL is not receiving any traffic when a connection attempt is made to localhost.
  • It doesn’t appear to be a Docker or WSL issue, for the same reason as the above point, and also because other applications are working using localhost.
  • It doesn’t appear to be an SSMS issue, as other applications using the Microsoft SQL Data Provider experience the same issue.

I don’t know the inner workings of the Microsoft SQL Data Provider, however, it feels like the provider itself is failing to resolve localhost or perhaps is trying to resolve it as a Named Pipes address and caching that (failed) result even when using the TCP/IP provider.

I am not running any SQL Server instances in Windows. Microsoft SQL Server 2019 LocalDB is confirmed as stopped as reported by sqllocaldb.

Other information:

  • SSMS is using Microsoft.Data.SqlClient version 3.13.23069.2
  • sqlcmd is using Microsoft ODBC Driver 17.10 for SQL Server version 2017.1710.3.1
  • Windows 11 Pro 22H2 build 22621.1928
  • Microsoft SQL Server Developer Edition (64-bit) version 16.0.4045 RTM (Docker)
  • Microsoft SQL Server Express (64-bit) version 15.0.4153.1 (when running)
  • Docker version 24.0.2, build cb74dfc
  • Installed Programs
    • Microsoft ODBC Driver 17 for SQL Server version 17.10.3.1
    • Microsoft OLE DB Driver for SQL Server version 18.6.5.0
    • Microsoft SQL Server 2019 LocalDB version 15.0.4153.1
    • Microsoft System CLR Types for SQL Server 2019 version 15.0.2000.5
  • ODBC Data Source Administrator (32-bit)
    • ODBC Driver 17 for SQL Server version 2017.1710.03.01
    • SQL Server version 10.00.22621.1848
  • ODBC Data Source Administrator (64-bit)
    • ODBC Driver 17 for SQL Server version 2017.1710.03.01
    • SQL Server version 10.00.22621.1848

SSMS:

SQL Server Management Studio 19.1.56.0
SQL Server Management Objects (SMO) 16.200.48044.0+eeb184ee48a91ebc6a27a5d192c0d67bdfaae8b6
Microsoft T-SQL Parser 17.0.8.0+3c5555b8bd579d12add8f155f1dbc871e3e734c4
Microsoft Analysis Services Client Tools 16.0.20010.0
Microsoft Data Access Components (MDAC) 10.0.22621.1848
Microsoft MSXML 3.0 6.0 
Microsoft .NET Framework 4.0.30319.42000
Operating System 10.0.22621

WSL

WSL version: 1.2.5.0
Kernel version: 5.15.90.1
WSLg version: 1.0.51
MSRDC version: 1.2.3770
Direct3D version: 1.608.2-61064218
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.22621.1928

I was unable to find any similar issues in this repo, other than #1455 which appears to have the opposite problem to mine.

There is also an issue (https://github.com/microsoft/mssql-docker/issues/813) in the mssql-docker repo which is the same issue as this.

My apologies in advance if this is the wrong place for this. Let me know and I’ll move it if required.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 3
  • Comments: 16 (7 by maintainers)

Most upvoted comments

Closing this issue as it is by design

That aligns with my testing. I see code in the native SNI library that appears to decide to use ComputerName when it sees localhost. (I’m not set up to debug it.) ComputerName doesn’t resolve to the localhost IPs, thus the behavior.

The MS ODBC Driver for SQL Server also has the same behavior. SQL Server installed locally, listening on TCP localhost IP addresses ONLY (127.0.0.1 and ::1):

C:\> sqlcmd -S tcp:127.0.0.1
1> exit
C:\> sqlcmd -S tcp:localhost
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : TCP Provider: The wait operation timed out.
.
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login timeout expired.
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : A network-related or instance-specific error has occurred while establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online..

I’ve inquired why it might behave this way. My thought is it might have to do with cluster or mirroring scenarios. Others have suggested it’s to improve the connection encryption experience with regard to the name in certificates. It does seem odd. But as you said, it’s easy to work around.

I was experience that exact same behavior that was driving me crazy. I’ve ended up going with a different workaroud. 1st Identify which IP is being resolved by the DNS server for ‘localhost’. In my case it was resolving for my hostname and the IP from my VPN connection. 2nd, enabled port forwarding from the previous identified IP:1433 to 127.0.0.1:1433 Now, all applications can indeed connect to localhost transparently without having to swap ‘localhost’ by ‘127.0.0.1’

used commands (as elevated priviledges)

  • Show all port forward rules: netsh interface portproxy show all
  • Reset all port forward rules: netsh interface portproxy reset
  • Enable port forwarding rule: netsh interface portproxy add v4tov4 listenaddress=[your resolved IP address] listenport=1433 connectaddress=127.0.0.1 connectport=1433

More info on port forwarding: https://woshub.com/port-forwarding-in-windows/ Hope this helps!!