|
|
@@ -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 {
|