ntop / n2n

Peer-to-peer VPN
GNU General Public License v3.0
6.14k stars 928 forks source link

How to forward UDP multicast package? #1067

Open King-Of-Knights opened 1 year ago

King-Of-Knights commented 1 year ago

Hi, there! Thanks for the great work. With n2n 3.0, I played MineCraft with my friends those day and I find we cannot see other's room in multiple player mode. We could connect to each other via ip:port mode but I still want to dig out why is that. After doing some research, I have tried the following methods but no luck:

  1. Some people said we have to set lower metric for the TAP-adapter, I set it to 1 and so did my pal.
  2. The offical document said I should enable -E and I enable it both on my and my pal edge.
  3. Disable Windows 10 firewall for my and my pal edge. Besides, I can ensure that my and my pal connect via p2p mode.

On the technical side, a Minecraft client with an opened LAN game sends a UDP multicast to the local address 224.0.2.60:4445 every 1.5 seconds. Other clients then listen for this multicast to show your game in their multiplayer menu. I open the game and used python socket to bind it, I really obtain UDP multicast but my pal received nothing. Any ideas is appreciated!

I upload the python script so you guys can simply reproduce it Client:

import socket
import time

MCAST_GRP = '224.0.2.60'
MCAST_PORT = 4445

MULTICAST_TTL = 2

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)

while True:
    time.sleep(2)
    sock.sendto(b"[MOTD]Saber - \xe6\x96\xb0\xe7\x9a\x84\xe4\xb8\x96\xe7\x95\x8c[/MOTD][AD]20000[/AD]", (MCAST_GRP, MCAST_PORT))

After running this you will find a fake room in LAN mode.

Server:

import socket
import struct

MCAST_GRP = '224.0.2.60'
MCAST_PORT = 4445
IS_ALL_GROUPS = True

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if IS_ALL_GROUPS:
    # on this port, receives ALL multicast groups
    sock.bind(('', MCAST_PORT))
else:
    # on this port, listen ONLY to MCAST_GRP
    sock.bind((MCAST_GRP, MCAST_PORT))
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
print('Start!')

while True:
    print(sock.recv(10240))

This script could obtain game room information.

hamishcoleman commented 1 year ago

Firstly, thanks for a very clearly described problem and corresponding test scripts!

I use multicast with n2n (it is required for IPv6 to work properly) and the "-E" option is the one you need.

I used your test client script and used tshark to look at the packets it was sending. I immediately can see that it was sending the multicast packets out the default interface - not the n2n interface. This is actually the expected result.

The sender is simply using the routing table to reach the 224.0.2.60, so you can control this by adding a specific route. Eg (on linux):

ip route add 224.0.2.60 dev n2n0

The receiver needs to bind to a multicast interface - while some documentation talks about being able to use INADDR_ANY, I couldn't make that work when I tested.

your server needs both an ipaddr and to change the mreq contents

MCAST_IF = ipaddr_of_recving_interface_on_server
mreq = struct.pack("4s4s", socket.inet_aton(MCAST_GRP), socket.inet_aton(MCAST_IF))

Once I did this, I was able to see traffic across my n2n link.

This binding to the interface is pretty standard, so I would hope that the minecraft software actually finds the list of all interfaces and binds to them all - so you might be able to simply add a route and have things work.

King-Of-Knights commented 1 year ago

@hamishcoleman I could not believe such a quick and detail response, which really give me a warm hug in the cold day. OK, cut the crap, I am a user of window 10 and found some more interesting thing. Inspired by your advise, I immediately checked multicast join situation by using netsh interface ip show joins. I found the 224.0.2.60 has joined my default network adapter, just like what you said, but not the n2n adapter. The reason is that I have launched this game before I installed n2n. So the game choose to register this ip address on my default network adapter. However, remove and set udp multicast is not easy thing in Window 10. I have google a lot but the vaild method is just reset winsock by:

  1. Open CMD with Administrator privilege
  2. netsh int ip reset c:/reseting.txt
  3. netsh winsock reset
  4. restart your computer and set n2n adapter metric to 1 before your start the game
  5. launch the game and Minecraft will register 224.0.2.60 into n2n adapter and won‘t change later
  6. my friend are astonished and happy to see the room.

The main reason that n2n cannot forward minecraft is that n2n cannot modify the setting in Window 10 udp multicast. The 224.0.2.60 will be trapped in default network adapter if the user played the game before using n2n.

Suggestion: I am very expecting n2n V4.0 new feature. I found it not very difficult to modify udp multicast by using some .NetFrameWork API or winsock function, like 'DropMulticastGroup' or something like that. Also, any traffic hijack may help. I am not very familiar with n2n code so it up to you brilliant dev people. Maybe it could be added to n2n utility, so people can change it due their situation.

PS: N2N are developed to be most prevalent tools P2P game helper in China, like EasyN2N. Your decision will light P2P gamer's world!

Logan007 commented 1 year ago

-x ... was introduced to set interface metric on Windows and make it use n2n interface also for multicast as Windows seems to send broadcast/multicast only through the the interface with lowest metric.

King-Of-Knights commented 1 year ago

@Logan007 I think that's not very correct, in my case, Windows won't release udp multicast even you set a lower metric once it has been registered. So, we need to reset winsock and set n2n adapter a lower metric to get multicast high priority register next round. I think we need to design a function to change target multicast network device. -x is good to some game rely on LAN IP, like counter strike.

King-Of-Knights commented 1 year ago

@hamishcoleman @Logan007 OK, after hours research and experiments, I found something wired here.

Tips: you could use my server script in win10/11 to reproduce, the bind process will create 224.0.2.60.

Is that n2n bug or windows system feature? It will really confuse people whether -x really works.

Logan007 commented 1 year ago

I think I remember that Windows is known for using only the default network adapter (or what it thinks it is) for broadcast/multicast. So even without further research on this, I would blame it on the OS... ;)

King-Of-Knights commented 1 year ago

@Logan007 @hamishcoleman Thanks you guy for quick and patience response, though we missing one piece puzzle to the elegant solution(-x and -E covers everything), my case has been settled anyway. Again, thanks for your time, gentleman!

Logan007 commented 1 year ago

I agree and if you still see that issue on Windows happening, we should leave this issue open until someone comes up with a better idea or better working -x implementation, which by the way already is specific to Windows only.

King-Of-Knights commented 1 year ago

@Logan007 That cannot be better!