WCF Endpoint Address using https (WebHttpBinding) - c#

I need to modify a WCF endpoint binding address. Here is some background on the issue:
I have an NT class service (if it matters, not a webservice). It creates a System.ServiceModel.ServiceHost with an Endpoint whose endpoint address is created this way:
var epa = new EndpointAddress(string.Format("https://localhost:{0}/ServiceAPI/", 8181));
The binding used for the ServiceEndpoint is a WebHttpBinding with Mode=WebHttpSecurityMode.Transport (i.e. https).
When the ServiceHost is opened, I can go to a command prompt, and do "Netstat -a" and see the address bound to the Listen as 0.0.0.0:8181.
So far, no problem. However, a large customer has raised a "security issue" with the fact that because the WCF "listen" is on address 0.0.0.0 instead of 127.0.0.1, that a potential attacker can connect to that address from an external machine. The test that they have constructed is to use telnet 8181 from an external machine, and if the connect occurs, then the test fails. The change request is to modify the service to "listen" on 127.0.0.1:8181 so that the only possibility of connecting to that port is from the local machine.
I have done a fair amount of modifications in an attempt to get WCF to "listen" on "127.0.0.1" instead of "0.0.0.0". In all of my attempts the only way to do this is to set HostNameComparisonMode to "Exact" and create the endpoint address in this way:
var epa = new EndpointAddress(string.Format("https://127.0.0.1:{0}/ServiceAPI/", 8181));
(Actually, as an aside, if I use a different binding such as NetTcpBinding, the above EndPointAddress construction will bind to address "127.0.0.1:8181" without altering HostNameComparisonMode. It only switches internally to "0.0.0.0:8181" when I use WebHttpBinding, and fail to set HostNameComparisonMode=Exact.)
However, this (setting HostNameComparisonMode=Exact) causes a breaking complication due to the fact that existing 3rd party code has already been developed that attempts to (onboard the server) connect to "https://localhost:8181/ServiceAPI", and when HostNameComparisonMode is set to "Exact", WCF only ever returns http error 506 to any request due to the difference between "localhost" and "127.0.0.1".
What I am currently looking for is either a means of setting up WCF to bind to "127.0.0.1:8181" (as determined by netstat -a) with the HostNameComparisonMode still set to the default "StrongWildcard" setting. Or barring any possibility of there being a way to do that, another creative suggestion to cause connects coming from external machines to be unable to connect to that port. (The test would be to use "telnet servername 8181" from a different machine, and it fail to connect.)
Any ideas? Thanks!

if i understand you right, you want to connect from remote machine to this address, so can you try BasicHttpBinding? Also you can try to host it at: "https://localhost:{0}/ServiceAPI/", 8181" Correct pls if i understand you wrong.

Related

WCF Relay already connected to a listener, but no listeners are connected?

I'm currently attempting to write two applications in C# - a client and a server - which connect to a WCF Relay I've got set up in Azure, but I'm getting a really strange error when I try to run either.
This is a brand new WCF Relay that I've set up which has no naming conflicts with anything else, but every time I try to open a connection to it as a listener with my service, it fails with this exception:
System.ServiceModel.AddressAlreadyInUseException:
Address sb://[MY_RELAY].servicebus.windows.net/[MY_WCF_RELAY] is already in use by an existing listener with different settings.
And when I try to run my client application connecting to the same relay URL, I get this exception:
System.ServiceModel.FaultException:
'50200: There are no listeners connected for the endpoint.
Kind of odd how there's already a listener connected, but at the same time no listeners are connected. I've even checked on the number of active connections to the relay, and it's never jumped past 0.
Anybody have any clue what might be going on here and how I could troubleshoot? Thanks!
Please Check you might have configured a tenant with a service path of ./. Because of this, the root path was taken and then every tenant that tried to register would get the below error "Address sb://[namespace].servicebus.windows.net/[WCF Relay name] is already in use by an existing listener with different settings" .
Try to turn off the bad endpoint then all the other endpoint will able to work again.
If you creating a WCF Relay explicitly in the portal (or with NamespaceManager.CreateRelay[Async]) for this endpoint, If so, then you need the binding's IsDynamic == false.
If you're not pre-creating the endpoint then the binding's IsDynamic must be true.

WCF service sometimes rejects client credentials

