I've got a Web API that must communicate with a few different services. Currently, I have the Web API set to use the following security protocol:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
When the API calls out to another service via HttpClient (say like Twitter), it will use that protocol. At the same time however, another request may come in to access something from the cloud, which for whatever reason, currently requires TLS (not TLS 1.2). The request to the cloud, before firing out, sets the security protocol again:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
The problem I'm running into is when two separate and unique requests come in, one for Twitter and one for the cloud, the security protocol could switch over to the "wrong one" before it's sent out, causing the request to fail.
Is there a way to set the security protocol on the HttpClient per request so that I'm not swapping around a setting in some singleton somewhere?
You don't need to set it.
You can use:
using System.Net;
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
Additional Notes:
Needed for .Net 4.5 because Tls12 is not a default protocol.
Need to write the above code only once within the application. (For example within Global.asax > Application_Start within Web application or equivalent in Winforms application)
For .Net 4.6 and above, Tls12 is a default protocol so it is not needed
There seems to be no way to do this. The SecurityProtocol property is only being used inside the internal TlsStream class in one place:
TlsStream seems to back all the internal TLS connections such as HTTP, FTP and SMTP.
I had hoped that ServicePoint allows you to configure this. For many settings ServicePointManager only provides the default. That hope was unfounded.
So this is quite strong evidence that this is not possible. It's no proof, though.
What should you do? I'd switch out the HTTP client library for the odd server you are talking to. HTTP is not a particularly complicated protocol. I'm sure there's some other implementation available.
Alternatively, use a proxy that terminates the HTTPS connection on your own server. .NET then only deals with HTTP.
Related
This has been discussed here but without a conclusion.
I would like to set up a WebSocket server in a self hosted Windows Service where I currently have multiple REST web services running on WCF. My requirements are not that advanced, I just need to consume an incoming stream of data. The problem is that I cannot change the way the data is send, if I could I would just convert it to a streamed HTTP POST, but this is not possible as the protocol is fixed.
According to Microsoft the WebSocket Class should be available from .NET Framework 4.5 and I am using .NET Framework 4.8 that is also supported but nowhere can I find how to self host it. There are many examples using IIS which I do not use.
So what I want to know is, 1) can the WebSocket class be used to self host a WebSocket Server inside a Windows Service?
If so how is it done? Looking for some example code.
EDIT
I think this might be somewhat undocumented but I finally got it to work. The magic seem to be replacing localhost or * with +. The following seem to work hosting the WebSocket while maintaining working WCF web services.
WebSocketsServer.Start("http://+:80/Socket/");
Some of it was described here but I could not make out when to use + or * and what their actual uses are.
When a port is specified, the host element can be replaced with "*" to
indicate that the HttpListener accepts requests sent to the port if
the requested URI does not match any other prefix. For example, to
receive all requests sent to port 8080 when the requested URI is not
handled by any HttpListener, the prefix is http://*:8080/. Similarly,
to specify that the HttpListener accepts all requests sent to a port,
replace the host element with the "+" character. For example,
https://+:8080. The "*" and "+" characters can be present in prefixes
that include paths.
I still do not think this makes sense fully. Anyone have a reference to why this would work?
I invested practically a whole working day in figuring out how to approach the task mentioned in the title best.
Here is what I found out so far:
There's at least one library that offers TLS 1.2 for .NET CF out of the box. The downside: they charge for a license. In case someone's interested in this easy solution, Rebex Library
There are several SSL/TLS libraries out there that allow to communicate with the server on a lower level. My approach was to get to compile the BouncyCastle library for the .NET Compact Framework which I accomplished.
From here on out I found an article that showed me how to implement the BouncyCastle interfaces and how to put the pieces together. See Making HTTPS call in C# with the BouncyCastle library for more information. This is pretty much how my code looks right now.
I accomplished to establish a connection with the server and sent a request and I also got the expected response. I then wanted to leverage the HttpWebRequest class so I don't have to code the HTTP requests myself. Or so I thought. Not possible. HttpWebRequest doesn't have public constructors. Therefore I cannot inherit from that class.
I also tried using RestSharp for example but this is also only relying on the WebRequest class. Basically all the HTTP clients available out there take the Uri and then open a stream themselves. Not a single one seems to take an already open stream and writes to it or offers to drop in some crypto API to use instead of what the platform offers by default (other than the mentioned Rebex library of course).
So my question is: is there any HTTP client that can write HTTP commands to an already open stream or at least give me a string representation of what I set on it? Or do I have to really code something like that myself even though there's a ton of these implementations out there already? Or am I completely missing a point and it can be solved way easier?
Based upon your research, could you setup a kind of proxy within your CF app?
Use HttpWebRequest and response in the rest of your app, but direct them to your internal proxy (at 127.0.0.1).
The proxy would deal with the TLS connection, and then it uses a socket listener to intercept the HTTP requests from your HttpWebRequest, but is doesn't need to parse them out, just forward them along your already open socket. Likewise, return TCP traffic would be sent back from the real host and to the local socket (again it is not parsed, just treated as a buffer).
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
I am developing a winform application in which I make calls to REST webservices. For http based web servers it works fine.But,when it was used for a https based server, they recieved an exception The request was aborted: Could not create SSL/TLS secure channel. Apparently, this is happening because they are using TLS v1.2 and I have not specified which version of protocol is to be used during webservice call.And, when I searched on internet found that adding the following code will do the job.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
But what if some other server uses different version of security protocol.How do I make the code robust, so that it detects the protocol being used and then sets the configuration accordingly?
I have a WCF web service using NetHttpBinding. I know I can control which protocols are available/used by using:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls|SecurityProtocolType.Tls11 |SecurityProtocolType.Tls12;
But is it possible to determine which protocol was actually used after make a service call?
I could explicitly set it to one protocol, then loop and make a call to see if it is successful, and repeat but that seems really clunky/slow. Any better ideas for doing this?