UDP over NAT (via Internet) - c#

I'm coding a system with server (behind NAT with UDP port forwarding, static white IP) and client (behind NAT without any custom settings).
The task is sending datas from server to client via Internet .
In order to Server knows client's endpoint (and client's router keeps translation table), Client sends every 5 second easy UDP request to Server like "Hello!".
Server code:
private void SendData(ref string destination, CancellationToken cancelToken)
{
UdpClient senderClient = new UdpClient(AddressFamily.InterNetwork);
try
{
while (true)
{
cancelToken.ThrowIfCancellationRequested();
if (string.IsNullOrEmpty(destination))
continue;
byte[] testMessage = Encoding.UTF8.GetBytes("AnyDatas");
string ip = destination.Split(':')[0];
string p = destination.Split(':')[1];
IPEndPoint clientEP = new IPEndPoint(IPAddress.Parse(ip), int.Parse(p));
senderClient.Send(testMessage, testMessage.Length, clientEP);
Thread.Sleep(3000);
}
}
catch (OperationCanceledException ex)
{ }
finally
{
if (senderClient != null)
senderClient.Close();
}
}
private void ListenConnectionSupport(ref string stClientEP, CancellationToken cancelToken)
{
IPEndPoint IpEp = new IPEndPoint(IPAddress.Any, 13001);
UdpClient listenClient = new UdpClient(IpEp);
try
{
while (true)
{
cancelToken.ThrowIfCancellationRequested();
IPEndPoint cIpEp=null;
byte[] messageBytes = listenClient.Receive(ref cIpEp);
if (Encoding.UTF8.GetString(messageBytes) == "UDP-support")
{
stClientEP = String.Format("{0}:{1}",cIpEp.Address,cIpEp.Port);
}
}
}
catch (OperationCanceledException ex)
{ }
finally
{
if (listenClient != null)
listenClient.Close();
}
}
And that works even!
But only if client under the same router, despite on sending client->server request to external server IP.
I use my smartphone like client's router and try again (client is another PC). But although server gets Hello-request and sends answer, however client gets nothing.
UPDATE-----------------
I need to develop system for scheme:
Server (192.168.0.3)-routerA (static public IP, has port forwarding for server)- INTERNET- routerB(any regular hotspot or router) - Client
Algorithm:
Client sends to routerA (in this context routerA=Server) "Hello, give me your data." For router table client sends this continusly.
Server from previous message (like STUN server) can note Client EP.
Server in WHILE(true) cycle sends datas to Client.
The error is "Client doesnt get data from server".
If that is matters
server listen 13001 port, Client knows this port number
In "one router case" case server see client's endpoint like "192.168.0.5" (his local IP) and in "two routers" case, client's endpoint looks like unknown IP (I dont know what is that, his ipconfig shows another).
Please, show me proper direction!

Related

Client IP Listing and Blocking in SignalR

In Asp.net (core) .net 5, on the SignalR side, how can we list (receive) client IPs and block or allow certain IP's connections and requests by IP?
In my research, I saw that only Azure SingalR was mentioned.
How can we tell SignalR Hub to request Client IPs and accept (whitelist) or block (blacklist) public connection requests from specific IPs by coding in the application?
Is it possible ?
In SignalR you can get the ip of the user with the HttpContext.
public class AppHub : Hub
{
public string Ip => Context.GetHttpContext().Connection.RemoteIpAddress.ToString();
public override async Task OnConnectedAsync()
{
if (Ip == "::1")
{
await Clients.All.SendAsync("ReceiveMessage", "Server", "Welcome to the server!");
}
else
{
throw new Exception("You are not allowed to connect to this server!");
}
await base.OnConnectedAsync();
}
}
Another solution would be to create a hub filter wich you can find the documentation here :
https://learn.microsoft.com/en-us/aspnet/core/signalr/hub-filters?view=aspnetcore-6.0

How can I get a user's IP address in C#/asp.net/MVC 5?

