ServiceStack communications with Windows Service - c#

I have an multi layered application that I have developed. I communicate with the windows service using http with ServiceStack (AppHostHttpListenerBase). While this works fine in clean environments, I often find that customers computers are not so clean and one of the first problem areas is the introduction of an unwanted Proxy with causes my application not to run. I get alot of bad press that the application does not work well, when in reality it is a result of a hidden issue on the customer machine.
When I go to query my endpoints the proxy interferes and I lose all communications with the Service.
I am thinking of going back to WCF and using namedpipes but before I do so, wondered if there was a better way in the ServiceStack world (Which I absolutely love)
Ideas? Suggestions?

If a local HTTP proxy is causing issues one thing you could try is to use SSL which will let you tunnel your traffic as an opaque binary through their proxy minimizing potential for interference.
Configuring SSL for HttpListener is configured the same way for all HttpListener's, i.e. it's not specific to ServiceStack - and it needs to be configured on the OS where it's run.
This answer shows how to configure SSL on Windows: https://stackoverflow.com/a/11457719/85785
You'll be able to use https with ServiceStack HttpListener self-host by following the steps above, I used "https://*:8443/" for the url and "CN=localhost" to bypass the SSL browser warning dialog.
It's not specifically clear in the answer but you can get the Thumbprint from the details tab of the certificate where you then need to remove spaces. If it's easier, you can follow the walkthrough in the answer below to use MMC to import the certificate: https://stackoverflow.com/a/33905011/85785

Related

In the .net MVC framework, is there a way to know which TLS version is being used? [duplicate]

