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

Commit

Permalink
gate QUIC connections via new ConnectionGater (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
aarshkshah1992 committed May 19, 2020
1 parent 0dfa364 commit 541e8a3
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 42 deletions.
78 changes: 67 additions & 11 deletions conn_test.go
Expand Up @@ -8,20 +8,54 @@ import (
"io/ioutil"
mrand "math/rand"
"net"
"sync"
"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 mockGater struct {
lk sync.Mutex
acceptAll bool
blockedPeer peer.ID
}

func (c *mockGater) InterceptAccept(addrs network.ConnMultiaddrs) bool {
c.lk.Lock()
defer c.lk.Unlock()
return c.acceptAll || !manet.IsIPLoopback(addrs.RemoteMultiaddr())
}

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

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

func (c *mockGater) InterceptSecured(_ network.Direction, p peer.ID, _ network.ConnMultiaddrs) (allow bool) {
c.lk.Lock()
defer c.lk.Unlock()
return !(p == c.blockedPeer)
}

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

var _ = Describe("Connection", func() {
var (
serverKey, clientKey ic.PrivKey
Expand Down Expand Up @@ -165,18 +199,13 @@ var _ = Describe("Connection", func() {
Eventually(done).Should(BeClosed())
})

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)
It("gates accepted connections", func() {
testMA, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234/quic")
Expect(err).ToNot(HaveOccurred())
Expect(filters.AddrBlocked(testMA)).To(BeTrue())
cg := &mockGater{}
Expect(cg.InterceptAccept(&connAddrs{rmAddr: testMA})).To(BeFalse())

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 +221,34 @@ 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.acceptAll = true
cg.lk.Unlock()
conn, err := clientTransport.Dial(context.Background(), ln.Multiaddr(), serverID)
Expect(err).ToNot(HaveOccurred())
conn.Close()
})

It("gates secured connections", func() {
serverTransport, err := NewTransport(serverKey, nil, nil)
Expect(err).ToNot(HaveOccurred())
ln := runServer(serverTransport, "/ip4/127.0.0.1/udp/0/quic")
defer ln.Close()

cg := &mockGater{acceptAll: true, blockedPeer: serverID}
clientTransport, err := NewTransport(clientKey, nil, cg)
Expect(err).ToNot(HaveOccurred())

// make sure that connection attempts fails
clientTransport.(*transport).clientConfig.HandshakeTimeout = 250 * time.Millisecond
_, err = clientTransport.Dial(context.Background(), ln.Multiaddr(), serverID)
Expect(err).To(HaveOccurred())

// now allow the peerId and make sure the connection goes through
clientTransport.(*transport).clientConfig.HandshakeTimeout = 2 * time.Second
cg.lk.Lock()
cg.blockedPeer = "none"
cg.lk.Unlock()
conn, err := clientTransport.Dial(context.Background(), ln.Multiaddr(), serverID)
Expect(err).ToNot(HaveOccurred())
conn.Close()
Expand Down
36 changes: 30 additions & 6 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
gater connmgr.ConnectionGater
}

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

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

func (c *filteredConn) ReadFrom(b []byte) (n int, addr net.Addr, rerr error) {
Expand All @@ -23,11 +44,14 @@ 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.gater.InterceptAccept(connAddrs) {
return
}
}
Expand Down
5 changes: 2 additions & 3 deletions go.mod
Expand Up @@ -4,13 +4,12 @@ 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.6
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
github.com/lucas-clemente/quic-go v0.15.7
github.com/minio/sha256-simd v0.1.1
github.com/multiformats/go-multiaddr v0.2.1
github.com/multiformats/go-multiaddr v0.2.2
github.com/multiformats/go-multiaddr-fmt v0.1.0
github.com/multiformats/go-multiaddr-net v0.1.5
github.com/onsi/ginkgo v1.12.0
Expand Down
13 changes: 6 additions & 7 deletions go.sum
Expand Up @@ -110,17 +110,15 @@ github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoR
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs=
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.6 h1:IxFH4PmtLlLdPf4fF/i129SnK/C+/v8WEX644MxhC48=
github.com/libp2p/go-libp2p-core v0.5.6/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo=
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=
github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M=
github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-netroute v0.1.2 h1:UHhB35chwgvcRI392znJA3RCBtZ3MpE3ahNCN5MR4Xg=
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 All @@ -147,11 +145,12 @@ github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI=
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
github.com/multiformats/go-multiaddr v0.2.1 h1:SgG/cw5vqyB5QQe5FPe2TqggU9WtrA9X4nZw7LlVqOI=
github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE=
github.com/multiformats/go-multiaddr v0.2.2 h1:XZLDTszBIJe6m0zF6ITBrEcZR73OPUhCBBS9rYAuUzI=
github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y=
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
github.com/multiformats/go-multiaddr-net v0.1.5 h1:QoRKvu0xHN1FCFJcMQLbG/yQE2z441L5urvG3+qyz7g=
Expand Down
10 changes: 10 additions & 0 deletions listener.go
Expand Up @@ -3,11 +3,14 @@ package libp2pquic
import (
"context"
"crypto/tls"
"fmt"
"net"

ic "github.com/libp2p/go-libp2p-core/crypto"
n "github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
tpt "github.com/libp2p/go-libp2p-core/transport"

p2ptls "github.com/libp2p/go-libp2p-tls"

quic "github.com/lucas-clemente/quic-go"
Expand Down Expand Up @@ -79,6 +82,7 @@ func (l *listener) setupConn(sess quic.Session) (tpt.CapableConn, error) {
if err != nil {
return nil, err
}

remotePeerID, err := peer.IDFromPublicKey(remotePubKey)
if err != nil {
return nil, err
Expand All @@ -87,6 +91,12 @@ func (l *listener) setupConn(sess quic.Session) (tpt.CapableConn, error) {
if err != nil {
return nil, err
}

connaddrs := &connAddrs{lmAddr: l.localMultiaddr, rmAddr: remoteMultiaddr}
if l.transport.gater != nil && !l.transport.gater.InterceptSecured(n.DirInbound, remotePeerID, connaddrs) {
return nil, fmt.Errorf("secured connection gated")
}

return &conn{
sess: sess,
transport: l.transport,
Expand Down
19 changes: 10 additions & 9 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, gater connmgr.ConnectionGater) *reuseConn {
if gater != nil {
conn = newFilteredConn(conn, gater)
}
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
gater connmgr.ConnectionGater

garbageCollectorRunning bool

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

func newReuse(filters *filter.Filters) *reuse {
func newReuse(gater connmgr.ConnectionGater) *reuse {
return &reuse{
filters: filters,
gater: gater,
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.gater)
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.gater)
rconn.IncreaseCount()

r.mutex.Lock()
Expand Down

0 comments on commit 541e8a3

Please sign in to comment.