Closed cmars closed 2 years ago
Thanks! I don't work on this library too much anymore tbh. But I think the best way to do this is to stop making ListenConf.LocalListener
and ListenConf.RemotePorts
required, and add a ForwardRemotePorts map[int][]string
that forwards port keys to local addrs.
Let me know if I'm mistaken, but it looks like zero values for ListenConf.LocalPort
and ListenConf.LocalListener
are valid config, resulting in a listener that gets created on an unused port. How would I differentiate between that and "no listener, just forwarding"? I'm not quite sure what you have in mind for this.
As an alternative... in this PR there are a lot of duplicate fields between the "Forward" and "Listen"-type structs (I did a quick and dirty hack here to get cmars/oniongrok working). What if we refactor this into common "HiddenService"-config related structs, and embed in both types (Listen- and Forward-related) of structs? And then refactor out the common bits among Tor.Forward / Tor.Listen into private methods? That way Listen can be all about setting up a hidden net.Listener, Forward can be just about local port forwards, and they can reuse all the common parts (setting up a hidden service in Tor).
I think either way, we're likely looking at a breaking API change.
Let me know if I'm mistaken, but it looks like zero values for ListenConf.LocalPort and ListenConf.LocalListener are valid config, resulting in a listener that gets created on an unused port. How would I differentiate between that and "no listener, just forwarding"? I'm not quite sure what you have in mind for this.
@cmars - Hrmm, that seems true. I had a whole thing typed out about how we could reuse Listen
by maybe adding DisableLocalListener bool
to ListenConf
, but it is clear my original intention of Listen
was to return something that implements net.Listener
which makes no sense for forwarding.
As an alternative... in this PR there are a lot of duplicate fields between the "Forward" and "Listen"-type structs (I did a quick and dirty hack here to get cmars/oniongrok working). What if we refactor this into common "HiddenService"-config related structs, and embed in both types (Listen- and Forward-related) of structs? And then refactor out the common bits among Tor.Forward / Tor.Listen into private methods? That way Listen can be all about setting up a hidden net.Listener, Forward can be just about local port forwards, and they can reuse all the common parts (setting up a hidden service in Tor).
After some thought, I agree with the idea but not exactly the impl. I don't think we want embeds (just copy the common fields, embeds is a backwards incompat change), but reusing any code internally is very reasonable if at all possible.
So, really, revisiting this PR, I think it's mostly good :-) Thanks for going in circles here with me, heh. I do think PortMap
should change to a map[int][]string
and remove LocalAddr
that way people can map to other local addrs, unix paths, etc. Basically anything HiddenServicePort
supports which will also make the code simple.
You may also want an integration test or two to confirm it works.
@cretz Updated the port mapping -- I found that it needs to be a map[string][]int
as we're mapping from a single local socket (which can be TCP or UNIX, so it must be a string) to one or more onion TCP ports, which are always port numbers.
I've tested this in cmars/oniongrok#1 and it seems to work. What do you think?
I started going further down the path of refactoring out common parts in Listen and Forward. I think it's doable, but I'm getting quite a bit worried about landing such a drastic change without unit test coverage. Something to revisit in a followup?
Could do some refactoring of Listen/Forward. If this is generally a good idea happy to tidy things up.