Anpassen der Tlsa Record Ausgabe im Modal

main
boban 2025-10-17 12:24:31 +02:00
parent 0a03324eec
commit 4a52284245
4 changed files with 65 additions and 24 deletions

14
a?->dns_string); Normal file
View File

@ -0,0 +1,14 @@
= App\Models\TlsaRecord {#6794
id: 1,
domain_id: 9,
service: "_25._tcp",
host: "mx.nexlab.at",
usage: 3,
selector: 1,
matching: 1,
hash: "0922eee5f6090b241a3f8554a366b3c1adc4088eb1cdffa94ae838c6e580b983",
cert_path: "/etc/ssl/mail/fullchain.pem",
created_at: "2025-10-06 15:24:56",
updated_at: "2025-10-06 15:24:56",
}

View File

@ -27,6 +27,7 @@ class DomainDnsList extends Component
$this->systemDomain = Domain::where('is_system', true)->first(); $this->systemDomain = Domain::where('is_system', true)->first();
// $this->userDomains = Domain::where('is_system', false)->orderBy('domain')->get(); // $this->userDomains = Domain::where('is_system', false)->orderBy('domain')->get();
$domains = Domain::where('is_system', false) $domains = Domain::where('is_system', false)
->where('is_server', false)
->withCount([ ->withCount([
'mailUsers as mailboxes_count', // -> mail_users 'mailUsers as mailboxes_count', // -> mail_users
'mailAliases as aliases_count', // -> mail_aliases 'mailAliases as aliases_count', // -> mail_aliases

View File

@ -3,6 +3,7 @@
namespace App\Livewire\Ui\Domain\Modal; namespace App\Livewire\Ui\Domain\Modal;
use App\Models\Domain; use App\Models\Domain;
use App\Models\TlsaRecord;
use App\Support\NetProbe; use App\Support\NetProbe;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use LivewireUI\Modal\ModalComponent; use LivewireUI\Modal\ModalComponent;
@ -20,7 +21,10 @@ class DomainDnsModal extends ModalComponent
/** @var array<int,array<string,string|int|null>> */ /** @var array<int,array<string,string|int|null>> */
public array $dynamic = []; public array $dynamic = [];
public static function modalMaxWidth(): string { return '6xl'; } public static function modalMaxWidth(): string
{
return '6xl';
}
public function mount(int $domainId): void public function mount(int $domainId): void
{ {
@ -43,38 +47,48 @@ class DomainDnsModal extends ModalComponent
$ipv6 = $ips['ipv6']; $ipv6 = $ips['ipv6'];
$this->zone = $this->extractZone($d->domain); $this->zone = $this->extractZone($d->domain);
$mta = env('MTA_SUB', 'mx').'.'.$this->zone; // mx.example.com $mta = env('MTA_SUB', 'mx') . '.' . $this->zone; // mx.example.com
// --- Statische Infrastruktur (für alle Domains gleich) --- // --- Statische Infrastruktur (für alle Domains gleich) ---
$this->static = [ $this->static = [
['type'=>'A','name'=>$mta,'value'=>$ipv4], ['type' => 'A', 'name' => $mta, 'value' => $ipv4],
['type'=>'PTR','name'=>$this->ptrFromIPv4($ipv4),'value'=>$mta], ['type' => 'PTR', 'name' => $this->ptrFromIPv4($ipv4), 'value' => $mta],
]; ];
if ($ipv6) { if ($ipv6) {
$this->static[] = ['type'=>'AAAA','name'=>$mta,'value'=>$ipv6]; $this->static[] = ['type' => 'AAAA', 'name' => $mta, 'value' => $ipv6];
$this->static[] = ['type'=>'PTR', 'name'=>$this->ptrFromIPv6($ipv6),'value'=>$mta]; $this->static[] = ['type' => 'PTR', 'name' => $this->ptrFromIPv6($ipv6), 'value' => $mta];
} }
if ($tlsa = config('mailwolt.tlsa')) {
$this->static[] = ['type'=>'TLSA','name'=>"_25._tcp.$mta",'value'=>$tlsa];
$tlsa = TlsaRecord::forServer()
->where('service', '_25._tcp')
->latest('id')
->first();
if ($tlsa?->dns_string) {
$this->static[] = [
'type' => 'TLSA',
'name' => "{$tlsa->service}.{$tlsa->host}",
'value' => "{$tlsa->usage} {$tlsa->selector} {$tlsa->matching} {$tlsa->hash}",
];
} }
$this->static[] = ['type'=>'MX','name'=>$this->domainName,'value'=>"10 $mta."];
// --- Domain-spezifisch --- // --- Domain-spezifisch ---
$spf = 'v=spf1 mx a -all'; $spf = 'v=spf1 mx a -all';
$dmarc = "v=DMARC1; p=none; rua=mailto:dmarc@{$this->domainName}; pct=100"; $dmarc = "v=DMARC1; p=none; rua=mailto:dmarc@{$this->domainName}; pct=100";
*
$dkim = DB::table('dkim_keys') $dkim = DB::table('dkim_keys')
->where('domain_id', $d->id)->where('is_active', 1)->orderByDesc('id')->first(); ->where('domain_id', $d->id)->where('is_active', 1)->orderByDesc('id')->first();
$selector = $dkim ? $dkim->selector : 'mwl1'; $selector = $dkim ? $dkim->selector : 'mwl1';
$dkimHost = "{$selector}._domainkey.{$this->domainName}"; $dkimHost = "{$selector}._domainkey.{$this->domainName}";
$dkimTxt = $dkim && !str_starts_with(trim($dkim->public_key_txt),'v=') $dkimTxt = $dkim && !str_starts_with(trim($dkim->public_key_txt), 'v=')
? 'v=DKIM1; k=rsa; p='.$dkim->public_key_txt ? 'v=DKIM1; k=rsa; p=' . $dkim->public_key_txt
: ($dkim->public_key_txt ?? 'v=DKIM1; k=rsa; p='); : ($dkim->public_key_txt ?? 'v=DKIM1; k=rsa; p=');
$this->dynamic = [ $this->dynamic = [
['type'=>'TXT','name'=>$this->domainName, 'value'=>$spf, 'helpLabel'=>'SPF Record Syntax','helpUrl'=>'http://www.open-spf.org/SPF_Record_Syntax/'], ['type' => 'TXT', 'name' => $this->domainName, 'value' => $spf, 'helpLabel' => 'SPF Record Syntax', 'helpUrl' => 'http://www.open-spf.org/SPF_Record_Syntax/'],
['type'=>'TXT','name'=>"_dmarc.{$this->domainName}", 'value'=>$dmarc, 'helpLabel'=>'DMARC Assistant','helpUrl'=>'https://www.kitterman.com/dmarc/assistant.html'], ['type' => 'TXT', 'name' => "_dmarc.{$this->domainName}", 'value' => $dmarc, 'helpLabel' => 'DMARC Assistant', 'helpUrl' => 'https://www.kitterman.com/dmarc/assistant.html'],
['type'=>'TXT','name'=>$dkimHost, 'value'=>$dkimTxt, 'helpLabel'=>'DKIM Inspector','helpUrl'=>'https://dkimvalidator.com/'], ['type' => 'TXT', 'name' => $dkimHost, 'value' => $dkimTxt, 'helpLabel' => 'DKIM Inspector', 'helpUrl' => 'https://dkimvalidator.com/'],
]; ];
} }
@ -83,7 +97,7 @@ class DomainDnsModal extends ModalComponent
$fqdn = strtolower(trim($fqdn, ".")); $fqdn = strtolower(trim($fqdn, "."));
$parts = explode('.', $fqdn); $parts = explode('.', $fqdn);
$n = count($parts); $n = count($parts);
return $n >= 2 ? $parts[$n-2] . '.' . $parts[$n-1] : $fqdn; // nimmt die letzten 2 Labels return $n >= 2 ? $parts[$n - 2] . '.' . $parts[$n - 1] : $fqdn; // nimmt die letzten 2 Labels
} }
private function detectIPv4(): string private function detectIPv4(): string
@ -106,13 +120,14 @@ class DomainDnsModal extends ModalComponent
private function ptrFromIPv4(string $ip): string private function ptrFromIPv4(string $ip): string
{ {
$p = array_reverse(explode('.', $ip)); $p = array_reverse(explode('.', $ip));
return implode('.', $p).'.in-addr.arpa'; return implode('.', $p) . '.in-addr.arpa';
} }
private function ptrFromIPv6(string $ip): string private function ptrFromIPv6(string $ip): string
{ {
$expanded = strtolower(inet_ntop(inet_pton($ip))); $expanded = strtolower(inet_ntop(inet_pton($ip)));
$hex = str_replace(':', '', $expanded); $hex = str_replace(':', '', $expanded);
return implode('.', array_reverse(str_split($hex))).'.ip6.arpa'; return implode('.', array_reverse(str_split($hex))) . '.ip6.arpa';
} }
public function render() public function render()

View File

@ -2,16 +2,27 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class TlsaRecord extends Model class TlsaRecord extends Model
{ {
protected $fillable = [ protected $fillable = [
'domain_id','service','host','usage','selector','matching','hash','cert_path', 'domain_id', 'service', 'host', 'usage', 'selector', 'matching', 'hash', 'cert_path',
]; ];
public function domain() { return $this->belongsTo(Domain::class); } // Relation zur Domain (FK: domain_id)
public function domain()
{
return $this->belongsTo(Domain::class);
}
public function scopeForServer(Builder $q): Builder
{
return $q->whereHas('domain', fn($d) => $d->where('is_server', true));
}
// Fertige Ausgabe-Zeile
public function getDnsStringAttribute(): string public function getDnsStringAttribute(): string
{ {
return "{$this->service}.{$this->host}. IN TLSA {$this->usage} {$this->selector} {$this->matching} {$this->hash}"; return "{$this->service}.{$this->host}. IN TLSA {$this->usage} {$this->selector} {$this->matching} {$this->hash}";