I wanted to run mosh through tailcat (over a DERP-relayed connection the typing lag is noticeable, and mosh's local echo fixes that), and found there's no way to get UDP to a served port from the CLI. The library has it all (Server.OnUDP, ServedUDPPorts, Client.DialUDPPort, ProxyPacketConns), and d0d5991 wired it up for exit nodes, but serve <ports> only ever sets OnTCP, and forward only listens on TCP. socks can dial UDP but mosh-client doesn't speak SOCKS.
Proposal:
tailcat serve --udp=60000-60010 no-auth-ssh # proxy those UDP ports to loopback
tailcat forward <tc-addr> udp:60001 # local udp 60001 -> server udp 60001
tailcat forward <tc-addr> udp:16001:60001
Server side is tiny. It gates on the port set and calls the existing udpForwardTo, plus sets ServedUDPPorts. Client side is a UDP listener that opens one DialUDPPort flow per local source address and reaps idle ones. I have this working and can send a PR, but there are two things I'd want your call on first.
tailcat serve --udp=60000-60010 22,no-auth-ssh vs tailcat serve 22,udp:60000-60010,no-auth-ssh. The flag is less code. The inline form matches the udp: prefix on the client side.
- Which loopback to proxy to. TCP dials
localhost via localhostdns and falls back between 127.0.0.1 and ::1, but UDP can't fall back. The dial "succeeds" against whichever is first (Go picks ::1) and packets to a listener on the other one just vanish. I defaulted to 127.0.0.1 with a --udp-host override.
One thing to know for mosh specifically is that it only works over ::1. mosh sizes packets by address family, 1252 bytes over IPv4, which is over MaxUDPPayload (1232) and gets dropped, vs 1216 over IPv6, which fits. Keystrokes are small so an IPv4 setup looks like it works until the first big screen redraw stalls it. With mosh-server -i ::1, mosh-client ::1, and --udp-host=::1 it's fine.
I wanted to run mosh through tailcat (over a DERP-relayed connection the typing lag is noticeable, and mosh's local echo fixes that), and found there's no way to get UDP to a served port from the CLI. The library has it all (
Server.OnUDP,ServedUDPPorts,Client.DialUDPPort,ProxyPacketConns), and d0d5991 wired it up for exit nodes, butserve <ports>only ever setsOnTCP, andforwardonly listens on TCP.sockscan dial UDP but mosh-client doesn't speak SOCKS.Proposal:
Server side is tiny. It gates on the port set and calls the existing
udpForwardTo, plus setsServedUDPPorts. Client side is a UDP listener that opens oneDialUDPPortflow per local source address and reaps idle ones. I have this working and can send a PR, but there are two things I'd want your call on first.tailcat serve --udp=60000-60010 22,no-auth-sshvstailcat serve 22,udp:60000-60010,no-auth-ssh. The flag is less code. The inline form matches theudp:prefix on the client side.localhostvialocalhostdnsand falls back between127.0.0.1and::1, but UDP can't fall back. The dial "succeeds" against whichever is first (Go picks::1) and packets to a listener on the other one just vanish. I defaulted to127.0.0.1with a--udp-hostoverride.One thing to know for mosh specifically is that it only works over
::1. mosh sizes packets by address family, 1252 bytes over IPv4, which is overMaxUDPPayload(1232) and gets dropped, vs 1216 over IPv6, which fits. Keystrokes are small so an IPv4 setup looks like it works until the first big screen redraw stalls it. Withmosh-server -i ::1,mosh-client ::1, and--udp-host=::1it's fine.