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
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 32 additions & 10 deletions conn_test.go
Expand Up @@ -11,17 +11,44 @@ import (
"sync/atomic"
"time"

"github.com/libp2p/go-libp2p-core/control"
ic "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
tpt "github.com/libp2p/go-libp2p-core/transport"
filter "github.com/libp2p/go-maddr-filter"

quicproxy "github.com/lucas-clemente/quic-go/integrationtests/tools/proxy"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr-net"

. "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.

allowAll bool
}

func (c *localhostMockGater) InterceptAccept(addrs network.ConnMultiaddrs) bool {
return c.allowAll || !manet.IsIPLoopback(addrs.RemoteMultiaddr())
}

func (c *localhostMockGater) InterceptPeerDial(p peer.ID) (allow bool) {
return true
}

func (c *localhostMockGater) InterceptAddrDial(peer.ID, ma.Multiaddr) (allow bool) {
return true
}

func (c *localhostMockGater) InterceptSecured(network.Direction, peer.ID, network.ConnMultiaddrs) (allow bool) {
return true
}

func (c *localhostMockGater) InterceptUpgraded(network.Conn) (allow bool, reason control.DisconnectReason) {
return true, 0
}

var _ = Describe("Connection", func() {
var (
serverKey, clientKey ic.PrivKey
Expand Down Expand Up @@ -166,17 +193,12 @@ var _ = Describe("Connection", func() {
})

It("filters addresses", func() {
filters := filter.NewFilters()
ipNet := net.IPNet{
IP: net.IPv4(127, 0, 0, 1),
Mask: net.IPv4Mask(255, 255, 255, 255),
}
filters.AddFilter(ipNet, filter.ActionDeny)
testMA, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234/quic")
Expect(err).ToNot(HaveOccurred())
Expect(filters.AddrBlocked(testMA)).To(BeTrue())
cg := &localhostMockGater{}
Expect(cg.InterceptAccept(&connAddrs{rmAddr: testMA})).To(BeFalse())
raulk marked this conversation as resolved.
Show resolved Hide resolved

serverTransport, err := NewTransport(serverKey, nil, filters)
serverTransport, err := NewTransport(serverKey, nil, cg)
Expect(err).ToNot(HaveOccurred())
ln := runServer(serverTransport, "/ip4/127.0.0.1/udp/0/quic")
defer ln.Close()
Expand All @@ -192,7 +214,7 @@ 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.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.

conn, err := clientTransport.Dial(context.Background(), ln.Multiaddr(), serverID)
Expect(err).ToNot(HaveOccurred())
conn.Close()
Expand Down
38 changes: 31 additions & 7 deletions filtered_conn.go
Expand Up @@ -3,17 +3,38 @@ package libp2pquic
import (
"net"

filter "github.com/libp2p/go-maddr-filter"
"github.com/libp2p/go-libp2p-core/connmgr"

ma "github.com/multiformats/go-multiaddr"
)

type connAddrs struct {
lmAddr ma.Multiaddr
rmAddr ma.Multiaddr
}

func (c *connAddrs) LocalMultiaddr() ma.Multiaddr {
return c.lmAddr
}

func (c *connAddrs) RemoteMultiaddr() ma.Multiaddr {
return c.rmAddr
}

type filteredConn struct {
net.PacketConn

filters *filter.Filters
lmAddr ma.Multiaddr
connGater connmgr.ConnectionGater
}

func newFilteredConn(c net.PacketConn, filters *filter.Filters) net.PacketConn {
return &filteredConn{PacketConn: c, filters: filters}
func newFilteredConn(c net.PacketConn, connGater connmgr.ConnectionGater) net.PacketConn {
lmAddr, err := toQuicMultiaddr(c.LocalAddr())
if err != nil {
panic(err)
}

return &filteredConn{PacketConn: c, connGater: connGater, lmAddr: lmAddr}
}

func (c *filteredConn) ReadFrom(b []byte) (n int, addr net.Addr, rerr error) {
Expand All @@ -23,12 +44,15 @@ func (c *filteredConn) ReadFrom(b []byte) (n int, addr net.Addr, rerr error) {
if n < 1 || b[0]&0x80 == 0 {
return
}
maddr, err := toQuicMultiaddr(addr)
rmAddr, err := toQuicMultiaddr(addr)
if err != nil {
panic(err)
}
if !c.filters.AddrBlocked(maddr) {

connAddrs := &connAddrs{lmAddr: c.lmAddr, rmAddr: rmAddr}

if c.connGater.InterceptAccept(connAddrs) {
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.

2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -4,7 +4,7 @@ go 1.13

require (
github.com/ipfs/go-log v1.0.4
github.com/libp2p/go-libp2p-core v0.5.3
github.com/libp2p/go-libp2p-core v0.5.5
github.com/libp2p/go-libp2p-tls v0.1.3
github.com/libp2p/go-maddr-filter v0.0.5
github.com/libp2p/go-netroute v0.1.2
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Expand Up @@ -112,6 +112,8 @@ github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS
github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco=
github.com/libp2p/go-libp2p-core v0.5.3 h1:b9W3w7AZR2n/YJhG8d0qPFGhGhCWKIvPuJgp4hhc4MM=
github.com/libp2p/go-libp2p-core v0.5.3/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y=
github.com/libp2p/go-libp2p-core v0.5.5 h1:/yiFUZDoBWqvpWeHHJ1iA8SOs5obT1/+UdNfckwD57M=
github.com/libp2p/go-libp2p-core v0.5.5/go.mod h1:vj3awlOr9+GMZJFH9s4mpt9RHHgGqeHCopzbYKZdRjM=
github.com/libp2p/go-libp2p-tls v0.1.3 h1:twKMhMu44jQO+HgQK9X8NHO5HkeJu2QbhLzLJpa8oNM=
github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M=
github.com/libp2p/go-maddr-filter v0.0.5 h1:CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg=
Expand All @@ -121,6 +123,8 @@ github.com/libp2p/go-netroute v0.1.2 h1:UHhB35chwgvcRI392znJA3RCBtZ3MpE3ahNCN5MR
github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk=
github.com/libp2p/go-openssl v0.0.4 h1:d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg=
github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-openssl v0.0.5 h1:pQkejVhF0xp08D4CQUcw8t+BFJeXowja6RVcb5p++EA=
github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-sockaddr v0.0.2 h1:tCuXfpA9rq7llM/v834RKc/Xvovy/AqM9kHvTV/jY/Q=
github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k=
github.com/lucas-clemente/quic-go v0.15.7 h1:Pu7To5/G9JoP1mwlrcIvfV8ByPBlCzif3MCl8+1W83I=
Expand Down
23 changes: 12 additions & 11 deletions reuse.go
Expand Up @@ -5,7 +5,8 @@ import (
"sync"
"time"

filter "github.com/libp2p/go-maddr-filter"
"github.com/libp2p/go-libp2p-core/connmgr"

"github.com/libp2p/go-netroute"
)

Expand All @@ -23,9 +24,9 @@ type reuseConn struct {
unusedSince time.Time
}

func newReuseConn(conn net.PacketConn, filters *filter.Filters) *reuseConn {
if filters != nil {
conn = newFilteredConn(conn, filters)
func newReuseConn(conn net.PacketConn, connGater connmgr.ConnectionGater) *reuseConn {
if connGater != nil {
conn = newFilteredConn(conn, connGater)
}
return &reuseConn{PacketConn: conn}
}
Expand Down Expand Up @@ -55,7 +56,7 @@ func (c *reuseConn) ShouldGarbageCollect(now time.Time) bool {
type reuse struct {
mutex sync.Mutex

filters *filter.Filters
connGater connmgr.ConnectionGater

garbageCollectorRunning bool

Expand All @@ -64,11 +65,11 @@ type reuse struct {
global map[int]*reuseConn
}

func newReuse(filters *filter.Filters) *reuse {
func newReuse(connGater connmgr.ConnectionGater) *reuse {
return &reuse{
filters: filters,
unicast: make(map[string]map[int]*reuseConn),
global: make(map[int]*reuseConn),
connGater: connGater,
unicast: make(map[string]map[int]*reuseConn),
global: make(map[int]*reuseConn),
}
}

Expand Down Expand Up @@ -168,7 +169,7 @@ func (r *reuse) dialLocked(network string, raddr *net.UDPAddr, source *net.IP) (
if err != nil {
return nil, err
}
rconn := newReuseConn(conn, r.filters)
rconn := newReuseConn(conn, r.connGater)
r.global[conn.LocalAddr().(*net.UDPAddr).Port] = rconn
return rconn, nil
}
Expand All @@ -180,7 +181,7 @@ func (r *reuse) Listen(network string, laddr *net.UDPAddr) (*reuseConn, error) {
}
localAddr := conn.LocalAddr().(*net.UDPAddr)

rconn := newReuseConn(conn, r.filters)
rconn := newReuseConn(conn, r.connGater)
rconn.IncreaseCount()

r.mutex.Lock()
Expand Down
13 changes: 7 additions & 6 deletions transport.go
Expand Up @@ -6,6 +6,8 @@ import (
"io"
"net"

"github.com/libp2p/go-libp2p-core/connmgr"

"github.com/minio/sha256-simd"
"golang.org/x/crypto/hkdf"

Expand All @@ -15,7 +17,6 @@ import (
"github.com/libp2p/go-libp2p-core/pnet"
tpt "github.com/libp2p/go-libp2p-core/transport"
p2ptls "github.com/libp2p/go-libp2p-tls"
filter "github.com/libp2p/go-maddr-filter"
quic "github.com/lucas-clemente/quic-go"
ma "github.com/multiformats/go-multiaddr"
mafmt "github.com/multiformats/go-multiaddr-fmt"
Expand Down Expand Up @@ -43,9 +44,9 @@ type connManager struct {
reuseUDP6 *reuse
}

func newConnManager(filters *filter.Filters) (*connManager, error) {
reuseUDP4 := newReuse(filters)
reuseUDP6 := newReuse(filters)
func newConnManager(connGater connmgr.ConnectionGater) (*connManager, error) {
reuseUDP4 := newReuse(connGater)
reuseUDP6 := newReuse(connGater)

return &connManager{
reuseUDP4: reuseUDP4,
Expand Down Expand Up @@ -93,7 +94,7 @@ type transport struct {
var _ tpt.Transport = &transport{}

// NewTransport creates a new QUIC transport
func NewTransport(key ic.PrivKey, psk pnet.PSK, filters *filter.Filters) (tpt.Transport, error) {
func NewTransport(key ic.PrivKey, psk pnet.PSK, connGater connmgr.ConnectionGater) (tpt.Transport, error) {
raulk marked this conversation as resolved.
Show resolved Hide resolved
if len(psk) > 0 {
log.Error("QUIC doesn't support private networks yet.")
return nil, errors.New("QUIC doesn't support private networks yet")
Expand All @@ -106,7 +107,7 @@ func NewTransport(key ic.PrivKey, psk pnet.PSK, filters *filter.Filters) (tpt.Tr
if err != nil {
return nil, err
}
connManager, err := newConnManager(filters)
connManager, err := newConnManager(connGater)
if err != nil {
return nil, err
}
Expand Down