Giter Club home page Giter Club logo

udp-proxy-2020's Introduction

udp-proxy-2020

A crappy UDP router for the year 2020 and beyond.

About

What is this for?

So I'm playing with Roon and I've got this complicated home network that throws Roon for a loop. I started debugging things and it turns out Roon sends broadcast messages to UDP/9003. My firewall/router will not forward these messages of course, because that's the right thing to do.

Unfortunately, I really want these broadcast messages to be forwarded to other VLAN/subnets on my local network. I started using udp-proxy-relay-redux which worked great at first.

But I also really like these messages forwarded over my OpenVPN connections which utilize the tun driver which is a point-to-point interface and explicity does not support broadcasts. This didn't work well with udp-proxy-relay-redux because Roon is poorly behaved and still tries sending "broadcasts" to the .255 address which are then dropped on the floor because my VPN server does not have the address x.x.x.255. Basically, on a point-to-point interface, these "broadcasts" were being treated as a packet destined to another host and rightfully ignored.

So what does this do?

Instead of using a normal UDP socket to listen for broadcast messages, udp-proxy-2020 uses libpcap to "sniff" the UDP broadcast messages. This means it can be a lot more flexible about what packets it "sees" so it can then sends them via libpcap/packet injection out all the other configured interfaces. If this makes you go "ew", well, welcome to 2020.

The good news...

I'm writing this in GoLang so at least cross compiling onto your random Linux/FreeBSD router/firewall is reasonably easy. No ugly cross-compling C or trying to install Python/Ruby and a bunch of libraries.

Also: HAHAHAHAHAHAHA! None of that is true! Needing to use libpcap means I have to cross compile using CGO because gopacket/pcapgo only supports Linux for reading & writing to (ethernet?) network interfaces.

Installation & Startup Scripts

Pretty much any Unix-like system is supported because the dependcy list is only libpcap and golang. I develop on MacOS and specifically target pfSense/FreeBSD and Ubiquiti USG, EdgeRouter and DreamMachine/Pro as those are quite common among the Roon user community.

Packages

If you are using a Linux RedHat or Debian based distro, the easiest way to install is grab the appropriate .rpm or .deb file and install it with your package manager. Then edit /etc/udp-proxy-2020.conf and start via: systemctl start udp-proxy-2020.

Docker

There is also a docker image available for Linux on AMD64 and ARM64 (like the Ubiquiti UDM).

Note that for Docker deployments, you should be using host networking.

Manual

I release binaries for Linux, FreeBSD (pfSense) and MacOS for Intel, ARM and MIPS hardware.

There are now instructions and startup scripts available in the startup-scripts directory. If you figure out how to add support for another platform, please send me a pull request!

Usage

Configuration

Run udp-proxy-2020 --help for a current list of command line options.
Also, please note on many operating systems you will need to run it as the root user. Linux systems can optionally grant the CAP_NET_RAW capability.

Currently there are only a few flags you probaly need to worry about:

  • --interface -- Specify two or more network interfaces to listen on.
  • --port -- Specify one or more UDP ports to monitor.
  • --level -- Specify the log level: [trace|debug|warn|info|error]

Advanced options:

  • --fixed-ip -- Hardcode an @ to always send traffic to. Useful for things like OpenVPN in site-to-site mode.
  • --timeout -- Number of ms for pcap timeout value. (default is 250ms)
  • --cache-ttl -- Number of minutes to cache IPs for. (default is 180min / 3hrs) This value may need to be increased if you have problems passing traffic to clients on OpenVPN tunnels if you can't use --fixed-ip because clients don't have a fixed ip.
  • --no-listen -- Do not listen on the specified UDP port(s) to avoid conflicts
  • --deliver-local -- Deliver packets locally on loopback interface

There are other flags of course, run ./udp-proxy-2020 --help for a full list.

Example:

udp-proxy-2020 --port 9003 --interface eth0,eth0.100,eth1,tun0 --cache-ttl 300

Would forward udp/9003 packets on four interfaces: eth0, eth1, VLAN100 on eth0 and tun0. Client IP's on tun0 would be remembered for 5 minutes once they are learned.

Note: "learning" requires the client to send a udp/9003 message first! If your application requires a message to be sent to the client first, then you would need to specify --fixed-ip=1.2.3.4@tun0 where 1.2.3.4 is the IP address of the client on tun0.