Because of compliance reasons we have to switch off the support of some ciphers and SSL2 on our webservers. This is not really a problem, but we would also like to inform them, after their successful login into the website, that we suggest switching on TLS 1.2 in their browser in case they are not already connecting to the server with TLS 1.2. So the question I have is:
How can I detect the protocol and cipher used in an https request to an ASP.net (MVC 4) application running in IIS?
I know that there are ways to log the SCHANNEL request to the event log and then read them out again, but this sounds very ugly to me.
And I have seen that the System.Net.Security.SslStream has the properties that I would need, e.g.: CipherAlgorithm, HashAlgorithm, KeyExchangeAlgorithm & SslProtocol, but I'm not sure where I can get these properties in my Controller Action in a mvc4 application.
The bad news, as determined by ILSpy, is that there is no way to get to a System.Net.SslStream instance from anywhere inside ASP.NET. That class is used for direct programming against the network, for example by the WCF framework. The best you can do from ASP.NET (whether using System.Web or OWIN on top of IIS or HttpListener) is to get a server variable (see list of IIS server variables) for whether the connection is secured by whatever secure transport was negotiated with the client.
As far as deterministically reading data from the event log during a web request... that seems scary. But if you can make it work, please share the code. :)
Alternatively, you could try to implement your own Owin host (aka web server!) that uses SslStream underneath. Maybe. :P See this article for a thorough introduction to SslStream programming.
But since you're already able to turn off certain protocols on your server (as in this article, I assume)... You could set up your site on two different subdomains, e.g. www.example.com and secure.example.com, where the former is a vanilla web server and the latter is configured to only accept TLS 1.2 connections. Then you'd write some bootstrapping logic that gets served from www.example.com and attempts to make an AJAX request to secure.example.com/securityUpgradeCheck (possibly with a nicely styled spinner animation and "Please wait, attempting to secure this connection" text to impress your users :)). If that request succeeds, the user can be redirected to secure.example.com (probably permanently, since that user agent is then known to support TLS 1.2 unless for some reason the user changes their browser settings).
For added impact, order an EV SSL certificate for the secure domain so your users will notice the upgrade in security. :)
UPDATE: I did some more digging, on the theoretical basis of writing a custom (native) ISAPI filter (or extension) to get at this information via the SChannel API. At first I was hopeful because I discovered a function HSE_REQ_GET_SSPI_INFO that would return an SSPI CtxtHandle structure, and which you could call from a custom ISAPI extension via the EXTENSION_CONTROL_BLOCK ServerSupportFunction function. That CtxtHandle structure, it turns out, represents an SChannel context and can get you a reference to a SECPKG_ATTR_CONNECTION_INFO attribute with which you can retrieve SSL connection-level information (the same information that's surfaced in the SslStream class in .NET, as far as I could tell). However, sadly, Microsoft anticipated that possibility and decided that this information is only available if you are using client certificates. The behavior is "by design."
There was one (native) SSPI function, QueryContextAttributes (Schannel), that I discovered during a long hunt through MSDN which may work. I haven't tried it, and it could simply fail for the same "by design" reason as the ISAPI API limitation linked to above. However, it may be worth a try. If you want to explore this route, here is an example of an ISAPI extension. Actually, with this approach you might be able to write an IIS module instead, using the newer IIS 7.0+ SDK.
But, assuming you don't have the luxury of requiring client certificates and that long shot doesn't work, that absolutely leaves only two options.
Use a different web server (Apache, etc.), running on the same physical/virtual machine but on a different port, etc. (as per our discussion in the comments, since you can't spin up another machine). If you only want to give the client an informational message, then this approach, coupled with an AJAX request, might be sufficient. Yes, a different port could well be blocked by a firewall somewhere, but hey - it's only an optional informational message anyways.
Rely on the semi-brittle approach with the System event log. Enable Schannel event logging and then write some event log querying code to try to correlate the request with the last-logged Schannel event. Note that you'll need to find a way to reliably correlate whatever gets put in the event log with the current HTTP request, so you might also need to write an ISAPI filter/extension or IIS module in this case to find the Schannel context handle (which is what I'm assuming the correlation would be based on).
By the way - is your load balancer configured to do any SSL interception? Because then this whole thing is moot anyways... Just a thought to consider.
UPDATE: Enabling Schannel logging netted this gem:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Schannel" Guid="{1F678132-5938-4686-9FDC-C8FF68F15C85}" />
<EventID>36880</EventID>
<Version>0</Version>
<Level>4</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime="2014-08-13T02:59:35.431187600Z" />
<EventRecordID>25943</EventRecordID>
<Correlation />
<Execution ProcessID="928" ThreadID="12912" />
<Channel>System</Channel>
<Computer>**********</Computer>
<Security UserID="S-1-5-18" />
</System>
<UserData>
<EventXML xmlns:auto-ns3="http://schemas.microsoft.com/win/2004/08/events" xmlns="LSA_NS">
<Type>client</Type>
<Protocol>TLS 1.2</Protocol>
<CipherSuite>0x3c</CipherSuite>
<ExchangeStrength>2048</ExchangeStrength>
</EventXML>
</UserData>
</Event>
This can be read out directly from managed code. I think the UserID only corresponds to the IIS worker process SID, unfortunately, but assuming you can come up with some kind of correlation heuristic, you could set up a background thread to continually poll the event log and give you a list of recently established client handshakes (use a ConcurrentDictionary perhaps).
There. That's it. No more curious investigating for me. I'm done. :P
Reading this with interest as we have exactly the same problem.
It occurred to me that there must be a public web service available to query this type of information and I did a little research and found this:
https://www.howsmyssl.com/s/api.html
The API is here
This API can be called from client side Javascript and it returns standard JSON which can be easily parsed and a suitable alert shown to your users.
You can also send the information to your own web service for logging purposes and try to combine the information with your existing IIS logs.
The only issue you face then is relying on a third party. This can be mitigated by standing up your own server and hosting the code which is freely available on GitHub.
We are going to be working on this solution so once I have some code in place I will update this answer.
Thanks again to Lars for the comprehensive answer above. I would have added this as a comment to that post however I thought it worth creating a separate answer so people can find it easier.
How do you check the Negotiated TLS Handshake from the Server? has the way to get this under IIS 8.5 and higher in ASP.Net MVC / WebAPI. At least it worked for me and a couple of others when I answered it yesterday.

Alchemy Websockets: Can't host server on Azure

I'm currently using Alchemy Websockets as my WebSocket solution, however this is proving to be a pain as I've spent quite a number of hours trying to figure out why I can't get it up and going on my WebRole (both on Compute Emulator and cloudapp.net itself). It runs okay locally.
I'm aware of this question that was asked previously, and I've followed everything in the code and done everything suggested, so I can't get why I still can't connect to my WebSocket server. I've tried connecting using WebSocket.org's Echo Test as well as an Android client (leveraging on Autobahn). I'm quite sure it's not a client-side issue anymore considering that both ways don't work, but more of a server-side issue (what is stopping me from opening the WebSocket server on Azure?!).
In summary, what I've done so far:
Included TCP InputEndpoint 8080 in my Azure
Start the WebSocket server in either Global.asax or RoleEntryPoint with port 8080
Tried connecting using both Echo Test & Autobahn for Android
If it helps, I've previously tried SuperWebSocket Server. I understand that the creator Kerry Jiang has uploaded some Azure samples, but the Command Assembly baffles me and I don't want that kind of extra logic in my application (I just want something that I can plug and play), so I decided to ditch that altogether.
Both Alchemy Websockets and SuperWebSocket Server work perfectly fine locally, but when it's on Azure (either emulator on uploaded on cloudapp.net) I can't seem to connect at all. Any guidance please...?
When using WebSocket with cloud-hosted VMs, a number of things can go wrong:
The cloud service might have firewalls in place that block any (non-standard) ports by default. On Amazon EC2, you can configure open (unblocked) inbound ports via AWS management console and the respective configuration of the "security group" that applies to the EC2 instance your WS server is running on.
Even if you use a standard Web port (like 80) and this port is open in the firewall, there might be a proxy, load-balancer or other so-called intemediary in place that is not WebSocket aware.
When running over non-local networks, there are all kinds of intermediaries that might interfere. For example, mobile networkwork providers have intermediaries that are too stupid for WebSocket (which uses the HTTP standard Upgrade mechanism .. it is standard .. but there is a lot of broken stuff out there).
To work around for 2. and 3. (and also in general), you probably want to run WebSocket over TLS (secure WebSocket .. WSS) in production. Running over TLS, and terminating the TLS connection at your server, no intermediary can interfere (there are exceptions even here .. so called MITM HTTPS proxies that unwrap the TLS .. but that only on some corporate networks and relies on the proxy being able to dynamically installing certificates in the user's browser).
To make a robust WSS connection, you MUST make sure the server certificate used is accepted by browsers without any problems. If it is self-signed e.g., a browser would normally not accept, but ask the user if he nevertheless wants to accept. With WS, the browser will not render such dialogs, because WS is a so called "subresource". Hence: make sure your cert is 100% ok.
With 5. being done, WebSocket (WSS then), will work (almost) all the time. Mobile, enterprise, public internet.

WCF and wsHttpBinding - Message encryption

I'm working on a client-server project implemented using WCF. The clients are deployed on different machines and communicate with services through the internet. I'm relatively new to WCF, and am a bit confused on choosing the appropriate binding for my Web services. The clients need to be authorized to perform operations, however, I'm implementing my own authentication algorithm and trying to avoid Windows authentication for various reasons, but I still need to make sure the message transferred in the channel is encrypted.
Right now I'm using wsHttpBinding with security mode set to Message. Full configuration looks like this:
I've set the authentication type in IIS to Anonymous Authentication to make sure the requests are passed through, and was expecting a service call to fail since MessageClientCredentialType in my binding is explicitly set to Windows. However, when I run the code, the service successfully gets called and returns the expected values. I have a feeling that I'm missing something - why is the call authorized? Can I make sure the message is still encrypted even though authentication type is set to Anonymous? Any help is appreciated.
Edit
To clarify on this, I tested the service with a client deployed to a machine outside the network on a different domain.
This MSDN article kind of sums up a lot of security issues relevant to WCF
http://msdn.microsoft.com/en-us/library/ms733836.aspx
regarding your specific situation,
the negotiateServiceCredential="true" means that you streamline certificate distribution to your clients for message encryption.
This option will only work with windows clients and has some performance problems.
read more here http://msdn.microsoft.com/en-us/library/ff647344.aspx
search the topic "streamline certificate distribution" in this page.
Which account do you use to make the call to the service? Allowing anonymous in IIS lets your request pass through to the service and service should authenticate if your caller has credentials that windows understands (Active directory/NTLM).
In your case, I think you are testing it in your own environment so service responds. Once you deploy it over internet, I doubt your service will allow anybody outside of your domain if you keep clientcredentialtype to windows.
Check these link for securing services on the Internet -
http://msdn.microsoft.com/en-us/library/ms734769.aspx
http://msdn.microsoft.com/en-us/library/ms732391.aspx

run C# code on client side in a web app

I have code on my server which works very well. It must crawl a few pages on remote sites to work properly. I know some users may want to abuse my site so instead of running the code which uses webclient and HttpRequest i would like it to run on client side so if it is abused the user may have his IP blacklisted instead of my server. How might i run this code client side? I am thinking silverlight may be a solution but i know nothing about it.
Yes, Silverlight is the solution that lets you run a limited subset of .NET code on client's machine. Just google for silverlight limitations to get more information about what's not available.
I don't know what is the scenario you're trying to implement, and whether you need real-time results, but I guess caching the crawl results could be a good idea?
In case you're after web scraping, you should be able to find a couple of JavaScript frameworks that for you.
I think your options here are Silverlight or somesort of desktop app
Unless maybe there is a jquery library or other client scripting language that can do same things
That's an interesting request (no pun). If you do use Silverlight then maybe instead of porting your logic to it, create a simple Proxy class in it that receives Requests from your server app and shuttles it forward for the dirty work. Same with the incoming Responses: have your Silverlight proxy send it back to the server app.
This way you have the option of running your server app through the Silverlight proxy in some instances, and on its own (with no proxy) in other scenarios. The silverlight plugin should provide a consistent API to program against no matter which browser it's running in.
If using a proxy solution in the web browser, you might even be able to skip Silverlight altogether and use JavaScript/AJAX calls. Of course this kind of thing is usually fraught with browser compatibility issues and it would be an obscure push/pull implementation for sure, but I think JavaScript can access domains and URLs and (in some cases of usage) not be restricted to the one it originated from.
If Silverlight security stands in the way you might look into other kinds of programmable (turing complete) browser plugins like Java, Flash, etc. If memory serves correct, for the Java plugin, it can only communicate over the network with the domain it originated from. This kind of security is too restrictive for your crawling needs.

Homemade .net stress tool only creates stress when Fiddler is on -- why?

When trying to apply some heavy stress on a new web app, we were having trouble with our usual array of free tools (WAS, some other free ms tool (wcat?)), so i created a v. quick and dirty tool that would use a .net webrequest object, open up new threads, and continually hit a list urls from a file. On a single thread it produced a little load previously.
Then once i started trying to multi-thread it (once by trying a thread.start(), and then another time by calling beginrequestgets on the webrequest object), the requests did not hit the server (nothing in the iis logs, no increase in requests executing, requests/sec, etc)---unless Fiddler was on! With fiddler on, it works just as I'd expect.
I'm not especially interested in using this little application much more (will probably try to find another free web stress tool -- any recommendations?) but my main question is, why did my little app only provide stress when going through the proxy of Fiddler? Any ideas?
You may take a look at Apache Bench. It is part of the Apache server software but ab.exe is completely standalone and you don't need to install the server. In the description it says that it is used to test the Apache Hypertext Transfer Protocol (HTTP) server but it works with any HTTP server. I've used it in multiple projects to perform stress testing and I can say that it is a great tool. As it allows posting data, it could be used to test web services as well.
Another alternative is WCAT from Microsoft.
Could be a missing proxy setting in your app. Do you normally use a proxy server to connect to your servers that you're stressing?
Fiddler operates within the context of the logged-in user, including any proxy settings. But when coding your own WebClient/HttpWebRequest, the proxy is not automatically used-- you need to enable use of a proxy yourself, either in code or configuration.
Also could be a permissions problem, if your stressed servers (or your proxies) require authentication.
Here's some code to play around with to address both a missing proxy and lack of authentication. Note that the same code can be used against WebClient as HttpWebRequest:
WebClient wc = new WebClient();
WebProxy wp = new WebProxy("http://myproxyserver:80/",true);
wp.UseDefaultCredentials = true;
wc.Proxy = wp;
wc.UseDefaultCredentials = true;
BTW, a tool I often use in weird situations like this is HttpWatch. It's expensive, but it is like fiddler but works as a browser plugin, meaning it will detect proxy issues and other problems which don't show up inside Fiddler. It also works nicely with HTTPS.

Categories