C# UDP client reading multicast IP (local interface), and sending unicast UDP to VPN
Asked Answered
V

1

10

I have a VPN client that works fine for sending unicast UDP packets over the VPN pipe but does not do that for multicast IP (UDP) packets (OpenVPN). So I thought I could write this little shim that would take the IP (port 3000) multicast and send them over the VPN as unicast.

I see the multicast packets arriving, but I see nothing arriving on the VPN side (WireShark is not helping, since unlike IpConfig /all) it does not see the VPN interface.).

I think my issue might be I am not really clear on the difference between BIND and CONNECT, and which interface (vpn or local) I should be binding the UDPClient to.

The command line is:

239.0.0.0 198.168.0.15 10.4.30.239 172.27.225.77
arg[0] = multicast from address
arg[1] = unicast to address
arg[2] = local physical ethernet assigned address
arg[3] = virtual address of computer on VPN network (client)

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace MUTunnel
{
    public class EchoBot
    {
        protected UdpClient sender;
        protected UdpClient listener;

        protected const int listenPort = 3000;
        protected const int outPort = 3000;

        protected IPEndPoint inPoint;
        protected IPEndPoint outPoint;
        protected IPAddress listenAddress;
        protected IPAddress sendAddress;
        protected IPAddress localAddress;
        protected IPAddress vpnAddress;

        public EchoBot(string from, string to, string local, string vpn)
        {
            bool parsed = IPAddress.TryParse(from, out listenAddress);
            parsed = IPAddress.TryParse(to, out sendAddress) && parsed;
            parsed = IPAddress.TryParse(local, out localAddress) && parsed;
            parsed = IPAddress.TryParse(vpn, out vpnAddress) && parsed;
            if (!parsed)
            {
                System.Console.WriteLine("Usage: MUTunnel <source multicast IP> <dest unicast IP> <local host IP address> <vpn IP address>");
                Environment.Exit(1);
            }
            listener = new UdpClient();
            listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            inPoint = new IPEndPoint(localAddress, listenPort);
            listener.Client.Bind(inPoint);
            listener.JoinMulticastGroup(listenAddress);

            sender = new UdpClient();
            sender.Ttl = 64;
            sender.AllowNatTraversal(true);
            //outPoint = new IPEndPoint(sendAddress, outPort);
            sender.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            sender.Connect(sendAddress, outPort);
        }

        public void send(byte[] bytes)
        {
            sender.Send(bytes, bytes.Length);
        }
        public void loop()
        {
            bool done = false;
            try
            {
                while (!done)
                {
                    byte[] bytes = listener.Receive(ref inPoint);
                    Console.WriteLine("Received Multicast from  {0} : length {1}\n", listenAddress.ToString(), bytes.Length);
                    this.send(bytes);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            finally
            {
                listener.Close();
                sender.Close();
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 4)
            {
                System.Console.WriteLine("Usage: MUTunnel <source multicast IP> <dest unicast IP> <local host IP address> <vpn IP address>");
                Environment.Exit(1);
            }
            EchoBot echoBot = new EchoBot(args[0], args[1], args[2], args[3]);
            Console.WriteLine("MUTunnel Waiting for messsages...");
            echoBot.loop();
        }
    }
}

The ipconfig /all reads as follows (when OpenVPN client is running)

P:\>ipconfig /all

Windows IP Configuration

   Host Name . . . . . . . . . . . . : YSG4206
   Primary Dns Suffix  . . . . . . . : draper.com
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : draper.com

Ethernet adapter Ethernet 3:

   Connection-specific DNS Suffix  . : draper.com
   Description . . . . . . . . . . . : Killer E2200 Gigabit Ethernet Controller
   Physical Address. . . . . . . . . : F8-B1-56-FF-8B-36
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   IPv4 Address. . . . . . . . . . . : 10.4.30.239(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.254.0
   Lease Obtained. . . . . . . . . . : Monday, June 18, 2018 5:28:03 PM
   Lease Expires . . . . . . . . . . : Thursday, June 21, 2018 8:46:50 PM
   Default Gateway . . . . . . . . . : 10.4.31.254
   DHCP Server . . . . . . . . . . . : 140.102.100.111
   DNS Servers . . . . . . . . . . . : 10.10.20.11
                                       10.10.20.12
   NetBIOS over Tcpip. . . . . . . . : Enabled

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : TAP Adapter OAS NDIS 6.0
   Physical Address. . . . . . . . . : 00-FF-91-E7-8A-38
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   IPv4 Address. . . . . . . . . . . : 172.27.225.77(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . :
   NetBIOS over Tcpip. . . . . . . . : Enabled

P:\>

Update

Added sender.Ttl = 64; sender.AllowNatTraversal(true); also ran the RawCap on the client with the VPN interface selected. The Dump of packets does not show of the multicast packets that I am converting to unicast and trying to send to 129.168.0.15 coming to that interface.

just some other stuff. (see wireshark display of the .pccap file from RawCap.

enter image description here

Vidicon answered 11/6, 2018 at 15:27 Comment(16)
Bind locally, Connect remotely. Your use of bind/connect seems fine. You read in the vpnaddress but never use it for anything, though?Declaration
@NickDechiara yes. I tried to bind it the local VPN address (as reported by IPConifg) but that throws an error. I have seen others just Connect the UDP client and that alone seems to work for them. But I do have two interfaces.Vidicon
You are really seeing your "Received Multicast from .." message? On windows, I think you can only bind the listener to any address (0.0.0.0) and get multicast, any other OS you could choose to instead bind with the multicast address to avoid unrelated traffic.Mieshamiett
Yes. I see the "Received Multicast from .." message. Yes, the contents are what is to be expected. No Wireshark does not see the VPN interface on the client, so I can't tell if the UDP unicast is leaving. I do see that nothing arrives at the VPN server (at least tcpdump does not see it).Vidicon
sender.Ttl = 16; looks a bit strict; what happens if you increase it, e.g. to 255? I mean it sounds like you're having trouble with packets mysteriously disappearing, and .Ttl's job is to specify how many hops a packet can take before it can just be discarded. 16 hops is unusually low (at least going by Wikipedia's cited recommendation of starting with a default of 64), and presumably using a VPN's adding more hops into the pathway.Deferred
I am only two hops away.Vidicon
Look at using [RawCap][1] to capture the VPN traffic. It captures at a different layer on the network stack and captures localhost traffic. It should allow you to capture VPN traffic also. [1]: netresec.com/?page=RawCapStays
The address used in sender.Connect(sendAddress, outPort); must be the VPN destination address. Not sure if your 172.27.225.77 is the From or To addressShondrashone
As per the UDCClient() docs: The UDP protocol is connectionless, the Connect method does not block. Are you sure you are connecting?Semiskilled
As shown above the physical interface is the 10.4 net, the 172.27.225.77 is the openvpn gateway. The openvpn is passing tcp data with no problems.Vidicon
Yea udp is connectionless. But the api asks to connect(). No errors, but no good way of knowing if it did anything.Vidicon
Have you tried testing on the local network to ensure the upd unicast works before you moved it over the VPN?Semiskilled
@Vidicon a shot in the dark here, but try writing this without using Connect (e.g. remove that line and change the send function to use the IP and port directly). I've been running this over in my head for a while and I think that's the first thing I would try.Declaration
If I try to do the .send() when I don't connect I get the error: + e {"The operation is not allowed on non-connected sockets."} System.Exception {System.InvalidOperationException}Vidicon
If you comment out the connect() you then need to use the overloaded Send(Byte[], Int32, IPEndPoint) method. msdn.microsoft.com/en-us/library/82dxxas0(v=vs.110).aspxSemiskilled
Ok, I can now send without the connect. What I am seeing is now the multicast is reporting two receives (it used to get one every 5 seconds, now it gets 2 at the 5 second heartbeat). RawCAP is still saying nothing is going out. And the other end of the VPN also shows nothing. (tcpdump eni any udp)Vidicon
S
0

I suspect you don't have anything listening to the other end of your unicast.

Unicast is the term used to describe communication where a piece of information is sent from one point to another point. In this case there is just one sender, and one receiver.

I added an additional listener to listen to the send endpoint and everything works and will print out the sent message.

Additional listener run on the computer with the ip: 198.168.0.15

IPAddress localAddress = IPAddress.Parse("198.168.0.15");
const int listenPort = 3000;

var listener = new UdpClient();
listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
var inPoint = new IPEndPoint(localAddress, listenPort);

listener.Client.Bind(inPoint);

while (true)
{
    byte[] bytes = listener.Receive(ref inPoint);
    Console.WriteLine("Received Message from  {0} : message {1}\n", localAddress.ToString(),Encoding.ASCII.GetString(bytes));
    Thread.Sleep(1000);
}
Semiskilled answered 20/6, 2018 at 19:44 Comment(7)
I do have a listener. I should also be seeing the packets arrive at the target via TCP dump (since it a Centos computer). The listener works for all traffic originating in the private cloud. What I am trying to do is get it to work for stuff coming over the VPN.Vidicon
Can you ping that centOS computer over the vpn? Can you ssh into that computer over the vpn at that IP?Semiskilled
Also have you tried enabling sender.AllowNatTraversal = true; msdn.microsoft.com/en-us/library/…Semiskilled
Are you sure this is not a network / VPN configuration issue? serverfault.com/questions/608517/…Semiskilled
Not sure if it is not a VPN config error. But see my latest additions to the note (I added sender.AllowNatTransversal. As well as the results of the RawCAPVidicon
Are you able to ping or ssh into that centos machine (over the vpn)?Semiskilled
Yes, I can ping, also the OpenVPN is working fine for connecting to all the machines beyond the OpenVPN server (AS) that are on that subnet inside the cloud (at least for the TCP and unicast UDP that I have going from programs other than the one shown above which is trying to ship the multicast).Vidicon

© 2022 - 2024 — McMap. All rights reserved.