mailwolt/app/Services/TlsaService.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,
]
);
}
}