C# 在Ubuntu VPS(14.04.1 LTS)上使用mono,为什么我的HTTPS HttpListener从未接收到上下文?
我正在运行一个安装了Ubuntu 14.04.1 LTS x64的VPS。我已经安装了mono complete。我正在尝试创建一个简单的HTTPS侦听器,然后再进行更大的操作。这是我第一次使用Mono进行开发 下面是我的测试应用程序的完整代码:C# 在Ubuntu VPS(14.04.1 LTS)上使用mono,为什么我的HTTPS HttpListener从未接收到上下文?,c#,linux,https,mono,httplistener,C#,Linux,Https,Mono,Httplistener,我正在运行一个安装了Ubuntu 14.04.1 LTS x64的VPS。我已经安装了mono complete。我正在尝试创建一个简单的HTTPS侦听器,然后再进行更大的操作。这是我第一次使用Mono进行开发 下面是我的测试应用程序的完整代码: namespace jvs { using System; using System.Net; using System.Text; using System.Linq; using System.IO; class Host
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) { }
}
}
}
并核实:
$ 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
当它运行时,我打开了另一个会话并运行了sudonetstat-antp | grep443
;这是输出:
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 15961/cli
我试图在本地连接到主机,但没有得到任何回报,这让我觉得mono没有获取证书:
$ 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>
$cat host.exe.config
应该注意,使用普通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
,将证书放在正确的位置
这么简单的问题真让人头疼
$ sudo httpcfg -add -port 443 -cert outpost.cer -pvk outpost.pvk