Using udp-proxy-2020 with VPNs

I have tested both "road warrior" VPN configs with Roon client running on my laptop and connecting back to my home firewall via OpenVPN and Wireguard. I personally use Wireguard instead of OpenVPN because it is more secure and has better performance.

I've also tested Site-to-Site VPN using Wireguard + pfSense. I followed the pfSense site-to-site Wireguard VPN directions and installed udp-proxy-2020 on both firewalls. You must configure the --interface option to include both the LAN and Wireguard network interfaces.

Building udp-proxy-2020

If you are building for the same platform you intend to run udp-proxy-2020 then you just need to make sure you have libpcap and the necessary headers (you may need a -dev package for that) and run make or gmake as appropriate (we need GNU Make, not BSD Make).

If you need to build cross platform, then one of the following targets may help you:

  • Linux on x86_64 make linux-amd64 via Docker
  • Linux on MIPS64 make linux-mips64 (Linux/MIPS64 big-endian for Ubiquiti USG/EdgeRouter) via Docker
  • Linux on ARM make linux-arm via Docker:
    • Linux on ARM64 for Ubiquiti UDM/UDM Pro
    • Linux on ARMv5 (software floating point)
    • Linux on ARMv6 (hardware floating point)
    • Linux on ARMv7 (hardware floating point)
  • FreeBSD 12.3 on x86_64, ARM64//v7 make freebsd (pfSense 2.6) via Vagrant & VirtualBox
  • Docker image to run udp-proxy-2020 in docker make docker

You can get a full list of make targets and basic info about them by running: make help.

FAQ

When should I use --no-listen?

Starting with v0.0.11, udp-proxy-2020 now by default creates a UDP listening socket on the specified --port(s). This prevents the underlying OS from issuing ICMP Port Unreachable messages which can break certain clients (noteably the Roon iOS client).

The only time you should need to use the --no-listen flag is if there is another piece of software that is running on the same host as udp-proxy-2020.

Does udp-proxy-2020 support running on the same host as Roon/etc?

As of v0.1.0, yes. You need to specify --deliver-local and --no-listen options so that it delivers packets via the loopback interface.

When should I use --pcap and --pcap-path?

These flags are for debugging problems with udp-proxy-2020. You should use these flags when I direct you to do so as part of a ticket you have opened for udp-proxy-2020.

Where can I download precompiled binaries?

From the releases page on Github.

So is it a "proxy"? Are there any proxy config settings I need to configure in my app?

Nope, it's not a proxy. It's more like a router. You don't need to make any changes other than running it on your home router/firewall.

Then why did you call it udp-proxy-2020?

Honestly, I didn't really think much about the name and this was the first thing that came to my mind. Also, naming is hard.

What network interface types are supported?

  • Ethernet
  • WiFi interfaces which appear as Ethernet
  • tun interfaces, like those used by OpenVPN
  • raw interfaces, like those used by Wireguard
  • vti interfaces for site-to-site IPSec

Note that L2TP VPN tunnels on Linux are not compatible with udp-proxy-2020 because the Linux kernel exposes those interfaces as Linux SLL which does not provide an accurate decode of the packets.

How can I get udp-proxy-2020 working with Wireguard on Ubiquiti USG?

So I haven't done this myself, but Bart Verhoeven over on the Roon Community forums wrote up this really detailed how to.

What binary is right for me?

udp-proxy-2020 is built for multiple OS and hardware platforms:

  • MacOS/Intel x86_64: darwin-amd64
  • Linux/Intel x86_64: linux-amd64
  • Linux/ARM64: linux-arm64 (RasPi 2 V1.2 and above, Ubiquiti UniFi Dream Machine)
  • Linux/ARMv7 (hardware floating point): linux-armv7 (RasPi 2 V1.1 and below)
  • Linux/ARMv6 (hardware floating point): linux-armv6
  • Linux/ARMv5 (software floating point): linux-armv5
  • Linux/MIPS64: linux-mips64 (Ubiquiti USG/EdgeRouter)
  • FreeBSD/Intel x86_64: freebsd-amd64 (works with pfSense on x86)
  • FreeBSD/ARMv8: freebsd-arm64 (Netgate SG-1100 & SG-2100)
  • FreeBSD/ARMv7: freebsd-armv7 (Netgate SG-3100)

How can I say thanks?

Honestly, just send me an email saying thanks or "star" this project in GitHub is enough thanks.