The following code works OK locally, but it will only get the server's IP (if I'm correct).
try
{
string externalIP;
externalIP = (new WebClient()).DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(#"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
model.IpCreacion = externalIP;
}
catch { }
I can't test this right now, because the two guys at my office that can make this as a public URL for testing on a server aren't here today. The code is in the controller of the project, so it runs on the server every time a client executes the app, it's not actually the client who is getting the IP address.
How can I make the client get his IP address, instead of the server, executing the code I just showed?
If I managed to put this functionality in a view, would it work as I'm intending to?
UPDATE: I tried other methods posted as answers, like
string ip = System.Web.HttpContext.Current.Request.UserHostAddress;
and
model.IpCreacion = null;
model.IpCreacion = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(model.IpCreacion))
{
model.IpCreacion = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
but now I'm only getting ::1 as a result. Which didn't happen before, as I was getting a correct IP address.
if you want to get client ip address,visit bellow post in stackoverflow
How can I get the client's IP address in ASP.NET MVC?
That gets only IP of server, because you send the request from Web Server to checkip.dyndns.org.
To get the client IP, you need to use JavaScript and do the same thing.
$.get('http://checkip.dyndns.org/', function(data) {
console.log(data); // client IP here.
})
UPDATED:
If you need client IP Address in ASP.NET Core, you can inject this service
private IHttpContextAccessor _accessor;
And use it as
_accessor.HttpContext.Connection.RemoteIpAddress.ToString()
Or in ASP.NET Framework
Public string GetIp()
{
string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(ip))
{
ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
return ip;
}
Public string GetIp()
{
string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(ip))
{
ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
return ip;
}

Answering to UDP datagram: response doesn't reach sender

I'm struggling with implementing UDP communication. I'm trying to create two instances of UdpClient, which exchange some information. I'm currently at a stage, where client1 (on port 13006) sends bytes to client2 (port 13007), client2 receives them correctly and send information back, but client1 doesn't receive that response. Both clients work on the same machine (I'm testing as integration test, using XUnit).
Both parties begins to listen the following way:
public override void SetupListener(int port)
{
udpClient = new UdpClient(port);
udpClient.BeginReceive(new AsyncCallback(HandleNewConnection), null);
}
Then client1 sends message to client2:
ConnectAsync(IPAddress.Loopback, client2.ListenerPort);
[...]
public override async Task ConnectAsync(IPAddress address, int port)
{
UdpClientSender = new UdpClient();
UdpClientSender.Connect(address, port);
_logger.LogInformation($"({CurrentConnectionId}) Sending ConnectionRequest to {address}:{port}");
var message = ProtocolHandler.InjectFrame((int)MessageType.ConnectionRequest, null);
UdpClientSender.Send(bytes, bytes.Length);
BeginReading();
}
And immadiately starts to listen:
public override void BeginReading()
{
Thread _thread = new Thread(() =>
{
UdpClientSender.BeginReceive(new AsyncCallback(HandleRead), null);
});
_thread.Start();
}
client2 receives properly a message and calls this function:
protected override Task WriteToNetworkStream(byte[] bytes)
{
_logger.LogDebug($"({CurrentConnectionId}) Sending. LocalEndpoint: {UdpClientSender.Client.LocalEndPoint}");
_logger.LogDebug($"({CurrentConnectionId}) Sending. RemoteEndpoint: {UdpClientSender.Client.RemoteEndPoint}");
UdpClientSender.Send(bytes, bytes.Length);
return Task.CompletedTask;
}
But response message doesn't reach client1.
I guess the problem lies in port translation. client1 sends message to port 13007 (which is proper port of client2 and that's why it is sent properly), but client2 receiving a message sees that it came from port 59464 and sends response there. Unfortunately I'm not really sure how to fix that. Any suggestions?

On the Server: Getting IP Address of Connected Clients

I've two machines: Server & Client
when I ask for the client ip in the client machine by
TcpClient client = new TcpClient();
client.Connect(serverip, PORTNO);
MessageBox.Show(client.Client.LocalEndPoint.ToString());
I get: 192.168.241.128:1025
It's the client ip.
but when I apply on the server the following:
_client = client;
_clientIP = client.Client.RemoteEndPoint.ToString();
AllClients.Add(_clientIP, this);
data = new byte[_client.ReceiveBufferSize];
_client.GetStream().BeginRead(data, 0, System.Convert.ToInt32(_client.ReceiveBufferSize), ReceiveMessage, null);
MessageBox.Show(client.Client.RemoteEndPoint.ToString());
I get 192.168.92.1:1047
which is the server ip!
What's the problem?
That happend to me one day...
the problem is using vmware!
when I tried to connect to a real network...I got the correct IP's
Try to do it with a real network!

How to send httpwebrequests through specific ip address

Yesterday, I've got mail, announcing tiny amazon EC2 instances being able to have up to 8 IP addresses.
Let's say, I'm running an application on one of the instances. I'm using httpwebrequest to access websites. How do I control, which IP the request goes from?
Taken from this question
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://stackoverflow.com");
req.ServicePoint.BindIPEndPointDelegate = delegate(
ServicePoint servicePoint,
IPEndPoint remoteEndPoint,
int retryCount) {
if (remoteEndPoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) {
return new IPEndPoint(IPAddress.IPv6Any, 0);
} else {
return new IPEndPoint(IPAddress.Any, 0);
}
};
Console.WriteLine(req.GetResponse().ResponseUri);

Categories