ServiceHost is binding to multiple hostnames/base addresses - c#

I'm running Windows 7 and Visual C# Express 2010.
I have the following rule in my ACL:
Reserved URL : http://www.example.com:8020/gamerecords/
User: Myricae\Dario
Listen: Yes
Delegate: No
SDDL: D:(A;;GX;;;S-1-5-21-3389095862-38437692-3014067205-1001)
Not that it really matters, but I also have an appropriate entry in my hosts file:
127.0.0.1 www.example.com
I'm trying to self-host a WCF service within a console application:
var baseAddress = new Uri("http://www.example.com:8020/gamerecords/");
using (ServiceHost host = new ServiceHost(typeof(Acme.Gaming.GameRecordsImpl), baseAddress))
{
...
}
I get the following exception:
Unhandled Exception: System.ServiceModel.AddressAccessDeniedException: HTTP could not register URL http://+:8020/gamerecords/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details). ---> System.Net.HttpListenerException: Access is denied
The reason is that ServiceHost tries to bind to any hostname (+), but the ACL rule only authorizes the current user for hostname www.example.com. If I change the rule to:
Reserved URL : http://+:8020/gamerecords/
User: Myricae\Dario
Listen: Yes
Delegate: No
SDDL: D:(A;;GX;;;S-1-5-21-3389095862-38437692-3014067205-1001)
everything works fine. However I don't think that ServiceHost should really try to bind to any hostname; instead it should only publish the service at www.example.com. Why WCF attempts to bind to multiple hostnames?.
I found a page which describes a similar issue.

Did you start your application via "Run-as-Administrator"?

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

ASP core HttpClient.Get From container to localhost site is failing

Given:
Windows 10 PC With Docker (linux container format)
Local website in IIS accessable on the bare machine (no container) http://localhost/foo
ASP Core DockerContainer which wants to access HTTP GET http://localhost/foo
Problem:
All requests to http://localhost are failing
var client = new HttpClient();
var result = await client.GetAsync("http://localhost/foo");
Then I get
System.Net.Http.HttpRequestException: An error
occurred while sending the request. --->
System.Net.Http.CurlException: Couldn't connect to server
at System.Net.Http.CurlHandler.ThrowIfCURLEError(CURLcode error)
at System.Net.Http.CurlHandler.MultiAge...
Is this expected? I thought access to localhost from inside container should work.
Also other protocols like mongodb are working with localhost. So it seems to be specific to http connections form asp core?
One question before: I suppose that the server you are trying to reach is in the same container, right?
If yes:
You should be able to connect from within the container using localhost.
The problem might be that this container doesn't expose the port 80 internally. Can you check the port internal port with "docker ps"?
If no:
In that case it means that localhost is used to connect to the host. My understanding is that it should not work.

Endpoint not found exception in a WCF Service

I'm approaching to WCF Service, starting with the tutorial provided by Microsoft. I created a very simple WCF Service (CalculatorService) and I've some doubts about the EndpointAddress of this service.
When I create the WCF Host, I set the Endpoint like this:
Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");
// Step 2 Create a ServiceHost instance
ServiceHost selfHost = new ServiceHost(typeof(Service1), baseAddress);
// Step 3 Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(IService1), new WSHttpBinding(), "CalculatorService");
Everything works if I debug the entire solution, but, if I launch the WCFHost executing its .exe file, launching also the application of the Client gives me the following exception:
System.ServiceModel.EndpointNotFoundException: No endpoint listening in http://localhost:8732/Design_Time_Address/WcfServiceLibrary/Service1/.
The fact is that if I try to open a browser and search the address http://localhost:8000/GettingStarted/, I get correctly the page of the Service. I suppose that the Service is hosted at one address and the Client tries to access to it via a different one.
Could anyone help me to solve this issue?
If you have, in the client code, hard coded this address http://localhost:8732, then change it there. But your client is probably (you didn't put that info unfortunately in your question) automatically generated. In that case client config is in App.config file(if we are talking about your solution), and in config file of the .exe file when you build your project. You should look into your [ClientApplicationName].exe.config file and update the endpoint address to port 8000.

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

PowerShell remoting from a Windows service

I have a Windows service that regulary runs a PowerShell script on a remote computer via WsManConnectionInfo/RunspaceFactory (following the steps from this article: Remotely Executing Commands in PowerShell using C#):
var connectionInfo = new WSManConnectionInfo(false, server, 5985, "/wsman",
"http://schemas.microsoft.com/powershell/Microsoft.PowerShell",
cred)
{
OperationTimeout = 4*60*1000,
OpenTimeout = 1*60*1000
};
using (var runSpace = RunspaceFactory.CreateRunspace(connectionInfo))
{
runSpace.Open();
using (var p = runSpace.CreatePipeline())
{
p.Commands.AddScript(script);
var output = p.Invoke();
...
}
}
Now, if I run the Windows service itself with an Administrator account, all is well. But if i run the service with the LocalSystem account, I get the following exception;
System.Management.Automation.Remoting.PSRemotingTransportException:
Connecting to remote server NOSRVDEV02 failed with the following error message :
WinRM cannot process the request. The following error with
errorcode 0x8009030d occurred while using Negotiate authentication:
A specified logon session does not exist. It may already have been terminated.
Possible causes are:
-The user name or password specified are invalid.
-Kerberos is used when no authentication method and no user name are specified.
-Kerberos accepts domain user names, but not local user names.
-The Service Principal Name (SPN) for the remote computer name and port does not exist.
-The client and remote computers are in different domains and there is no trust between the two domains.
After checking for the above issues, try the following:
-Check the Event Viewer for events related to authentication.
-Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
Note that computers in the TrustedHosts list might not be authenticated.
-For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.
at System.Management.Automation.Runspaces.AsyncResult.EndInvoke()
at System.Management.Automation.Runspaces.Internal.RunspacePoolInternal.EndOpen(IAsyncResult asyncResult)
at System.Management.Automation.RemoteRunspace.Open()
...
Note: This has nothing to do with the credentials in WSManConnectionInfo - just the account settings in the service properties "Log On" tab.
I don't want to give the service admin privileges. Any ideas why the LocalSystem user fails to log in?
Additional info:
The remote computer is not a member of a domain.
I have tried to connect both by IP address and hostname (both are listed in the local computer's TrustedHosts).
EDIT: Even more info (summary of the comments):
Local computer: Windows 7 Ultimate 64bit (virtual machine on a Windows 8 box).
Remote computer: Windows Server 2008R2 Datacenter 64bit.
The main reason we don't want to change service user accounts is that this is an update to an old service which is already deployed on many clients (customers).
The service also accesses the Windows registry and the file system on the local computer, so setting the user account to something more restricted, like NetworkService, would just open a different can of worms.
A rather surprising solution to this one: The username in the PSCredential object (cred) needed to be prefixed with the domain-less remote computer's name, e.g. "MYREMOTESERVERNAME\remoteusername" and not just "remoteusername".
I have no idea why the prefix is needed only when connecting with the LocalSystem account though...

Categories

Resources