Do Packet Filtering and Translation
An alternative would be to setup packet filtering and translation in the host machine to direct all incoming TCP requests to your process, regardless of the destination port. sshuttle does this to tunnel all requests to an ssh server. This way, your process would not need to open thousands of files.
In freeBSD/macOS the configuration is achieved as follows. Other OSs will have their specific way of doing this (e.g. nftables' nft(8) in Debian).
Configuration File
Create a file (named rules.txt for this example) with the following contents:
# Redirect incoming traffic on interface en0 to localhost:5000
rdr pass on en0 inet proto tcp all -> 127.0.0.1 port 5000
Change en0 to the interface that you wish to intercept incoming connections on. Remove inet or replace with inet6 to accept both IP and IPv6 or just IPv6, respectively. Check pf.conf(5) for exact semantics and syntax of this file.
Enable Rules
With administrative access run the following to load up the rules contained in the previously created file.
Enable packet filtering and translation:
pfctl -e
Flush everything (be careful as this will erase existing routing and translating configurations already set):
pfctl -F a
Load the rules:
pfctl -f rules.txt
Test it out.
Also Include Outgoing Traffic
If you also want to include outgoing traffic, as sshuttle does, you should append the next line to rules.txt:
pass out route-to lo0 inet proto tcp all
You can also tweak this rule to be more selective and avoid setting yourself a networking jail (see entry 1 of notes below).
Notes
- If you include outgoing traffic, you will be unable to communicate with the outside world unless you receive a connection first or have an alternative interface. This is because outgoing traffic will be routed to your catchall process (due to the
route-to keyword).
- Beware that this method allows processes bound to localhost to be reachable from the outside. In the setup above, anyone connecting to any port on
en0 will be able to talk to the process bound to 127.0.0.1:5000.
- Remember to reload the rules after changing
rules.txt for them to take effect.
- To disable packet filtering and translation run
pfctl -d.