支持 HTTPS 的 Httplisten

似乎有很多令人困惑,有时相互矛盾的信息,关于制定一个。NET HTTPListener HTTPS 支持。我的理解是:

  • 一个人的 C # 代码需要一个 https前缀(例如,https://*:8443) ,以便侦听器理解它需要在这个端口服务 SSL 请求。

  • 实际的 SSL 握手发生在封面之下,由 http.sys(隐藏在 Windows 机器的某个地方)处理。C # 代码不必显式地管理 SSL 握手,因为它是在幕后进行的。

  • 我们需要在 httpListener机器上有一个“ X.509受信任证书”,而且该证书需要以某种方式绑定到端口8443(在本例中)。

我上面的理解正确吗? 如果不正确,请告诉我。

关于 X.509证书,我的理解是:

  • 使用 makecert创建 X.509证书。该证书存储在个人存储中,需要移动到可信存储(HTTP 侦听器将在此处查看)。看起来我可以使用 certMgr来执行移动,或者我可以使用 mmc来执行移动。似乎有不止一种 X.509证书格式(DERBase64pks、 pswd protected、 pks private 等) ... ... 是否有我应该使用的首选格式?

将证书放入受信任的存储区后,需要将其绑定到 TCP 端口。我在 Windows 7: 我应该使用 httpcfg还是 netsh

91758 次浏览

我做了很多功课,让这个起作用了。对象添加 SSL 支持的步骤。NET HttpListener 是:

  1. 更新 C # 应用程序代码以包含 https前缀:

    String[] prefixes = { "http://*:8089/","https://*:8443/" };
    

    代码方面就是这样。

  2. 对于证书方面的事情,使用 Windows SDK命令控制台或 VisualStudioProfessional 命令控制台

    • 使用 makecert.exe创建证书颁发机构。示例:

      makecert -n "CN=vMargeCA" -r -sv vMargeCA.pvk vMargeCA.cer
      
    • Use makecert.exe to create an SSL certificate

      makecert -sk vMargeSignedByCA -iv vMargeCA.pvk -n "CN=vMargeSignedByCA" -ic vMargeCA.cer vMargeSignedByCA.cer -sr localmachine -ss My
      
    • Use MMC GUI to install CA in Trusted Authority store

    • Use MMC GUI to install an SSL certificate in Personal store
    • Bind certificate to IP address:port and application. Example:

      netsh http add sslcert ipport=0.0.0.0:8443 certhash=585947f104b5bce53239f02d1c6fed06832f47dc appid={df8c8073-5a4b-4810-b469-5975a9c95230}
      

      Certhash 是 SSL 证书中的拇指指纹。 应用程序可以在 Visual Studio 中找到... ... 通常在 Assembly.cs 中,查找 GUID 值

There may be other ways to accomplish the above, but this worked for me.

