Talking to Roon from another VLAN (I got it working)

@Aaron_Turner when I start it manually it works. Well, it complains about missing arguments ofcourse, but it seems to work.

I had tried all again, and now I have a different error… Really sorry, it must be me being noobish at bsd :slight_smile:

Contents of the txt file:

The error I am now getting when trying to start the service:

Thanks again for all the help!

@Martin_Timmermans you get a different error when you run udp-proxy-2020 start is because you forgot service ... and thus calling the udp-proxy-2020 binary directly and not using the startup script.

Honestly, I downloaded my script again and tried it and it works for me. can you review the other steps listed and ensure they are completed correctly? I’ve reached out to some other pfSense users to see if they have any ideas what that error means.

FYI, the latest build for Roon (release yesterday) apparently has a fix for local zones not appearing on iOS devices. Dunno if that will help (or make things worse!) but might be worth looking into if you’re having problems.

@Aaron_Turner will this work if my roon server is on a subnet on a remote network (through a site-to-site VPN in pfsense) from the client?

Yes, but for a site-to-site VPN, you’ll need to run udp-proxy-2020 on both VPN endpoints.

I see. It’s through a wireguard VPN. Does that matter? Any disadvantage of running this at all?

I can’t think of any. Honestly I haven’t tried this specific configuration- but it should work like any other site to site config.

Got it. I was reading the github page for udp-proxy-2020 and if I understand it correctly the installation on pfsense is pretty much manual. I have two docker hosts in my network. Would using your docker container be a smarter/easier choice compared to installing manual stuff in pfsense that could be overwritten when there’s an update to the base software or something?

I run pfSense myself. I do not use Docker and don’t really recommend using Docker because it’s actually more complicated to setup & debug. FWIW, I don’t believe there is a Docker package for pfSense?

Anyways, multiple people have gotten it working using the docs provided. Feel free to ask questions if you run into trouble.

Yeah, there isn’t a docker container for pfsense. I just thought you can spin up a docker container on a docker host in your network and it “catches” the broadcast traffic and does the redirect through the pfsense gateway or something.

Anyway, I can try the manual installation on pfsense first, no problem. Does it get overwritten when pfsense gets updated to a newer version?

So based on the README, it says this:

--interface – Specify two or more network interfaces to listen on.

For my use case, does that mean I need to specify the WG interface (for each side) for my site to site link AND the LAN (for each side) where the roon server and clients are?

I now have udp-proxy-2020 running on both pfsense endpoints but when I try to search for my Roon Core from one machine in the remote site, I still can’t see it?

Contents of the conf file on the main site where the Roon Server is located at:

# change the port and add --interface {dev-name} as many times as needed.
udp_vars="--port 9003 --interface igb1.10,tun_wg0 --logfile /var/log/udp-proxy-2020.log"
  • igb1.10 is the interface of the subnet where the Roon Server is located at
  • tun_wg0 is the WG interface in the s2s link

Contents of the conf file on the main site where the Roon Client is located at:

# change the port and add --interface {dev-name} as many times as needed.
udp_vars="--port 9003 --interface igb1,tun_wg0 --logfile /var/log/udp-proxy-2020.log"
  • igb1 is the interface of the subnet where the Roon Client is located at
  • tun_wg0 is the WG interface in the s2s link

The services on both pfsense boxes are running as expected.

“can’t see it” meaning your client can’t see the Roon Core/Server or your Roon client doesn’t show up as a audio output device?

Anyways, the above seems correct. I assume your s2s vpn routes are working and you verified that udp-proxy-2020 was actually running?

So the standard debug process is:

  1. Fully quit Roon on the client (it’s important it is not running in the background, especially if running n a phone/tablet)
  2. Add --pcap --pcap-dir=/root to the udp-proxy-2020 options restart udp-proxy-2020. You’ll want to do this on BOTH pfSense boxes.
  3. Start the Roon client
  4. Wait 30sec
  5. zip the *.pcap files in the /root directory and open a ticket here and attach both zip files to the ticket: Sign in to GitHub · GitHub

Afterwords, I recommend stopping udp-proxy-2020 just so it doesn’t keep writing to those files and potentially fill up your disk.

My client can’t see the Roon Core so it goes without saying that the Roon Client is also not showing as an audio output device in the Core settings section.

Yes, routing from the LAN subnets of both sides is working perfectly. And yes, the udp-proxy-2020 service is running on both sides.

