-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
[http_proxy_over_p2p] #5526
[http_proxy_over_p2p] #5526
Conversation
FYI this link appears to be broken |
2cb7199
to
f984368
Compare
Thanks! You should be able to add a sharness test which hijacks the request the request using netcat as is done in https://github.com/ipfs/go-ipfs/blob/master/test/sharness/t0235-cli-request.sh#L14. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks quite good, it would be nice to get some better tests though.
@magik6k thanks for the swift feedback; have started and will munge that script into an sharness test as suggested. |
3dbdeb4
to
2c91cb6
Compare
So, I believe this should actually be using the ReverseProxy helper. That will copy and modify all the right headers and handle all the edge-cases. However, that may just make it more complicated so take this as a suggestion. (You won't be able to use the I believe we also need to read while writing. That is, the current version expects to write the entire request before it reads any response. We should start the request and then read the response as some worker finishes writing the request. Note: We can probably fix these later if they turn out to be difficult to get right. |
core/corehttp/proxy.go
Outdated
s := bufio.NewReader(stream) | ||
proxyResponse, err := http.ReadResponse(s, proxyReq) | ||
|
||
defer func() { proxyResponse.Body.Close() }() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this? I believe proxyResponse.Write
will close the body when done.
Also, I'm not sure if this is valid if err != nil
. Will it not panic?
60092b8
to
5d20453
Compare
@cboddy @Stebalien this might be a little late in the PR cycle to suggest but, if I understand correctly, @hsanjuan has built |
Hello, yes, https://github.com/hsanjuan/go-libp2p-http will probably simplify this (along with The The only problem would be to attach a custom transport tag to every Roundtripper. We can easily enable this upstream (currently a single tag is used for all), if you are willing to go down this path. |
@Stebalien @lanzafame thanks for the feedback. Will look into using |
9f6e044
to
4400212
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slightly more complicated but I think this'll have better header handling.
core/corehttp/proxy.go
Outdated
} | ||
|
||
// open connect to peer | ||
stream, err := ipfsNode.P2P.PeerHost.NewStream(ipfsNode.Context(), parsedRequest.target, protocol.ID("/x/"+parsedRequest.name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this should be using the request context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
core/corehttp/proxy.go
Outdated
sendRequest := func() { | ||
err := req.Write(*rt.stream) | ||
if err != nil { | ||
(*(rt.stream)).Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be rt.stream.Reset()
.
core/corehttp/proxy.go
Outdated
} | ||
|
||
type roundTripper struct { | ||
stream *inet.Stream |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No real need for the pointer. This is already an interface (class-like thing) so we can just say inet.Stream
.
fyi, protocol tags per Roundtripper coming about: libp2p/go-libp2p-http#12 |
One more thing we'll need to do before merging this: put it behind an experimental feature-gate. Take a look at how the I don't really see this needing a long stabilization period, but we should probably leave it experimental at last until we stabilize the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a re-implementation of the logic of go-libp2p-http but it doesn't close the streams. And it if did, it probably would miss handling connection closing correctly (like this: https://github.com/hsanjuan/go-libp2p-gostream/blob/master/conn.go#L37).
This is all handled in go-libp2p-http because we have already hit a number of edge cases. I really don't like that we are cloning the logic here.
core/corehttp/proxy.go
Outdated
return | ||
} | ||
//send proxy request and response to client | ||
newReverseHTTPProxy(parsedRequest, &stream).ServeHTTP(w, request) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something is fishy here. For every request a new proxy is created but I think the stream is never closed ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. That's fixed now.
@hsanjuan We can't use the RoundTripper in go-libp2p-http because it assumes a different incoming request format, and we don't want to do an extra socket+http round trip. We used your technique to close the stream though. |
199d25e
to
2fd1c26
Compare
@Stebalien Does that mean we need a PR to go-ipfs-config to add a new config option and then gx publish that before this can be merged, or can we use the existing Libp2pStreamMounting option? |
That's not true. You just need to rewrite the path, which you are already doing anyway. |
We don't need to do this for every test and our tests are slow enough. License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
License: MIT Signed-off-by: Ian Preston <ianopolous@protonmail.com>
License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
License: MIT Signed-off-by: Ian Preston <ianopolous@protonmail.com>
License: MIT Signed-off-by: Ian Preston <ianopolous@protonmail.com>
License: MIT Signed-off-by: Ian Preston <ianopolous@protonmail.com>
License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
License: MIT Signed-off-by: Ian Preston <ianopolous@protonmail.com> Co-Authored-By: ianopolous <ianopolous@protonmail.com>
License: MIT Signed-off-by: Ian Preston <ianopolous@protonmail.com>
License: MIT Signed-off-by: Ian Preston <ianopolous@protonmail.com> Co-Authored-By: ianopolous <ianopolous@protonmail.com>
License: MIT Signed-off-by: Ian Preston <ianopolous@protonmail.com>
181aa64
to
6c35fbc
Compare
Instead of repeatedly starting the netcat server, start it once and wait for it to fully start. Then, feed responses in using a fifo. License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
6c35fbc
to
9a443ad
Compare
OK, tests pass and @hsanjuan has given a ✔️ 🚂 (this train may be a bit slow...). |
Hooray! The last critical feature we need for Peergos! @Stebalien is the plan to enable this on ipfs.io? |
@Stebalien @magik6k @hsanjuan thanks for your help with this one! |
Probably not for a while, if ever. We'll have to seriously consider the security and performance implications and, really, the public gateway's more of a crutch (we'd prefer if users would just load js-libp2p from their DAPP). |
:-( That's a shame, because can do some really cool demos if that is enabled. Loading js-libp2p will never be an option for us for security reasons. |
Are you forbidding javascript entirely? Can you not spin up a js-ipfs node in a sandboxed worker? I do agree this would allow for some pretty cool demos but I'd like to sit on it at least until it's stabilized. |
@Stebalien In general, we veto anything that uses npm which is anathema to basic security practices. We're also trying to keep the JS down to a small easily auditable amount (as much as possible) for the same reasons. As well as being much harder to audit for attacks, having a complex P2P daemon running in the same process as that which has the secret keys is also asking for trouble. Browsers explicitly don't defend against spectre attacks within the same page to my knowledge (they'd have to run every worker in an independent OS process, not just different OS threads). We also have reproducible builds for the web-ui already. For now we can just preface all ipfs-only demos with, install ipfs and enable these two flags, then browse to this local url. |
Well, I can't really blame you there...
Sandboxing has more to do with origins/contexts than pages. I'm not familiar with browser spectre mitigations but, a page in a sandboxed iframe/worker should have equivalent security to a page running in a separate tab. |
If the p2p daemon was running from a separate domain in an iframe, I believe this might be safe in some browsers (depending on their site isolation properties), but it's much harder to prove it safe, and it requires you to have two separate origins. We don't have any 3rd party hosted content in our web-ui - it's all self hosted (partially to enable easy offline and localhost access). How about we continue this on irc to stop spamming all the other contributors to this pr? :-) |
This implements an http-proxy over p2p-streams, for context see #5341.
This script is a useful test of the functionality. In case it causes portability issues I've not included it as a sharness test (since it uses python to serve HTTP content, although happy to add it since python be ~ as available as bash).
(inline since GH doesn't support
*.sh
as an attachment)