SSL TLS communication in c# with self signed certificate not working - c#

I have a .pem certificate file which is used to communicate between two servers. For communication I have written a program in C# like this:
var client = new RestClient("https://aaaaa.com:1111");
client.ClientCertificates = new X509CertificateCollection();
client.ClientCertificates.Add(new X509Certificate(#"C:\Users\aaa\Desktop\bbb.pem"));
var request = new RestRequest("/qqq/www", Method.POST);
request.AddJsonBody(new { create = new { msgBdy="Test" } });
var response = client.Execute(request);
Console.WriteLine(response.StatusCode);
//The underlying connection was closed: An unexpected error occurred on a send.
When I post the request through SoapUI it goes through, but when I try to send it through Postman or the above C# program it doesn't.
Screenshot from wireshark is below:
The change cipher spec event is called for the successful API call but through postman and c# application this event is never called.
I have tried to do this as explained in this article as well https://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication but that also didn't work.
How can I fix this issue.

Related

C#.Net Core 3.1 HttpRequest timeout or SSL connection issue

Ok i have the following code
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
clientHandler.UseProxy = false;
using (HttpClient client = new HttpClient(clientHandler))
{
var reqUri = string.Format("{0}/{1}?getBIC=true&validateBankCode=true", AppSettings.Instance.ValidationSettings.IBANValidationUri, iban);
Logger.Instance.LogInfo("IBAN Validation: Sending request");
using (HttpResponseMessage res = await client.GetAsync(reqUri))
{
using (HttpContent content = res.Content)
{
if (content != null)
{
Logger.Instance.LogInfo("IBAN Validation: Reading data");
var data = res.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(data.Result))
{
result = JsonConvert.DeserializeObject<IBANValidationResult>(data.Result);
}
}
}
}
}
Now this code simply makes a rquest to the openiban api to get the specific bank information from a IBAN number.
This code runs on a ASP.NET Core 3.1 Web API that is running on a IIS Server.
Now we have 3 exact same server with the same web api.
The problem:
when i call the service from a browser on server 1, the service works fine i get the response etc.
when i call the service from a browser on server 2 it works also fine.
when i call the service from a browser on server 3 it takes too long and then i receive following error on the backend:
ERROR: The SSL connection could not be established, see inner
exception
ERROR: Authentication failed because the remote party has closed the
transport stream.
The funny thing is: This issue does not depend on one server, sometimes the server 3 works but then server 2 does not work, sometimes server 1 does not work an the other servers are working.
Does anybody have a clue what is going on here?
PS: The SSL certificates are installed on the server
Thanks a lot

Adding SSL cert causes 404 only in browser calls

I am working in an internal corporate environment. We have created a webapi installed on iis on port 85. We call this from another MVC HelperApp on port 86. It all works as expected. Now we want to tighten security and add an SSL cert to iis on port 444 and bind it to our API.
Initially we test it with Postman, SoapUI, and a C# console app and it all works. Now we try calling it from our MVC HelperApp and it returns a 404 sometimes.
Deeper debugging; I put the code into a C# DLL (see below). Using the console app I call the Dll.PostAPI and it works as expected. Now I call that same Dll.PostAPI from the MVC HelperApp and it won't work. When I step through the code I make it as far as this line await client.PostAsync(url, data); and the code bizarrely ends, it doesn't return and it doesn't throw an exception. Same for Post and Get. I figure it makes the call and nothing is returned, no response and no error.
Also, if I change the url to "https://httpbin.org/post" or to the open http port85 on iss it will work. I have concluded that the C# code is not the problem (but I'm open to being wrong).
Therefore I have come to the conclusion that for some reason the port or cert is refusing calls from browsers.
We are looking at:
the "Subject Alternative Name" but all the examples show
WWW.Addresses which we are not using.
the "Friendly Name" on the cert creation.
and CORS Cross-Origin Resource Sharing.
These are all subjects we lack knowledge in.
This is the calling code used exactly the same in the console app and the web app:
var lib = new HttpsLibrary.ApiCaller();
lib.makeHttpsCall();
This is what's in the DLL that gets called:
public async Task<string> makeHttpsCall()
{
try
{
List<Quote> quotes = new List<Quote>();
quotes.Add(CreateDummyQuote());
var json = JsonConvert.SerializeObject(quotes);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var url = "https://httpbin.org/post"; //this works in Browser
//url = "https://thepath:444//api/ProcessQuotes"; //444 DOES NOT WORK in browsers only. OK in console app.
//url = "http://thepath:85/api/ProcessQuotes"; //85 works.
var client = new HttpClient();
var response = await client.PostAsync(url, data); //<<<this line never returns when called from browser.
//var response = await client.GetAsync(url); //same outcome for Get or Post
var result = await response.Content.ReadAsStringAsync();
return result;
}
catch (Exception ex)
{
throw;
}
}

404 not found error using ServiceStack ServerEventsClient with Pipedream SSE API

I'm using Pipedream as a data source which provides event data via an SSE API.
As per the instructions here, I'm using the following code to subscribe to the SSE:
var client = new ServerEventsClient("https://api.pipedream.com/sources/dc_mXugEA/sse")
{
EventStreamRequestFilter = req => req.AddBearerToken("[MYTOKEN]"),
OnMessage = message => Console.WriteLine(message.Json)
}.Start();
However, I get a System.Net.WebException with the message 'The remote server returned an error: (404) Not Found.'
But if I use HttpClient directly, it succeeds:
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "[MYTOKEN]");
using var reader = new StreamReader(await client.GetStreamAsync("https://api.pipedream.com/sources/dc_mXugEA/sse"));
while (!reader.EndOfStream)
{
Console.WriteLine($"Received message: {await reader.ReadLineAsync()}");
}
Of course, I want to use ServerEventsClient instead of HttpClient to avoid the boilerplate looping code. But why is ServerEventsClient not working in this case?
ServiceStack’s Server Events clients only works with ServiceStack’s Server Events feature, I.e. it can’t be used to consume a 3rd Party SSE stream.

