Httplistener with Https on Monotouch

HttpListener with HTTPS on MonoTouch

This is a very good question. In some cases, like for HttpListener, .NET requires tools or .config files (using System.Configuration) to tweak the configuration of an application. In many cases there are API do achieve the same purpose, but not always (and not in this case).

The solution is to look at Mono's source code to see what it expects the HttpCfg.exe tool to setup for the application. From github:

string dirname = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
string path = Path.Combine (dirname, ".mono");
path = Path.Combine (path, "httplistener");
string cert_file = Path.Combine (path, String.Format ("{0}.cer", port));
if (!File.Exists (cert_file))
return;
string pvk_file = Path.Combine (path, String.Format ("{0}.pvk", port));
if (!File.Exists (pvk_file))
return;
cert = new X509Certificate2 (cert_file);
key = PrivateKey.CreateFromFile (pvk_file).RSA;

So the solution is to create the same directory structure (it's possible since it will point under the Documents directory) and copy the .cer file (binary DER-encoded certificate) and the .pvk file (which is the private key in the format that makecert creates) with the port number as the file name.

With those files in place you should be able to start the HttpListener and have it load the required certificate and private key required to handle SSL requests.

HTTPS Client Certificates with Monotouch

Use HttpWebRequest. In the question notes point 2 I said the HttpWebRequest.ClientCertificates property throws a not implemented exception, and I therefore ruled out this option. It does if you try to set it the property with a new collection, but if you just use the Get accessor, you can add a client certificate to the collection.

As a side note, using HttpWebRequest makes the app more transportable to other devices, part of the reason we are using MonoDevelop so win-win.

C# HttpListener total failure on SSL

2 Solutions for this problem:

If you need a quick fix for localhost (Just for localhost)

Thanks to SushiHangovers comment, setting the missing environment variable 'MONO_TLS_PROVIDER' to 'btls' (BoringSSL) fixed the problem.

$ MONO_TLS_PROVIDER=btls mono servertest.exe

If you need it to work on a server

Thanks to Gusman here is a short and simple to follow guide on how to use Nginx for managing SSL and sending Http requests to the Mono server.

1. First install/setup Nginx

www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04

2. Then install Certbot

certbot.eff.org

3. And secure Nginx with Certbot

www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04

4. Reverse proxy to your HttpListener port (taken from here)

4.1 Open the Nginx configfile

 $ sudo nano /etc/nginx/sites-available/default

4.2 Comment out the default try_files line and specify the Reverse proxy settings

 . . .
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;

# Reverse proxy settings
include proxy_params;
proxy_pass http://localhost:8010;
}
. . .

And change

server_name _;

to

server_name example.com www.example.com;

Now you should be good to go.

How to use SSL with HttpListener with an mkbundle'd Mono app

Yes the path that HttpListener expects to find certificates at is predefined, and cannot be specified by the user, programatically or through a config file. The Mono EndPointListener class will look for the path:

~/.config/.mono/httplistener/

HttpListener code:

string dirname = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
string path = Path.Combine (dirname, ".mono");
path = Path.Combine (path, "httplistener");

As you have noted this is the same path the httpcfg copies certificates to.

Even though you are using mkbundle, this is still where HttpListener will expect to read the certificate from, regardless of the fact that the Mono runtime is installed.

In your application startup, you should:

  • Check for the existence of the directories, and create as required
  • Write your certificate and key to that path from an embedded resource in your application. PouPou's answer here shows the method used by HttpCfg.exe.

Therefore eliminating the requirement to run httpcfg, you will effectively be building that functionality straight into your application.


Does Mono perform any validation of the certificates it loads from there for HttpListener? i.e., will it expect to find the issuer's certificate in the certificate store?

I don't know for sure if Mono checks for a valid corresponding issuers certificate in the certificate store at the point of creating the listener, or upon each connection request. However you can add a CA cert to the certificate store yourself, or import all the standard Mozroot certificates.

The full source code for Mozroots is here. This shows how to import the CA certs.

Is the path to the certificate store also hard-coded?

The certificate store should be managed through the X509StoreManager provider.

C# HTTPS Server on Ubuntu

This is dependent on the backend web server being used. On Ubuntu, you'd probably be using Kestrel. For Kestrel, an SSL certificate can be defined using:

"Kestrel": {
"Certificates": {
"Default": {
"Path": "<path>/fullchain.pem",
"KeyPath": "<path>/privkey.pem"
}
},
"Endpoints": {
"Http": {
"Url": "http://*:80"
},
"Https": {
"Url": "https://*:443"
}
}

in appsettings.json

For more information about how to set up SSL for Kestrel refer to: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-6.0

HttpListener (.NET Core) doesn't work with https on windows dockers

According to the "official" answer in the .NET Core forum:

"In general the HttpListener class is a legacy component we ported from .NET Framework (which is Windows only) to .NET Core. But HTTPS functionality is not supported on Linux. See: #19752

If you need a cross-platform HTTP/HTTPS server, we recommend you use ASP.NET Core. The 'Kestrel' component supports HTTPS fully and is available cross platform (Windows/Linux/Mac).
See: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.1"



Related Topics



Leave a reply



Submit