Kerberos no se usa al llamar a un servicio WCF
Este artículo le ayuda a resolver el problema en el que se autentica a través de NTLM en lugar de Kerberos y no se puede delegar cuando se llama a un servicio WCF que usa el enlace net.tcp con seguridad de transporte, credenciales de transporte de Windows y tiene el nivel de protección establecido en ninguno.
Versión del producto original: Windows Communication Foundation
Número KB original: 2970779
Síntomas
Imagine la siguiente situación:
Tiene un servicio WCF que usa el enlace net.tcp con seguridad de transporte, credenciales de transporte de Windows y tiene el nivel de protección establecido en ninguno, como el ejemplo siguiente:
<netTcpBinding> <binding name="NetTcpBindingConfig"> <security mode="Transport"> <transport clientCredentialType="Windows" protectionLevel="None" /> </security> </binding> </netTcpBinding>Para configurar el extremo y proporcionar una identidad válida, use el enlace de la siguiente manera:
<endpoint address="net.tcp://srv1/Service/Service1.svc" binding="netTcpBinding" bindingConfiguration="NetTcpBindingConfig" contract="Contoso.IService1" behaviorConfiguration="NoNTLM" name="NetTcpContosoService"> <identity> <servicePrincipalName value="WCFService/ContosoService" /> </identity> </endpoint> (...) <behaviors> <endpointBehaviors> <behavior name="NoNTLM"> <clientCredentials> <windows allowNtlm="false"/> </clientCredentials> </behavior> </endpointBehaviors> </behaviors>Cree un proxy y llame a este servicio WCF.
En este escenario, se autentica a través de NTLM en lugar de Kerberos y no se puede delegar. La parte que llama al servicio es similar a la siguiente:
Service1Client client = null;
try
{
client = new Service1Client("NetTcpBindingConfig");
string returnStr = client.GetData(5);
Console.WriteLine(returnStr);
client.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if(client != null)
{
client.Abort();
}
}
Si System.Net los seguimientos están habilitados, muestra NTLM que se usó antes de intentar usar Kerberos:
System.Net.Sockets Verbose: 0 : [5964] DNS::GetHostEntry(srv1)
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Verbose: 0 : [5964] DNS::GetHostByName(srv1)
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Verbose: 0 : [5964] Salir de DNS::GetHostByName() -> IPHostEntry#14993092
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Verbose: 0 : [5964] Salir de DNS::GetHostEntry() -> IPHostEntry#14993092
DateTime=2014-05-09T12:57:41.3298728Z System.Net.Sockets Verbose: 0 : [5964] Socket#720107::Socket(AddressFamily#2)
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Verbose: 0 : [5964] Salir de Socket#720107::Socket()
DateTime=2014-05-09T12:57:41.3298728Z
System.Net.Sockets Verbose: 0 : [5964] Socket#720107::Conectar(10.1.0.5:808#403439906)
DateTime=2014-05-09T12:57:41.3298728Z
Información de System.Net.Sockets: 0 : [5964] Socket#720107: conexión creada de 10.1.0.10:46321 a 10.1.0.5:808.
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Verbose: 0 : [5964] Salir de Socket#720107::Conectar()
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Verbose: 0 : [5964] Socket#720107::Send()
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Verbose: 0 : [5964] Datos de Socket#720107::Send DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Verbose: 0 : [5964] 00000000 : 00 01 00 01 02 02 31 6E-65 74 2E 74 63 70 3A 2F : ...... 1net.tcp:/
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Verbose: 0 : [5964] 00000010 : 2F 73 72 76 31 2F 53 65-72 76 69 63 65 2F 53 65 : /srv1/Service/Se
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Verbose: 0 : [5964] 00000020 : 72 76 69 63 65 31 2E 73-76 63 03 08 00 00 00 : rvice1.svc......
DateTime=2014-05-09T12:57:41.3454728Z System.Net.Sockets Verbose: 0 : [5964] Exiting Socket#720107::Send() -> Int32#58
DateTime=2014-05-09T12:57:41.3454728Z
System.Net.Sockets Verbose: 0 : [5964] Socket#720107::Send()
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Verbose: 0 : [5964] Datos de Socket#720107::Send
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Verbose: 0 : [5964] 00000000 : 09 15 61 70 70 6C 69 63-61 74 69 6F 6E 2F 6E 65 : .. application/ne
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Verbose: 0 : [5964] 00000010 : 67 6F 74 69 61 74 65 : gotiate
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Verbose: 0 : [5964] Salir de Socket#720107::Send() -> Int32#23
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Verbose: 0 : [5964] Socket#720107::Receive()
DateTime=2014-05-09T12:57:41.3610728Z
System.Net.Sockets Verbose: 0 : [5964] Datos de Socket#720107::Receive
DateTime=2014-05-09T12:57:42.1098728Z
System.Net.Sockets Verbose: 0 : [5964] 00000000 : 0A : .
DateTime=2014-05-09T12:57:42.1098728Z
System.Net.Sockets Verbose: 0 : [5964] Salir de Socket#720107::Receive() -> Int32#1
DateTime=2014-05-09T12:57:42.1098728Z
System.Net: 0 : [5964] Enumerar paquetes de seguridad:
DateTime=2014-05-09T12:57:42.1254728Z
System.Net: 0 : [5964] Negociar
DateTime=2014-05-09T12:57:42.1254728Z
System.Net: 0 : [5964] NegoExtender
DateTime=2014-05-09T12:57:42.1254728Z
System.Net: 0 : [5964] Kerberos
DateTime=2014-05-09T12:57:42.1254728Z
System.Net: 0 : [5964] NTLM
DateTime=2014-05-09T12:57:42.1254728Z
System.Net: 0 : [5964] Schannel
DateTime=2014-05-09T12:57:42.1254728Z
System.Net: 0 : [5964] Proveedor de protocolos de seguridad unificada de Microsoft
DateTime=2014-05-09T12:57:42.1254728Z
System.Net información: 0 : [5964] WDigest
DateTime=2014-05-09T12:57:42.1254728Z
System.Net: 0 : [5964] TSSSP
DateTime=2014-05-09T12:57:42.1254728Z
System.Net información: 0 : [5964] pku2u
DateTime=2014-05-09T12:57:42.1254728Z
System.Net: 0 : [5964] CREDSSP
DateTime=2014-05-09T12:57:42.1254728Z
System.Net información: 0 : [5964] AcquireDefaultCredential(package = NTLM, intent = Outbound) DateTime=2014-05-09T12:57:42.1254728Z
System.Net: 0 : [5964] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY,
context = (null), targetName = WCFService/ContosoService, inFlags = Connection, AcceptIntegrity) DateTime=2014-05-09T12:57:42.1254728Z
Importante
Aunque la identidad es necesaria en el extremo junto con la configuración del nombre de entidad de seguridad de servicio (SPN) para habilitar la delegación Kerberos en net.tcp, este artículo no resolverá esto. Se supone que la configuración kerberos ha finalizado correctamente.
Causa
Si el nivel de protección se establece en None en el enlace, NTLM se usará incluso si el comportamiento no permite NTLM.
Solución
Para resolver este problema, use el nivel de protección Sign o EncryptAndSign para habilitar la autenticación Kerberos. El ejemplo siguiente es la configuración de enlace actualizada:
<netTcpBinding>
<binding name="NetTcpBindingConfig">
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
</security>
</binding>
</netTcpBinding>