How to make my C# client application to accept my NodeJS server certificates

I am following this tutorial to make PEM certificates working between a NodeJS Server and a NodeJS Client.
My situation is similar, at server I have a NodeJS server, but, at client side, I have a C# Client application (.NET Framework 4.7.2).
Just for a test, at C# Client application we have:
bool pingSuccess = false;
using (var wb = new WebClient())
{
string response = wb.UploadString(nodeJSURL, "POST", "{\"message\":\"ping\"}");
if (response == "success") pingSuccess = true;
}
if (!pingSuccess) throw new HttpListenerException(503, "Il server NodeJS risulta non raggiungibile dall'indirizzo " + nodeJSURL);
But (obviously) I get this expected error:
Web Client Exception: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel
What I tried to do, is to try applying the procedure used by Anders Brownworth in his tutorial for its NodeJS Client adapting this code to C#:
var fs = require('fs');
var https = require('https');
var options = {
hostname: 'localhost',
port: 4433,
path: '/',
method: 'GET',
ca: fs.readFileSync('ca-crt.pem')
};
var req = https.request(options, function(res) {
res.on('data', function(data) {
process.stdout.write(data);
});
});
req.end();
But I am quite new in C#, how can I rewrite this code to be equivalent and use it in C#?
In other words, what I need is for my C# client code to accept the certificates provided by my NodeJS server. I looked for other solutions, but I found them too complex, is there a lean and clean way to do it?
I tried a workaround, adding following line just before the HTTP request:
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
works, but this is not what I need, because I want to trust just only the certificates provided by my NodeJS server. However thanks to this workaround I was able to verify that the rest of the application is working properly.
Sidenote: I created my PEM certificates following the already abovementione tutorial but using Wind64 OPENSSL and it works perfectly n Windows 10.

HTTP POST not working in OWIN Self-Host Web API

I am self self hosting a Web API. Any Get Reqeust I make from my integration tests works fine. However any POST request throws connection refused. I can't seem to get a handle on what is happening.
Error Message
system.Net.HttpRequestException: An error occured while sending the request to the remote server. SocketException: no connection could be made because the target machine actively refused.
Code
using (WebApp.Start<App_Start.TestConfiguration>("http:/localhost:8216"))
{
var client = new HttpClient();
client.BaseAddress = new System.Uri("http://127.0.0.1:8216");
var response = await client.PostAsync("/api/MyController", new StringContent("something"));
}
controller
public string Post(string value)
{
return "Hello!";
}
I've got the same issue and found that it is necessary to use [FromBody] attribute before your method params. In this case it can parse request payload and you can reach your methods
Hope that helps
Could it be you're missing a / on:
using (WebApp.Start<App_Start.TestConfiguration>("http:/localhost:8216"))
it should be http://localhost:8216.

Categories