Occasionally, someone will ask about giving me a few bucks, but I really don't need any money. If you still would like to throw a few bucks my way, I'd much rather you donate to Second Harvest Food Bank which is local to me and could put your money to better work than I would.

udp-proxy-2020's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

udp-proxy-2020's Issues

Add support for site-to-site OpenVPN tunnels

We can't rely on udp-proxy-2020's auto-learn functionality with site-to-site VPN's because the client/initiator side must have it's packets forwarded over the point-to-point VPN tunnel before we can learn. Ideally, we should use some kind of POSIX API call to figure out the IP address or something of the other end, but for initial testing purposes I guess we can just have the user specify an IP address?

iPhone not appearing as audio zone

Hi Aaron,

Thanks for taking the time to take a look! As far as I can tell, everything seems to be running udp-proxy-2020 service is running, I can ping my iPhone from the wireguard machine when it's connected via VPN. A few more notes:

  1. Wireguard and udp-proxy-2020 are running on a Raspberry Pi 4. Appears in pcap logs as wireguard.udm-local (local IP 10.0.1.112)
  2. Roon Rock (dedicated NUC) appears in logs as rock.udm-local (local IP 10.0.1.25)
  3. Router is 10.0.1.1 (different from the wireguard machine, but needed wireguard port forwarding rules are already in place)
  4. UDP-proxy version is udp-proxy-2020-0.0.11-linux-armv7
  5. UDP-proxy is started via systemd script with: /usr/bin/udp-proxy-2020-0.0.11-linux-armv7 --port 9003 --interface eth0,wg0 --cache-ttl 500 --pcap --pcap-path /home/pi/udp/logs
  6. systemctl status shows no errors
  7. no difference when using --no-listen flag
  8. iphone connects to Wireguard VPN, and I can access Roon (as well as other local resources). The iPhone just doesn't show as an audio zone.

I've included logs with this ticket. Please let me know if anything obvious jumps out at you.

Also, based on some other comments, I was under the impression that ump-proxy-2020 does work with a dedicated Roon Rock install like I have (with wireguard installed on a separate device), but if that's not the case, then please let me know.

Again, very much appreciate you taking a quick look.

-Greg W
Archive.zip
Screen Shot 2022-05-01 at 8 17 50 PM

Write logs to a file

Generally improve logging and support writing logs directly to a file.

Specifically, there seems to be some bug which causes a crash? seems to happen quite rarely though.

Learn clients on Loopback interfaces

On Loopback/Null interfaces, we can't use a broadcast address, but we still don't want to require users to specify the IP address on the CLI. The solution would be to automatically learn the source IP of packets we receive and then send those IP's any packets received on a different interface.

Have to figure out a timeout? Unlike mulitcast/IGMP, clients do not ever "leave". Also, I don't think we'd receive an ICMP host-unreachable error? If so, that would be nice??

rename --listen and --promisc

The existing flags are probably confusing for non-technical people. In reality, they're more about what kind of interface you're using so it would be more like --ethernet and --loopback

Add --daemon flag / pid file

Would be nice if udp-proxy-2020 supported running as a daemon and writing a pid file to /var/run/udp-proxy-2020.pid or other user defined path.

udp-proxy-2020 on Raspberry

Dear all
I installed udp-proxy-2020 on a Raspberry 4 (hopefuly correctly) according the guide.
If I ask for the status I get an error like this:

image

What do I have to do?
P.S. How can I exit the window after receicving this message?
Thanks a lot.

Downlaod of Docker image fails

Dear all
I am trying to install the docker image on my Synology.
After choosing "latest" the downlaod alwas fails.
What could be the reason?

test longer timeout for VPN tunnels

I think one of the reasons Roon on the iPhone tends to have issues is the timeout in udp-proxy-2020 is too short. maybe it should be much longer or never expire until it is over written? Should do more testing.

Compile version for UDM/UDMP

Could someone help me to compile a version for the UDM/UDMP, would be great. The version for the USG does not work

Figure out & fix the LinkLayer issue with Raw

The whole thing about Raw interfaces is because LinkLayer for RAW is 101, but calling pcap.Handle.LinkType() returns the DLT not the LinkType! The result is for Raw interfaces you get either 12 or 14 (depending on OS) instead of 101 which causes nothing but pain. :-/

Armv7 Release