I have a WCF service that creates its own secondary IP (using netsh) upon startup and listens on that IP. Sometimes it just so happens that the when server starts listening clients from the same machine can't connect (client credentials are rejected). From other machines, however, there are no such connection problems.
When starting service on the original IP, connection problems don't seem to occur, but the non-deterministic behavior of the previous scenario prevents me from making any conclusions.
This is what is used for credentials and protection level:
TcpClientCredentialType clientCredentialType = TcpClientCredentialType.Windows;
ProtectionLevel protectionLevel = ProtectionLevel.EncryptAndSign;
I would like to know what is happening here. Any suggestions/insights are welcome.

'No connection could be made because the target machine actively refused it'

I am working on a 'Smart Device Project' using .Net Framework 3.5. I am trying to connect to some Java SOAP services on a remote server.
In order to do that, I added 'Web References' to my project.
When I try to call my web service I get a WebException 'Unable to connect to the remote server' with the inner exception being 'No connection could be made because the target machine actively refused it'.
I searched quite a lot on the Web and StackOverflow and found a lot of ASP configuration and 'Unavaliable port' answers, but as I have another application using the exact same Service successfully, I can't get why the new one isn't getting through (It did sometimes through my tests so I suppose my client implementation isn't that bad)
I tried to look if there was some connection issue on the port by using some TcpClient:
System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient();
try
{
client.Connect("myServerName", 8087);
MessageBox.Show("Success");
} catch (Exception ex)
{
MessageBox.Show("Failure");
}
finally
{
client.Close();
}
This connection succeed.
Here is a sample on how I call my WebService:
WSServiceExtended srv = new WSServiceExtended();
srv.Proxy = new System.Net.WebProxy();
ServeurWSI wsi = new ServeurWSI();
srv.Url = "http://myServerName:8087/myServerApp/services/myService";
wsr = srv.login(wsi);
The service is called 'Extended' because I overrided the auto-generated one in order to add Cookie managment since I am using the Compact Framework. Following the sample in this thread:
https://social.msdn.microsoft.com/Forums/en-US/34d88228-0b68-4fda-a8cd-58efe6b47958/no-cookies-sessionstate-in-compact-framework?forum=vssmartdevicesvbcs
EDIT:
I made some new tests with the Web references and got it to work.
When I add the Web Reference, I have to put some Url to the Web Service. When I set it with the actual hostname instead of the 'localhost' everything is fine.
But then, since I set it manually to the real address just before the call, it shouldn't matter
srv.Url = "http://myServerName:8087/myServerApp/services/myService";
EDIT2:
I might have forgotten some specifics about my environnement.
The Web Services are exposed on my computer on some Tomcat Server.
The application I am working on is also developped on this computer (That's why I can add Web References by putting 'localhost' in the address)
The application is then deployed on a distant device (Windows CE) that will make calls the Web Services through WIFI (There, localhost wouldn't work then)
I tried calling the Web services from other computers successfully.
I'm beginning to think that there might be some differential between the called Url and the one that is set, otherwise, how would I have a difference in behaviour such as the one described in the first edit?
EDIT3:
Well..Seems like it's not a network issue but a .Net compact framework (usage?) issue...
The Url property of the Web Service implementation is simply ignored and the one in the Reference.cs is used in place.
If someone had some idea on how I could troubleshot this, I would really appreciate it.
That error means that you reached a server and the server said "no way". So you're either hitting the wrong server or the wrong port.
I find the telnet client is useful for testing stuff like this. From the command line, you can do:
telnet [servername] [port]
So something like:
telnet myServerName 8087
If it goes to a blank screen, then it connected successfully. If it does not connect, it'll tell you.
The telnet client is no longer installed by default in Windows 7+, so you'll have to install it. See here for instructions: https://technet.microsoft.com/en-ca/library/cc771275
If the connection does open, you could paste in an actual HTTP request to see what happens. A simple GET would look something like this:
GET /myServerApp/services/myService HTTP/1.1
Host: myServerName:8087
One reason for this error can be that the service binds to only a certain IP address. It could well be that the service only listens on the IP that is assigned to the host name, but not on the localhost IP (127.0.0.1).
For example:
If the host myServerName has the public IP 192.168.0.1, your service can choose to listen on all IPs assigned to the host (sometimes specifying 0.0.0.0), or it can specifically listen on 192.168.0.1 only. In that case you will not be able to connect through 127.0.0.1, because the service simply doesn't listen on that IP.
You can "use" this inverse of this feature to make a service accessible only to local clients, not on the public IP-Address, by listening on 127.0.0.1 only, but not on the public IP. This is sometimes used on Linux for example to make MySQL only accessible on the host itself.
I was starting to forget this post but I finally found the problem that was messing things up and it has nothing to do with programmation.
I was doing the calls while the device was connected to the computer via the 'Windows Mobile Device Center' allowing to access the device from Windows.
While connected, the host provided is ignored and all calls on the specified port are handled by the connected computer.
Disconnecting the device allows to communicate properly...

force WCF channel to ip address

I have two computers and they are connected via ethernet, i have set up an WCF connection and this all works ok, however when i host the same wcf on the local pc as the one i want to comunicate to and then do a wcf request via a channel, the request does not go to the remote pc but to my local pc. Is there a way to force a wcf request from a channel to go trough a specific ipaddress and not just go to any?
i'll try to explain how i use this:
there are two computers they are both similar and have two network adapters who have the same ipaddess and run thesame wcf software. so for example ipaddress for adapter 1 is: 10.10.10.1 and the other adapter is 10.10.10.2 on the same pc, and the other pc is similar. now these two pc need to communicate so i wire the two network adapters in cross example: pc 1 network adapter one goes to pc 2 network adapter 2. this so they are connected in 2 ways. so if i want to communicate with a simple socket from one to the other and back over the second adapter this all goes ok becouse i can bind a socket to a ipaddress and it will send it via the adapter it is bound to. but this does not seem to work with WCF. if i have two hosts on one pc, one for adapter 10.10.10.1 and one on 10.10.10.2 for the other adapter and i send a message to 10.10.10.2 that is on the remote pc, it will go in via the second network adapeter.
PC1 network adapter 1 (10.10.10.1) <--direct patch cable connection--> PC2 network adapter 2 (10.10.10.2)
PC1 network adapter 2 (10.10.10.2) <--direct patch cable connection--> PC2 network adapter 1 (10.10.10.1)
These connection arrows are direct connection patch cables!
all network adapters have a wcf hosted, and the software on both pc's is thesame.
this is all done for redundancy, more then two pc can be connected in a chain with this.
this is a little example of how i setup a request to the remote host:
public void Test()
{
string endPoint = "net.tcp://10.10.10.2:9985/connection";
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
binding.ListenBacklog = 2000;
binding.MaxConnections = 2000;
binding.TransferMode = TransferMode.Buffered;
binding.MaxReceivedMessageSize = 104857600;
binding.SendTimeout = new TimeSpan(0, 1, 0);
binding.CloseTimeout = new TimeSpan(0, 0, 1);
binding.OpenTimeout = new TimeSpan(0, 0, 1);
binding.ReceiveTimeout = new TimeSpan(0, 1, 0);
//binding.HostNameComparisonMode = HostNameComparisonMode.Exact;
//binding.PortSharingEnabled = false;
ChannelFactory<Connection> pipeFactory = new ChannelFactory<Connection>(binding, new EndpointAddress(endPoint));
var pipeProxy = this.ChannelFactory.CreateChannel();
//fictional method: pipeProxy.SendRequestTunnelTo("10.10.10.1"); //this is the ipaddress that it should go out to however it goes out to "10.10.10.2"
//and this is another network adapter also on the local mashine and here is also a wcf host on
((IClientChannel)pipeProxy).AllowOutputBatching = true;
((IClientChannel)pipeProxy).Open();
pipeProxy.SystemRequest(); //do function
}
Ok, the issue here is routing. If windows thinks it can deliver the traffic directly to the other IP Address, it will do so.
In this case, it can't differentiate between the local 10.10.10.2 that it knows about and one that's on another network hidden behind a NAT.
The preferred solution is to not use the same subnet (so have 10.10.10.2 and 10.11.10.2 or similar), however that can sometimes require significant changes.
The next best option is to use the IP address of the NAT and have it port forward.
Say you have a setup like this (where the boxes with 2 ip addresses are NATing routers with both public and internal IPs)...
10.10.10.2 --- [10.10.10.1 | 1.2.3.4] --- Internet --- [5.6.7.8 | 10.10.10.1] -- 10.10.10.2
Then the machine on the left should try to connect to 5.6.7.8 which should forward connections to the machine on the right (and vice-versa with the right machine connecting to 1.2.3.4).
If you've got a WAN setup that makes the machines appear to be in the same network, that's as much of a problem as being on the same network. None of the routers on the network will be able to determine which 10.10.10.2 you mean,
If you weren't using exactly the same IP address, you might be able to force the issue using routing tables on your windows box. This can allow you to specify preferential routes so that all traffic for a given IP address goes out over the specified NIC. Unfortunately, beyond that point it's out of your control and entirely up to the network hardware how the packets are routed. If you have the ability to configure routing on the intermediate hardware, you could fix the route the whole way to the destination but this is usually an awful lot of work and likely to be broken when kit is updated/replaced as it's non-standard.
If you decide to look into forcing routes, start with the Windows route command
Edit: Re: Forcing routing over an interface...
the syntax is route add target mask gateway costmetric interfaceid
run route print at a command prompt and make a note of the interface id you want to use form the top of the output
then add a route like this:
route add 10.10.10.2 255.255.255.255 10.10.10.2 1 [interface id from above]
on my machine that would be
route add 10.10.10.2 255.255.255.255 10.10.10.2 1 11
Note that in this case we're telling it to use 10.0.0.2 as a gateway. I have no idea what the consequences of doing this will be as software attempting to access itself via a locally bound port might get very confused. Last caveat: I don't have a pair of physical machines to hand that I can test this on, and VMs don't really count as their networking is slightly different.
We're providing a cost metric of 1. This should give it a very high priority meaning it should be chosen above all other routes to that IP address.
The route will be lost when the system reboots. You can use a -p flag after route add to make the route persistent. I suggest you don't do this until you're sure it's working as intended.
2nd Edit: I think you're heading down a rabbit hole here. While it may be possible to trick the system into working this way, it's definitely not a common usage and I haven't been able to find anything that says it's supported.
It seems like your fundamental problem is that you've got no way to negotiate before assigning IP addresses as you have no network connectivity.
Some thoughts...
Sharing the IP is not going to be robust, so decouple from it. Instead of using a fixed IP in the url, determine the other IP address programatically.
You could have two builds, one which uses .1/.2 and the other which uses .3/.4. Any build1 could then talk to any build2 but not 1-1 or 2-2. This is a bit awkward but would work with little effort on your part.
Better would be to assign unique IPs to every machine you build, then provide a way to detect the other machine's address. Service location protocol is a likely candidate for this approach. Once you know the IP address you need to communicate with, configuring WCF should be trivial.
If assigning unique IPs is problematic, you could potentially have DHCP servers on all nodes but only turn them on if another one doesn't exist on that network (pair). That way, every machine would end up with valid IP addresses with no prior configuration.
Your endpoint address needs to identify the IP address you are targetting.

WCF listen base address anyip

i want my servicehost to have the base address of any IP
so i tried this
new ServiceHost(typeof(LoggingController),new Uri("0.0.0.0"));
and it gives me invalid URI format
any one knows how should i write this ?
well i tried to access it from outside of my local lan and it didnt work , i made a small test software using tcpiplistener and i started listening to the same port and i set the base address of the tcpip protocol to anyip and the small test software worked so i figured out all i need to do is setting the same for the Webservice –
TcpListener tcpListener = new TcpListener(IPAddress.Any,10021);
this works which also mean my system admin did his job of making sure the port/server is accessable from outside, now shouldnt my webservice work !? it work but i cant access it from outside , i can access it from the same pc if i run client on the same pc
The following code works for me in a similar situation:
Uri baseAddress = new Uri("net.tcp://0.0.0.0:8080/MyService");
host = new ServiceHost(typeof(MyServer), baseAddress);
Reminds me of a problem we had with our software. The default configuration of the webservice used windows network credentials to apply message based security which - due to the domain/network credentials - won't work from another network. Our solution was to disable security on the service binding (which may be a bit tricky depending on the binding you use). For the default bindings like WebHttpBinding it's just passing a parameter in the constructor.
Hope this helps!

Categories