Browse Source

Merge remote-tracking branch 'origin/master' into multiport

Wade Simmons 2 years ago
parent
commit
a2b9747b0f
4 changed files with 152 additions and 7 deletions
  1. 73 2
      CHANGELOG.md
  2. 8 2
      cert/ca.go
  3. 70 2
      cert/cert.go
  4. 1 1
      connection_manager.go

+ 73 - 2
CHANGELOG.md

@@ -7,12 +7,82 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 
 ## [Unreleased]
 ## [Unreleased]
 
 
+## [1.7.0] - 2023-05-17
+
 ### Added
 ### Added
+
 - `nebula-cert ca` now supports encrypting the CA's private key with a
 - `nebula-cert ca` now supports encrypting the CA's private key with a
   passphrase. Pass `-encrypt` in order to be prompted for a passphrase.
   passphrase. Pass `-encrypt` in order to be prompted for a passphrase.
   Encryption is performed using AES-256-GCM and Argon2id for KDF. KDF
   Encryption is performed using AES-256-GCM and Argon2id for KDF. KDF
   parameters default to RFC recommendations, but can be overridden via CLI
   parameters default to RFC recommendations, but can be overridden via CLI
-  flags `-argon-memory`, `-argon-parallelism`, and `-argon-iterations`.
+  flags `-argon-memory`, `-argon-parallelism`, and `-argon-iterations`. (#386)
+
+- Support for curve P256 and BoringCrypto has been added. See README section
+  "Curve P256 and BoringCrypto" for more details. (#865, #861, #769, #856, #803)
+
+- New firewall rule `local_cidr`. This could be used to filter destinations
+  when using `unsafe_routes`. (#507)
+
+- Add `unsafe_route` option `install`. This controls whether the route is
+  installed in the systems routing table. (#831)
+
+- Add `tun.use_system_route_table` option. Set to true to manage unsafe routes
+  directly on the system route table with gateway routes instead of in Nebula
+  configuration files. This is only supported on Linux. (#839)
+
+- The metric `certificate.ttl_seconds` is now exposed via stats. (#782)
+
+- Add `punchy.respond_delay` option. This allows you to change the delay
+  before attempting punchy.respond. Default is 5 seconds. (#721)
+
+- Added SSH commands to allow the capture of a mutex profile. (#737)
+
+- You can now set `lighthouse.calculated_remotes` to make it possible to do
+  handshakes without a lighthouse in certain configurations. (#759)
+
+- The firewall can be configured to send REJECT replies instead of the default
+  DROP behavior. (#738)
+
+- For macOS, an example launchd configuration file is now provided. (#762)
+
+### Changed
+
+- Lighthouses and other `static_host_map` entries that use DNS names will now
+  be automatically refreshed to detect when the IP address changes. (#796)
+
+- Lighthouses send ACK replies back to clients so that they do not fall into
+  connection testing as often by clients. (#851, #408)
+
+- Allow the `listen.host` option to contain a hostname. (#825)
+
+- When Nebula switches to a new certificate (such as via SIGHUP), we now
+  rehandshake with all existing tunnels. This allows firewall groups to be
+  updated and `pki.disconnect_invalid` to know about the new certificate
+  expiration time. (#838, #857, #842, #840, #835, #828, #820, #807)
+
+### Fixed
+
+- Always disconnect blocklisted hosts, even if `pki.disconnect_invalid` is
+  not set. (#858)
+
+- Dependencies updated and go1.20 required. (#780, #824, #855, #854)
+
+- Fix possible race condition with relays. (#827)
+
+- FreeBSD: Fix connection to the localhost's own Nebula IP. (#808)
+
+- Normalize and document some common log field values. (#837, #811)
+
+- Fix crash if you set unlucky values for the firewall timeout configuration
+  options. (#802)
+
+- Make DNS queries case insensitive. (#793)
+
+- Update example systemd configurations to want `nss-lookup`. (#791)
+
+- Errors with SSH commands now go to the SSH tunnel instead of stderr. (#757)
+
+- Fix a hang when shutting down Android. (#772)
 
 
 ## [1.6.1] - 2022-09-26
 ## [1.6.1] - 2022-09-26
 
 
@@ -405,7 +475,8 @@ created.)
 
 
 - Initial public release.
 - Initial public release.
 
 
-[Unreleased]: https://github.com/slackhq/nebula/compare/v1.6.1...HEAD
+[Unreleased]: https://github.com/slackhq/nebula/compare/v1.7.0...HEAD
+[1.7.0]: https://github.com/slackhq/nebula/releases/tag/v1.7.0
 [1.6.1]: https://github.com/slackhq/nebula/releases/tag/v1.6.1
 [1.6.1]: https://github.com/slackhq/nebula/releases/tag/v1.6.1
 [1.6.0]: https://github.com/slackhq/nebula/releases/tag/v1.6.0
 [1.6.0]: https://github.com/slackhq/nebula/releases/tag/v1.6.0
 [1.5.2]: https://github.com/slackhq/nebula/releases/tag/v1.5.2
 [1.5.2]: https://github.com/slackhq/nebula/releases/tag/v1.5.2

+ 8 - 2
cert/ca.go

@@ -91,9 +91,15 @@ func (ncp *NebulaCAPool) ResetCertBlocklist() {
 	ncp.certBlocklist = make(map[string]struct{})
 	ncp.certBlocklist = make(map[string]struct{})
 }
 }
 
 
-// IsBlocklisted returns true if the fingerprint fails to generate or has been explicitly blocklisted
+// NOTE: This uses an internal cache for Sha256Sum() that will not be invalidated
+// automatically if you manually change any fields in the NebulaCertificate.
 func (ncp *NebulaCAPool) IsBlocklisted(c *NebulaCertificate) bool {
 func (ncp *NebulaCAPool) IsBlocklisted(c *NebulaCertificate) bool {
-	h, err := c.Sha256Sum()
+	return ncp.isBlocklistedWithCache(c, false)
+}
+
+// IsBlocklisted returns true if the fingerprint fails to generate or has been explicitly blocklisted
+func (ncp *NebulaCAPool) isBlocklistedWithCache(c *NebulaCertificate, useCache bool) bool {
+	h, err := c.sha256SumWithCache(useCache)
 	if err != nil {
 	if err != nil {
 		return true
 		return true
 	}
 	}

+ 70 - 2
cert/cert.go

@@ -17,6 +17,7 @@ import (
 	"math"
 	"math"
 	"math/big"
 	"math/big"
 	"net"
 	"net"
+	"sync/atomic"
 	"time"
 	"time"
 
 
 	"golang.org/x/crypto/curve25519"
 	"golang.org/x/crypto/curve25519"
@@ -42,6 +43,14 @@ const (
 type NebulaCertificate struct {
 type NebulaCertificate struct {
 	Details   NebulaCertificateDetails
 	Details   NebulaCertificateDetails
 	Signature []byte
 	Signature []byte
+
+	// the cached hex string of the calculated sha256sum
+	// for VerifyWithCache
+	sha256sum atomic.Pointer[string]
+
+	// the cached public key bytes if they were verified as the signer
+	// for VerifyWithCache
+	signatureVerified atomic.Pointer[[]byte]
 }
 }
 
 
 type NebulaCertificateDetails struct {
 type NebulaCertificateDetails struct {
@@ -562,6 +571,27 @@ func (nc *NebulaCertificate) CheckSignature(key []byte) bool {
 	}
 	}
 }
 }
 
 
+// NOTE: This uses an internal cache that will not be invalidated automatically
+// if you manually change any fields in the NebulaCertificate.
+func (nc *NebulaCertificate) checkSignatureWithCache(key []byte, useCache bool) bool {
+	if !useCache {
+		return nc.CheckSignature(key)
+	}
+
+	if v := nc.signatureVerified.Load(); v != nil {
+		return bytes.Equal(*v, key)
+	}
+
+	verified := nc.CheckSignature(key)
+	if verified {
+		keyCopy := make([]byte, len(key))
+		copy(keyCopy, key)
+		nc.signatureVerified.Store(&keyCopy)
+	}
+
+	return verified
+}
+
 // Expired will return true if the nebula cert is too young or too old compared to the provided time, otherwise false
 // Expired will return true if the nebula cert is too young or too old compared to the provided time, otherwise false
 func (nc *NebulaCertificate) Expired(t time.Time) bool {
 func (nc *NebulaCertificate) Expired(t time.Time) bool {
 	return nc.Details.NotBefore.After(t) || nc.Details.NotAfter.Before(t)
 	return nc.Details.NotBefore.After(t) || nc.Details.NotAfter.Before(t)
@@ -569,7 +599,26 @@ func (nc *NebulaCertificate) Expired(t time.Time) bool {
 
 
 // Verify will ensure a certificate is good in all respects (expiry, group membership, signature, cert blocklist, etc)
 // Verify will ensure a certificate is good in all respects (expiry, group membership, signature, cert blocklist, etc)
 func (nc *NebulaCertificate) Verify(t time.Time, ncp *NebulaCAPool) (bool, error) {
 func (nc *NebulaCertificate) Verify(t time.Time, ncp *NebulaCAPool) (bool, error) {
-	if ncp.IsBlocklisted(nc) {
+	return nc.verify(t, ncp, false)
+}
+
+// VerifyWithCache will ensure a certificate is good in all respects (expiry, group membership, signature, cert blocklist, etc)
+//
+// NOTE: This uses an internal cache that will not be invalidated automatically
+// if you manually change any fields in the NebulaCertificate.
+func (nc *NebulaCertificate) VerifyWithCache(t time.Time, ncp *NebulaCAPool) (bool, error) {
+	return nc.verify(t, ncp, true)
+}
+
+// ResetCache resets the cache used by VerifyWithCache.
+func (nc *NebulaCertificate) ResetCache() {
+	nc.sha256sum.Store(nil)
+	nc.signatureVerified.Store(nil)
+}
+
+// Verify will ensure a certificate is good in all respects (expiry, group membership, signature, cert blocklist, etc)
+func (nc *NebulaCertificate) verify(t time.Time, ncp *NebulaCAPool, useCache bool) (bool, error) {
+	if ncp.isBlocklistedWithCache(nc, useCache) {
 		return false, ErrBlockListed
 		return false, ErrBlockListed
 	}
 	}
 
 
@@ -586,7 +635,7 @@ func (nc *NebulaCertificate) Verify(t time.Time, ncp *NebulaCAPool) (bool, error
 		return false, ErrExpired
 		return false, ErrExpired
 	}
 	}
 
 
-	if !nc.CheckSignature(signer.Details.PublicKey) {
+	if !nc.checkSignatureWithCache(signer.Details.PublicKey, useCache) {
 		return false, ErrSignatureMismatch
 		return false, ErrSignatureMismatch
 	}
 	}
 
 
@@ -809,6 +858,25 @@ func (nc *NebulaCertificate) Sha256Sum() (string, error) {
 	return hex.EncodeToString(sum[:]), nil
 	return hex.EncodeToString(sum[:]), nil
 }
 }
 
 
+// NOTE: This uses an internal cache that will not be invalidated automatically
+// if you manually change any fields in the NebulaCertificate.
+func (nc *NebulaCertificate) sha256SumWithCache(useCache bool) (string, error) {
+	if !useCache {
+		return nc.Sha256Sum()
+	}
+
+	if s := nc.sha256sum.Load(); s != nil {
+		return *s, nil
+	}
+	s, err := nc.Sha256Sum()
+	if err != nil {
+		return s, err
+	}
+
+	nc.sha256sum.Store(&s)
+	return s, nil
+}
+
 func (nc *NebulaCertificate) MarshalJSON() ([]byte, error) {
 func (nc *NebulaCertificate) MarshalJSON() ([]byte, error) {
 	toString := func(ips []*net.IPNet) []string {
 	toString := func(ips []*net.IPNet) []string {
 		s := []string{}
 		s := []string{}

+ 1 - 1
connection_manager.go

@@ -427,7 +427,7 @@ func (n *connectionManager) isInvalidCertificate(now time.Time, hostinfo *HostIn
 		return false
 		return false
 	}
 	}
 
 
-	valid, err := remoteCert.Verify(now, n.intf.caPool)
+	valid, err := remoteCert.VerifyWithCache(now, n.intf.caPool)
 	if valid {
 	if valid {
 		return false
 		return false
 	}
 	}