How can I redirect all UDP traffic from one port to another on BSD / OS X?

10,671

I tried the steps below, which should work, but does not work on Mac (forwards port 20 UDP text messages to port 29), but you might want to try it anyway:

  1. cd /tmp
  2. mkfifo backpipe
  3. sudo nc -ulk 20 0<backpipe |sudo nc -ulk 29 | tee backpipe
  4. On another terminal - test it with echo -n “this is a test” | sudo nc -4u -w1 localhost 20

It's possible the usage is mangled or the fifo special file isn't working.

However, I found an "easier" way.

  1. Download a very small c program source file called: udp_redirect (click here to download it)
  2. Compile it with gcc -w udp_redirect.c -o udp_redirect
  3. Run it in background sudo ./udp_redirect 127.0.0.1 20 127.0.0.1 29 &
  4. Set up a listener on port 29 to test it sudo nc -ul 29
  5. On a second terminal, test it with echo “this is a test” | sudo nc -4u -w1 localhost 20

This test sends UDP text messages to port 20, and watch the listener on port 29 in the first terminal print the messages. You can also set up a listener on port 20 and see NO messages are available, they are all forwarded (not duplicated) to port 29.

I say it's 'easier' because the udp_redirect binary has much easier usage, does not have the requirement for a special fifo file, does not require pipes, does not require the nc utility, and most importantly, it works!

Share:
10,671

Related videos on Youtube

cwd
Author by

cwd

Updated on September 18, 2022

Comments

  • cwd
    cwd almost 2 years

    On Mac OS X 10.9.5 I am running boot2docker and would like to temporarily forward a non-privileged UDP port 69 to port 69 of the boot2docker virtual machine. Virtualbox only supports forwarding privileged ports.

    I've tried running socat like so:

    socat UDP-LISTEN:69,fork,reuseaddr UDP:192.168.59.101:69
    

    It works just fine until I try to make a tftp connection and then it crashes with:

    socat[32232] E bind(5, {LEN=16 AF=2 0.0.0.0:69}, 16): Address already in use
    

    Checking netstat -an doesn't show much open as far as UDP:

    udp6       0      0  *.58669                *.*
    udp4       0      0  *.58669                *.*
    

    The only related thing I could find on the web was not of much help.

    How on Mac OS X what is what is a good way to 'mirror' UDP traffic from one port to another?

    • FloHimself
      FloHimself about 9 years
      Do you want to forward from OS X to a running tftpd in a docker container?
    • cwd
      cwd about 9 years
      @FloHimself - I can access tftpd from OS X but want to allow access from another machine on the network. I have looked at setting up an additional network interface in Virtualbox in bridged mode but it will expose all ports instead of just the single port that I'd like to expose, which then will require some sort of a firewall or at least changing the default password on boot2docker as this isn't (arguably) the way it was designed to be used. Also I'd like like to know how to be able to mirror / port forward UDP on OS X, because I think that socat command will work with most linux distros.
    • FloHimself
      FloHimself about 9 years
      Your mapping for port 69 with socat is correct. The problem is with the TFTP. Port 69 is only used for the initial request. For further communication TFTP uses diffferent ports. You may want to read about that in Initial Connection Protocol of RFC 1350. So while the initial request will work over the socat mapping, the data transfer will never be established because of the port switch.
    • cwd
      cwd about 9 years
      @FloHimself - Thank you for the link to the RFC. I read over the entire thing. The way I understand the spec is basically that the server will listen on UDP port 69 by default, but the client may be connecting from a different port. At one end of the connection the TID will thus include port 69, but the other TID can include a different port. Once the two TIDs are established they are "used for the duration of that connection"
    • FloHimself
      FloHimself about 9 years
      Both peers use a random TID (and therefore port) that are negotiated in the initial communication. You may want to take a look at the TFTP page on wikipedia which also has graphs of the communication: S replies with an option ACK [...]. [The] Packet is sent from a randomly allocated ephemeral port, and all future packets to host S should be directed to this port.
    • cwd
      cwd about 9 years
      @FloHimself - thank you. thant helps a lot. maybe it worked with only UDP 69 open in my linux tests because I was using less than 512 bytes of data. Anyhow, also found on this man page it looks like one option is to use -R port:port - Force the originating port number to be in the specified range of port numbers. - but I still need to figure out how to forward UDP traffic on OS X / BSD.
    • FloHimself
      FloHimself about 9 years
      Note that the man page you referring to is for a tftp client, but the real problem belongs to the port switch of the server. For general information about port forwarding take a look into man pfctl. Maybe you should explain the purpose of your setup in more detail to find an easier solution.
  • cwd
    cwd about 9 years
    +1 this looks like a great option. I haven't had time to try it yet. reminds me of the udp-reflector although that didn't look like it had much activity or support for os x. thanks so much
  • FloHimself
    FloHimself about 9 years
    @cwd I wonder if this solved the problem with TFTP.