-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dialer does not support TCP semantics #37
Comments
Thanks for reaching out, @fortuna. Thank you for you and your team's contribution to the circumvention community with the Outline project and more. To address your questions/concerns:
Yes, you are absolutely correct and I have noticed this issue as well. However we are yet to figure out a easy way to do it: unlike other tools which has a by-all-means flexible way to block on I/O operations until the underlying operation on the
While this might be a good advice in terms of disambiguate, it violates the consistency of function signatures comparing to
For the same reason of simply respecting the signature and support the existing projects/codebases... Lastly, I understand your concerns and I do think they are valuable and informative. Again, WATER is still in the shape of a research project. While we hope to bring it into the community to be used in the real-world as soon as possible, there are plenty of rooms for improvement and we are trying our best to work on it. We are always open to more advice, critiques and suggestions from the community, and contributions are always much appreciated! |
Same reason why we choose to use Dial. But would you perhaps suggest that we should do some type assertion checking and return a custom interface that embeds |
My other thought is that perhaps WATER should provide higher level primitives. In particular, expose default Stream and Packet Dialers that the WASM code can use, rather than have WASM use tcp/udp. That way the implemented transport can actually be composed, like we do in the Outline SDK. The composition will make your transports more reusable and powerful. For example, I should be able to do multiple hops by combining different transports. Or I can inject a base dialer that tunnels traffic to a remote server to test a transport from that server. |
You can use a Furthermore, you now force me to implement two methods instead of one in order to provide a It's much nicer if I just need to provide one method. Even better if you provide a constructor to turn a function into a dialer so I don't need to create types to create custom Dialers (example). I'll note that it's also hard to implement your I recommend sticking to a single method per interface when possible. As Rob Pike says in his Go Proverbs: "The bigger the interface, the weaker the abstraction"
Not a type assertion, but your |
If you provide Dialer primitives to the WASM code, then you can probably block all system calls, addressing the security concern you brought up in your paper. |
Understood. But who should be invoking the syscall becomes the new issue. The host (WATER Runtime API) or the guest (Transport Module)? The former one is agnostic to the actual progress of a previous writing started by It is actually possible (and almost always the case given WebAssembly runs much slower than native) that when the
I totally agree with you on this and it will be the ultimate goal for a production-ready WATER. One of our promise, or let's say compatibility guarantee (hopefully) is that we never wanted to conflict with the current mainline standard (i.e., I will definitely keep exploring possible ways to achieve this, please feel welcome to make suggestions on more specific design/implementation details.
Of course I can't use it. What I was saying is regarding the consistency of the function signature, not the interface interchangeability.
Could you please provide a use case where you need to PROVIDE a water.Dialer? It is usually the case that you USE a
Same reason, it is not meant to be "implemented" but used.
Yes. But for the dialerFunc WATER is expecting some
Again, so far we can't really do it given the lack of ability to transmit types other than |
(wow that's a super long response) |
I am assuming you were talking about
... this part? I would be curious how provide Dialer primitives to the WASM code would mitigate this risk. |
For a developer wants to import WATER, Don't get confused by RegisterDialer, RegisterListener and RegisterRelay, these are called when you import a certain version of transport (e.g., import (
_ "github.com/gaukas/water/transport/v0"
_ "github.com/gaukas/water/transport/v1" // future
_ "github.com/gaukas/water/transport/v2" // future
// _ "github.com/gaukas/water/transport/v3" // not imported, support will not be compiled into the binary
_ "github.com/gaukas/water/transport/v4" // future
) But I guess this part is confusing. I should add better documentation on these 3 functions as well as the "importing transport/vN" part. Edit: now seriously considering moving these 3 functions into an internal package. And more seriously questioning my decision on why not doing so when I created them. Edit 2: I remembered. It is left public to allow any third party transport version support using WATER's infrastructure. |
Hi there, congratulations on getting this project to this state, it looks quite promising!
As part of the development of Outline and Outline SDK, I played with interfaces a lot. One thing that became clear to me is that the Go dial API isn't that great.
Most critically,
Dial
returns anet.Conn
, which doesn't support TCP semantics. To support TCP, you need to be able to close the write end (which sends a FIN). WhileTCPConn
hasCloseRead()
andCloseWrite()
,net.Conn
does not. That's a big omission, and the reason why we useStreamConn
instead in the Outline SDK. You must be able to indicate you are done sending without tearing down the entire connection.Other less important issues, perhaps personal preference:
DialContext
is unnecessarily verbose, and having two Dials is redundant and confusing. Just makeDial
take acontext.Context
.network
parameter in the Dial is unnecessary, and a violation of the encapsulation. It leaks the implementation of the Dialer. Want to dial using TCP? Use a TCP dialer. Want to use IPv6? Use a dialer that uses IPv6. In the Outline SDK, we explicitly have different calls for stream and datagram (packet) dial and connections to give the developer stronger typing, since the connections are semantically different.The text was updated successfully, but these errors were encountered: