Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

gate QUIC connections via new ConnectionGater #152

Merged
merged 6 commits into from May 19, 2020
Merged

Conversation

aarshkshah1992
Copy link
Collaborator

@aarshkshah1992 aarshkshah1992 commented May 18, 2020

For libp2p/go-libp2p#931.

  • This PR intercepts packets read from the UDP socket to determine if they should be passed upwards in the stack or gated right away.
  • It does so by calling the InterceptAccept method of the Connection Gater that is passed to the QUIC transport during initialization.

@raulk
I am not sure if we can actually call InterceptSecured here as the security handshake seems to be part of making a QUIC connection and is handled completely by the QUIC library we use.

conn_test.go Outdated

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

type localhostMockGater struct {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@raulk I know this will make you cringe and add some entropy to thy life. But, I have added a TODO at libp2p/go-libp2p#930 to replace this with the "Functional Gater" that we plan to implement.

For all that you hold dear on this good Earth, rest assured, this shall be fixed.

Copy link
Member

@raulk raulk left a comment

Choose a reason for hiding this comment

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

We need to call InterceptSecured and InterceptUpgraded. Even if there are no explicit steps in the QUIC transport, those checkpoints still exist virtually. We should provide a normalised experience. The implementor of ConnectionGater should not be aware of the individual nuances in each transport.

Note: the InterceptUpgraded will be redundant with the swarm's call (we should remove it from there).

filtered_conn.go Outdated
return
}
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

go fmt missing.

transport.go Outdated Show resolved Hide resolved
@aarshkshah1992
Copy link
Collaborator Author

Note: the InterceptUpgraded will be redundant with the swarm's call (we should remove it from there).

I am not sure why we need to call InterceptUpgraded here. The Swarm will call InterceptUpgraded for ALL transports. There's no special casing there. We don't call InterceptUpgraded in any of the other transports(upgrader) as well.

@raulk
Copy link
Member

raulk commented May 18, 2020

@aarshkshah1992 It's a separation of concerns argument. The component that's responsible for returning an upgraded connection is the transport, therefore it should be the one intercepting, in my view. However, OTOH the swarm receives only upgraded connections from the transports, so it's safe to just leave the interception point there... No right or wrong here, disregard my comment about InterceptUpgraded and let's implement only InterceptSecured here.

@raulk
Copy link
Member

raulk commented May 18, 2020

@aarshkshah1992 We should update the godocs in go-libp2p-core to make it explicit what's expected to be implemented by transport writers and what isn't...

@aarshkshah1992
Copy link
Collaborator Author

@raulk Have addressed your changes. Please take a look now.

conn_test.go Outdated Show resolved Hide resolved
conn_test.go Outdated
@@ -192,7 +218,9 @@ var _ = Describe("Connection", func() {

// now allow the address and make sure the connection goes through
clientTransport.(*transport).clientConfig.HandshakeTimeout = 2 * time.Second
filters.AddFilter(ipNet, filter.ActionAccept)
cg.lk.Lock()
cg.allowAll = true
Copy link
Member

Choose a reason for hiding this comment

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

A test for InterceptSecured would be great (mostly for regression testing).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is done.

listener.go Outdated Show resolved Hide resolved
@Stebalien
Copy link
Member

Note: It's not actually possible to call InterceptUpgraded here as we have a transport.CapableConn, not a network.Conn.

@aarshkshah1992
Copy link
Collaborator Author

@raulk Have added a test for InterceptSecured as well. Please approve and merge if happy.

@raulk
Copy link
Member

raulk commented May 19, 2020

Note: It's not actually possible to call InterceptUpgraded here as we have a transport.CapableConn, not a network.Conn.

Correct. I knew there was a reason I had originally planned InterceptUpgraded to take a transport.CapableConn. But that wouldn't have worked anyway, because the calling component will, in the future, need to return a disconnect reason over a control stream, for which we need a network.Conn that's working with multistream.

conn_test.go Outdated
Comment on lines 31 to 32
allowAllAccepted bool
disableSecuredPeer peer.ID
Copy link
Member

Choose a reason for hiding this comment

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

I've simplified these names @aarshkshah1992.

@raulk raulk changed the title Add Connection Gating to the QUIC transport by intercepting packets read from the Socket gate QUIC connections via new ConnectionGater May 19, 2020
@raulk raulk merged commit 541e8a3 into master May 19, 2020
@raulk raulk deleted the feat/conn-gating branch May 19, 2020 11:48
Copy link
Collaborator

@marten-seemann marten-seemann left a comment

Choose a reason for hiding this comment

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

Hi guys, just came back after a few days OOO.

The code here mostly lgtm, but I think we need to close the connection when InterceptSecured rejects it.

Furthermore, I have one question: I assume there's an InterceptAccept and an InterceptSecured to allow rejecting connection both from a certain multiaddr as well as from a certain peer ID. This much makes sense to. But what's the point of having an InterceptUpgraded on the connection gater? And why is it not called here?

Edit: Found the answer: #152 (comment).

@@ -178,6 +183,13 @@ func (t *transport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tp
pconn.DecreaseCount()
return nil, err
}

connaddrs := &connAddrs{lmAddr: localMultiaddr, rmAddr: remoteMultiaddr}
if t.gater != nil && !t.gater.InterceptSecured(n.DirOutbound, p, connaddrs) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We need to close the connection at this point. Otherwise the peer will never know that we closed the connection. As from quic-go's point of view the connection is fully established, there won't be any connection-level timeout here either.

@Stebalien Stebalien mentioned this pull request May 26, 2020
77 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants