Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
TLS (Seguridad de la capa de transporte) es un protocolo criptográfico diseñado para proteger la comunicación entre dos equipos a través de Internet. El protocolo TLS se expone en .NET a través de la SslStream clase .
En este artículo se presentan los procedimientos recomendados para configurar la comunicación segura entre el cliente y el servidor y se supone el uso de .NET. Para conocer los procedimientos recomendados con .NET Framework, consulte Procedimientos recomendados de seguridad de la capa de transporte (TLS) con .NET Framework.
Selección de la versión de TLS
Aunque es posible especificar la versión del protocolo TLS que se usará a través de la EnabledSslProtocols propiedad , se recomienda aplazar la configuración del sistema operativo mediante None el valor (este es el valor predeterminado).
Aplazar la decisión del sistema operativo automáticamente usa la versión más reciente de TLS disponible y permite a la aplicación recoger los cambios después de las actualizaciones del sistema operativo. El sistema operativo también puede impedir el uso de versiones TLS que ya no se consideran seguras.
Selección de conjuntos de cifrado
SslStream
permite a los usuarios especificar qué conjuntos de cifrado se pueden negociar mediante el protocolo de enlace TLS a través de la CipherSuitesPolicy clase . Al igual que con las versiones de TLS, se recomienda permitir que el sistema operativo decida cuáles son los mejores conjuntos de cifrado con los que negociar y, por lo tanto, se recomienda evitar el uso de CipherSuitesPolicy.
Nota:
CipherSuitesPolicy no se admite en Windows y los intentos de crear instancias de él producirán una excepción NotSupportedException.
Especificar un certificado de servidor
Al autenticarse como servidor, SslStream requiere una instancia de X509Certificate2. Se recomienda usar siempre una X509Certificate2 instancia que también contenga la clave privada.
Hay varias maneras de pasar un certificado de servidor a SslStream:
- Directamente como parámetro a SslStream.AuthenticateAsServerAsync o a través de la propiedad SslServerAuthenticationOptions.ServerCertificate.
- Desde una devolución de llamada de selección en la propiedad SslServerAuthenticationOptions.ServerCertificateSelectionCallback.
- Pasando SslStreamCertificateContext en la propiedad SslServerAuthenticationOptions.ServerCertificateContext.
El enfoque recomendado es usar la SslServerAuthenticationOptions.ServerCertificateContext propiedad . Cuando el certificado se obtiene de una de las otras dos maneras, la SslStreamCertificateContext implementación crea internamente una SslStream instancia. La creación de un SslStreamCertificateContext implica construir un X509Chain, lo cual es una operación intensiva en el uso del CPU. Es más eficaz crear una SslStreamCertificateContext vez y reutilizarlo para varias SslStream instancias.
La reutilización de SslStreamCertificateContext instancias también permite características adicionales, como la reanudación de la sesión TLS en los servidores Linux.
Validación personalizada X509Certificate
Hay ciertos escenarios en los que el procedimiento de validación de certificados predeterminado no es adecuado y se requiere cierta lógica de validación personalizada. Las partes de la lógica de validación se pueden personalizar especificando SslClientAuthenticationOptions.CertificateChainPolicy o SslServerAuthenticationOptions.CertificateChainPolicy. Como alternativa, se puede proporcionar lógica completamente personalizada a través de la <propiedad System.Net.Security.SslClientAuthenticationOptions.RemoteCertificateValidationCallback> . Para obtener más información, consulte Confianza de certificado personalizada.
Confianza de certificado personalizada
Al encontrar un certificado que no ha sido emitido por ninguna de las entidades de certificación de confianza del equipo (incluidos los certificados autofirmados), se producirá un error en el procedimiento de validación de certificados predeterminado. Una manera posible de resolver esto es agregar los certificados de emisor necesarios al almacén de confianza de la máquina. Sin embargo, esto podría afectar a otras aplicaciones del sistema y no siempre es posible.
La solución alternativa consiste en especificar certificados raíz de confianza personalizados a través de .X509ChainPolicy Para especificar una lista de confianza personalizada que se usará en lugar de la lista de confianza del sistema durante la validación, considere el ejemplo siguiente:
SslClientAuthenticationOptions clientOptions = new();
clientOptions.CertificateChainPolicy = new X509ChainPolicy()
{
TrustMode = X509ChainTrustMode.CustomRootTrust,
CustomTrustStore =
{
customIssuerCert
}
};
Los clientes configurados con la directiva anterior solo aceptarían certificados en los que confíe customIssuerCert
.
Omitir errores de validación específicos
Considere un dispositivo IoT sin un reloj persistente. Después de encenderse, el reloj del dispositivo comenzaría muchos años atrás y, por tanto, todos los certificados se considerarían "no válidos aún". Vea el siguiente código, que muestra una implementación de devolución de llamada de validación que omite las infracciones del período de validez.
static bool CustomCertificateValidationCallback(
object sender,
X509Certificate? certificate,
X509Chain? chain,
SslPolicyErrors sslPolicyErrors)
{
// Anything that would have been accepted by default is OK
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true;
}
// If there is something wrong other than a chain processing error, don't trust it.
if (sslPolicyErrors != SslPolicyErrors.RemoteCertificateChainErrors)
{
return false;
}
Debug.Assert(chain is not null);
// If the reason for RemoteCertificateChainError is that the chain built empty, don't trust it.
if (chain.ChainStatus.Length == 0)
{
return false;
}
foreach (X509ChainStatus status in chain.ChainStatus)
{
// If an error other than `NotTimeValid` (or `NoError`) is present, don't trust it.
if ((status.Status & ~X509ChainStatusFlags.NotTimeValid) != X509ChainStatusFlags.NoError)
{
return false;
}
}
return true;
}
Asignación de certificados
Otra situación en la que es necesaria la validación de certificados personalizada es cuando los clientes esperan que los servidores usen un certificado específico o un certificado de un pequeño conjunto de certificados conocidos. Esta práctica se conoce como anclaje de certificados. El fragmento de código siguiente muestra una devolución de llamada de validación que comprueba que el servidor presenta un certificado con una clave pública conocida específica.
static bool CustomCertificateValidationCallback(
object sender,
X509Certificate? certificate,
X509Chain? chain,
SslPolicyErrors sslPolicyErrors)
{
// If there is something wrong other than a chain processing error, don't trust it.
if ((sslPolicyErrors & ~SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
return false;
}
Debug.Assert(certificate is not null);
const string ExpectedPublicKey =
"3082010A0282010100C204ECF88CEE04C2B3D850D57058CC9318EB5C" +
"A86849B022B5F9959EB12B2C763E6CC04B604C4CEAB2B4C00F80B6B0" +
"F972C98602F95C415D132B7F71C44BBCE9942E5037A6671C618CF641" +
"42C546D31687279F74EB0A9D11522621736C844C7955E4D16BE8063D" +
"481552ADB328DBAAFF6EFF60954A776B39F124D131B6DD4DC0C4FC53" +
"B96D42ADB57CFEAEF515D23348E72271C7C2147A6C28EA374ADFEA6C" +
"B572B47E5AA216DC69B15744DB0A12ABDEC30F47745C4122E19AF91B" +
"93E6AD2206292EB1BA491C0C279EA3FB8BF7407200AC9208D98C5784" +
"538105CBE6FE6B5498402785C710BB7370EF6918410745557CF9643F" +
"3D2CC3A97CEB931A4C86D1CA850203010001";
return certificate.GetPublicKeyString().Equals(ExpectedPublicKey);
}
Consideraciones para la validación de certificados de cliente
Las aplicaciones de servidor deben tener cuidado al requerir y validar certificados de cliente. Los certificados pueden contener la extensión AIA (acceso a la información de la autoridad) que especifica dónde se puede descargar el certificado del emisor. Por lo tanto, el servidor puede intentar descargar el certificado del emisor desde un servidor externo cuando compila el X509Chain para el certificado de cliente. Del mismo modo, es posible que los servidores necesiten ponerse en contacto con servidores externos para asegurarse de que no se ha revocado el certificado de cliente.
La necesidad de ponerse en contacto con servidores externos durante la construcción y validación de X509Chain puede exponer la aplicación a ataques de denegación de servicio si los servidores externos son lentos para responder. Por tanto, las aplicaciones de servidor deben configurar el comportamiento de compilación de X509Chain con CertificateChainPolicy.