Would love to try this out! I'm attempting to access PS Remote play via the internet behind a double NAT. So I'd like to do port forwarding through zerotier or tailscale on a intranet device that would relay the packets to the playstation and back.

Unfortunately, I only have a raspberry pi to work with as my relay device. Any chance you could do an armv7 release?

"Address family not supported by protocol family"

Should dig into this error a bit:

level=warning msg="Unable to send 130 bytes from ovpns6 out tun_wg0: send: Address family not supported by protocol family"

and:

level=warning msg="Unable to send 387 bytes from lagg0.500 out tun_wg0: send: Address family not supported by protocol family"

No audio devices / zones found unless pfsense service is stoped and started

Hey,

Tkronic from the roon forums here. As the title says, roon does not find any audio zones / devices unless i stop and restart the service. After I have done this, the zones stay up and controllable until the device shuts down / disconnects from network. If I leave my desktop where I primarily listen to music at home on 24/7 it is not an issue. When I turn it off or suspend it, I need to access pfsense and stop and start the service. OpenVPN with my phone is not as convenient. I believe openVPN disconnects when the phone is idle / screen off for any significant amount of time. This means, every time I want to listen to Roon on my phone, i need to access pfsense and run the stop start commands.

Note: the phone connects to my core (ROCK on a VM) just fine, it just does not see it as a playable / stream able audio device / zone.

Please let me know what logs I can send, or additional information I can provide that can be of use.

Thanks so much again.

Docker compose Roon, udp-proxy-2020 and OpenVPN

Basically, provide a single docker-compose.yaml file for running Roon, udp-proxy-2020 and OpenVPN. then people only need to worry about port forwarding the OpenVPN port via their firewall.

build pfSense app

since I'm using this on pfSense, might be nice to build a proper package for it.

Can we run this proxy somewhere else than the router?

Great project, thanks for putting the time into this. I'm using a Peplink router and have limited access to it via SSH, meaning I can't install any package on my own. I still need to use this project, though, because I want to forward broadcast messages between my home network and my Wireguard network (whose service runs in an instance inside my homelab).

Does udp-proxy work if I run it inside the instance which also runs Wireguard instead of my router? I was trying to get it to work recently and failed, and was wondering if it was possible at all.

Docker image synfinatic/udp-proxy-2020:latest does not exist

Whe I try to run the startup script /mnt/data/on_boot.d/40-udp-proxy-2020.sh on my UNifi UDM-Pro it ends with this error:

Trying to pull docker.io/synfinatic/udp-proxy-2020...
manifest unknown: manifest unknown

The problem is that the docker container image is referenced as synfinatic/udp-proxy-2020:latest in the script but this label does not exist. If i change the label to :v0.0.8 the image is available and the container starts successfully.

Add mDNS support

Not that important, but maybe a nice feature for the future: mDNS repeater like avahi struggle with the same problem that multicast is not supported on point-to-point connections like openvpn tun devices. Just using the mDNS port 5353 with udp-proxy-2020 doesn't work out of the box in a first test

monitor for dynamic interfaces?

Not sure if there is a use case for this... definitely doesn't seem to be for OpenVPN, but might be nice to be able to specify a prefix or glob or simple regex eth[0-3] to dynamically match NIC's that come and go.

Fix vagrant build for freebsd

Right now the Vagrant file is copying the source code via rsync when the VM is built, not run. The result is that if you don't run make freebsd-clean you'll build an outdated binary. :(

Need to copy the code over and build after the VM comes up.

pfsense startup instructions

Thanks for this program, it works great! However, I was having issues with the pfsense startup script instructions. Here is what I got to work properly on 2.5:

  1. udp-proxy-2020.conf should be in /usr/local/etc/

  2. startup rc script udp-proxy-2020 should be in /usr/local/etc/rc.d/; made executable with chmod +x

  3. /etc/rc.conf.local doesn't exist by default and will have to be created or copied from this repo. Unlike freebsd, the rc.conf file gets cleared at boot, so it's important to use rc.conf.local.

  4. the freebsd-amd64 binary should be placed in /usr/local/bin; made executable with chmod +x

  5. The rc script can't have the dashes in the variable name or a variable error is thrown; this means the start/stop/cleanup/status/commands need to be modified as well.

  6. wget isn't installed on pfsense by default but fetch is. This was probably the easiest way to download the files from this repo to their proper directories over ssh.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.