下面是我使用 OpenSSL 为 C # HTTPListener应用程序创建自签名证书在 Windows 上设置独立服务器所遵循的详细步骤。它包括大量的链接,如果你想做进一步的研究。

  1. 通过 HttpListener在.NET 中创建独立服务器:

    var prefixes = {"http://localhost:8080/app/root", "https://localhost:8443/app/root"};
    var listener = new HttpListener();
    foreach (string s in prefixes)
    listener.Prefixes.Add(s);
    listener.Start();
    
  2. Create self-signed certificate:*

    1. openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365, which will prompt you for the value of each of the certificate's fields on the command line. For the common name, type the domain name (e.g. localhost)
    2. openssl pkcs12 -inkey bob_key.pem -in bob_cert.cert -export -out bob_pfx.pfx, so that it can be imported with its key on the target machine.

    *For an alternative using makecert, see Walter's own answer.

  3. Open Certificate Manager for the Local Machine. When you run certmgr.msc, it opens the Certificate Manager for the current user, which is not what we want here. Instead:

    1. From an administrative command prompt on the target machine, run mmc
    2. Press Ctrl + M, or Click File > Add/Remove Snap-in
    3. Choose Certificates, and click Add >
    4. In the dialog that appears, Choose Computer Account, and click Next
    5. Choose Local Computer. Click Finish, then Okay
  4. Import the certificate (pfx) into the Windows Certificate Store on the target machine

    1. In the mmc window previously opened, drill down to Certificates (Local Computer) > Personal
    2. Right-click on Personal, then click on All Tasks -> Import...
    3. In the 2nd screen of the dialog that appears, find and import your certificate. You'll have to change the file-type filter to Personal Information Exchange or All Files in order to find it
    4. On the next screen, enter the password you chose in step 2.1, and pay close attention to the first check box. This determines how securely your certificate is stored, and also how convenient it is to use
    5. On the last screen, choose Place all certificates in the following store. Verify that it says Personal, then click Finish
    6. Repeat the import procedure above for the Trusted Root Certification Authorities certificates section.
  5. Create the port associations for your application. On Windows Vista and later, use netsh, as I did. (For Windows XP and earlier, use httpcfg)

    • From the administrative command line, type the following to set up the SSL binding* to your app, and the appropriate port. NB: This command is easy to get wrong, because (in PowerShell) the braces need to be escaped. The following PowerShell command will work:

      netsh http add sslcert ipport=0.0.0.0:8443 `
      certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 `
      appid=`{00112233-4455-6677-8899-AABBCCDDEEFF`}
      

      对于 cmd.exe,应使用以下代码:

      netsh http add sslcert ipport=0.0.0.0:8443 certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}
      
      • ipport参数将导致 SSL 证书绑定到每个网络接口上的端口 8443; 要绑定到特定接口(仅) ,请选择与该网络接口关联的 IP 地址。
      • certhash只是证书的缩略图,删除了空格
      • appid是存储在应用程序的组装信息中的 GUID。(旁注: 从这个 有个问题及其答案判断,netsh机制显然是一个 COM 接口)

      * 微软已经将 SSL 绑定链接从 给你重定向到 那里

  6. Start up your web-server, and you're good to go!

由于在答案中自行签署证书对我来说不起作用,而且这个问题特别要求作出一个。NET HTTPListener HTTPS 的能力,并要求任何提示/建议,我想分享我的方法。

你需要一个主机名,比如 www.made-up.com,它需要指向你的 WAN IP 地址(例如询问你的主机提供商的指令) ,然后将它的端口(例如443)转发到你的本地机器上。不要忘记在本地机器的防火墙中打开入站443端口。

I used https://letsencrypt.org/. On Windows this not as easy as on Linux, because there isn't any official certbot ACME client for windows. However, you can use https://github.com/Lone-Coder/letsencrypt-win-simple, of which there are also binaries around. However "Currently only IIS is supported". But you can easily trick it to create a certificate on your computer such that you can approach your HTTP listener the SSL way:

  1. 安装 IIS (通过在/of 上安装 Windows 功能) ,在 IIS 中创建一个网站并分配主机名。也使它的一个安全(443端口)网站。
  2. Run the letsencrypt-win-simple EXE file (I used version 1.9.1). Answer the questions to let it generate the certificate.
  3. After that you can stop de IIS server.

我相信您必须注意生成的刷新任务,因为我不确定几个月后它是否会成功(您可能必须重新启动 IIS 才能更新证书)。

我们可以使用 PowerShell 和 C # 导入证书(不需要手动步骤)。

For details, see: https://blog.davidchristiansen.com/2016/09/howto-create-self-signed-certificates-with-powershell/

我用这个代码:

