diff --git a/src/System.Data.SqlClient/src/System.Data.SqlClient.csproj b/src/System.Data.SqlClient/src/System.Data.SqlClient.csproj
index 0058e7c0cacc..3228a3b32b5b 100644
--- a/src/System.Data.SqlClient/src/System.Data.SqlClient.csproj
+++ b/src/System.Data.SqlClient/src/System.Data.SqlClient.csproj
@@ -205,6 +205,8 @@
+
+
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.Unix.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.Unix.cs
new file mode 100644
index 000000000000..b587dedee32a
--- /dev/null
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.Unix.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Data.SqlClient.SNI
+{
+ ///
+ /// Managed SNI proxy implementation. Contains many SNI entry points used by SqlClient.
+ ///
+ internal partial class SNIProxy
+ {
+ // On Unix/Linux the format for the SPN is SERVICE@HOST. This is because the System.Net.Security.Native
+ // GSS-API layer uses GSS_C_NT_HOSTBASED_SERVICE format for the SPN.
+ private const string SpnServiceHostSeparator = "@";
+ }
+}
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.Windows.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.Windows.cs
new file mode 100644
index 000000000000..581056643151
--- /dev/null
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.Windows.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Data.SqlClient.SNI
+{
+ ///
+ /// Managed SNI proxy implementation. Contains many SNI entry points used by SqlClient.
+ ///
+ internal partial class SNIProxy
+ {
+ // On Windows the format for the SPN is SERVICE/HOST. So the separator character between the
+ // SERVICE and HOST components is "/".
+ private const string SpnServiceHostSeparator = "/";
+ }
+}
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.cs
index 9c778972e49a..92b8ffeca4ea 100644
--- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.cs
+++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SNI/SNIProxy.cs
@@ -18,7 +18,7 @@ namespace System.Data.SqlClient.SNI
///
/// Managed SNI proxy implementation. Contains many SNI entry points used by SqlClient.
///
- internal class SNIProxy
+ internal partial class SNIProxy
{
private const int DefaultSqlServerPort = 1433;
private const int DefaultSqlServerDacPort = 1434;
@@ -342,7 +342,7 @@ private static byte[] GetSqlServerSPN(string hostNameOrAddress, string portOrIns
// If the DNS lookup failed, then resort to using the user provided hostname to construct the SPN.
fullyQualifiedDomainName = hostEntry?.HostName ?? hostNameOrAddress;
}
- string serverSpn = SqlServerSpnHeader + "/" + fullyQualifiedDomainName;
+ string serverSpn = SqlServerSpnHeader + SpnServiceHostSeparator + fullyQualifiedDomainName;
if (!string.IsNullOrWhiteSpace(portOrInstanceName))
{
serverSpn += ":" + portOrInstanceName;