Here you go: Roon client cannot see roon core through a wireguard tunnel using udp-proxy-2020 on both vpn endpoints · Issue #99 · synfinatic/udp-proxy-2020 · GitHub

P.S. It’s supposed to be --pcap-path and not --pcap-dir.

Thanks for this! I’ve installed it on my pfSense box and using OpenVPN. The instructions were perfect, and easy to follow - I can now see Roon and more importantly stream on my Android phone remotely.

I couldn’t get it working with Tailscale (front end to wireguard) though this is probably my configuration.

Great job!

you got Tailscale running on pfSense??? I’m actually really curious to hear more about this. :slight_smile:

Also, I don’t believe it will work with Tailscale because their mesh network topology breaks broadcast messages which Roon relies on. At least I’ve never gotten it to work and nobody on the Tailscale forum tells me otherwise. Works fine with Wireguard though.

I hope I’m not necroing a thread. But I thought it would be helpful to have this config under the same topic. I have a slightly different configuration at home with my multi VLAN network. I’m using a /20 at home and the RoonCore (docker container) is running on 10.0.10.110. I have the 10.0.0.0/24 (wired) and 10.0.2.0/24 (wireless). I’m not using pfSense as the Layer 3 device between VLANs. I’m using a Cisco switch (3750) for that. At first, I setup mDNS rebroadcasting on the switch to re-broadcast mDNS traffic between certain VLANs. I went with a “nuke it from orbit” config on the switch for that:

service-list mdns-sd PERMIT-ALL permit 10
service-routing mdns-sd

interface Vlan10
 description Home LAN
 ip address 10.0.0.1 255.255.255.0
 ip pim sparse-dense-mode
 service-routing mdns-sd
  service-policy PERMIT-ALL IN
  service-policy PERMIT-ALL OUT
  redistribute mdns-sd

interface Vlan12
 description Home WLAN
 ip address 10.0.2.1 255.255.255.0
 ip helper-address 10.0.10.255 
 ip pim sparse-dense-mode
 service-routing mdns-sd
  service-policy PERMIT-ALL IN
  service-policy PERMIT-ALL OUT
  redistribute mdns-sd

interface Vlan19
 description Home Media
 ip address 10.0.9.1 255.255.255.0
 ip pim sparse-dense-mode
 service-routing mdns-sd
  service-policy PERMIT-ALL IN
  service-policy PERMIT-ALL OUT
  redistribute mdns-sd

interface Vlan20
 description Home Server
 ip address 10.0.10.1 255.255.255.0
 ip pim sparse-dense-mode
 service-routing mdns-sd
  service-policy PERMIT-ALL IN
  service-policy PERMIT-ALL OUT
  redistribute mdns-sd

Unfortunately, Roon doesn’t use blanket multicast for all devices (for some unknown, horrible reason). It does seem to utilize multicast for Chromecast devices (and maybe AirPlay?) So, to get this working (along with a Linux laptop running Roon Bridge, which is also running firewalld), I needed to find out the ports that Roon uses, which seems to have changed over the different versions. If there’s a single place that has all the port requirements, I haven’t found it. It is absolutely essential that this info is published. For my Roon 2.0 (CORE Build 1193, Linux Bridge 1.8 Build 125, Android 2.0 Build 1192) it appears that Roon (of various types above) send to the subnet’s broadcast address on the destination port 9003. On the Cisco switch, I had to enable a combo of ip helper-address, ip forward-protocol (with an accompanying extended ACL) and ip directed-broadcast (with that same ACL). Below is the complete config combining the above and the new commands:

service-list mdns-sd PERMIT-ALL permit 10
service-routing mdns-sd

ip forward-protocol udp 9003

#Roon Server IP is 10.0.10.110)
access-list 100 permit udp host 10.0.10.110 any eq 9003

interface Vlan10
 description Home LAN
 ip address 10.0.0.1 255.255.255.0
 ip helper-address 10.0.10.255 
 ip directed-broadcast 101
 ip pim sparse-dense-mode
 service-routing mdns-sd
  service-policy PERMIT-ALL IN
  service-policy PERMIT-ALL OUT
  redistribute mdns-sd

interface Vlan12
 description Home WLAN
 ip address 10.0.2.1 255.255.255.0
 ip helper-address 10.0.10.255 
 ip directed-broadcast 101
 ip pim sparse-dense-mode
 service-routing mdns-sd
  service-policy PERMIT-ALL IN
  service-policy PERMIT-ALL OUT
  redistribute mdns-sd