/// <summary>
/// Create and install a self-signed certificate for HTTPS use
/// </summary>
private static void CreateInstallCert(int expDate, string password, string issuedBy)
{
// Create/install certificate
using (var powerShell = System.Management.Automation.PowerShell.Create())
{
var notAfter = DateTime.Now.AddYears(expDate).ToLongDateString();
var assemPath = Assembly.GetCallingAssembly().Location;
var fileInfo = new FileInfo(assemPath);
var saveDir = Path.Combine(fileInfo.Directory.FullName, "CertDir");
if (!Directory.Exists(saveDir))
{
Directory.CreateDirectory(saveDir);
}


// This adds certificate to Personal and Intermediate Certification Authority
var rootAuthorityName = "My-RootAuthority";
var rootFriendlyName = "My Root Authority";
var rootAuthorityScript =
$"$rootAuthority = New-SelfSignedCertificate" +
$" -DnsName '{rootAuthorityName}'" +
$" -NotAfter '{notAfter}'" +
$" -CertStoreLocation cert:\\LocalMachine\\My" +
$" -FriendlyName '{rootFriendlyName}'" +
$" -KeyUsage DigitalSignature,CertSign";
powerShell.AddScript(rootAuthorityScript);


// Export CRT file
var rootAuthorityCrtPath = Path.Combine(saveDir, "MyRootAuthority.crt");
var exportAuthorityCrtScript =
$"$rootAuthorityPath = 'cert:\\localMachine\\my\\' + $rootAuthority.thumbprint;" +
$"Export-Certificate" +
$" -Cert $rootAuthorityPath" +
$" -FilePath {rootAuthorityCrtPath}";
powerShell.AddScript(exportAuthorityCrtScript);


// Export PFX file
var rootAuthorityPfxPath = Path.Combine(saveDir, "MyRootAuthority.pfx");
var exportAuthorityPfxScript =
$"$pwd = ConvertTo-SecureString -String '{password}' -Force -AsPlainText;" +
$"Export-PfxCertificate" +
$" -Cert $rootAuthorityPath" +
$" -FilePath '{rootAuthorityPfxPath}'" +
$" -Password $pwd";
powerShell.AddScript(exportAuthorityPfxScript);


// Create the self-signed certificate, signed using the above certificate
var gatewayAuthorityName = "My-Service";
var gatewayFriendlyName = "My Service";
var gatewayAuthorityScript =
$"$rootcert = ( Get-ChildItem -Path $rootAuthorityPath );" +
$"$gatewayCert = New-SelfSignedCertificate" +
$" -DnsName '{gatewayAuthorityName}'" +
$" -NotAfter '{notAfter}'" +
$" -certstorelocation cert:\\localmachine\\my" +
$" -Signer $rootcert" +
$" -FriendlyName '{gatewayFriendlyName}'" +
$" -KeyUsage KeyEncipherment,DigitalSignature";
powerShell.AddScript(gatewayAuthorityScript);


// Export new certificate public key as a CRT file
var myGatewayCrtPath = Path.Combine(saveDir, "MyGatewayAuthority.crt");
var exportCrtScript =
$"$gatewayCertPath = 'cert:\\localMachine\\my\\' + $gatewayCert.thumbprint;" +
$"Export-Certificate" +
$" -Cert $gatewayCertPath" +
$" -FilePath {myGatewayCrtPath}";
powerShell.AddScript(exportCrtScript);


// Export the new certificate as a PFX file
var myGatewayPfxPath = Path.Combine(saveDir, "MyGatewayAuthority.pfx");
var exportPfxScript =
$"Export-PfxCertificate" +
$" -Cert $gatewayCertPath" +
$" -FilePath {myGatewayPfxPath}" +
$" -Password $pwd"; // Use the previous password
powerShell.AddScript(exportPfxScript);


powerShell.Invoke();
}
}

Requires PowerShell 4 or higher.

下面的命令为 localhost 生成为期10年的自签名证书,将其导入到本地计算机存储器并在输出中显示 Thumbprint (certhash) :

powershell -Command "New-SelfSignedCertificate -DnsName localhost -CertStoreLocation cert:\LocalMachine\My -NotAfter (Get-Date).AddYears(10)"

然后,您可以从输出中复制 Thumbprint,并使用 netsh.exe 将证书附加到 localhost: 443,例如:

netsh http add sslcert ipport=localhost:443 certhash=110000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}

适用于 Windows8或更高版本。需要管理员权限。