Get Data from WebSocket using .Net ClientWebSocket - c#

I need to collect data from a WebSocket.
If I try to test the websocket with this site: http://www.websocket.org/echo.html I can connect and send message without problem but when I try to connect to the websocket using .Net Framework libraries I get:
System.Net.WebException: Internal Server Error (500).
The code I use to connect is this:
string uri = "wss://wss.xxx.xxx";
ClientWebSocket webSocket = null;
try
{
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(uri), CancellationToken.None);
await Task.WhenAll(Receive(webSocket), Send(webSocket));
}
catch (Exception ex)
{
Console.WriteLine("Exception: {0}", ex);
}
If I try to connect to any other web socket, the code works well...
The difference with the other websocket is that the address starts with "wss" instead of "ws" ( think its because of secure connection).
If I test with a browser like Chrome the websocket connetion works, but not in .Net, may be I have to add some header in order to simulate a Browser Agent ?
Thanks to support

Finally After some search I find out the problem: I just had to add headers to the ClientWebSocket.
The problem is that ClientWebSocket doesn't provide methods to add specific headers and I had to make a force of ClientWebSocket.
This thread help me a lot to solve my problem:
Setting "User-Agent" HTTP header in ClientWebSocket
Using this new version of ClientWebSocket I was able to add Headers.

Related

C# - Port Mapping with .Net Core 5.0

Expected Outcome
I'm attempting to make an ASP.NET Core 5.0 application using Kestrel, and I would like to auto port forward the server's port.
Package
I'm currently using the OpenNat.Core package. I have also tried the regular OpenNat and the same issue arises.
Issue
When port forwarding, the program says it has mapped everything correctly and the map even shows when listing all mapped ports on my router. Yet, when I attempt to view its status via CanYouSeeMe.org it returns a timed out error, and I am unable to access the server outside the network.
What I've Tried
I thought that the port mapping might have been opening after the server started, so I manually opened the port and then restarted the Kestrel server.
I made sure that my router supported UPnP
I also have a Synology NAS that I port forward from, and it works just fine.
I had a friend use ZenMap to check the port.
The port shows that it's filtered but not open (and no service was specified).
Code
using Open.Nat;
using System;
using System.Threading;
using System.Threading.Tasks;
...
public static async Task OpenPort(int port, string description)
{
try
{
NatDiscoverer discoverer = new NatDiscoverer();
CancellationTokenSource cts = new CancellationTokenSource(10000);
NatDevice device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cts);
Mapping map = new(Protocol.Tcp, port, port, description);
await device.CreatePortMapAsync(map);
Console.WriteLine($"Created {map}");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
Nevermind my firewall was blocking the application. I was able to dynamically add a firewall rule to fix the issue.

How to access the websocket URL from C# which is in remote ip?

My Websocket URL is like this
"ws://someip:port/demo/"
i am trying to access the URL and it will return the Json. I am new to C#. I tried the below code
var client = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("ipvalue"),portvalue );
client.Connect(ep);
var receivedData = client.Receive(ref ep);
Console.Write("receive data from " + ep.ToString());
Console.Read()
but it shows invalid Url. I have tried other codes also, but its also error. Please guide me.
Thanks
WebSocket != Socket
WebSocket is a protocol built on the top of TCP and requires HTTP for establishing the connection. Unfortunately you're not going to achieve anything with new UdpClient().
In order to connect to a websocket, you need to get a websocket library (alternatively, it looks like .NET already supports it) and use it instead of creating a TCP socket.

How to send valid HTTPS requests to a web service via SslStream and TcpClient

