c# - 在 Ubuntu VPS (14.04.1 LTS) 上使用单声道,为什么我的 HTTPS HttpListener 从未收到上下文?

标签 c# linux https mono httplistener

我正在运行安装了 Ubuntu 14.04.1 LTS x64 的 VPS。我已经安装了单声道完成。在我继续做更大的事情之前,我试图创建一个简单的 HTTPS 监听器。这是我第一次使用 Mono 进行任何开发。

下面是我的测试应用程序的完整代码:

namespace jvs
{
  using System;
  using System.Net;
  using System.Text;
  using System.Linq;
  using System.IO;

  class Host
  {
    public HttpListener Server { get; set; }
    public TextWriter Log { get; set; }

    public Host()
    {
      this.Server = null;
      this.Log = Console.Out;
    }

    public Host(TextWriter log)
    {
      this.Server = null;
      this.Log = log;
    }

    public void Start()
    {
      this.Server = new HttpListener();
      this.Server.Prefixes.Add("https://*:443/");
      this.Server.AuthenticationSchemes = AuthenticationSchemes.Basic;
      this.Server.Start();
      this.Server.BeginGetContext(this.OnContextReceived, this.Server);
      Log.WriteLine("Host started; listening on:");
      foreach (var prefix in this.Server.Prefixes)
      {
        Log.WriteLine("  {0}", prefix.ToString());
      }
    }

    public void Stop()
    {
      this.Server.Stop();
      this.Server = null;
    }

    private void OnContextReceived(IAsyncResult ar)
    {
      // This function is NEVER called
      var server = ar.AsyncState as HttpListener;
      var context = this.Server.EndGetContext(ar);
      var identity = context.User.Identity as HttpListenerBasicIdentity;
      var response = context.Response;
      Log.WriteLine("Connection received");
      Log.WriteLine("  User: {0}\n  Password: {1}", identity.Name, identity.Password);
      server.BeginGetContext(this.OnContextReceived, server);
      using (var ms = new MemoryStream())
      using (var w = new StreamWriter(ms) { AutoFlush = true })
      {
        w.WriteLine(
        @"<html>
        <head>
        <title>Vorpalnet</title>
        </head>
        <body>
        <div style=""text-align: center; vertical-align: middle; width: 100%; height: 80%"">
        it worked.
        </div>
        </body>
        </html>");
        var buffer = ms.ToArray();
        response.ContentLength64 = buffer.Length;
        response.OutputStream.Write(buffer, 0, buffer.Length);
        response.OutputStream.Close();
      }

    }

    public static void Main(string[] args)
    {
      Host host = new Host();
      host.Start();
      Console.Error.WriteLine("PID {0}", System.Diagnostics.Process.GetCurrentProcess().Id);
      while (true) { }
    }
  }
}

编译代码并运行后(通过 sudo 以允许使用端口 443),一切似乎都很好。但是,当我打开 Firefox 并导航到 VPS 地址时,我收到消息“连接已中断。”

此外,如评论中所述,永远不会调用 OnContextReceived

我已经生成了用于测试的自签名证书,并按照以下方式配置它们以供使用:

$ makecert -r -n "CN=outpost" -sv outpost.pkv outpost.cer
$ httpcfg -add -port 443 -cert outpost.cer -pvk outpost.pvk

并验证:

$ httpcfg -list
Port: 443 Thumbprint: 02F57058BB31783710E6836E5646601A5AEBEB48
$ ll ~/.config/.mono/httplistener
total 16
drwxrwxr-x 2 vps vps 4096 Sep 17 16:42 ./
drwxrwxr-x 3 vps vps 4096 Sep 17 15:35 ../
-rw------- 1 vps vps  425 Sep 17 16:40 443.cer
-rw------- 1 vps vps  620 Sep 17 16:40 443.pvk
$ sudo ./host.exe
Host started; listening on:
  https://*:443/
PID 15961

当它运行时,我打开了另一个 session 并运行 sudo netstat -antp | grep 443;这是输出:

tcp    0     0 0.0.0.0:443         0.0.0.0:*           LISTEN      15961/cli

我尝试在本地连接到主机,但没有返回,这让我觉得单声道没有获取证书:

$ openssl s_client -connect outpost:443
CONNECTED(00000003)
2348096:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 318 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

我什至通过 host.exe.config 启用了网络跟踪日志记录由于没有写入输出,mono 似乎忽略了:

$ cat host.exe.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="System.Net" tracemode="includehex" maxdatasize="1024">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
      <source name="System.Net.Cache">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
      <source name="System.Net.Http">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
      <source name="System.Net.HttpListener">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
      <source name="System.Net.Sockets">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
      <source name="System.Net.WebSockets">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="System.Net" value="Verbose"/>
      <add name="System.Net.Cache" value="Verbose"/>
      <add name="System.Net.Http" value="Verbose"/>
      <add name="System.Net.HttpListener" value="Verbose"/>
      <add name="System.Net.Sockets" value="Verbose"/>
      <add name="System.Net.WebSockets" value="Verbose"/>
    </switches>
    <sharedListeners>
      <add name="System.Net"
        type="System.Diagnostics.TextWriterTraceListener"
        initializeData="network.log"
      />
    </sharedListeners>
    <trace autoflush="true"/>
  </system.diagnostics>
</configuration>

应该注意的是,使用纯 HTTP ("http://*:80/") 完全没有问题。一切正常。不幸的是,我将需要 HTTPS 来实现该项目的最终目标。

此时我几乎已经把头上剩下的头发都拔掉了。我用谷歌搜索过的所有内容在 Windows 上都有针对此问题的解决方案,但在 Linux 上没有任何用处。

这是单声道配置问题吗?我缺少一个步骤吗?我生成的证书有误吗?

最佳答案

解决方案是:

$ sudo httpcfg -add -port 443 -cert outpost.cer -pvk outpost.pvk

原因:我通过 sudo 运行 host.exe 以获得使用端口 443 的权限。结果,证书从 /中提取root/.config/.mono/httplistener 而不是 /home/vps/.config/.mono/httplistener。通过 sudo 运行 httpcfg 将证书放在正确的位置。

这么简单的问题真让人头疼。

关于c# - 在 Ubuntu VPS (14.04.1 LTS) 上使用单声道,为什么我的 HTTPS HttpListener 从未收到上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25900174/

相关文章:

linux - 为什么在 shell 脚本中使用 ${@+"$@"}?

performance - 我必须做什么才能使通过 HTTPS 提供的图像等内容缓存在客户端?

c# - 在 C# 中将图形转换为图像

c# - 如何使用 ListView /组合框 uwp 设置默认选定项

linux - 从 bash 脚本作为 cronjob 启动 bash 脚本

ruby-on-rails - AWS Elastic Load Balancer 有选择地启用 SSL

curl - 如何在 Go 中设置空授权 header ?

c# - 从不同的代码隐藏更改 ascx 内容

c# - WebAPI 序列化程序序列化基类而不是笨拙的子类

linux - [[ ]] 中的 Bash == 运算符太聪明了!