48 lines
1.5 KiB
PHP
48 lines
1.5 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
use App\Models\Domain;
|
|
use App\Models\TlsaRecord;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class TlsaService
|
|
{
|
|
/**
|
|
* Erstellt/aktualisiert TLSA für SMTP (_25._tcp) am MTA-Host.
|
|
* host = <MTA_SUB>.<BASE_DOMAIN> (z.B. mx.example.com)
|
|
*/
|
|
public function createForDomain(Domain $domain): void
|
|
{
|
|
$mtaHost = (env('MTA_SUB', 'mx') ?: 'mx') . '.' . env('BASE_DOMAIN', 'example.com');
|
|
$service = '_25._tcp';
|
|
$certPath = "/etc/letsencrypt/live/{$mtaHost}/fullchain.pem";
|
|
|
|
if (!is_file($certPath)) {
|
|
Log::warning("TLSA skipped: Zertifikat fehlt: {$certPath}");
|
|
return;
|
|
}
|
|
|
|
// SHA256 über SubjectPublicKeyInfo
|
|
$cmd = "openssl x509 -in ".escapeshellarg($certPath)." -noout -pubkey"
|
|
. " | openssl pkey -pubin -outform DER"
|
|
. " | openssl dgst -sha256 | awk '{print \$2}'";
|
|
$hash = trim((string)@shell_exec($cmd));
|
|
|
|
if ($hash === '') {
|
|
Log::error("TLSA failed: Hash konnte nicht berechnet werden ({$mtaHost})");
|
|
return;
|
|
}
|
|
|
|
TlsaRecord::updateOrCreate(
|
|
['domain_id' => $domain->id, 'service' => $service, 'host' => $mtaHost],
|
|
[
|
|
'usage' => 3, // DANE-EE
|
|
'selector' => 1, // SPKI
|
|
'matching' => 1, // SHA-256
|
|
'hash' => $hash,
|
|
'cert_path'=> $certPath,
|
|
]
|
|
);
|
|
}
|
|
}
|