2008-08-06 10 views
36

ediciones más recientes en negrita estoy usando la clase de .NET HttpListener, pero estoy no ejecutar en IIS y no estoy usando ASP.net. Este web site describe qué código de uso real para implementar SSL con asp.net y this site describe cómo configurar los certificados (aunque no estoy seguro si solo funciona para IIS).¿Cómo agrego SSL para una aplicación .NET que utiliza httplistener - que * no * estar ejecutándose en IIS

La documentación de la clase describe varios tipos de autenticación (básica, resumen, Windows, etc.) --- ninguno de ellos hace referencia a SSL. Sí dice que si HTTPS is used, you will need to set a server certificate. ¿Va a ser una configuración de propiedad de una línea y HttpListener se da cuenta del resto?

En resumen, necesito saber cómo configurar los certificados y cómo modificar el código para implementar SSL.

A pesar de que no se produce cuando estoy tratando de acceder a HTTPS, Me di cuenta de un error en mi registro de sistema - la fuente es "Schannel" y el contenido del mensaje es:

Se produjo un error fatal al intentar para acceder a la credencial del servidor SSL clave privada. El código de error devuelto del módulo criptográfico es 0x80090016.

Editar:
Las medidas adoptadas hasta ahora

  • Creado un trabajo HttpListener en C# que funciona para las conexiones HTTP (por ejemplo, "http://localhost:8089/foldername/"
  • creado un certificado mediante makecert.exe
  • Agregó el certificado para ser confiable usando certmgr.exe
  • Usó Httpcfg.exe para escuchar fo r conexiones SSL en un puerto de prueba (p. 8090)
  • puerto Agregado 8080 a la HttpListener través listener.Prefixes.Add (https://localhost:8090/foldername/ ");
  • probado una conexión HTTP del cliente, por ejemplo (http://localhost:8089/foldername/") en un navegador y recibir correcto retorno
  • probado un cliente de HTTPS conexión, por ejemplo (http://localhost:8090/foldername/ ") en un navegador y recibe" Transferencia de datos interrumpida "(en Firefox)
  • la depuración en Visual Studio muestra que la devolución de llamada del oyente que recibe las solicitudes nunca se activa cuando se inicia la conexión HTTPS - No veo ningún lugar que pudiera establecer un punto de interrupción para atrapar cualquier otra cosa antes.
  • netstat muestra que los puertos de escucha están abiertas tanto para HTTPS y HTTP. puerto HTTPS no ir a TIME_WAIT después de que se intenta establecer una conexión.
  • Fiddler y HTTPAnalyzer Don' Para captar algo del tráfico, supongo que no llega lo suficientemente lejos en el proceso para aparecer en las herramientas de análisis HTTP

Preguntas

  • Cuál podría ser el problema?
  • ¿Hay una pieza de código .NET que me falta (es decir, tengo que hacer más en C# además de simplemente agregar un prefijo al oyente que apunta a HTTPS, que es lo que he hecho)
  • Have a missed un paso de configuración en alguna parte?
  • ¿Qué más podría hacer para analizar el problema?
  • ¿El mensaje de error en el registro del evento del sistema es una señal del problema? Si es así, ¿cómo se solucionaría?

Respuesta

6

No lo tengo completamente implementado aún, pero este sitio web parece dar un good walkthrough de la configuración de los certificados y el código.

3

El class documentation

tiene esta nota:

Si crea una HttpListener usando https, debe seleccionar un Certificado de servidor para ese oyente. De lo contrario, una consulta HttpWebRequest de este HttpListener fallará con un cierre inesperado de la conexión .

y esto:

Puede configurar certificados de servidor y otras opciones del receptor mediante el uso de HttpCfg.exe. Consulte http://msdn.microsoft.com/library/default.asp?url=/library/en-us/http/http/httpcfg_exe.asp para obtener más información. El archivo ejecutable es incluido con Windows Server 2003, o se puede compilar a partir del código fuente disponible en Platform SDK.

¿La primera nota explicada por la segunda? Como se indica en la pregunta, utilicé httpcfg.exe para vincular el certificado a un puerto específico. Si intentan algo más que esto, la nota es ambigua.

2

He encontrado el mismo problema que usted. Afortunadamente después de googlear los pasos difíciles en this page hacer que SSL funcione con mi HttpListener.

9

Tengo un problema similar, y parece que podría haber un problema con el certificado en sí.

Aquí está el camino que funcionó para mí:

makecert.exe -r -a sha1 -n CN=localhost -sky exchange -pe -b 01/01/2000 -e 01/01/2050 -ss my -sr localmachine 

mirad certificado thumbprint, copiarlo en el portapapeles y quitar espacios. Este será un parámetro después -h en el siguiente orden:

HttpCfg.exe set ssl -i 0.0.0.0:801 -h 35c65fd4853f49552471d2226e03dd10b7a11755 

continuación, ejecute un host de servicio en https://localhost:801/ y funciona perfectamente.

Lo que no puedo hacer funcionar es que https se ejecute en un certificado autogenerado. Aquí está el código corro para generar una (la gestión de errores sacado para mayor claridad):

LPCTSTR pszX500 = subject; 
DWORD cbEncoded = 0; 
CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL); 
pbEncoded = (BYTE *)malloc(cbEncoded); 
CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL); 

// Prepare certificate Subject for self-signed certificate 
CERT_NAME_BLOB SubjectIssuerBlob; 
memset(&SubjectIssuerBlob, 0, sizeof(SubjectIssuerBlob)); 
SubjectIssuerBlob.cbData = cbEncoded; 
SubjectIssuerBlob.pbData = pbEncoded; 

// Prepare key provider structure for self-signed certificate 
CRYPT_KEY_PROV_INFO KeyProvInfo; 
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo)); 
KeyProvInfo.pwszContainerName = _T("my-container"); 
KeyProvInfo.pwszProvName = NULL; 
KeyProvInfo.dwProvType = PROV_RSA_FULL; 
KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET; 
KeyProvInfo.cProvParam = 0; 
KeyProvInfo.rgProvParam = NULL; 
KeyProvInfo.dwKeySpec = AT_SIGNATURE; 

