9
votes

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

1
Bind locally, Connect remotely. Your use of bind/connect seems fine. You read in the vpnaddress but never use it for anything, though?N.D.C.
@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.Dr.YSG
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.lossleader
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).Dr.YSG
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.Nat

1 Answers

0
votes

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);
}