NancyFX and IPv6 issues - c#

I have a client-server application that works using a https connection with a self signed certificate and a Nancy Selfhost server.
After installing the application i run the following scripts to prepeare the server.
Add SSL Certificate to store
Check witch ip:ports are configured with netsh http show sslcert
Remove all registrations with port number 4443 (only if they are found with previous step):
netsh http del sslcert ipport=0.0.0.0:4443
netsh http del sslcert ipport=[::]:4443
netsh http del urlacl url=https://+:4443/
And then add url reservation with: netsh http add urlacl url=https://+:4443/ user=everyone
Add SSL Certicates with:
netsh http add sslcert ipport=0.0.0.0:4443 certhash=XXX appid={XXX}
netsh http add sslcert ipport=[::]:4443 certhash=XXX appid={XXX}
Then I start the server. The code for starting the self host server is:
public void Start(string baseUrl) {
string url = baseUrl;
Uri uri = new Uri(url);
var uris = new[]
{
new Uri($"{uri.Scheme}://localhost:{uri.Port}"),
};
server = new NancyHost(new CustomBootstrapper(url, Api1, Api2, applicationConfiguration), uris);
server.Start();
}
In this code is the baseURL the Hostname of the machine.
The client server connection works in most cases, but one situation it doesn't. This is when i try to run the the server on a specific computer. It has the following differences from other servers:
Windows 8
Pinging the hostname of this returns a IPv6 adress.
When starting the client application, it gives the following error:
The underlying connection was closed: Could not establsh trust relationship for the ssl/tls secure channel
Now i'm stuck, because I am not sure why it would not work.

Apparently I had some old certification registrations and url reservations still active. After clearing them all, the issue was resolved.

Related

Why do we need to add a URL via netsh when listening to "http://*:8080" using HttpListener, but not when creating an HTTP server in Asp.NET Core?

Recently I am writing an HTTP server using HttpListener and met a problem.
I want my program listen to all IP address on port 8080. However I have to either run the program as administrator or add url http://*:8080 using netsh, otherwise it will throw an exception.
As far as I know, the built-in server like IIS or HttpSys from Asp.NET core can do the similar thing by just listening to IP address 0.0.0.0 without any administrator privileges or netsh thing.
How can they do this?
Edit:
I start an HttpListener like below:
var _listener = new HttpListener();
_listener.Prefixes.Add($"http://*:8080/");
_listener.Start(); // <-- Thrown exception "Access Denied" here

How can i make HttpListener to listen on 443 on mac OS?

I am setting up a simple server based on HttpListener in .net core that needs to run on MacOS. Works great on http, but i need it to run on https (port 443. Tried a custom port but still no success)
On windows, it works with "netsh add iplisten" and binding the cert with "netsh add sslcert". And it works great for both http and https.
On Mac OS however, first thing i found out was to set up an alias for localhost "ifconfig lo0 alias 127.0.0.9 up" so i'm allowed to start the httplistener.
That worked, and whenever i make a HTTP request to 127.0.0.9 i get the response i hard-coded in the browser.
Https still doesn't work. So i tried binding the certificate.
I used openssl to create a certificate => got a .p12 cert self-signed.
Used "httpcfg -add -port 443 -p12 server.p12 -pwd mypassword"
That worked, as i could see 2 files appeared in "~/.config/.mono/httplistener/" called 443.cer and 443.pvk.
However, if i navigate to https://127.0.0.9 i get an error connection reset in the browser.
I have no idea what else to try, and i can't find any answer.
Did anybody tried to do this on Mac OS?
var ipAddress = "127.0.0.9";
var httpListener = new HttpListener();
var httpPrefix = string.Format("http://{0}/", ipAddress);
var httpsPrefix = string.Format("https://{0}/", ipAddress);
httpListener.Prefixes.Add(httpPrefix);
httpListener.Prefixes.Add(httpsPrefix);
httpListener.Start();
WaitForNewRequest(httpListener);
In the "WaitForNewRequest(httpListener)" method i just write a hard-coded "hello world" response and wait for the next request. Nothing complicated.
Thank you!
Ports below 1024 are privileged, you need to run your app as root to open them.
If you need to use 443 in production, I highly recommend using apache or nginx to listen on the SSL port and proxy the traffic to your .net code.

Web API self host - bind on all network interfaces

