我正在运行安装了Ubuntu 14.04.1 LTS x64的VPS。 我已经安装了mono-complete。 我正在尝试创build一个简单的HTTPS侦听器,然后再继续处理更大的事情。 这是我第一次用Mono做任何开发。
以下是我的testing应用程序的完整代码:
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
从不被调用。
我已生成自签名证书进行testing,并将其configuration为以下列方式使用:
$ makecert -r -n "CN=outpost" -sv outpost.pkv outpost.cer $ httpcfg -add -port 443 -cert outpost.cer -pvk outpost.pvk
并validation:
$ 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
当它运行时,我打开了另一个会话,并运行sudo netstat -antp | grep 443
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 ---
我什至启用networking跟踪日志logging通过host.exe.config 单声道似乎忽略作为没有输出写 :
$ 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来实现这个项目的最终目标。
在这一点上,我差点把头发从头脑里拔出来。 我所search到的所有东西都可以在Windows上解决这个问题,但在Linux上没有任何用处。
这是一个单一的configuration问题? 有没有我失踪的一步? 我是否生成错误的证书?
解决方案是:
$ sudo httpcfg -add -port 443 -cert outpost.cer -pvk outpost.pvk
原因是:我通过sudo
运行host.exe
以获得使用端口443的权限。因此,证书是从/root/.config/.mono/httplistener
而不是/home/vps/.config/.mono/httplistener
/root/.config/.mono/httplistener
的/home/vps/.config/.mono/httplistener
。 通过sudo
运行httpcfg
把证书放在正确的位置。
这么简单的问题真让人头痛。