2019-11-19 10:00:20 -07:00
|
|
|
package nebula
|
|
|
|
|
|
|
|
import (
|
2021-11-02 12:14:26 -06:00
|
|
|
"context"
|
2021-10-20 12:23:33 -06:00
|
|
|
"crypto/ed25519"
|
|
|
|
"crypto/rand"
|
2019-11-19 10:00:20 -07:00
|
|
|
"net"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/flynn/noise"
|
|
|
|
"github.com/slackhq/nebula/cert"
|
2021-11-03 19:54:04 -06:00
|
|
|
"github.com/slackhq/nebula/iputil"
|
2021-11-10 20:47:38 -07:00
|
|
|
"github.com/slackhq/nebula/test"
|
2021-11-03 19:54:04 -06:00
|
|
|
"github.com/slackhq/nebula/udp"
|
2019-12-09 17:53:56 -07:00
|
|
|
"github.com/stretchr/testify/assert"
|
2019-11-19 10:00:20 -07:00
|
|
|
)
|
|
|
|
|
2021-11-03 19:54:04 -06:00
|
|
|
var vpnIp iputil.VpnIp
|
2019-11-19 10:00:20 -07:00
|
|
|
|
|
|
|
func Test_NewConnectionManagerTest(t *testing.T) {
|
2021-11-10 20:47:38 -07:00
|
|
|
l := test.NewLogger()
|
2019-11-19 10:00:20 -07:00
|
|
|
//_, tuncidr, _ := net.ParseCIDR("1.1.1.1/24")
|
|
|
|
_, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
|
|
|
|
_, localrange, _ := net.ParseCIDR("10.1.1.1/24")
|
2021-11-03 19:54:04 -06:00
|
|
|
vpnIp = iputil.Ip2VpnIp(net.ParseIP("172.1.1.2"))
|
2019-11-19 10:00:20 -07:00
|
|
|
preferredRanges := []*net.IPNet{localrange}
|
|
|
|
|
|
|
|
// Very incomplete mock objects
|
2021-03-26 08:46:30 -06:00
|
|
|
hostMap := NewHostMap(l, "test", vpncidr, preferredRanges)
|
2019-11-19 10:00:20 -07:00
|
|
|
cs := &CertState{
|
|
|
|
rawCertificate: []byte{},
|
|
|
|
privateKey: []byte{},
|
|
|
|
certificate: &cert.NebulaCertificate{},
|
|
|
|
rawCertificateNoKey: []byte{},
|
|
|
|
}
|
|
|
|
|
2022-03-14 11:35:13 -06:00
|
|
|
lh := &LightHouse{l: l, atomicStaticList: make(map[iputil.VpnIp]struct{}), atomicLighthouses: make(map[iputil.VpnIp]struct{})}
|
2019-11-19 10:00:20 -07:00
|
|
|
ifce := &Interface{
|
|
|
|
hostMap: hostMap,
|
2021-11-12 09:47:36 -07:00
|
|
|
inside: &test.NoopTun{},
|
2021-11-03 19:54:04 -06:00
|
|
|
outside: &udp.Conn{},
|
2019-11-19 10:00:20 -07:00
|
|
|
certState: cs,
|
|
|
|
firewall: &Firewall{},
|
|
|
|
lightHouse: lh,
|
2021-11-03 19:54:04 -06:00
|
|
|
handshakeManager: NewHandshakeManager(l, vpncidr, preferredRanges, hostMap, lh, &udp.Conn{}, defaultHandshakeConfig),
|
2021-03-26 08:46:30 -06:00
|
|
|
l: l,
|
2019-11-19 10:00:20 -07:00
|
|
|
}
|
|
|
|
now := time.Now()
|
|
|
|
|
|
|
|
// Create manager
|
2021-11-02 12:14:26 -06:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
nc := newConnectionManager(ctx, l, ifce, 5, 10)
|
2020-11-19 16:44:05 -07:00
|
|
|
p := []byte("")
|
|
|
|
nb := make([]byte, 12, 12)
|
|
|
|
out := make([]byte, mtu)
|
|
|
|
nc.HandleMonitorTick(now, p, nb, out)
|
2019-11-19 10:00:20 -07:00
|
|
|
// Add an ip we have established a connection w/ to hostmap
|
2021-11-08 12:46:22 -07:00
|
|
|
hostinfo, _ := nc.hostMap.AddVpnIp(vpnIp, nil)
|
2019-11-19 10:00:20 -07:00
|
|
|
hostinfo.ConnectionState = &ConnectionState{
|
2021-03-05 19:18:33 -07:00
|
|
|
certState: cs,
|
|
|
|
H: &noise.HandshakeState{},
|
2019-11-19 10:00:20 -07:00
|
|
|
}
|
|
|
|
|
2021-11-03 19:54:04 -06:00
|
|
|
// We saw traffic out to vpnIp
|
|
|
|
nc.Out(vpnIp)
|
|
|
|
assert.NotContains(t, nc.pendingDeletion, vpnIp)
|
|
|
|
assert.Contains(t, nc.hostMap.Hosts, vpnIp)
|
2019-11-19 10:00:20 -07:00
|
|
|
// Move ahead 5s. Nothing should happen
|
|
|
|
next_tick := now.Add(5 * time.Second)
|
2020-11-19 16:44:05 -07:00
|
|
|
nc.HandleMonitorTick(next_tick, p, nb, out)
|
2019-11-19 10:00:20 -07:00
|
|
|
nc.HandleDeletionTick(next_tick)
|
|
|
|
// Move ahead 6s. We haven't heard back
|
|
|
|
next_tick = now.Add(6 * time.Second)
|
2020-11-19 16:44:05 -07:00
|
|
|
nc.HandleMonitorTick(next_tick, p, nb, out)
|
2019-11-19 10:00:20 -07:00
|
|
|
nc.HandleDeletionTick(next_tick)
|
|
|
|
// This host should now be up for deletion
|
2021-11-03 19:54:04 -06:00
|
|
|
assert.Contains(t, nc.pendingDeletion, vpnIp)
|
|
|
|
assert.Contains(t, nc.hostMap.Hosts, vpnIp)
|
2019-11-19 10:00:20 -07:00
|
|
|
// Move ahead some more
|
|
|
|
next_tick = now.Add(45 * time.Second)
|
2020-11-19 16:44:05 -07:00
|
|
|
nc.HandleMonitorTick(next_tick, p, nb, out)
|
2019-11-19 10:00:20 -07:00
|
|
|
nc.HandleDeletionTick(next_tick)
|
|
|
|
// The host should be evicted
|
2021-11-03 19:54:04 -06:00
|
|
|
assert.NotContains(t, nc.pendingDeletion, vpnIp)
|
|
|
|
assert.NotContains(t, nc.hostMap.Hosts, vpnIp)
|
2019-11-19 10:00:20 -07:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_NewConnectionManagerTest2(t *testing.T) {
|
2021-11-10 20:47:38 -07:00
|
|
|
l := test.NewLogger()
|
2019-11-19 10:00:20 -07:00
|
|
|
//_, tuncidr, _ := net.ParseCIDR("1.1.1.1/24")
|
|
|
|
_, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
|
|
|
|
_, localrange, _ := net.ParseCIDR("10.1.1.1/24")
|
|
|
|
preferredRanges := []*net.IPNet{localrange}
|
|
|
|
|
|
|
|
// Very incomplete mock objects
|
2021-03-26 08:46:30 -06:00
|
|
|
hostMap := NewHostMap(l, "test", vpncidr, preferredRanges)
|
2019-11-19 10:00:20 -07:00
|
|
|
cs := &CertState{
|
|
|
|
rawCertificate: []byte{},
|
|
|
|
privateKey: []byte{},
|
|
|
|
certificate: &cert.NebulaCertificate{},
|
|
|
|
rawCertificateNoKey: []byte{},
|
|
|
|
}
|
|
|
|
|
2022-03-14 11:35:13 -06:00
|
|
|
lh := &LightHouse{l: l, atomicStaticList: make(map[iputil.VpnIp]struct{}), atomicLighthouses: make(map[iputil.VpnIp]struct{})}
|
2019-11-19 10:00:20 -07:00
|
|
|
ifce := &Interface{
|
|
|
|
hostMap: hostMap,
|
2021-11-12 09:47:36 -07:00
|
|
|
inside: &test.NoopTun{},
|
2021-11-03 19:54:04 -06:00
|
|
|
outside: &udp.Conn{},
|
2019-11-19 10:00:20 -07:00
|
|
|
certState: cs,
|
|
|
|
firewall: &Firewall{},
|
|
|
|
lightHouse: lh,
|
2021-11-03 19:54:04 -06:00
|
|
|
handshakeManager: NewHandshakeManager(l, vpncidr, preferredRanges, hostMap, lh, &udp.Conn{}, defaultHandshakeConfig),
|
2021-03-26 08:46:30 -06:00
|
|
|
l: l,
|
2019-11-19 10:00:20 -07:00
|
|
|
}
|
|
|
|
now := time.Now()
|
|
|
|
|
|
|
|
// Create manager
|
2021-11-02 12:14:26 -06:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
nc := newConnectionManager(ctx, l, ifce, 5, 10)
|
2020-11-19 16:44:05 -07:00
|
|
|
p := []byte("")
|
|
|
|
nb := make([]byte, 12, 12)
|
|
|
|
out := make([]byte, mtu)
|
|
|
|
nc.HandleMonitorTick(now, p, nb, out)
|
2019-11-19 10:00:20 -07:00
|
|
|
// Add an ip we have established a connection w/ to hostmap
|
2021-11-08 12:46:22 -07:00
|
|
|
hostinfo, _ := nc.hostMap.AddVpnIp(vpnIp, nil)
|
2019-11-19 10:00:20 -07:00
|
|
|
hostinfo.ConnectionState = &ConnectionState{
|
2021-03-05 19:18:33 -07:00
|
|
|
certState: cs,
|
|
|
|
H: &noise.HandshakeState{},
|
2019-11-19 10:00:20 -07:00
|
|
|
}
|
|
|
|
|
2021-11-03 19:54:04 -06:00
|
|
|
// We saw traffic out to vpnIp
|
|
|
|
nc.Out(vpnIp)
|
|
|
|
assert.NotContains(t, nc.pendingDeletion, vpnIp)
|
|
|
|
assert.Contains(t, nc.hostMap.Hosts, vpnIp)
|
2019-11-19 10:00:20 -07:00
|
|
|
// Move ahead 5s. Nothing should happen
|
|
|
|
next_tick := now.Add(5 * time.Second)
|
2020-11-19 16:44:05 -07:00
|
|
|
nc.HandleMonitorTick(next_tick, p, nb, out)
|
2019-11-19 10:00:20 -07:00
|
|
|
nc.HandleDeletionTick(next_tick)
|
|
|
|
// Move ahead 6s. We haven't heard back
|
|
|
|
next_tick = now.Add(6 * time.Second)
|
2020-11-19 16:44:05 -07:00
|
|
|
nc.HandleMonitorTick(next_tick, p, nb, out)
|
2019-11-19 10:00:20 -07:00
|
|
|
nc.HandleDeletionTick(next_tick)
|
|
|
|
// This host should now be up for deletion
|
2021-11-03 19:54:04 -06:00
|
|
|
assert.Contains(t, nc.pendingDeletion, vpnIp)
|
|
|
|
assert.Contains(t, nc.hostMap.Hosts, vpnIp)
|
2019-11-19 10:00:20 -07:00
|
|
|
// We heard back this time
|
2021-11-03 19:54:04 -06:00
|
|
|
nc.In(vpnIp)
|
2019-11-19 10:00:20 -07:00
|
|
|
// Move ahead some more
|
|
|
|
next_tick = now.Add(45 * time.Second)
|
2020-11-19 16:44:05 -07:00
|
|
|
nc.HandleMonitorTick(next_tick, p, nb, out)
|
2019-11-19 10:00:20 -07:00
|
|
|
nc.HandleDeletionTick(next_tick)
|
|
|
|
// The host should be evicted
|
2021-11-03 19:54:04 -06:00
|
|
|
assert.NotContains(t, nc.pendingDeletion, vpnIp)
|
|
|
|
assert.Contains(t, nc.hostMap.Hosts, vpnIp)
|
2019-11-19 10:00:20 -07:00
|
|
|
|
|
|
|
}
|
2021-10-20 12:23:33 -06:00
|
|
|
|
|
|
|
// Check if we can disconnect the peer.
|
|
|
|
// Validate if the peer's certificate is invalid (expired, etc.)
|
|
|
|
// Disconnect only if disconnectInvalid: true is set.
|
|
|
|
func Test_NewConnectionManagerTest_DisconnectInvalid(t *testing.T) {
|
|
|
|
now := time.Now()
|
2021-11-10 20:47:38 -07:00
|
|
|
l := test.NewLogger()
|
2021-10-20 12:23:33 -06:00
|
|
|
ipNet := net.IPNet{
|
|
|
|
IP: net.IPv4(172, 1, 1, 2),
|
|
|
|
Mask: net.IPMask{255, 255, 255, 0},
|
|
|
|
}
|
|
|
|
_, vpncidr, _ := net.ParseCIDR("172.1.1.1/24")
|
|
|
|
_, localrange, _ := net.ParseCIDR("10.1.1.1/24")
|
|
|
|
preferredRanges := []*net.IPNet{localrange}
|
|
|
|
hostMap := NewHostMap(l, "test", vpncidr, preferredRanges)
|
|
|
|
|
|
|
|
// Generate keys for CA and peer's cert.
|
|
|
|
pubCA, privCA, _ := ed25519.GenerateKey(rand.Reader)
|
|
|
|
caCert := cert.NebulaCertificate{
|
|
|
|
Details: cert.NebulaCertificateDetails{
|
|
|
|
Name: "ca",
|
|
|
|
NotBefore: now,
|
|
|
|
NotAfter: now.Add(1 * time.Hour),
|
|
|
|
IsCA: true,
|
|
|
|
PublicKey: pubCA,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
caCert.Sign(privCA)
|
|
|
|
ncp := &cert.NebulaCAPool{
|
|
|
|
CAs: cert.NewCAPool().CAs,
|
|
|
|
}
|
|
|
|
ncp.CAs["ca"] = &caCert
|
|
|
|
|
|
|
|
pubCrt, _, _ := ed25519.GenerateKey(rand.Reader)
|
|
|
|
peerCert := cert.NebulaCertificate{
|
|
|
|
Details: cert.NebulaCertificateDetails{
|
|
|
|
Name: "host",
|
|
|
|
Ips: []*net.IPNet{&ipNet},
|
|
|
|
Subnets: []*net.IPNet{},
|
|
|
|
NotBefore: now,
|
|
|
|
NotAfter: now.Add(60 * time.Second),
|
|
|
|
PublicKey: pubCrt,
|
|
|
|
IsCA: false,
|
|
|
|
Issuer: "ca",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
peerCert.Sign(privCA)
|
|
|
|
|
|
|
|
cs := &CertState{
|
|
|
|
rawCertificate: []byte{},
|
|
|
|
privateKey: []byte{},
|
|
|
|
certificate: &cert.NebulaCertificate{},
|
|
|
|
rawCertificateNoKey: []byte{},
|
|
|
|
}
|
|
|
|
|
2022-03-14 11:35:13 -06:00
|
|
|
lh := &LightHouse{l: l, atomicStaticList: make(map[iputil.VpnIp]struct{}), atomicLighthouses: make(map[iputil.VpnIp]struct{})}
|
2021-10-20 12:23:33 -06:00
|
|
|
ifce := &Interface{
|
|
|
|
hostMap: hostMap,
|
2021-11-12 09:47:36 -07:00
|
|
|
inside: &test.NoopTun{},
|
2021-11-03 19:54:04 -06:00
|
|
|
outside: &udp.Conn{},
|
2021-10-20 12:23:33 -06:00
|
|
|
certState: cs,
|
|
|
|
firewall: &Firewall{},
|
|
|
|
lightHouse: lh,
|
2021-11-03 19:54:04 -06:00
|
|
|
handshakeManager: NewHandshakeManager(l, vpncidr, preferredRanges, hostMap, lh, &udp.Conn{}, defaultHandshakeConfig),
|
2021-10-20 12:23:33 -06:00
|
|
|
l: l,
|
|
|
|
disconnectInvalid: true,
|
|
|
|
caPool: ncp,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create manager
|
2021-11-02 12:14:26 -06:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
nc := newConnectionManager(ctx, l, ifce, 5, 10)
|
2021-10-20 12:23:33 -06:00
|
|
|
ifce.connectionManager = nc
|
2021-11-08 12:46:22 -07:00
|
|
|
hostinfo, _ := nc.hostMap.AddVpnIp(vpnIp, nil)
|
2021-10-20 12:23:33 -06:00
|
|
|
hostinfo.ConnectionState = &ConnectionState{
|
|
|
|
certState: cs,
|
|
|
|
peerCert: &peerCert,
|
|
|
|
H: &noise.HandshakeState{},
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move ahead 45s.
|
|
|
|
// Check if to disconnect with invalid certificate.
|
|
|
|
// Should be alive.
|
|
|
|
nextTick := now.Add(45 * time.Second)
|
2021-11-03 19:54:04 -06:00
|
|
|
destroyed := nc.handleInvalidCertificate(nextTick, vpnIp, hostinfo)
|
2021-10-20 12:23:33 -06:00
|
|
|
assert.False(t, destroyed)
|
|
|
|
|
|
|
|
// Move ahead 61s.
|
|
|
|
// Check if to disconnect with invalid certificate.
|
|
|
|
// Should be disconnected.
|
|
|
|
nextTick = now.Add(61 * time.Second)
|
2021-11-03 19:54:04 -06:00
|
|
|
destroyed = nc.handleInvalidCertificate(nextTick, vpnIp, hostinfo)
|
2021-10-20 12:23:33 -06:00
|
|
|
assert.True(t, destroyed)
|
|
|
|
}
|