libp2p / go-libp2p-http

HTTP on top of libp2p
MIT License
63 stars 20 forks source link

Client authentication #64

Closed ianopolous closed 4 years ago

ianopolous commented 4 years ago

I'm trying to understand whether p2p http streams (especially as used in ipfs) are client authenticated. I've noticed that the Host header is set to the nodeId of the origin, but it's not clear if that is in anyway verified by the recipient.

I think it boils down to whether or not client certificates are enabled in the TLS stream.

To expand further, if nodeA dials nodeB: a) does nodeB authenticate that the connection is from nodeA's keypair? b) does nodeB check the Host header against nodeA's keypair?

If not, is there a way to enable this?

hsanjuan commented 4 years ago

Hey, so this is tunneling http on a libp2p stream in the end. So the connection on which it travels is authenticated as other libp2p connections. And iirc, the host header is used to call NewStream() to that host.

Does that answer?

ianopolous commented 4 years ago

Thanks @hsanjuan but not really. I know the source authenticates the destination (that's true of any TLS connection). I'm asking about the reverse, does the destination authenticate the source (e.g. almost all browser TLS connections won't do this). Assuming we're using TLS 1.3, does the TLS handshake use client certification?

The host header is a secondary issue which I can test easily enough with a fake Host header I think.

marten-seemann commented 4 years ago

Assuming we're using TLS 1.3, does the TLS handshake use client certification?

Yes, it does: https://github.com/libp2p/go-libp2p-tls/blob/80ca73ebd4a434ba164188a0bd7c6bda232dd45d/crypto.go#L79-L104

ianopolous commented 4 years ago

Excellent! That is great, thank you, @marten-seemann That proves (a). Is there any checking on the http level that the claimed Host header matches the connection source id as well?

hsanjuan commented 4 years ago

Is there any checking on the http level that the claimed Host header matches the connection source id as well?

The host header is not indicating the source peer ID (client), but the destination (server).

There is no way to know client's peer ID at the HTTP level since the protocol is tunneled, unless the client declares itself (via an additional header etc) and you trust it. To perform a deeper check on source peer id, you need to go down one level (go-libp2p-gostream) and do the check there.