Can't seem to reach UDP app

I’m attempting to run a server that uses UDP protocol, more specifically Minecraft Bedrock’s server. My fly.toml looks like this:

[build]
  image = "itzg/minecraft-bedrock-server"
[[services]]
  internal_port = 19132
  protocol = "udp"

[services.concurrency]
  hard_limit = 1
  soft_limit = 1
  type = "connections"

[[services.ports]]
  port = "10000"

[[services]]
  internal_port = 19133
  protocol = "udp"

[services.concurrency]
  hard_limit = 1
  soft_limit = 1
  type = "connections"

[[services.ports]]
  port = "10001"

[mounts]
  source="mc_volume"
  destination="/data"

My problem is that I cannot seem to reach the server whether I use the 10000 (internal 19132 IPv4) or 10001 (internal 19133 IPv6). I can’t find more info on which settings to modify so I’m recurring to the forum.

I also attempted to connect directly with the IP addresses to no avail.

Which IP address is the server listening on? There’s a special IP for UDP in your VMs, you can sometimes listen on the fly-global-services IP, sometimes you need to resolve it in a script and use the IP directly. Alternatively, you can listen on :: and it should work fine.

@michael was experimenting with a Minecraft server so he might have the magic incantation to make it work.

1 Like

Sadly I think the image I’m using doesn’t let you specify which IP to listen on. Or maybe I’m misunderstanding what you’re referring to?

I managed to get this working with the same image but the bedrock server didn’t make it easy.

There seems to be an issue with the server’s netcode library. UDP connections over anycast (your app’s app-name.fly.dev hostname or ipv4/v6) reach the server but responses aren’t being sent to the right socket. There’s a related issue in that image’s repo, and @Thomas, who wrote our UDP code, told me this when I tried this after we rolled out UDP:

the problem will be that by default, vanilla socket code will use the kernel’s default source address selection for response packets
because udp is stateless, so the kernel doesn’t know when you call sendto that it’s a reply to a packet that arrived on some other address

It does work if we skip anycast and go straight to the VM though…

First, grab the VM’s IP with flyctl ips private Then put that into Minecraft and use port 19133 for ipv6 (instead of 19132 for v4) and you should be able to connect.

You’ll also need to add this in your fly.toml file to allow access to that port:

[experimental]
allowed_public_ports = [ 19133 ]

I don’t have time now, but I think running a UDP proxy in the VM alongside the bedrock server might get anycast working.

Edit: I forgot to mention you’ll need to have wireguard on to use the private network. I also needed to use the IPv6 address directly rather than the app-name.internal address because Minecraft kept saying app-name.internal was an invalid hostname.

Thanks! Some of it went over my head but I think I understand a bit more how fly works under the hood. I’ll try to experiment with an UDP proxy later.