// Prepare algorithm structure for self-signed certificate 
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm; 
memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm)); 
SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA; 

// Prepare Expiration date for self-signed certificate 
SYSTEMTIME EndTime; 
GetSystemTime(&EndTime); 
EndTime.wYear += 5; 

// Create self-signed certificate 
pCertContext = CertCreateSelfSignCertificate(NULL, &SubjectIssuerBlob, 0, &KeyProvInfo, &SignatureAlgorithm, 0, &EndTime, 0); 
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY"); 
CertAddCertificateContextToStore(hStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, 0); 

certificado demuestra muy bien y tiene una clave privada que trabaja, pero https agotará el tiempo, como si nunca fue huella digital registrada.Si alguien sabe por qué - PLZ comentar

EDIT1: Después de algún jugando, he encontrado la inicialización para CertCreateSelfSignCertificate que genera el certificado adecuado:

CRYPT_KEY_PROV_INFO KeyProvInfo; 
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo)); 
KeyProvInfo.pwszContainerName = _T("my-container"); 
KeyProvInfo.pwszProvName = _T("Microsoft RSA SChannel Cryptographic Provider"); 
KeyProvInfo.dwProvType = PROV_RSA_SCHANNEL; 
KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET; 
KeyProvInfo.cProvParam = 0; 
KeyProvInfo.rgProvParam = NULL; 
KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE; 
7

Sólo hay que unir un certificado a una ip: puerto y luego abra su oyente con un prefijo https: //. 0.0.0.0 se aplica a todas las ip. appid es cualquier GUID aleatorio, y certhash es el hash del certificado (a veces llamado thumprint).

Ejecute lo siguiente con cmd.exe utilizando privilegios de administrador.

netsh http add sslcert ipport=0.0.0.0:1234 certhash=613bb67c4acaab06def391680505bae2ced4053b appid={86476d42-f4f3-48f5-9367-ff60f2ed2cdc} 

Si desea crear un certificado autofirmado para probar esto,

  1. Abrir IIS
  2. Haga clic en el nombre del equipo
  3. certificados de servidor
  4. clic en el icono
  5. clic en Generar auto -certificado firmado
  6. haga doble clic y vaya a los detalles
  7. Verá la huella digital allí, solo elimine los espacios.

    HttpListener listener = new HttpListener(); 
    listener.Prefixes.Add("https://+:1234/"); 
    listener.Start(); 
    Console.WriteLine("Listening..."); 
    HttpListenerContext context = listener.GetContext(); 
    
    using (Stream stream = context.Response.OutputStream) 
    using (StreamWriter writer = new StreamWriter(stream)) 
        writer.Write("hello, https world"); 
    
    Console.ReadLine(); 
    

Después de ejecutar este programa acabo navegado a https://localhost:1234 para ver el texto impreso. Como el certificado CN no coincide con la url y no está en el almacén de certificados de confianza, recibirá una advertencia de certificado. El texto está encriptado, sin embargo, como puede verificar con una herramienta como Wire Shark.

Si desea tener más control sobre la creación de un certificado x509 autofirmado, openssl es una gran herramienta y hay un puerto para Windows. He tenido mucho más éxito que la herramienta makecert.


Es también muy importante que a si se está comunicando con un servicio https de código que tiene una advertencia SSL, debe configurar el validador certificado en el gestor de punto de servicio a prescindir de ella para propósitos de prueba.

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true; 
4

Aquí es una forma alternativa para obligar a la certifiate SSL para la combinación IP/puerto sin utilizar httpcfg.exe (XP) o netsh.exe (Vista +).

http://dotnetcodebox.blogspot.com.au/2012/01/how-to-work-with-ssl-certificate.html

El quid de la cuestión es que se puede utilizar una API de C++ HttpSetServiceConfiguration incorporado en las ventanas de hacerlo mediante programación en lugar de a través de la línea de comandos, eliminando por tanto la dependencia del sistema operativo y tener httpcfg instalado.

+1

He publicado este código como [paquete Nuget] (https://www.nuget.org/packages/SslCertBinding.Net/). Sientase libre de usarlo. –

Cuestiones relacionadas