I'm essentially attempting to setup a HTTPS client I can use for automated testing APIs and other web services I'm developing. I'm familiar with using sockets, but not so much with using SSL/TLS in code. I've started by attempting to setup a client that sends an HTTP request to google.com with the following header: GET / HTTP/1.1
The idea is to receive a basic HTTP response from Google, via an encrypted connection of course. This is really easy when using unencrypted HTTP - I can even telnet into google over port 80 and enter GET / HTTP/1.1 and I receive a nice HTTP response header and HTML payload. Implementing the C/C# code for making unencrypted HTTP requests is also not very difficult. It's SSL that is giving me a difficult time.
Using the code below (full sample found at https://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-3), which is an almost identical implementation to what is provided by MSDN for reference, I can successfully connect to google.com and validate the server certificate:
// Create a TCP/IP client socket.
// machineName is the host running the server application.
TcpClient client = new TcpClient(machineName, 443);
Console.WriteLine("Client connected.");
// Create an SSL stream that will close the client's stream.
SslStream sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
// The server name must match the name on the server certificate.
try
{
sslStream.AuthenticateAsClient(serverName);
}
catch (AuthenticationException e)
{
Console.WriteLine("Exception: {0}", e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
}
Console.WriteLine("Authentication failed - closing the connection.");
client.Close();
return;
}
The issue is when the following code executes, the ReadMessage(sslStream) instruction hangs, as in I don't receive a response for a very long time, and when the response finally comes in it is an empty string:
// Encode a test message into a byte array.
// Signal the end of the message using the "<EOF>".
byte[] messsage = Encoding.UTF8.GetBytes("GET / HTTP/1.1<EOF>");
// Send hello message to the server.
sslStream.Write(messsage);
sslStream.Flush();
// Read message from the server.
string serverMessage = ReadMessage(sslStream);
Console.WriteLine("Server says: {0}", serverMessage);
Therefore, I'm unable to receive the HTTP response I was looking for (or anything at all) when I make this request over a secure socket connection. The idea in the long run is to start using this client to send customized HTTP requests to my own APIs and web services, but I certainly cannot do that if I cannot even get a generic response from google.com. Does anyone have an idea why the ReadMessage() function is timing out or otherwise providing no response? The sample code seems very straightforward so I'm having a hard time understanding what I'm doing wrong.
One thing that immediately caught my attention is that the Microsoft example does not provide the "count" argument for sslStream.Write(), which I believe may be related to your issue. Also note, ReadMessage() appears to be a function you have not provided a definition for. Without knowing what ReadMessage() is doing specifically, the exact cause of your problem cannot be determined. I modified the provided code for sending a HTTPS request and reading the response. It seems to work fine with sites I've tried thus far.
// Send request
byte[] buffer = new byte[2048];
int bytes;
byte[] request = Encoding.UTF8.GetBytes(String.Format("GET https://{0}/ HTTP/1.1\r\nHost: {0}\r\n\r\n", serverName));
sslStream.Write(request, 0, request.Length);
sslStream.Flush();
// Read response
do
{
bytes = sslStream.Read(buffer, 0, buffer.Length);
Console.Write(Encoding.UTF8.GetString(buffer, 0, bytes));
} while (bytes == 2048);
As a side note, I also noticed sslStream.AuthenticateAsClient(serverName); which certainly works for many web services; however, I've had issues with that particular overload when accessing sites that strictly use TLS1.2. Try sslStream.AuthenticateAsClient(serverName,null,SslProtocols.Tls12,false); if you want to enable support for strictly TLS1.2 agents.

Azure connection failed because connected host has failed to respond ip:443

So I implemented an interface to communicate with a rest web service using the HttpClient class to make requests.
The code works perfectly locally, but when I deploy to Azure my application can't fire the request, it crashes on this line:
using (var response = await HttpClient.PostAsync(uri, content)) { ... }
// uri = https://api-rest.zenvia360.com.br/services/send-sms
The exact exception message is this:
A connection attempt failed because the connected party did not properly
respond after a period of time, or established connection failed because
connected host has failed to respond 200.203.125.26:443
The web service provider states that "if you use firewall or proxy you must add and exception for our IPs. For HTTPS, use port 443:
200.203.125.24
200.203.125.25
200.203.125.26 (the ip of the exception message)
200.203.125.27
200.203.125.28
200.203.125.29"
I looked everywhere in Azure looking for a firewall or something and I got nothing. Also this exception message is pretty cryptc. I tested the same code with another url (fired a post to www.gooogle.com) and it worked.
Any ideas?
The problem turned out to be on the web service side. The service I'm using blocks international requests by default. I asked them to whitelist the azure outbound IPs and now it works.

C# Socket: connect to server through proxy server

VS 2008
I am using the code below to detect if the client can connect to our SIP server. This was working fine. However, the client has changed there network and now my application has to connect to the SIP server from behind a proxy server.
The error I get is the:
"A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond xxx.xxx.xx.xx:xx"
This code was working ok, until I have to connect from behind a proxy server.
I could not see any properties there I can add the proxy address to the socket.
Am I missing something?
Many thanks for any suggestions,
public bool IsSIPServerAvailable()
{
bool isAvailable = true;
Socket sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
try
{
sock.Connect("xxx.xxx.xx.xx", xx);
}
catch (SocketException ex)
{
Console.WriteLine(ex.Message);
isAvailable = false;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
isAvailable = false;
}
finally
{
if (sock.Connected)
{
sock.Close();
}
}
return isAvailable;
}
See my answer here, maybe it will be helpful. The general idea is to first establish connection to a proxy, and then use HTTP CONNECT command to open another TCP connection to a given host and port.
This is very similar to this question. I don't think it is possible to create a socket connection through a proxy server. You would need some kind of a protocol and more over, usually administrators set up proxy servers to refuse connections from ports other than standard HTTP, HTTPS.
One solution would be to use tunneling over HTTP.
The whole idea of a proxy is to change the network topology without changing the applications. Thus there is no need to change the app, but a change is required in the proxy configuration/setup.
To check the proxy config independently of your application, you can use Telnet Host Port and see if you get the same timeout/error message or if you get disconnected after entering a few characters.

Categories