How do you make a Web API self host bind on all network interfaces?
I have the below code currently. Unfortunately, it binds only on localhost. So access to this server from other than localhost is failing.
var baseAddress = string.Format("http://localhost:9000/");
using (WebApp.Start<Startup> (baseAddress))
{
Console.WriteLine("Server started");
Thread.Sleep(1000000);
}
Just change the base address like this
var baseAddress = "http://*:9000/";
using (WebApp.Start<Startup> (baseAddress))
{
Console.WriteLine("Server started");
Thread.Sleep(1000000);
}
And it should bind correctlly to all interfaces.
If you get access exceptions, please DO NOT start Visual Studio as admin user. Add an URL reservation instead. The following example assumes that you want to open port 9000 as HTTP service on all ports & hostnames (http://+:9000/) without any user restriction.
Start a command console window as administrator and execute:
netsh
netsh> http add urlacl url="http://+:9000/" sddl=D:(A;;GX;;;S-1-1-0)
The SDDL translates to "all users" from your current domain / machine.
Modify your code accordingly:
var baseAddress = "http://+:9000/";
using (WebApp.Start<Startup> (baseAddress))
{
// your code here
}
You can delete the reservation by running:
netsh
netsh> http delete urlacl url="http://+:9000/"
However, Microsoft recommends to avoid Top-level wildcard bindings, see:
https://learn.microsoft.com/en-us/windows/win32/http/add-urlacl
For more information about the difference between http://*:9000/ and http://+:9000/ see:
What does a plus sign mean in a http url? -> http://+:80

WebAPI self-host 503 error (HttpSelfHostConfiguration setted HttpSelfHostConfiguration)

I have a window service using self-hosted WebAPI.
HttpSelfHostConfiguration.HostNameComparisonMode set HostNameComparisonMode.Exact for hostname strong match.
var config = new HttpSelfHostConfiguration(uri);
config.HttpSelfHostConfiguration = System.ServiceModel.HostNameComparisonMode.Exact;
this._server = new HttpSelfHostServer(config);
_server.OpenAsync().Wait();
And URL reservation for the specified URL namespace for the domain.
netsh http add urlacl url=https://+:443/ user=EVERYONE
To bind an SSL certificate to a port number.
netsh http add sslcert ipport=0.0.0.0:443 certhash=xxxxxxxxxxx appid={xxxxxxxxx}
But Result appear HTTP 503 error.
I don't know state.
I had a similar problem. Problem in my case was duplicate urlacl for my URL.
netsh http show urlacl
...
http://+:80/api
http://127.0.0.1:80/api (or any IP)
Remove any possible duplicate urlacl for your program.

Self hosted OWIN and urlacl

I've created a self hosted Nancy/SignalR application self-hosted in OWIN using Microsoft.Owin.Host.HttpListener and Microsoft.Owin.Hosting
Things work perfectly fine locally but as soon as I try to use anything but localhost to access the app I get a HTTP Error 503. The service is unavailable error. I can't even access the app using 127.0.0.1 or the machine name.
I've tried adding the port to urlacl using
http add urlacl http://*:8989/ user=EVERYONE but doesn't seem to do anything.
here are the OWIN start options that I've tried,
var options = new StartOptions
{
Url = "127.0.0.1",
App = GetType().AssemblyQualifiedName,
Port = _configFileProvider.Port
};
var options = new StartOptions
{
App = GetType().AssemblyQualifiedName,
Port = _configFileProvider.Port
};
Here is the source code for the file that starts and stops the server.
so it turns out you need to pass in a url into StartOptions in the same format as the urlacl.
Changing the start options to the code below fixed the problem. now the app is accessible across the network.
var options = new StartOptions("http://*:8989")
{
ServerFactory = "Microsoft.Owin.Host.HttpListener"
};
I spend many hours solving similar issue on Windows 8.1.
StartOptions options = new StartOptions();
options.Urls.Add("http://localhost:9000");
options.Urls.Add("http://127.0.0.1:9000");
options.Urls.Add("http://192.168.0.102:9000");
options.Urls.Add(string.Format("http://{0}:9000", Environment.MachineName));
WebApp.Start<Startup>(options);
I could not listen or was getting 503 error...
If you want to listen on several IP addresses, each address needs its own urlacl record:
Does NOT work:
netsh http>add urlacl http://+:9000/ user=EveryOne
OK:
netsh http>add urlacl http://localhost:9000/ user=EveryOne
netsh http>add urlacl http://127.0.0.1:9000/ user=EveryOne
etc.
After adding reservation for each address individually, everything works fine.
Thanks to the info that #kay.one provided I was able to access my self-hosted Web API 2.2 (OWIN/Katana, console app) from the same machine via IP address. However just consolidate it into a simple step-by-step:
In Main of Program.cs (for console app): WebApp.Start<Startup>("http://*:8080");
From Windows Command Prompt (run as Administrator) enter netsh http add urlacl http://*:8080/ user=EVERYONE
Go to Windows Firewall with Advanced Security and add an Inbound Rule that opens up TCP port 8080
You should then be able to access from another machine using IP address or computer name.
Disclaimer: I'm not a security expert so I don't know the security implications of doing this.

Categories

Resources