Skip to content
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

Add libp2phttp command #40

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

MarcoPolo
Copy link
Contributor

This lets you make http requests over libp2p streams.

The strategy I went with was to listen on a unix socket and proxy any HTTP requests received on that socket to the target. This lets us reuse curl to do the actual HTTP parts.

Example:

$ vole libp2p http '/ip4/127.0.0.1/udp/4002/quic-v1/webtransport/certhash/uEiA14HNun3qVa6Z2XXinYHwx_XxGgTuCUJ_yWyzuU_AXcw/certhash/uEiBBv5HyzsoM_k-sxUOTm-VkDdNhWJpUyuk-7IHN2mm1EA/p2p/12D3KooWJzkorELQQRrWBwePjkTwkeJcLya9LZLLVMGHmRj62PZB'

Proxying on:
/var/folders/6t/nky73jj94hlcpcf1gf2mljb00000gn/T/libp2phttp-4159826572.sock

Example curl request:
curl --unix-socket /var/folders/6t/nky73jj94hlcpcf1gf2mljb00000gn/T/libp2phttp-4159826572.sock http://example.com/

In another terminal:

$  curl --unix-socket /var/folders/6t/nky73jj94hlcpcf1gf2mljb00000gn/T/libp2phttp-4159826572.sock http://example.com/

Hello World

Copy link
Contributor

@aschmahmann aschmahmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this 🙏. This looks a lot like https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#p2p-http-proxy.

Do you think adding it's sister https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#ipfs-p2p (i.e. TCP proxying over libp2p streams) would be valuable as well (would be a separate PR)?

lib/libp2phttp.go Outdated Show resolved Hide resolved
lib/libp2phttp.go Outdated Show resolved Hide resolved
lib/libp2phttp_test.go Outdated Show resolved Hide resolved
lib/libp2phttp_test.go Outdated Show resolved Hide resolved
hasTLS := false
hasHTTP := false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this logic get into trouble if say /ws/tls is being used for a relay and combined with /http?

Maybe not relevant though since I'm not sure if there are multiaddrs where /http is valid when combined with /p2p/.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this logic get into trouble if say /ws/tls is being used for a relay and combined with /http?

/http represents the HTTP transport. It shouldn't be combined with /ws.

Maybe not relevant though since I'm not sure if there are multiaddrs where /http is valid when combined with /p2p/.

Not yet, but these could be combined. I just need to finish peer id auth over http and we could have a valid multiaddr that looks like /.../http/p2p/12Foo

},
},
Usage: "Make http requests to the given multiaddr with a unix socket",
Description: `This command creates a unix socket that can be used with curl to make HTTP requests to the provided multiaddr.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing something but given this is under the "libp2p" command I wonder if it's worth explicitly mentioning that this will enable setting up a standard HTTP proxy that uses multiaddr but otherwise doesn't use any libp2p specs at all (i.e. listening on an http multiaddr).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does HTTP over streams in the spec defined way?

}
server.TLSConfig = c

fmt.Println("Endpoint is an HTTPS endpoint. Using a self signed cert locally to proxy.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is obvious, but can you give me some context on the value of "if the endpoint is HTTPS, let's add a self-signed cert on the unix socket proxy" rather not doing it at all or having the self-signed cert being a separate flag

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imagine you run:

$ vole libp2p http --socket-path=/tmp/vole.sock /dns/google.com/https

What do you expect the curl request to look like?

I would expect:

curl --unix-socket /tmp/vole.sock https://www.google.com

Not

curl --unix-socket /tmp/vole.sock http://www.google.com

https:// vs http://

The only way we can do that is if our proxy itself is an https server, and thus we need a cert. Self signed is easiest. So we actually need to add a -k to the curl command.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you expect the curl request to look like?

I guess this is probably my issue. Because I'm having trouble seeing the value of the HTTP -> HTTP proxy other than to demonstrate that it's possible via libp2p multiaddrs the need to drop an s vs to add a -k doesn't mean a ton to me.

On the other hand it doesn't really hurt, so as long as it's not causing trouble and you think it's useful I don't really mind

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I'm having trouble seeing the value of the HTTP -> HTTP proxy other than to demonstrate that it's possible via libp2p multiaddrs

This is not the main use case, but it's nice that it works consistently. You can make the exact same curl request to a standard HTTP server as you would to a libp2p node over a stream.

Value: "",
},
},
Usage: "Make http requests to the given multiaddr with a unix socket",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good enough for now, certainly for more in-depth debugging of a specific endpoint. Wonder if supporting some basic curl like functionality would be good here so people can do one-line http-over-libp2p requests. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a simple GET request, and anything else would require the unix socket proxy? Does the unix socket proxy trick even work on windows?

Implementing the GET request sounds good to me, but how about we do that in a future PR once the next go-libp2p version is released? That one includes code that will make this easier. User's could make a request to multiaddr:/dns4/example.com/http/http-path/subpath and we can just pass that to go-libp2p.

@MarcoPolo
Copy link
Contributor Author

For context, I used this when playing around with the caddy server to test its HTTP over libp2p streams ability

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants