Files
sultan/pkg/crypto/pin.go
T
br ca6cdcca63 software steht so weit.
jetzt build + docker build und testen
2026-10-02 13:25:34 +02:00

46 lines
1.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package crypto
import (
"crypto/tls"
"errors"
"fmt"
)
var (
// ErrUnknownServer: Kein Fingerprint bekannt – ein ungeprüfter Kontakt
// wird verweigert (kein blindes TOFU).
ErrUnknownServer = errors.New("crypto: unbekannter Server – Fingerprint aus der Einladung erforderlich")
// ErrFingerprintMismatch: Das Server-Zertifikat passt nicht zum Pin
// (möglicher Man-in-the-Middle).
ErrFingerprintMismatch = errors.New("crypto: Server-Fingerprint stimmt nicht – möglicher Man-in-the-Middle")
)
// PinnedTLSConfig liefert die TLS-Konfiguration des Agenten. Statt einer CA
// wird der Fingerprint des Server-Zertifikats geprüft – unabhängig von der
// Adresse, über die der Server erreicht wird (DNS, interne IP, NetBird):
// Derselbe Server hat überall denselben Fingerprint.
//
// Beim Erstkontakt kommt want aus der Einladung, danach aus node.json. Die
// Prüfung läuft im TLS-Handshake, also bevor irgendein Request-Byte (Token,
// Signatur, Body) gesendet wird. Nur TLS 1.3.
func PinnedTLSConfig(want Fingerprint) *tls.Config {
return &tls.Config{
MinVersion: tls.VersionTLS13,
// Die CA- und Hostnamen-Prüfung entfällt bewusst; VerifyConnection
// ersetzt sie durch die strengere Fingerprint-Prüfung.
InsecureSkipVerify: true,
VerifyConnection: func(cs tls.ConnectionState) error {
if want == "" {
return ErrUnknownServer
}
if len(cs.PeerCertificates) == 0 {
return fmt.Errorf("%w: kein Zertifikat", ErrFingerprintMismatch)
}
if got := FingerprintOf(cs.PeerCertificates[0]); got != want {
return fmt.Errorf("%w: Server präsentiert %s, erwartet %s", ErrFingerprintMismatch, got, want)
}
return nil
},
}
}