mirror of
https://github.com/slackhq/nebula.git
synced 2026-05-15 20:37:36 +02:00
Switch to slog, remove logrus (#1672)
This commit is contained in:
541
handshake_ix.go
541
handshake_ix.go
@@ -2,11 +2,12 @@ package nebula
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/flynn/noise"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/slackhq/nebula/cert"
|
||||
"github.com/slackhq/nebula/header"
|
||||
)
|
||||
@@ -18,8 +19,11 @@ import (
|
||||
func ixHandshakeStage0(f *Interface, hh *HandshakeHostInfo) bool {
|
||||
err := f.handshakeManager.allocateIndex(hh)
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("vpnAddrs", hh.hostinfo.vpnAddrs).
|
||||
WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).Error("Failed to generate index")
|
||||
f.l.Error("Failed to generate index",
|
||||
"error", err,
|
||||
"vpnAddrs", hh.hostinfo.vpnAddrs,
|
||||
"handshake", m{"stage": 0, "style": "ix_psk0"},
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -39,28 +43,32 @@ func ixHandshakeStage0(f *Interface, hh *HandshakeHostInfo) bool {
|
||||
|
||||
crt := cs.getCertificate(v)
|
||||
if crt == nil {
|
||||
f.l.WithField("vpnAddrs", hh.hostinfo.vpnAddrs).
|
||||
WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).
|
||||
WithField("certVersion", v).
|
||||
Error("Unable to handshake with host because no certificate is available")
|
||||
f.l.Error("Unable to handshake with host because no certificate is available",
|
||||
"vpnAddrs", hh.hostinfo.vpnAddrs,
|
||||
"handshake", m{"stage": 0, "style": "ix_psk0"},
|
||||
"certVersion", v,
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
crtHs := cs.getHandshakeBytes(v)
|
||||
if crtHs == nil {
|
||||
f.l.WithField("vpnAddrs", hh.hostinfo.vpnAddrs).
|
||||
WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).
|
||||
WithField("certVersion", v).
|
||||
Error("Unable to handshake with host because no certificate handshake bytes is available")
|
||||
f.l.Error("Unable to handshake with host because no certificate handshake bytes is available",
|
||||
"vpnAddrs", hh.hostinfo.vpnAddrs,
|
||||
"handshake", m{"stage": 0, "style": "ix_psk0"},
|
||||
"certVersion", v,
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
ci, err := NewConnectionState(f.l, cs, crt, true, noise.HandshakeIX)
|
||||
ci, err := NewConnectionState(cs, crt, true, noise.HandshakeIX)
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("vpnAddrs", hh.hostinfo.vpnAddrs).
|
||||
WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).
|
||||
WithField("certVersion", v).
|
||||
Error("Failed to create connection state")
|
||||
f.l.Error("Failed to create connection state",
|
||||
"error", err,
|
||||
"vpnAddrs", hh.hostinfo.vpnAddrs,
|
||||
"handshake", m{"stage": 0, "style": "ix_psk0"},
|
||||
"certVersion", v,
|
||||
)
|
||||
return false
|
||||
}
|
||||
hh.hostinfo.ConnectionState = ci
|
||||
@@ -76,9 +84,12 @@ func ixHandshakeStage0(f *Interface, hh *HandshakeHostInfo) bool {
|
||||
|
||||
hsBytes, err := hs.Marshal()
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("vpnAddrs", hh.hostinfo.vpnAddrs).
|
||||
WithField("certVersion", v).
|
||||
WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).Error("Failed to marshal handshake message")
|
||||
f.l.Error("Failed to marshal handshake message",
|
||||
"error", err,
|
||||
"vpnAddrs", hh.hostinfo.vpnAddrs,
|
||||
"certVersion", v,
|
||||
"handshake", m{"stage": 0, "style": "ix_psk0"},
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -86,8 +97,11 @@ func ixHandshakeStage0(f *Interface, hh *HandshakeHostInfo) bool {
|
||||
|
||||
msg, _, _, err := ci.H.WriteMessage(h, hsBytes)
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("vpnAddrs", hh.hostinfo.vpnAddrs).
|
||||
WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).Error("Failed to call noise.WriteMessage")
|
||||
f.l.Error("Failed to call noise.WriteMessage",
|
||||
"error", err,
|
||||
"vpnAddrs", hh.hostinfo.vpnAddrs,
|
||||
"handshake", m{"stage": 0, "style": "ix_psk0"},
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -104,18 +118,21 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
cs := f.pki.getCertState()
|
||||
crt := cs.GetDefaultCertificate()
|
||||
if crt == nil {
|
||||
f.l.WithField("from", via).
|
||||
WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).
|
||||
WithField("certVersion", cs.initiatingVersion).
|
||||
Error("Unable to handshake with host because no certificate is available")
|
||||
f.l.Error("Unable to handshake with host because no certificate is available",
|
||||
"from", via,
|
||||
"handshake", m{"stage": 0, "style": "ix_psk0"},
|
||||
"certVersion", cs.initiatingVersion,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
ci, err := NewConnectionState(f.l, cs, crt, false, noise.HandshakeIX)
|
||||
ci, err := NewConnectionState(cs, crt, false, noise.HandshakeIX)
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
Error("Failed to create connection state")
|
||||
f.l.Error("Failed to create connection state",
|
||||
"error", err,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,26 +141,32 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
|
||||
msg, _, _, err := ci.H.ReadMessage(nil, packet[header.Len:])
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
Error("Failed to call noise.ReadMessage")
|
||||
f.l.Error("Failed to call noise.ReadMessage",
|
||||
"error", err,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
hs := &NebulaHandshake{}
|
||||
err = hs.Unmarshal(msg)
|
||||
if err != nil || hs.Details == nil {
|
||||
f.l.WithError(err).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
Error("Failed unmarshal handshake message")
|
||||
f.l.Error("Failed unmarshal handshake message",
|
||||
"error", err,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
rc, err := cert.Recombine(cert.Version(hs.Details.CertVersion), hs.Details.Cert, ci.H.PeerStatic(), ci.Curve())
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
Info("Handshake did not contain a certificate")
|
||||
f.l.Info("Handshake did not contain a certificate",
|
||||
"error", err,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -154,23 +177,30 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
fp = "<error generating certificate fingerprint>"
|
||||
}
|
||||
|
||||
e := f.l.WithError(err).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
WithField("certVpnNetworks", rc.Networks()).
|
||||
WithField("certFingerprint", fp)
|
||||
|
||||
if f.l.Level >= logrus.DebugLevel {
|
||||
e = e.WithField("cert", rc)
|
||||
attrs := []slog.Attr{
|
||||
slog.Any("error", err),
|
||||
slog.Any("from", via),
|
||||
slog.Any("handshake", m{"stage": 1, "style": "ix_psk0"}),
|
||||
slog.Any("certVpnNetworks", rc.Networks()),
|
||||
slog.String("certFingerprint", fp),
|
||||
}
|
||||
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
||||
attrs = append(attrs, slog.Any("cert", rc))
|
||||
}
|
||||
|
||||
e.Info("Invalid certificate from host")
|
||||
// LogAttrs is intentional: attrs is a pre-built []slog.Attr slice that
|
||||
// callers grow conditionally, which has no pair-form equivalent.
|
||||
//nolint:sloglint
|
||||
f.l.LogAttrs(context.Background(), slog.LevelInfo, "Invalid certificate from host", attrs...)
|
||||
return
|
||||
}
|
||||
|
||||
if !bytes.Equal(remoteCert.Certificate.PublicKey(), ci.H.PeerStatic()) {
|
||||
f.l.WithField("from", via).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
WithField("cert", remoteCert).Info("public key mismatch between certificate and handshake")
|
||||
f.l.Info("public key mismatch between certificate and handshake",
|
||||
"from", via,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
"cert", remoteCert,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -178,12 +208,13 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
// We started off using the wrong certificate version, lets see if we can match the version that was sent to us
|
||||
myCertOtherVersion := cs.getCertificate(remoteCert.Certificate.Version())
|
||||
if myCertOtherVersion == nil {
|
||||
if f.l.Level >= logrus.DebugLevel {
|
||||
f.l.WithError(err).WithFields(m{
|
||||
"from": via,
|
||||
"handshake": m{"stage": 1, "style": "ix_psk0"},
|
||||
"cert": remoteCert,
|
||||
}).Debug("Might be unable to handshake with host due to missing certificate version")
|
||||
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
||||
f.l.Debug("Might be unable to handshake with host due to missing certificate version",
|
||||
"error", err,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
"cert", remoteCert,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Record the certificate we are actually using
|
||||
@@ -192,10 +223,12 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
}
|
||||
|
||||
if len(remoteCert.Certificate.Networks()) == 0 {
|
||||
f.l.WithError(err).WithField("from", via).
|
||||
WithField("cert", remoteCert).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
Info("No networks in certificate")
|
||||
f.l.Info("No networks in certificate",
|
||||
"error", err,
|
||||
"from", via,
|
||||
"cert", remoteCert,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -209,12 +242,15 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
vpnAddrs := make([]netip.Addr, len(vpnNetworks))
|
||||
for i, network := range vpnNetworks {
|
||||
if f.myVpnAddrsTable.Contains(network.Addr()) {
|
||||
f.l.WithField("vpnNetworks", vpnNetworks).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Refusing to handshake with myself")
|
||||
f.l.Error("Refusing to handshake with myself",
|
||||
"vpnNetworks", vpnNetworks,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
vpnAddrs[i] = network.Addr()
|
||||
@@ -226,20 +262,28 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
if !via.IsRelayed {
|
||||
// We only want to apply the remote allow list for direct tunnels here
|
||||
if !f.lightHouse.GetRemoteAllowList().AllowAll(vpnAddrs, via.UdpAddr.Addr()) {
|
||||
f.l.WithField("vpnAddrs", vpnAddrs).WithField("from", via).
|
||||
Debug("lighthouse.remote_allow_list denied incoming handshake")
|
||||
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
||||
f.l.Debug("lighthouse.remote_allow_list denied incoming handshake",
|
||||
"vpnAddrs", vpnAddrs,
|
||||
"from", via,
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
myIndex, err := generateIndex(f.l)
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("vpnAddrs", vpnAddrs).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to generate index")
|
||||
f.l.Error("Failed to generate index",
|
||||
"error", err,
|
||||
"vpnAddrs", vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -257,18 +301,18 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
},
|
||||
}
|
||||
|
||||
msgRxL := f.l.WithFields(m{
|
||||
"vpnAddrs": vpnAddrs,
|
||||
"from": via,
|
||||
"certName": certName,
|
||||
"certVersion": certVersion,
|
||||
"fingerprint": fingerprint,
|
||||
"issuer": issuer,
|
||||
"initiatorIndex": hs.Details.InitiatorIndex,
|
||||
"responderIndex": hs.Details.ResponderIndex,
|
||||
"remoteIndex": h.RemoteIndex,
|
||||
"handshake": m{"stage": 1, "style": "ix_psk0"},
|
||||
})
|
||||
msgRxL := f.l.With(
|
||||
"vpnAddrs", vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"initiatorIndex", hs.Details.InitiatorIndex,
|
||||
"responderIndex", hs.Details.ResponderIndex,
|
||||
"remoteIndex", h.RemoteIndex,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
|
||||
if anyVpnAddrsInCommon {
|
||||
msgRxL.Info("Handshake message received")
|
||||
@@ -280,8 +324,9 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
hs.Details.ResponderIndex = myIndex
|
||||
hs.Details.Cert = cs.getHandshakeBytes(ci.myCert.Version())
|
||||
if hs.Details.Cert == nil {
|
||||
msgRxL.WithField("myCertVersion", ci.myCert.Version()).
|
||||
Error("Unable to handshake with host because no certificate handshake bytes is available")
|
||||
msgRxL.Error("Unable to handshake with host because no certificate handshake bytes is available",
|
||||
"myCertVersion", ci.myCert.Version(),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -291,32 +336,43 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
|
||||
hsBytes, err := hs.Marshal()
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("vpnAddrs", hostinfo.vpnAddrs).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to marshal handshake message")
|
||||
f.l.Error("Failed to marshal handshake message",
|
||||
"error", err,
|
||||
"vpnAddrs", hostinfo.vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
nh := header.Encode(make([]byte, header.Len), header.Version, header.Handshake, header.HandshakeIXPSK0, hs.Details.InitiatorIndex, 2)
|
||||
msg, dKey, eKey, err := ci.H.WriteMessage(nh, hsBytes)
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("vpnAddrs", hostinfo.vpnAddrs).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to call noise.WriteMessage")
|
||||
f.l.Error("Failed to call noise.WriteMessage",
|
||||
"error", err,
|
||||
"vpnAddrs", hostinfo.vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
} else if dKey == nil || eKey == nil {
|
||||
f.l.WithField("vpnAddrs", hostinfo.vpnAddrs).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Noise did not arrive at a key")
|
||||
f.l.Error("Noise did not arrive at a key",
|
||||
"vpnAddrs", hostinfo.vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -358,13 +414,20 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
if !via.IsRelayed {
|
||||
err := f.outside.WriteTo(msg, via.UdpAddr)
|
||||
if err != nil {
|
||||
f.l.WithField("vpnAddrs", existing.vpnAddrs).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("cached", true).
|
||||
WithError(err).Error("Failed to send handshake message")
|
||||
f.l.Error("Failed to send handshake message",
|
||||
"vpnAddrs", existing.vpnAddrs,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
"cached", true,
|
||||
"error", err,
|
||||
)
|
||||
} else {
|
||||
f.l.WithField("vpnAddrs", existing.vpnAddrs).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("cached", true).
|
||||
Info("Handshake message sent")
|
||||
f.l.Info("Handshake message sent",
|
||||
"vpnAddrs", existing.vpnAddrs,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
"cached", true,
|
||||
)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
@@ -374,50 +437,67 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
}
|
||||
hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
|
||||
f.SendVia(via.relayHI, via.relay, msg, make([]byte, 12), make([]byte, mtu), false)
|
||||
f.l.WithField("vpnAddrs", existing.vpnAddrs).WithField("relay", via.relayHI.vpnAddrs[0]).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("cached", true).
|
||||
Info("Handshake message sent")
|
||||
f.l.Info("Handshake message sent",
|
||||
"vpnAddrs", existing.vpnAddrs,
|
||||
"relay", via.relayHI.vpnAddrs[0],
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
"cached", true,
|
||||
)
|
||||
return
|
||||
}
|
||||
case ErrExistingHostInfo:
|
||||
// This means there was an existing tunnel and this handshake was older than the one we are currently based on
|
||||
f.l.WithField("vpnAddrs", vpnAddrs).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("oldHandshakeTime", existing.lastHandshakeTime).
|
||||
WithField("newHandshakeTime", hostinfo.lastHandshakeTime).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
|
||||
WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
Info("Handshake too old")
|
||||
f.l.Info("Handshake too old",
|
||||
"vpnAddrs", vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"oldHandshakeTime", existing.lastHandshakeTime,
|
||||
"newHandshakeTime", hostinfo.lastHandshakeTime,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"initiatorIndex", hs.Details.InitiatorIndex,
|
||||
"responderIndex", hs.Details.ResponderIndex,
|
||||
"remoteIndex", h.RemoteIndex,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
|
||||
// Send a test packet to trigger an authenticated tunnel test, this should suss out any lingering tunnel issues
|
||||
f.SendMessageToVpnAddr(header.Test, header.TestRequest, vpnAddrs[0], []byte(""), make([]byte, 12, 12), make([]byte, mtu))
|
||||
return
|
||||
case ErrLocalIndexCollision:
|
||||
// This means we failed to insert because of collision on localIndexId. Just let the next handshake packet retry
|
||||
f.l.WithField("vpnAddrs", vpnAddrs).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
|
||||
WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
WithField("localIndex", hostinfo.localIndexId).WithField("collision", existing.vpnAddrs).
|
||||
Error("Failed to add HostInfo due to localIndex collision")
|
||||
f.l.Error("Failed to add HostInfo due to localIndex collision",
|
||||
"vpnAddrs", vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"initiatorIndex", hs.Details.InitiatorIndex,
|
||||
"responderIndex", hs.Details.ResponderIndex,
|
||||
"remoteIndex", h.RemoteIndex,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
"localIndex", hostinfo.localIndexId,
|
||||
"collision", existing.vpnAddrs,
|
||||
)
|
||||
return
|
||||
default:
|
||||
// Shouldn't happen, but just in case someone adds a new error type to CheckAndComplete
|
||||
// And we forget to update it here
|
||||
f.l.WithError(err).WithField("vpnAddrs", vpnAddrs).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
|
||||
WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
|
||||
Error("Failed to add HostInfo to HostMap")
|
||||
f.l.Error("Failed to add HostInfo to HostMap",
|
||||
"error", err,
|
||||
"vpnAddrs", vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"initiatorIndex", hs.Details.InitiatorIndex,
|
||||
"responderIndex", hs.Details.ResponderIndex,
|
||||
"remoteIndex", h.RemoteIndex,
|
||||
"handshake", m{"stage": 1, "style": "ix_psk0"},
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -426,15 +506,20 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
f.messageMetrics.Tx(header.Handshake, header.MessageSubType(msg[1]), 1)
|
||||
if !via.IsRelayed {
|
||||
err = f.outside.WriteTo(msg, via.UdpAddr)
|
||||
log := f.l.WithField("vpnAddrs", vpnAddrs).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
|
||||
WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"})
|
||||
log := f.l.With(
|
||||
"vpnAddrs", vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"initiatorIndex", hs.Details.InitiatorIndex,
|
||||
"responderIndex", hs.Details.ResponderIndex,
|
||||
"remoteIndex", h.RemoteIndex,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to send handshake")
|
||||
log.Error("Failed to send handshake", "error", err)
|
||||
} else {
|
||||
log.Info("Handshake message sent")
|
||||
}
|
||||
@@ -448,14 +533,18 @@ func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H)
|
||||
// it's correctly marked as working.
|
||||
via.relayHI.relayState.UpdateRelayForByIdxState(via.remoteIdx, Established)
|
||||
f.SendVia(via.relayHI, via.relay, msg, make([]byte, 12), make([]byte, mtu), false)
|
||||
f.l.WithField("vpnAddrs", vpnAddrs).WithField("relay", via.relayHI.vpnAddrs[0]).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
|
||||
WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
|
||||
Info("Handshake message sent")
|
||||
f.l.Info("Handshake message sent",
|
||||
"vpnAddrs", vpnAddrs,
|
||||
"relay", via.relayHI.vpnAddrs[0],
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"initiatorIndex", hs.Details.InitiatorIndex,
|
||||
"responderIndex", hs.Details.ResponderIndex,
|
||||
"remoteIndex", h.RemoteIndex,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
)
|
||||
}
|
||||
|
||||
f.connectionManager.AddTrafficWatch(hostinfo)
|
||||
@@ -483,7 +572,12 @@ func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packe
|
||||
if !via.IsRelayed {
|
||||
// The vpnAddr we know about is the one we tried to handshake with, use it to apply the remote allow list.
|
||||
if !f.lightHouse.GetRemoteAllowList().AllowAll(hostinfo.vpnAddrs, via.UdpAddr.Addr()) {
|
||||
f.l.WithField("vpnAddrs", hostinfo.vpnAddrs).WithField("from", via).Debug("lighthouse.remote_allow_list denied incoming handshake")
|
||||
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
||||
f.l.Debug("lighthouse.remote_allow_list denied incoming handshake",
|
||||
"vpnAddrs", hostinfo.vpnAddrs,
|
||||
"from", via,
|
||||
)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -491,18 +585,24 @@ func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packe
|
||||
ci := hostinfo.ConnectionState
|
||||
msg, eKey, dKey, err := ci.H.ReadMessage(nil, packet[header.Len:])
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("vpnAddrs", hostinfo.vpnAddrs).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("header", h).
|
||||
Error("Failed to call noise.ReadMessage")
|
||||
f.l.Error("Failed to call noise.ReadMessage",
|
||||
"error", err,
|
||||
"vpnAddrs", hostinfo.vpnAddrs,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
"header", h,
|
||||
)
|
||||
|
||||
// We don't want to tear down the connection on a bad ReadMessage because it could be an attacker trying
|
||||
// to DOS us. Every other error condition after should to allow a possible good handshake to complete in the
|
||||
// near future
|
||||
return false
|
||||
} else if dKey == nil || eKey == nil {
|
||||
f.l.WithField("vpnAddrs", hostinfo.vpnAddrs).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
|
||||
Error("Noise did not arrive at a key")
|
||||
f.l.Error("Noise did not arrive at a key",
|
||||
"vpnAddrs", hostinfo.vpnAddrs,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
)
|
||||
|
||||
// This should be impossible in IX but just in case, if we get here then there is no chance to recover
|
||||
// the handshake state machine. Tear it down
|
||||
@@ -512,8 +612,12 @@ func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packe
|
||||
hs := &NebulaHandshake{}
|
||||
err = hs.Unmarshal(msg)
|
||||
if err != nil || hs.Details == nil {
|
||||
f.l.WithError(err).WithField("vpnAddrs", hostinfo.vpnAddrs).WithField("from", via).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).Error("Failed unmarshal handshake message")
|
||||
f.l.Error("Failed unmarshal handshake message",
|
||||
"error", err,
|
||||
"vpnAddrs", hostinfo.vpnAddrs,
|
||||
"from", via,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
)
|
||||
|
||||
// The handshake state machine is complete, if things break now there is no chance to recover. Tear down and start again
|
||||
return true
|
||||
@@ -521,10 +625,12 @@ func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packe
|
||||
|
||||
rc, err := cert.Recombine(cert.Version(hs.Details.CertVersion), hs.Details.Cert, ci.H.PeerStatic(), ci.Curve())
|
||||
if err != nil {
|
||||
f.l.WithError(err).WithField("from", via).
|
||||
WithField("vpnAddrs", hostinfo.vpnAddrs).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
|
||||
Info("Handshake did not contain a certificate")
|
||||
f.l.Info("Handshake did not contain a certificate",
|
||||
"error", err,
|
||||
"from", via,
|
||||
"vpnAddrs", hostinfo.vpnAddrs,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -535,32 +641,41 @@ func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packe
|
||||
fp = "<error generating certificate fingerprint>"
|
||||
}
|
||||
|
||||
e := f.l.WithError(err).WithField("from", via).
|
||||
WithField("vpnAddrs", hostinfo.vpnAddrs).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
|
||||
WithField("certFingerprint", fp).
|
||||
WithField("certVpnNetworks", rc.Networks())
|
||||
|
||||
if f.l.Level >= logrus.DebugLevel {
|
||||
e = e.WithField("cert", rc)
|
||||
attrs := []slog.Attr{
|
||||
slog.Any("error", err),
|
||||
slog.Any("from", via),
|
||||
slog.Any("vpnAddrs", hostinfo.vpnAddrs),
|
||||
slog.Any("handshake", m{"stage": 2, "style": "ix_psk0"}),
|
||||
slog.String("certFingerprint", fp),
|
||||
slog.Any("certVpnNetworks", rc.Networks()),
|
||||
}
|
||||
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
||||
attrs = append(attrs, slog.Any("cert", rc))
|
||||
}
|
||||
|
||||
e.Info("Invalid certificate from host")
|
||||
// LogAttrs is intentional: attrs is a pre-built []slog.Attr slice that
|
||||
// callers grow conditionally, which has no pair-form equivalent.
|
||||
//nolint:sloglint
|
||||
f.l.LogAttrs(context.Background(), slog.LevelInfo, "Invalid certificate from host", attrs...)
|
||||
return true
|
||||
}
|
||||
if !bytes.Equal(remoteCert.Certificate.PublicKey(), ci.H.PeerStatic()) {
|
||||
f.l.WithField("from", via).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
|
||||
WithField("cert", remoteCert).Info("public key mismatch between certificate and handshake")
|
||||
f.l.Info("public key mismatch between certificate and handshake",
|
||||
"from", via,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
"cert", remoteCert,
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
if len(remoteCert.Certificate.Networks()) == 0 {
|
||||
f.l.WithError(err).WithField("from", via).
|
||||
WithField("vpnAddrs", hostinfo.vpnAddrs).
|
||||
WithField("cert", remoteCert).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
|
||||
Info("No networks in certificate")
|
||||
f.l.Info("No networks in certificate",
|
||||
"error", err,
|
||||
"from", via,
|
||||
"vpnAddrs", hostinfo.vpnAddrs,
|
||||
"cert", remoteCert,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -601,12 +716,14 @@ func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packe
|
||||
|
||||
// Ensure the right host responded
|
||||
if !correctHostResponded {
|
||||
f.l.WithField("intendedVpnAddrs", hostinfo.vpnAddrs).WithField("haveVpnNetworks", vpnNetworks).
|
||||
WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
|
||||
Info("Incorrect host responded to handshake")
|
||||
f.l.Info("Incorrect host responded to handshake",
|
||||
"intendedVpnAddrs", hostinfo.vpnAddrs,
|
||||
"haveVpnNetworks", vpnNetworks,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
)
|
||||
|
||||
// Release our old handshake from pending, it should not continue
|
||||
f.handshakeManager.DeleteHostInfo(hostinfo)
|
||||
@@ -618,10 +735,11 @@ func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packe
|
||||
newHH.hostinfo.remotes = hostinfo.remotes
|
||||
newHH.hostinfo.remotes.BlockRemote(via)
|
||||
|
||||
f.l.WithField("blockedUdpAddrs", newHH.hostinfo.remotes.CopyBlockedRemotes()).
|
||||
WithField("vpnNetworks", vpnNetworks).
|
||||
WithField("remotes", newHH.hostinfo.remotes.CopyAddrs(f.hostMap.GetPreferredRanges())).
|
||||
Info("Blocked addresses for handshakes")
|
||||
f.l.Info("Blocked addresses for handshakes",
|
||||
"blockedUdpAddrs", newHH.hostinfo.remotes.CopyBlockedRemotes(),
|
||||
"vpnNetworks", vpnNetworks,
|
||||
"remotes", newHH.hostinfo.remotes.CopyAddrs(f.hostMap.GetPreferredRanges()),
|
||||
)
|
||||
|
||||
// Swap the packet store to benefit the original intended recipient
|
||||
newHH.packetStore = hh.packetStore
|
||||
@@ -639,15 +757,20 @@ func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packe
|
||||
ci.window.Update(f.l, 2)
|
||||
|
||||
duration := time.Since(hh.startTime).Nanoseconds()
|
||||
msgRxL := f.l.WithField("vpnAddrs", vpnAddrs).WithField("from", via).
|
||||
WithField("certName", certName).
|
||||
WithField("certVersion", certVersion).
|
||||
WithField("fingerprint", fingerprint).
|
||||
WithField("issuer", issuer).
|
||||
WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
|
||||
WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
|
||||
WithField("durationNs", duration).
|
||||
WithField("sentCachedPackets", len(hh.packetStore))
|
||||
msgRxL := f.l.With(
|
||||
"vpnAddrs", vpnAddrs,
|
||||
"from", via,
|
||||
"certName", certName,
|
||||
"certVersion", certVersion,
|
||||
"fingerprint", fingerprint,
|
||||
"issuer", issuer,
|
||||
"initiatorIndex", hs.Details.InitiatorIndex,
|
||||
"responderIndex", hs.Details.ResponderIndex,
|
||||
"remoteIndex", h.RemoteIndex,
|
||||
"handshake", m{"stage": 2, "style": "ix_psk0"},
|
||||
"durationNs", duration,
|
||||
"sentCachedPackets", len(hh.packetStore),
|
||||
)
|
||||
if anyVpnAddrsInCommon {
|
||||
msgRxL.Info("Handshake message received")
|
||||
} else {
|
||||
@@ -663,8 +786,10 @@ func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packe
|
||||
f.handshakeManager.Complete(hostinfo, f)
|
||||
f.connectionManager.AddTrafficWatch(hostinfo)
|
||||
|
||||
if f.l.Level >= logrus.DebugLevel {
|
||||
hostinfo.logger(f.l).Debugf("Sending %d stored packets", len(hh.packetStore))
|
||||
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
||||
hostinfo.logger(f.l).Debug("Sending stored packets",
|
||||
"count", len(hh.packetStore),
|
||||
)
|
||||
}
|
||||
|
||||
if len(hh.packetStore) > 0 {
|
||||
|
||||
Reference in New Issue
Block a user