Rather than proxying data, why wouldn't you just bind the socket, and then transfer the file descriptor over the UNIX domain socket (using sendmsg/recvmsg)?
Or acept() incoming connections, and then pass the connection's file descriptor.
User space proxying for protocols other than http, though, is a bit tricky. If you aren't exposing things like source ip, listen queue depth, buffer sizes, errno from failures, etc...you are potentially limiting how well it works. Plus the read/write overhead. I'm not convinced this is any better than other approaches. Brokered iptables (or pf,etc) port rewrites seems cleaner, though it has issues as well.
> If you aren't exposing things like source ip, listen queue depth, buffer sizes, errno from failures, etc...you are potentially limiting how well it works.
This is a good point.
> Plus the read/write overhead.
The author's code uses OpenBSD's `SO_SPLICE` for zero-copy socket data transfers.
Edit: apparently `SO_SPLICE` can't splice IP sockets onto unix domain sockets yet, so the presented code is kind of wishful thinking. It sounds like this is in the works though.
It sounds like you should probably just go the whole hog and give each user their own network namespace and bridge them to the main network. Then they can run DHCP and get their own address and do with it what they like.
Wouldn't really work for Internet accessible IPv4 addresses, but IPv6 would be fine.
This is neat. There's a minor race condition at startup because scanhostdir calls scanportdir before watchdir. Reversing the order of calls would close the gap and shouldn't have any adverse effects.
For the most common case of lots of users needing ports (web apps), there's the option in nginx and newer Apache versions to proxy to a UNIX socket, so no port is needed for the user app. It's not gonna work for everything but many web app servers are fine with using a socket instead of a port.
There's also http://cyberelk.net/tim/software/portreserve/ for when ports are really needed (not as elegant as the solution under discussion, though, as it just holds a port by binding to it until the rightful owner/service comes along).
I think these days I would approach the problem by creating per-user network namespaces and hack the privileged port limitation away from kernel (is there a sysctl for that/why not?)
- Then, as of kernel version 4.11, you can set where the non-privileged ports start, like "sysctl net.ipv4.ip_unprivileged_port_start=0" Somewhat helpful in that you could have them start above things like sshd (22), but below port 80. Still not great for multi-tenant, etc, though.
See discussion here: https://news.ycombinator.com/item?id=14712576