Home > Software design >  Connect to a remote endpoint using UDP Socket in Xamarin (C#) only works when activating a VPN
Connect to a remote endpoint using UDP Socket in Xamarin (C#) only works when activating a VPN

Time:11-30

I have a UDP Socket connection working between devices with local IPs (192.168.x.x), that I want to switch to a connection with an external server, with the following configuration:

Create socket

private Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
private const int bufSize = 4096 * 4;
private State state = new State();
private EndPoint epFrom = new IPEndPoint(IPAddress.Any, 0);
private AsyncCallback recv = null;
private static int PORT = 27000;

Openning device as a server to listen through the socket

_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
_socket.Bind(new IPEndPoint(IPAddress.Any, port));
Receive(); // Function to receive datagrams through the socket, irrelevant to this issue

Connect socket to remote endpoint

// {address:port} of an external server
_socket.Connect(new IPEndPoint(IPAddress.Parse(address), port));

Send data to socket

_socket.BeginSend(data, 0, data.Length, SocketFlags.None, (ar) =>
{
       try
       {
             _socket.EndSend(ar);
       }
       catch (Exception ex)
       {
             Console.WriteLine("[UDP] Error Send: "   ex.ToString());
       }
}, state);

The code above works fine for local IP addresses, the problem came when trying to use as a remote ip endpoint a public IP of a remote server.

The datagram seemed to be sent but it never arrived to the server. I tried to connect the phone to a VPN and the local IP changed from a 192.168.x.x to a 10.0.x.x, and then the connection to the external server worked.

Therefore, connection with an external IP only worked when the device's IP was a private IP of class A, but it didn't work with a class C range (https://www.meridianoutpost.com/resources/articles/IP-classes.php).

I want to find a solution to be able to connect to external IP address without having to connect a third party VPN software.

CodePudding user response:

If someone has the same question, I have already solved it.

To access external IPs with local class C IPs and no VPN you should do UDP hole punching instead of trying to establish a connection.

Erase the .Connect() and the .Bind() methods, and, instead of using BeginSend/EndSend, use the SendTo or SendToAsync methods with the server's public IP as the endpoint destination.

Additionally, I recommend changing:

SocketOptionName.ReuseAddress

to:

SocketOptionName.PacketInformation
  • Related