interface Vlan20
 description Home Server
 ip address 10.0.10.1 255.255.255.0
 ip helper-address 10.0.0.255 
 ip helper-address 10.0.2.255 
 ip directed-broadcast 101
 ip pim sparse-dense-mode
 service-routing mdns-sd
  service-policy PERMIT-ALL IN
  service-policy PERMIT-ALL OUT
  redistribute mdns-sd

The above config is saying we’ll allow broadcasts on UDP 9003 (forward command). We then create an ACL for allowing the Roon Server to talk to anything on 9003/UDP We then apply that directed broadcast command on each VLAN interface and telling it to use the ACL 100 we created above. Next, we have to tell each interface where it’s allowed to send it’s broadcasts (the destination of the broadcasts). On the SERVER VLAN (where Roon lives) we tell it that it can broadcast into the WIRED and WIRELESS VLANs. Since the ROON BRIDGE and other ROON CAPABLE devices can also broadcast, we go the WIRED and WIRELESS VLANs and tell them that they can broadcast back into the SERVER VLAN. This is accomplished with the IP HELPER-ADDRESS command pointing to the BROADCAST address of the /24 network (10.0.0.255 or 10.0.2.255 or 10.0.10.255).

After doing all this, I now no longer have to put in the Roon Core IP address in all my computer end points. It just shows up automagically. However, there were still some issues WRT firewalld and opening ports. Long story short, here are the ports I had to open just for other Roon devices (my Android phone for example) to even see the Roon Bridge I installed on my Arch laptop:

sudo firewall-cmd --permanent --new-service=RoonBridge
sudo firewall-cmd --permanent --service=RoonBridge --set-description=Inbound from RoonServer
sudo firewall-cmd --permanent --service=RoonBridge --set-short=SVC_IN_RoonBridge
sudo firewall-cmd --permanent --service=RoonBridge --add-port=9100-9200/tcp
sudo firewall-cmd --permanent --service=RoonBridge --add-port=9330-9332/tcp
sudo firewall-cmd --permanent --service=RoonBridge --add-port=9003/udp
sudo firewall-cmd --permanent --service=RoonBridge --add-port=1900/udp
sudo firewall-cmd --permanent --service=RoonBridge --add-protocol=igmp
sudo firewall-cmd --permanent --zone=home --add-rich-rule='   rule family="ipv4"   source address="10.0.10.110/32"   port protocol="tcp" accept'
sudo firewall-cmd --permanent --zone=home --add-service=RoonBridge
sudo firewall-cmd --reload

Even after these commands were added, and the Roon Bridge was now visible, I still couldn’t enable my DAC. Using the app on my phone to enable the DAC, the field was stuck on “Enabling” and not letting me enter a name for the DAC. After setting firewalld to log all denies and searching the journalctl for anything from the IP of my Android phone, I found that Roon on the phone (and presumably other devices) will use a random high numbered port to name the DAC. Once I enabled that port, the naming field immediately became available and writeable. I will be honest that I didn’t look through a pcap on my laptop for that port number listed in the INFO of a packet coming in on a broadcast or another packet. My point here is, how does Roon Remote (Android) tell the Bridge what port to listen on for the device rename? Why is this not an API on one of the already known ports? Or why doesn’t RoonBridge “open” this port on the firewall (using info gathered from other established states) by implementing a source IP and port / dest IP and port reversal so the state is already open on the local firewall?

Don’t get my started on the whole “Roon uses UDP to send audio traffic” thing.

“I’d tell you a UDP joke, but you probably wouldn’t get it.”

If there’s anything I missed or got wrong, please let me know. Thank you!!

Using a Cisco L3 switch??? Oh man, you do like making it hard.

I’ll be honest, been a few decades since I touched Cisco switches… I sure as heck don’t know modern IOS. I might sorta remember the old Catalyst switches though :smiley:

Anyways, to get this to work, you have to remember the Roon Client sends the first UDP/9003 broadcast discovery packet- not the core. So just allowing the core to send traffic on that won’t work.

Since you’re clearly networking savvy, might I suggest you download Wireshark 4.x??? I wrote a protocol dissector for the Roon discovery protocol and it will not doubt help you visualize what is going on and what you need to forward.

@Aaron_Turner In the post I show that I did get this working. I wanted to get all the data out there so that other users would have it in case they went the same route.

I should have looked at the Wireshark capture I was running more closely. The issue is that Wireshark was only capturing what firewalld was letting through, not what was hitting the interface. That being said, the config I posted is working. I could try getting rid of the server VLAN config.