IT-Blog von Sebastian van de Meer

Schlagwort: Windows

Windows Server 2012 R2: RRAS mit sicheren Cipher Suites härten

RRAS Routing und RAS Icon.

Wenn ich schon bei den ganzen Microsoft Themen bin, warum nicht gleich noch „sicheres“ RRAS Routing- und RAS  mit einem Windows Server 2012 R2?! Im speziellen Beispiel an einem L2TP IPsec VPN für Clientsysteme.

Hat mein alles im Routing und RAS konfiguriert verbinden sich die Clients im Standard mit etwas wie: SHA-1 3DES und der DH Group 2 was ein modp1024 (1024-bit) ist. Pfffffff SHA-1 ja, ok… 3DES muss nicht unbedingt und modp1024 möchte man auch nicht oder?

Screenshot der Windows-Firewall mit erweiterter Sicherheit und angezeichnetem Klickpfad um die Sichereheitsmethoden zu konfigurieren.

Wie konfiguriert man dieses nun also „weg“? Ich muss zugeben dafür einige Zeit gelesen zu haben. Dann ich hätte erwartet dieses irgendwo in der Nähe vom Routing und RAS konfigurieren zu müssen. Dem ist aber nicht so. Die Konfiguration dieser Parameter findet man über die Windows-Firewall mit erweiterter Sicherheit auf dem Windows Server. Irgendeinen Grund wird es schon haben es dort zu ~verstecken~ und sicher ist dieser absolut einleuchtend, wenn man sich näher damit auskennt. Ich hätte dort von alleine sicher niemals gesucht. Man findet es also über: Windows Firewall ==> recht Maus: Windows-Firewall mit erweiterter Sicherheit ==> Eigenschaften ==> IPsec-Einstellungen ==> IPsec-Standardeinstellungen Button „Anpassen“ ==> Schlüsselaustausch.

Hier kann man nun die Einstellungen konfigurieren… *kopfschüttel* Windows Firewall…. Hat jemand eine Idee warum es ausgerechnet da ist? Wie auch immer…

Screenshot der Windows-Firewall mit erweiterter Sicherheit und angezeichnetem Klickpfad um die Datenschutzeinstellungen zu konfigurieren.

Steht der Windows RRAS hinter einem NAT sollte man ebenfalls noch UDP Encapsulation aktivieren. Dafür habe ich folgendes Registry File für euch:

Nach diesen Änderungen sollte man natürlich ganz Windowslike den Server einmal durchstarten. Baut man nun von einem Windows Client eine neue VPN Verbindung auf kann man auf diesem natürlich per PowerShell (bitte mit erweiterten Rechten) prüfen ob seine Änderungen gegriffen haben:

Get-NetIPsecMainModeSA | Select-Object -First 1
Screenshot des Kommandos Get-NetIPsecMainModeSA | Select-Object -First 1 inkl Konsolenausgabe.

Wichtig sind dann:

CipherAlgorithm
HashAlgorithm
GroupId

Im Standard wäre es:

Encryption: 3DES
Authentication/Integrity: SHA-1
Key Size: DH Group 2 (1024 bit)

Nach unseren Änderungen:

Encryption: AES256
Authentication/Integrity: SHA-1
Key Size: DH Group 20 (384-bit elliptic curve group)

Windows Firewall…. Pfff… Ja natürlich lässt sich das Thema mit Gruppenrichtlinien erschlagen, nur ist dieses noch einmal ein Thema für sich, hm? Vor allem habe ich mich sehr schwer damit getan hier die Reihenfolge korrekt vorzugeben.

Fragen? Dann wie immer fragen 🙂

WSUS-Bereinigung: Timeouts beheben und Speicherplatz freigeben

WSUS Windows Server Update Service Icon

Pfffff…. Einen dauerhaft richtig gut laufenden WSUS Server habe ich tatsächlich noch nie gesehen; was auch an mir liegen kann ;-). Irgendwann werden die Dinger laaaaannnnggggssssaaammmm. Dann gibt es Timeouts, dann läuft irgendwann die Serverbereinigung nicht mehr durch und man muss sich mit so einem System beschäftigen, bevor die Platten voll sind.

WSUS ist einfach kein Dienst, den man konfiguriert und dann läuft er, abgesehen von Sicherheitsupdates, durch. Nein… WSUS möchte dauerhaft Aufmerksamkeit. Was mir dabei so aufgefallen ist, möchte ich kurz mit euch teilen!

Screenshot inkl. Klickpfade der WSUS Update Service Oberfläche zum Konfigurieren der Produkte und Klassifizierungen.

Mache NIE (wirklich NIE) Treiberupdates über WSUS. Hier explodiert der Platzverbrauch für die Updates!
Sollte es jemand aktiviert haben. Als erstes über „Windows Server Update Services (WSUS) ==> Optionen ==> Produkte und Klassifizierungen ==> Klassifizierungen ==> Treiber“ rauswerfen. Dann über „Updates ==> Alle Updates“ zu den Dropdown Menus und hier: Genehmigung: Genehmigt und Status: Alle. Warten bis die Liste vollständig ist und nach Klassifizierung sortieren. Alle Treiberupdates auswählen und ablehnen.

Was mir auch geholfen hat ist das folgende PowerShell Script. Dieses läuft zwar ewig, räumt aber viel weg:

[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
Screenshot der Windows PowerShell ISE inkl. script.
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer();
$wsus.GetUpdates() | Where {$_.IsDeclined -eq $true} | ForEach-Object {$wsus.DeleteUpdate($_.Id.UpdateId.ToString()); Write-Host $_.Title removed }

Wo wir beim Aufräumen sind… Es gibt so einen wunderschönen „Assistent für die Serverbereinigung“. Dieser sollte überflüssige Updates weg löschen. Also wenn die Computer für die Updates nicht mehr da sind, die Updates von anderen ersetzt wurden oder heruntergeladene Updates abgelehnt wurden. Es ergibt daher Sinn, diesen Assistenten ggf. täglich laufen zu lassen. Er ist nur leider nicht direkt zu automatisieren. Dafür benötigt man ebenfalls ein PowerShell Script welches man täglich per Aufgabenplanung ausführen lässt. Mir hat folgendes bisher immer gute Dienste geleistet.

# Variablen
$DateFormat = Get-Date -format yyyyMMdd-HH-mm
$Logfile = "H:\Logs\wsus-bereinigung-$DateFormat.log"

# WSUS Bereinigung durchführen
Invoke-WsusServerCleanup -CleanupObsoleteUpdates -CleanupUnneededContentFiles -CompressUpdates -DeclineExpiredUpdates -DeclineSupersededUpdates | Out-File $Logfile

# Mail Variablen
$MailSMTPServer = "smtp.kernel-error.de"
$MailFrom = "administrator@firma88.inf"
$MailTo = "dev@null.de"
$MailSubject = "${env:COMPUTERNAME} Bereinigung $DateFormat"
$MailBody = Get-Content $Logfile | Out-String

# Mail versenden
Send-MailMessage -SmtpServer $MailSMTPServer -From $MailFrom -To $MailTo -subject $MailSubject -body $MailBody -Encoding Unicode

Es räumt auf, erstellt ein Logfile und sendet einem zusätzlich noch eine Status E-Mail darüber zu.

Was aber wenn man in der WSUS Timeout Hölle gefangen ist und die ganzen Versuche fehlschlagen das Ding wieder „sauber“ zu machen? Dabei hat mir folgendes geholfen.

IIS umstellen:
IIS-Manager ==> Anwendungspools ==> WsusPool ==> Erweiterte Einstellungen

Limit für den privaten Speicher (KB): 6000000
Maximale Anzahl von Arbeitsprozessen: 0
Startmodus: AlwaysRunning

Nicht vergessen den IIS neu zu starten oder besser den ganzen Server, es ist ja ein Windows 😉

Screenshot der Database Properties - SUSDB zur WSUS Datenbank.

Windows Internel Database WDI umstellen:
Mit dem Microsoft SQL Server Management Studio zu folgendem Server verbinden: \\.\pipe\MICROSOFT##WID\tsql\query

Dann „Databases ==> SUSDB ==> rechte Maus Properties ==> Options ==> „Compatibility level:“ SQL Server 2012 (110)

Man kann hier auch über „Databases ==> SUSDB ==> rechte Maus Tasks ==> Shrink ==> Database“ den freien Speicherplatz der Datenbank zusammenfassen lassen.

Screenshot der Database Properties - SUSDB zur WSUS Datenbank. Shrink Database.

Wenn man schon hier ist lässt sich die Synchronisierungshistory mit folgender SQL Query aufräumen:

USE SUSDB
GO
DELETE FROM tbEventInstance WHERE EventNamespaceID = '2' AND EVENTID IN ('381', '382', '384', '386', '387', '389')
Screenshot vom Micosoft SQL Server Manager mit SQL Query zur Bereinigung der WSUS Datenbank.

Einfach „New Query“ copy&paste „Execute“.

Wenn die Serverbereinigung weiterhin hängen bleibt hilft es scheinbar oft das erste Update in der „zu löschen“ Liste von Hand zu löschen:

USE SUSDB
GO
exec spGetObsoleteUpdatesToCleanup

Jetzt die erste Update ID notieren und:

USE SUSDB
GO
exec spDeleteUpdate @localUpdateID=HIERUPDATEID

Über den Weg lässt sich auch kontrollieren ob die Versuche das Ding aufzuräumen irgendwie einen Fortschritt bringen. Kommt man auch so nicht weiter hat mir folgende SQL Query geholfen (auch wenn sie unglaublich lange läuft):

USE SUSDB
DECLARE @var1 INT, @curitem INT, @totaltodelete INT
DECLARE @msg nvarchar(200)
CREATE TABLE #results (Col1 INT) INSERT INTO #results(Col1)
EXEC spGetObsoleteUpdatesToCleanup
SET @totaltodelete = (SELECT COUNT(*) FROM #results)
SELECT @curitem=1
DECLARE WC Cursor FOR SELECT Col1 FROM #results
OPEN WC
FETCH NEXT FROM WC INTO @var1 WHILE (@@FETCH_STATUS > -1)
BEGIN SET @msg = cast(@curitem as varchar(5)) + '/' + cast(@totaltodelete as varchar(5)) + ': Deleting ' + CONVERT(varchar(10), @var1) + ' ' + cast(getdate() as varchar(30))
RAISERROR(@msg,0,1) WITH NOWAIT
EXEC spDeleteUpdate @localUpdateID=@var1
SET @curitem = @curitem +1
FETCH NEXT FROM WC INTO @var1
END
CLOSE WC
DEALLOCATE WC
DROP TABLE #results

Ebenfalls gibt es die Möglichkeit seine Datenbank zu re-indexieren. Indexe in einer Datenbank neu aufzubauen hat selten geschadet, hm?

/****************************************************************************** 
This sample T-SQL script performs basic maintenance tasks on SUSDB 
1. Identifies indexes that are fragmented and defragments them. For certain 
   tables, a fill-factor is set in order to improve insert performance. 
   Based on MSDN sample at http://msdn2.microsoft.com/en-us/library/ms188917.aspx 
   and tailored for SUSDB requirements 
2. Updates potentially out-of-date table statistics. 
******************************************************************************/ 
 
USE SUSDB; 
GO 
SET NOCOUNT ON; 
 
-- Rebuild or reorganize indexes based on their fragmentation levels 
DECLARE @work_to_do TABLE ( 
    objectid int 
    , indexid int 
    , pagedensity float 
    , fragmentation float 
    , numrows int 
) 
 
DECLARE @objectid int; 
DECLARE @indexid int; 
DECLARE @schemaname nvarchar(130);  
DECLARE @objectname nvarchar(130);  
DECLARE @indexname nvarchar(130);  
DECLARE @numrows int 
DECLARE @density float; 
DECLARE @fragmentation float; 
DECLARE @command nvarchar(4000);  
DECLARE @fillfactorset bit 
DECLARE @numpages int 
 
-- Select indexes that need to be defragmented based on the following 
-- * Page density is low 
-- * External fragmentation is high in relation to index size 
PRINT 'Estimating fragmentation: Begin. ' + convert(nvarchar, getdate(), 121)  
INSERT @work_to_do 
SELECT 
    f.object_id 
    , index_id 
    , avg_page_space_used_in_percent 
    , avg_fragmentation_in_percent 
    , record_count 
FROM  
    sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'SAMPLED') AS f 
WHERE 
    (f.avg_page_space_used_in_percent < 85.0 and f.avg_page_space_used_in_percent/100.0 * page_count < page_count - 1) 
    or (f.page_count > 50 and f.avg_fragmentation_in_percent > 15.0) 
    or (f.page_count > 10 and f.avg_fragmentation_in_percent > 80.0) 
 
PRINT 'Number of indexes to rebuild: ' + cast(@@ROWCOUNT as nvarchar(20)) 
 
PRINT 'Estimating fragmentation: End. ' + convert(nvarchar, getdate(), 121) 
 
SELECT @numpages = sum(ps.used_page_count) 
FROM 
    @work_to_do AS fi 
    INNER JOIN sys.indexes AS i ON fi.objectid = i.object_id and fi.indexid = i.index_id 
    INNER JOIN sys.dm_db_partition_stats AS ps on i.object_id = ps.object_id and i.index_id = ps.index_id 
 
-- Declare the cursor for the list of indexes to be processed. 
DECLARE curIndexes CURSOR FOR SELECT * FROM @work_to_do 
 
-- Open the cursor. 
OPEN curIndexes 
 
-- Loop through the indexes 
WHILE (1=1) 
BEGIN 
    FETCH NEXT FROM curIndexes 
    INTO @objectid, @indexid, @density, @fragmentation, @numrows; 
    IF @@FETCH_STATUS < 0 BREAK; 
 
    SELECT  
        @objectname = QUOTENAME(o.name) 
        , @schemaname = QUOTENAME(s.name) 
    FROM  
        sys.objects AS o 
        INNER JOIN sys.schemas as s ON s.schema_id = o.schema_id 
    WHERE  
        o.object_id = @objectid; 
 
    SELECT  
        @indexname = QUOTENAME(name) 
        , @fillfactorset = CASE fill_factor WHEN 0 THEN 0 ELSE 1 END 
    FROM  
        sys.indexes 
    WHERE 
        object_id = @objectid AND index_id = @indexid; 
 
    IF ((@density BETWEEN 75.0 AND 85.0) AND @fillfactorset = 1) OR (@fragmentation < 30.0) 
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE'; 
    ELSE IF @numrows >= 5000 AND @fillfactorset = 0 
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD WITH (FILLFACTOR = 90)'; 
    ELSE 
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD'; 
    PRINT convert(nvarchar, getdate(), 121) + N' Executing: ' + @command; 
    EXEC (@command); 
    PRINT convert(nvarchar, getdate(), 121) + N' Done.'; 
END 
 
-- Close and deallocate the cursor. 
CLOSE curIndexes; 
DEALLOCATE curIndexes; 
 
 
IF EXISTS (SELECT * FROM @work_to_do) 
BEGIN 
    PRINT 'Estimated number of pages in fragmented indexes: ' + cast(@numpages as nvarchar(20)) 
    SELECT @numpages = @numpages - sum(ps.used_page_count) 
    FROM 
        @work_to_do AS fi 
        INNER JOIN sys.indexes AS i ON fi.objectid = i.object_id and fi.indexid = i.index_id 
        INNER JOIN sys.dm_db_partition_stats AS ps on i.object_id = ps.object_id and i.index_id = ps.index_id 
 
    PRINT 'Estimated number of pages freed: ' + cast(@numpages as nvarchar(20)) 
END 
GO 
 
 
--Update all statistics 
PRINT 'Updating all statistics.' + convert(nvarchar, getdate(), 121)  
EXEC sp_updatestats 
PRINT 'Done updating statistics.' + convert(nvarchar, getdate(), 121)  
GO

Meist scheint eine Kombination auf verschiedenen Dingen zu helfen. Bisher hat mir zumindest immer irgendetwas davon geholfen. Auch wenn ich dafür einige Zeit in Suchmaschinen verschwenden musste. Dieses ist also eher so etwas wie eine Sammlung gefundener Dinge 😉

Fragen? Dann fragen…

Windows Server 2012 R2 mit Exchange 2016: SSL Labs A-Rating erreichen

Qualis A+ Icon.

Ich habe hier einen Windows Server 2012 R2 mit einem Exchange 2016. Out of the Box spricht das Ding TLS 1.0, SSLv3 und RC4. Da gehen einem schnell die Haare hoch, oder?

Kann man so ein System auf ein A+ im Qualys Rating bekommen und es arbeitet dann noch? Kleiner Spoiler, ja geht!

Ich muss zugeben, Microsoft Produkte strengen mich in dieser Hinsicht immer sehr an. Auch wenn sie ganz sicher ihre Daseinsberechtigung haben.

Nun gut… Für ein A+ benötigen wir neben brauchbaren ciphern, sauberen Protokollen usw. noch HTTP Strict Transport Security (https://de.wikipedia.org/wiki/HTTP_Strict_Transport_Security). Dieses ist im Grunde nur ein http response header und dieses konfigurieren wir im IIS Manager. Das besagte Testsystem kümmert sich nur um den Exchangeserver, daher konfiguriere ich es ganz oben (so wird es überall hin vererbt).

IIS-Manager ==> HTTP-Antwortheader ==> Hinzufügen

Screenshot der Internetinformationsdienste (IIS)-Manager.

Name: strict-transport-security
Wert: max-age=31536000; includeSubdomains

Wie auch im Bild zu sehen.

Qualis A+ Wertung.

Jetzt der spannende Teil. Man muss einige Änderungen in der Registrierung vornehmen um MD5, RC4 usw. zu deaktivieren. Ich habe da etwas vorbereitet um dieses zu tun. Ebenfalls wird SSLv3, TLS 1.0, TLS 1.1 deaktiviert. TLS 1.2 und TLS 1.3  wird aktiviert (TLS 1.3 dabei nur für die Zukunft). Ebenfalls werden super schwache Cipher deaktiviert. Die bestmöglichen dafür aktiviert und es wird auch eine Cipherorder vorgegeben. Das File einfach herunterladen, ausführen und im Anschluss den Server durchstarten (Microsoft halt…).

Aber dann sollte man sein A+ haben. Auch wenn ich gerne noch schönere Cipher hätte :-/ aber mehr ging nicht, bzw. habe ich nicht hin bekommen!

Qualis Wertung mit Blick auf Cipher Suites und Protocols.

Oh natürlich… Das Registry Snippet zum Download:

Fragen? Dann fragen…

FreeBSD als IPsec/L2TP-Client für Microsoft Windows Routing und RAS VPN

FreeBSD IPsec L2TP Client to Microsoft Windows Routing RAS Server Diagramm.

Vor einigen Monaten habe ich meinen FreeBSD (damals noch 11 heute 12) Desktop an einen Microsoft Windows Routing und RAS VPN Server angebunden. Das eingesetzte VPN war ein IPsec L2TP. Heute schaffe ich es endlich das Thema mal wegzuschreiben. Grob gesehen ist dieses der Aufbau.

Der FreeBSD Desktop hat dabei die IPv4 Adresse 192.168.10.57, der Windows Routing RAS VPN Server hat den FQDN vpnserver.domain.tld mit der IPv4 88.88.88.88 und der IPsec Tunnel hat den Namen vpnname. Die Netze im Unternehmen sind 172.16.0.0/12 und 10.0.0.0/8.

Tunneltyp ist ein IPsec L2TP an dem Windows „Ding“ mit PSK für den IPsec Tunnel und normaler Dämenenanmeldung über L2TP.

Auf meinem FreeBSD Desktop brauche ich also ipsec für den Tunnel und ich nutze mpd5 für L2TP. Ich „glaube“ l2tpd wäre vielleicht etwas besser, da mpd5 etwas manuelle Arbeit benötigt. Da ich an ein paar anderen Stellen ebenfalls mpd5 nutze und hier ohne Windows auch keine Handarbeit mehr nötig ist…. Es geht mir halt leichter von der Hand 🙂 Insg. ist die gesamte Konfiguration aber sehr einfach.

Meine ipsec Konfiguration sie wie folgt aus:

/usr/local/etc/ipsec.conf

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

#config setup
	# strictcrlpolicy=yes
	# uniqueids = no

# Add connections here.

# Sample VPN connections

#conn sample-self-signed
#      leftsubnet=10.1.0.0/16
#      leftcert=selfCert.der
#      leftsendcert=never
#      right=192.168.0.2
#      rightsubnet=10.2.0.0/16
#      rightcert=peerCert.der
#      auto=start

#conn sample-with-ca-cert
#      leftsubnet=10.1.0.0/16
#      leftcert=myCert.pem
#      right=192.168.0.2
#      rightsubnet=10.2.0.0/16
#      rightid="C=CH, O=Linux strongSwan CN=peer name"
#      auto=start

config setup

conn %default
        ikelifetime=60m
        keylife=20m
        rekeymargin=3m
        keyingtries=1
        keyexchange=ikev1
        authby=psk

conn vpnname
        type=transport
        leftfirewall=yes
        right=vpnserver.domain.tld
        rightid = %any
        rightsubnet=0.0.0.0/0
        auto=add
        left=%defaultroute
        leftprotoport=17/%any
        rightprotoport=17/1701
        ike=3des-sha1-modp1024!
        esp=3des-sha1
        modeconfig=push

Der PSK steht in der /usr/local/etc/ipsec.secrets

# ipsec.secrets - strongSwan IPsec secrets file
vpnserver.domain.tld %any : PSK "abcdefg1234567"

Den IPsec Tunnel baut man nun einfach wie folgt auf:

root@errortest:~ # ipsec up vpnname
initiating Main Mode IKE_SA vpnname[20] to 88.88.88.88
generating ID_PROT request 0 [ SA V V V V V ]
sending packet: from 192.168.10.57[500] to 88.88.88.88[500] (176 bytes)
received packet: from 88.88.88.88[500] to 192.168.10.57[500] (208 bytes)
parsed ID_PROT response 0 [ SA V V V V V V ]
received MS NT5 ISAKMPOAKLEY vendor ID
received NAT-T (RFC 3947) vendor ID
received draft-ietf-ipsec-nat-t-ike-02\n vendor ID
received FRAGMENTATION vendor ID
received unknown vendor ID: fb:1d:e3:cd:f3:41:b7:ea:16:b7:e5:be:08:55:f1:20
received unknown vendor ID: e3:a5:96:6a:76:37:9f:e7:07:22:82:31:e5:ce:86:52
selected proposal: IKE:3DES_CBC/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
generating ID_PROT request 0 [ KE No NAT-D NAT-D ]
sending packet: from 192.168.10.57[500] to 88.88.88.88[500] (244 bytes)
received packet: from 88.88.88.88[500] to 192.168.10.57[500] (260 bytes)
parsed ID_PROT response 0 [ KE No NAT-D NAT-D ]
local host is behind NAT, sending keep alives
generating ID_PROT request 0 [ ID HASH ]
sending packet: from 192.168.10.57[4500] to 88.88.88.88[4500] (68 bytes)
received packet: from 88.88.88.88[4500] to 192.168.10.57[4500] (68 bytes)
parsed ID_PROT response 0 [ ID HASH ]
IKE_SA vpnname[20] established between 192.168.10.57[192.168.10.57]...88.88.88.88[88.88.88.88]
scheduling reauthentication in 3402s
maximum IKE_SA lifetime 3582s
generating QUICK_MODE request 2082742542 [ HASH SA No ID ID NAT-OA NAT-OA ]
sending packet: from 192.168.10.57[4500] to 88.88.88.88[4500] (220 bytes)
received packet: from 88.88.88.88[4500] to 192.168.10.57[4500] (212 bytes)
parsed QUICK_MODE response 2082742542 [ HASH SA No ID ID NAT-OA NAT-OA ]
selected proposal: ESP:3DES_CBC/HMAC_SHA1_96/NO_EXT_SEQ
CHILD_SA vpnname{38} established with SPIs c387d93f_i 4720cab6_o and TS 192.168.10.57/32[udp] === 88.88.88.88/32[udp/l2f]
connection 'vpnname' established successfully

Ob der IPsec Tunnel steht sieht man mit:

root@errortest:~ # ipsec statusall
Status of IKE charon daemon (strongSwan 5.7.1, FreeBSD 12.0-RELEASE-p3, amd64):
  uptime: 12 hours, since Apr 03 21:26:07 2019
  worker threads: 11 of 16 idle, 5/0/0/0 working, job queue: 0/0/0/0, scheduled: 5
  loaded plugins: charon aes des blowfish rc2 sha2 sha1 md4 md5 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem openssl fips-prf curve25519 xcbc cmac hmac curl attr kernel-pfkey kernel-pfroute resolve socket-default stroke vici updown eap-identity eap-md5 eap-mschapv2 eap-tls eap-ttls eap-peap xauth-generic whitelist addrblock counters
Listening IP addresses:
  2003:88:53dd:a800:eef4:bbff:fe47:c54c
  fd00::eef4:bbff:fe47:c54c
  192.168.10.57
Connections:
      vpnname:  %any...vpnserver.domain.tld  IKEv1
      vpnname:   local:  [192.168.10.57] uses pre-shared key authentication
      vpnname:   remote: uses pre-shared key authentication
      vpnname:   child:  dynamic[udp] === 0.0.0.0/0[udp/l2f] TRANSPORT
Security Associations (1 up, 0 connecting):
      vpnname[20]: ESTABLISHED 14 seconds ago, 192.168.10.57[192.168.10.57]...88.88.88.88[88.88.88.88]
      vpnname[20]: IKEv1 SPIs: 8d3cfef7264b42cc_i* 0d322a1593a9db84_r, pre-shared key reauthentication in 56 minutes
      vpnname[20]: IKE proposal: 3DES_CBC/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
      vpnname{38}:  INSTALLED, TRANSPORT, reqid 10, ESP in UDP SPIs: c387d93f_i 4720cab6_o
      vpnname{38}:  3DES_CBC/HMAC_SHA1_96, 0 bytes_i, 0 bytes_o, rekeying in 14 minutes
      vpnname{38}:   192.168.10.57/32[udp] === 88.88.88.88/32[udp/l2f]

Jetzt fehlt also nur noch L2TP, meine mpd5 Konfiguration sieht dabei so aus /usr/local/etc/mpd5/mpd.conf :

startup:
      # Set web self 127.0.0.1 5008
      # Set user vpntest vpntest admin
      # Set web open
log +ALL +EVENTS -FRAME -ECHO
default:
      load L2TP_client

L2TP_client:
    create bundle static B1
	set iface up-script /home/kernel/vpnname-up.sh
	set iface down-script /home/kernel/vpnname-down.sh
	set bundle enable crypt-reqd
	set bundle enable compression
	set bundle enable ipv6cp
	set ccp yes mppc
	set mppc no e40 e56
	set mppc yes e128 stateless
	set ipcp ranges 0.0.0.0/0 0.0.0.0/0
	set ipcp enable req-pri-dns
	set ipcp enable req-sec-dns
	set iface route 172.16.0.0/12
	set iface route 10.0.0.0/8
	set iface enable tcpmssfix



    create link static L1 l2tp
    set link action bundle B1
    set auth authname "AD-USERNAME"
    set auth password "AD-PASSWORD"
    set link max-redial 0
    set link mtu 1400
    set link keep-alive 20 75
    set link accept chap-msv2
	set link no pap eap


    set l2tp peer vpnserver.domain.tld
    open

Einfach starten mit:

root@errortest:/ # mpd5
Multi-link PPP daemon for FreeBSD

process 10142 started, version 5.8 (root@120amd64-quarterly-job-15 02:54  8-Feb-2019)
[B1] Bundle: Interface ng0 created
[L1] [L1] Link: OPEN event
[L1] LCP: Open event
[L1] LCP: state change Initial --> Starting
[L1] LCP: LayerStart
L2TP: Initiating control connection 0x800caa310 0.0.0.0 0 <-> 88.88.88.88 1701
L2TP: Control connection 0x800caa310 192.168.10.57 38844 <-> 88.88.88.88 1701 connected
[L1] L2TP: Incoming call #7540000 via control connection 0x800caa310 initiated
[L1] L2TP: Call #7540000 connected
[L1] Link: UP event
[L1] LCP: Up event
[L1] LCP: state change Starting --> Req-Sent
[L1] LCP: SendConfigReq #1
[L1]   ACFCOMP
[L1]   PROTOCOMP
[L1]   MRU 1500
[L1]   MAGICNUM 0x2d8654b6
[L1] LCP: SendConfigReq #2
[L1]   ACFCOMP
[L1]   PROTOCOMP
[L1]   MRU 1500
[L1]   MAGICNUM 0x2d8654b6
[L1] LCP: rec'd Configure Request #0 (Req-Sent)
[L1]   MRU 1400
[L1]   AUTHPROTO EAP
[L1]   MAGICNUM 0x74943399
[L1]   PROTOCOMP
[L1]   ACFCOMP
[L1]   CALLBACK 6
[L1]   MP MRRU 1614
[L1]   ENDPOINTDISC [LOCAL] 01 d0 15 a9 b4 71 4f f4 a0 97 8e 3c e4 ef 93 d7 00 00 0
[L1] LCP: SendConfigRej #0
[L1]   CALLBACK 6
[L1]   MP MRRU 1614
[L1] LCP: rec'd Configure Ack #2 (Req-Sent)
[L1]   ACFCOMP
[L1]   PROTOCOMP
[L1]   MRU 1500
[L1]   MAGICNUM 0x2d8654b6
[L1] LCP: state change Req-Sent --> Ack-Rcvd
[L1] LCP: rec'd Configure Request #1 (Ack-Rcvd)
[L1]   MRU 1400
[L1]   AUTHPROTO EAP
[L1]   MAGICNUM 0x74943399
[L1]   PROTOCOMP
[L1]   ACFCOMP
[L1]   ENDPOINTDISC [LOCAL] 01 d0 15 a9 b4 71 4f f4 a0 97 8e 3c e4 ef 93 d7 00 00 0
[L1] LCP: SendConfigNak #1
[L1]   AUTHPROTO CHAP MSOFTv2
[L1] LCP: rec'd Configure Request #2 (Ack-Rcvd)
[L1]   MRU 1400
[L1]   AUTHPROTO CHAP MSOFTv2
[L1]   MAGICNUM 0x74943399
[L1]   PROTOCOMP
[L1]   ACFCOMP
[L1]   ENDPOINTDISC [LOCAL] 01 d0 15 a9 b4 71 4f f4 a0 97 8e 3c e4 ef 93 d7 00 00 0
[L1] LCP: SendConfigAck #2
[L1]   MRU 1400
[L1]   AUTHPROTO CHAP MSOFTv2
[L1]   MAGICNUM 0x74943399
[L1]   PROTOCOMP
[L1]   ACFCOMP
[L1]   ENDPOINTDISC [LOCAL] 01 d0 15 a9 b4 71 4f f4 a0 97 8e 3c e4 ef 93 d7 00 00 0
[L1] LCP: state change Ack-Rcvd --> Opened
[L1] LCP: auth: peer wants CHAP, I want nothing
[L1] LCP: LayerUp
[L1] CHAP: rec'd CHALLENGE #0 len: 26
[L1]   Name: "VPN-SERVER"
[L1] CHAP: Using authname "AD-USERNAME"
[L1] CHAP: sending RESPONSE #0 len: 60
[L1] CHAP: rec'd SUCCESS #0 len: 46
[L1]   MESG: S=39CCB87E756B7996C5A261EEC4CA14D30E4616E0
[L1] LCP: authorization successful
[L1] Link: Matched action 'bundle "B1" ""'
[L1] Link: Join bundle "B1"
[B1] Bundle: Status update: up 1 link, total bandwidth 64000 bps
[B1] IPCP: Open event
[B1] IPCP: state change Initial --> Starting
[B1] IPCP: LayerStart
[B1] IPV6CP: Open event
[B1] IPV6CP: state change Initial --> Starting
[B1] IPV6CP: LayerStart
[B1] CCP: Open event
[B1] CCP: state change Initial --> Starting
[B1] CCP: LayerStart
[B1] IPCP: Up event
[B1] IPCP: state change Starting --> Req-Sent
[B1] IPCP: SendConfigReq #1
[B1]   IPADDR 0.0.0.0
[B1]   COMPPROTO VJCOMP, 16 comp. channels, no comp-cid
[B1]   PRIDNS 0.0.0.0
[B1]   SECDNS 0.0.0.0
[B1] IPV6CP: Up event
[B1] IPV6CP: state change Starting --> Req-Sent
[B1] IPV6CP: SendConfigReq #1
[B1] CCP: Up event
[B1] CCP: state change Starting --> Req-Sent
[B1] CCP: SendConfigReq #1
[B1]   MPPC
[B1]     0x01000040:MPPE(128 bits), stateless
[B1] IPV6CP: rec'd Configure Request #4 (Req-Sent)
[B1] IPV6CP: SendConfigAck #4
[B1] IPV6CP: state change Req-Sent --> Ack-Sent
[B1] CCP: rec'd Configure Request #5 (Req-Sent)
[B1]   MPPC
[B1]     0x01000001:MPPC, stateless
[B1] CCP: SendConfigNak #5
[B1]   MPPC
[B1]     0x01000040:MPPE(128 bits), stateless
[B1] IPCP: rec'd Configure Request #6 (Req-Sent)
[B1]   IPADDR 10.16.100.13
[B1]     10.16.100.13 is OK
[B1] IPCP: SendConfigAck #6
[B1]   IPADDR 10.16.100.13
[B1] IPCP: state change Req-Sent --> Ack-Sent
[B1] IPCP: rec'd Configure Reject #1 (Ack-Sent)
[B1]   COMPPROTO VJCOMP, 16 comp. channels, no comp-cid
[B1] IPCP: SendConfigReq #2
[B1]   IPADDR 0.0.0.0
[B1]   PRIDNS 0.0.0.0
[B1]   SECDNS 0.0.0.0
[B1] IPV6CP: rec'd Configure Ack #1 (Ack-Sent)
[B1] IPV6CP: state change Ack-Sent --> Opened
[B1] IPV6CP: LayerUp
[B1]   eef4:bbff:fe47:c54c -> e467:e46a:5b1f:dfc1
[B1] IFACE: Up event
[B1] CCP: rec'd Configure Ack #1 (Req-Sent)
[B1]   MPPC
[B1]     0x01000040:MPPE(128 bits), stateless
[B1] CCP: state change Req-Sent --> Ack-Rcvd
[B1] CCP: rec'd Configure Request #7 (Ack-Rcvd)
[B1]   MPPC
[B1]     0x01000040:MPPE(128 bits), stateless
[B1] CCP: SendConfigAck #7
[B1]   MPPC
[B1]     0x01000040:MPPE(128 bits), stateless
[B1] CCP: state change Ack-Rcvd --> Opened
[B1] CCP: LayerUp
[B1] CCP: Compress using: mppc (MPPE(128 bits), stateless)
[B1] CCP: Decompress using: mppc (MPPE(128 bits), stateless)
[B1] IPCP: rec'd Configure Nak #2 (Ack-Sent)
[B1]   IPADDR 10.16.100.34
[B1]     10.16.100.34 is OK
[B1]   PRIDNS 10.16.0.53
[B1]   SECDNS 10.16.0.52
[B1] IPCP: SendConfigReq #3
[B1]   IPADDR 10.16.100.34
[B1]   PRIDNS 10.16.0.53
[B1]   SECDNS 10.16.0.52
[B1] IPCP: rec'd Configure Ack #3 (Ack-Sent)
[B1]   IPADDR 10.16.100.34
[B1]   PRIDNS 10.16.0.53
[B1]   SECDNS 10.16.0.52
[B1] IPCP: state change Ack-Sent --> Opened
[B1] IPCP: LayerUp
[B1]   10.16.100.34 -> 10.16.100.13

Ob alles steht sieht man ebenfalls mit ifconfig :

ng0: flags=88d1<UP,POINTOPOINT,RUNNING,NOARP,SIMPLEX,MULTICAST> metric 0 mtu 1396
	inet6 fe80::eef4:bbff:fe47:c54c%ng0 prefixlen 64 scopeid 0x3
	inet 10.16.100.34 --> 10.16.100.13 netmask 0xffffffff
	nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>

Damit sollte auch schon der Tunnel stehen.

Der Windows VPN Server übermittelt zwar eigentlich die Routen, DNS Server usw., dieses nimmt der mpd5 aber nicht alles gut an. Das meinte ich mit manueller Handarbeit. Sicher nichts für die Masse aber wenn man als Admin „ran“ möchte sicher kein größeres Problem. set ccp yes mppc activiert hierbei die MPPC Komprimierung und Verschlüsselung. set mppc yes e128 stateless ist dabei für die Zusammenarbeit mit dem Windows Server wichtig, denn e128 / stateless ermöglicht als einzige Option die Zusammenarbeit mit MS-CHAPv2 (was hier zum Einsatz kommt). Per IPCP frage ich zwar die Konfiguration wie die ersten beiden DNS-Server ab ( set ipcp enable req-pri-dns / set ipcp enable req-sec-dns ), aktuell mache ich aber damit nichts. Diese Werte werden automatisch mit an die iface up-scripte/down-scripte übermittelt und könnten dort mitbenutzt werden, da ich nur eine solche Verbindung habe und die DNS Konfiguration kenne, nutze die die up/down-scripte nur um die jeweilige /etc/resolv.conf zu kopieren.

Mit den Routen ist es ähnlich, ich kenne die Routen und kann sie also einfach mitgeben: set iface route 172.16.0.0/12 / set iface route 10.0.0.0/8 diese Liste kann nach Belieben eingepasst werden.

Wie gesagt, alles sehr einfach und überschaubar.

Ich starte IPsec und in folge mpd5 meist von Hand, wenn ich es mal brauche, man kann aber auch alles per Dienst starten lassen oder sich irgendeinen Startknopf bauen.

Fragen? Dann fragen!

IPv6 ULA (fd00::/8), fc00::/7 und warum die Priorität oft anders ist als erwartet

Pv6 Unique Local Address fd00::/8 vs IPv4 – Priorität, Prefix Policy und Default Address Selection

Unique Local IPv6 Addresses sind eines dieser Themen, über die man meist erst stolpert, wenn man IPv6 ernsthaft benutzt. Nicht beim ersten „IPv6 ist an“-Häkchen, sondern dann, wenn man anfängt, Netze sauber zu trennen, VPNs aufzubauen, interne Services umzuziehen oder einfach keine Lust mehr auf NAT und IPv4-Private hat.

ULA sollen genau das sein: lokal, eindeutig genug, nicht global routbar. Im Prinzip der IPv6-Nachfolger von 10/8 & Co. Klingt simpel. Ist es auch – bis man merkt, dass Betriebssysteme mit ULA manchmal Dinge tun, die man nicht intuitiv erwartet.

Fangen wir vorne an.

Der reservierte Adressraum für ULA ist fc00::/7. Das liest man oft so, und formal ist das auch korrekt. Praktisch relevant ist davon aber nur fd00::/8. Das sogenannte L-Bit (local) muss gesetzt sein. Der andere Teil, also fc00::/8, ist bis heute nicht weiter definiert und sollte in realen Netzen schlicht nicht verwendet werden. Wenn man ULA nutzt, dann immer fd….

Eine typische ULA sieht dann so aus:

fdXX:XXXX:XXXX::/48

Aufgeschlüsselt:

| 8 Bit | 40 Bit    | 16 Bit | 64 Bit        |
| fd    | Global ID | Subnet | Interface ID |
  • fd → Local-Bit gesetzt
  • Global ID → pseudozufällig, soll Kollisionen vermeiden
  • Subnet → klassische Subnetzstruktur
  • Interface ID → wie bei anderen IPv6-Unicast-Adressen

Die Global ID ist nicht „zentral vergeben“, sondern wird lokal generiert. Ziel ist nicht Sicherheit, sondern praktische Eindeutigkeit, falls Netze später zusammengeführt werden. In der Praxis funktioniert das erstaunlich gut.

Bis hierhin ist alles noch harmlos. Die eigentliche Verwirrung beginnt in dem Moment, in dem ein Host mehrere mögliche Wege zum Ziel hat.

Dual-Stack ist heute der Normalfall. IPv4 und IPv6 gleichzeitig. Und plötzlich steht ein System vor der Frage:
Nehme ich IPv4? Nehme ich IPv6? Und wenn IPv6 – welche Adresse eigentlich?

Die Antwort darauf regelt RFC 6724. Dort ist die Default Address Selection definiert. Vereinfacht gesagt: eine Prioritätenliste für Adresspräfixe. Jedes Präfix bekommt eine Präzedenz. Höher gewinnt.

Und genau hier liegt der Punkt, der viele überrascht:
IPv6 ULA haben nach RFC 6724 eine niedrigere Priorität als IPv4.

Das heißt ganz konkret:
Ist ein Ziel sowohl über IPv4 als auch über IPv6-ULA erreichbar, wird IPv4 bevorzugt.

Das fühlt sich erstmal kontraintuitiv an. IPv6 ist doch „das Neue“. Aber aus Sicht des Standards ist die Logik klar: ULA sind bewusst lokal begrenzt. IPv4 ist – trotz aller Altlasten – global eindeutig. Also gewinnt IPv4.

In der Praxis sieht man dieses Verhalten regelmäßig, vor allem auf Linux- und FreeBSD-Systemen, die sich sehr nah am RFC orientieren. Windows und Apple-Systeme mischen zusätzlich noch Happy-Eyeballs-Mechanismen hinein, was das Verhalten manchmal schwerer nachvollziehbar macht, am Grundprinzip aber nichts ändert.

Wenn man verstehen will, was ein System tatsächlich tut, hilft ein Blick in die jeweilige Prefix-Policy.

Diagnose: Welche Prioritäten nutzt mein System?

Linux:

ip -6 addr show
ip -6 route show
ip -f inet6 addrlabel show

Interessant ist vor allem die Ausgabe der Address-Labels. Dort sieht man, mit welcher Präzedenz fd00::/8, IPv4-Mapped-Adressen und andere Präfixe bewertet werden.

Windows:

netsh interface ipv6 show prefixpolicies

Hier sieht man sehr direkt, welche Präzedenz Windows den einzelnen Präfixen zuordnet. In der Default-Konfiguration liegt ULA unter IPv4.

FreeBSD:

ip6addrctl

Auch hier ist die RFC-6724-Policy gut sichtbar.

Spätestens an dieser Stelle wird klar, warum ein interner Dienst trotz sauber konfigurierter IPv6-ULA plötzlich doch über IPv4 angesprochen wird. Das System macht exakt das, was der Standard vorsieht.

Nun kann man sagen: „Okay, verstanden.“
Oder man kann sagen: „Das ist nicht das Verhalten, das ich will.“

Beides ist legitim.

Anpassung: ULA bewusst höher priorisieren

Wenn ULA für interne Kommunikation wichtiger sind als IPv4 – etwa in reinen IPv6-Infrastrukturen mit IPv4 nur als Fallback – kann man die Präzedenz anpassen.

Linux (/etc/gai.conf):

# IPv6 ULA höher priorisieren als IPv4
precedence fd00::/8  45

Nach einem Reload des Stacks oder Neustart gilt die neue Reihenfolge.

Windows:

netsh interface ipv6 set prefixpolicy fd00::/8 precedence=45 label=1

Damit liegt ULA über IPv4. Windows speichert diese Einstellung persistent.

FreeBSD:

Je nach Version über ip6addrctl oder entsprechende rc-Settings.

Wichtig: Das ist keine rein kosmetische Änderung. Man greift hier bewusst in die Adressauswahl ein. Das sollte man nur tun, wenn man das Netzdesign verstanden hat und weiß, warum man es will.

ULA sind kein Ersatz für Global Unicast Addresses. Sie sind auch kein Allheilmittel. Sie sind ein Werkzeug. Ein gutes – aber eben eines mit klar definiertem Scope.

Spannend ist, dass es inzwischen Entwürfe gibt, die das Verhalten von RFC 6724 weiterentwickeln. Ziel ist unter anderem, ULA-zu-ULA-Kommunikation besser zu priorisieren und bestimmte unerwünschte IPv4-Fallbacks zu vermeiden. Stand heute ist das aber noch nicht flächendeckend umgesetzt. Man sollte sich also nicht darauf verlassen, sondern das Verhalten der eigenen Systeme prüfen.

Am Ende bleibt:

ULA funktionieren. Sie sind sauber spezifiziert. Aber ihre Priorität ist kein Zufall, sondern eine bewusste Designentscheidung. Wer sie einsetzt, sollte wissen, warum IPv4 manchmal „gewinnt“ – und dann entscheiden, ob das so bleiben soll oder nicht.

Wie so oft bei IPv6 liegt das eigentliche Problem nicht im Protokoll, sondern in den Erwartungen, die man aus der IPv4-Welt mitbringt.

Outlook Autodiscover für IMAP/SMTP: Wie die automatische Kontoeinrichtung funktioniert

Benutzer wollen ihr E-Mail-Postfach einrichten. Sie geben E-Mail-Adresse und Passwort ein — den Rest soll der Client erledigen. Bei Exchange mit Active Directory funktioniert das seit Jahren automatisch. Aber was, wenn der Mailserver Postfix und Dovecot heißt und kein Exchange in Sicht ist?

Microsoft Outlook unterstützt auch für IMAP und SMTP die automatische Konfiguration per Autodiscover. Man muss nur wissen, wo Outlook nachschaut — und dort die richtigen Antworten bereithalten.

Outlook Autodiscover für IMAP und SMTP – automatische Mailkonto-Konfiguration über DNS, HTTPS und XML

Wo Outlook nach der Konfiguration sucht

Outlook arbeitet eine feste Reihenfolge ab. Sobald ein Schritt eine gültige Konfiguration liefert, ist die Einrichtung fertig. Schlägt ein Schritt fehl, geht es zum nächsten:

1. Active Directory (SCP) — Ist der Rechner Domänenmitglied, fragt Outlook per LDAP nach einem Service Connection Point. Dort steht normalerweise die URL des Exchange-Servers. Für reine IMAP-Setups irrelevant.

2. HTTPS auf der E-Mail-Domain — Outlook versucht https://example.org/autodiscover/autodiscover.xml. Funktioniert nur, wenn der Webserver der Domain den Pfad bedient.

3. HTTPS auf autodiscover.<domain> — Outlook versucht https://autodiscover.example.org/autodiscover/autodiscover.xml. Das ist der Weg, den wir nutzen. Ein Webserver unter diesem Hostnamen mit gültigem TLS-Zertifikat — mehr braucht es nicht.

4. HTTP-Redirect — Outlook versucht http://autodiscover.example.org/autodiscover/autodiscover.xml und folgt einem 301/302-Redirect. Weniger sicher, aber ein Fallback.

5. DNS SRV-Record — Outlook fragt _autodiscover._tcp.example.org und folgt dem SRV-Eintrag. Bei einem SRV-Verweis auf eine andere Domain zeigt Outlook eine Sicherheitsabfrage: „Konfiguration von dieser Webseite zulassen?“ Einmalig bestätigen, danach läuft es.

6. Lokale XML-Datei — Outlook sucht auf dem Rechner nach einer vorinstallierten Konfigurationsdatei. Für Firmenumgebungen mit Software-Verteilung relevant.

7. Manueller Assistent — Wenn nichts funktioniert hat, öffnet Outlook den Konfigurationsassistenten. Genau das wollen wir vermeiden.

Was Outlook per POST schickt und erwartet

Outlook macht einen HTTP-POST auf /autodiscover/autodiscover.xml und schickt im Body ein XML mit der E-Mail-Adresse des Benutzers:

<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
  <Request>
    <EMailAddress>benutzer@example.org</EMailAddress>
    <AcceptableResponseSchema>
      http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a
    </AcceptableResponseSchema>
  </Request>
</Autodiscover>

Die Antwort enthält IMAP- und SMTP-Einstellungen. Der Clou: Weil Outlook die E-Mail-Adresse im POST mitschickt, kann ein PHP-Script sie auslesen und als <LoginName> in die Antwort einsetzen. Ohne diesen Trick würde Outlook nur den Teil vor dem @ als Benutzernamen verwenden — bei Mailservern, die die volle E-Mail-Adresse als Login erwarten, ein Problem.

Multi-Domain per DNS SRV-Record

Ein Autodiscover-Webserver reicht für beliebig viele Maildomains. Jede zusätzliche Domain braucht nur einen SRV-Record im DNS:

_autodiscover._tcp.example.org.  IN SRV 0 0 443 autodiscover.kernel-error.de.

Outlook folgt dem SRV-Record, zeigt einmalig die Sicherheitsabfrage, und hat danach die komplette Konfiguration. Das PHP-Script auf dem Zielserver beantwortet Anfragen für alle Domains — die E-Mail-Adresse kommt ja im POST mit.

Umsetzung und aktuelle Konfiguration

Die konkrete Einrichtung — nginx-Konfiguration, PHP-Script und DNS — beschreibe ich im Nachfolgebeitrag: Outlook Autodiscover für IMAP und SMTP konfigurieren. Dort steht auch das Update von 2026 mit den Korrekturen am PHP-Script (GET-Absicherung, XSS-Schutz) und der Zusammenlegung mit Thunderbird Autoconfig.

Wer seine Konfiguration testen will: Microsoft bietet unter testconnectivity.microsoft.com den „Microsoft Remote Connectivity Analyzer“ an. Dort den Autodiscover-Test auswählen und die eigene E-Mail-Adresse eingeben.

Fragen? Gerne per Kontaktformular.

Windows Server Backup mit Nagios überwachen

Möchte man die Windows Server Sicherung seines Microsoft Windows Server 2008 oder jünger per Nagios überwachen gibt es viele Wege….
Ich habe einen sehr einfachen gesucht und leider konnte Google mir auf Anhieb keinen nennen.
Auf den zu überwachenden Systemen ist jeweils eine voll (Bare Metal) Sicherung eingerichtet. Diese startet 1 bis x mal am Tag. Ist man auf dem Server angemeldet kann man einfach in der Management Console in die Windows Server-Sicherung schauen und den Zustand der letzten Sicherungen sehen. Natürlich auch ob gerade eine Sicherung läuft, wohin gesichert wird, wie viele Kopien vorhanden sind usw. usw…

Alles Dinge die mich erst einmal nicht interessieren. Der für mich spannende Punkt ist, wann war die letzte erfolgreiche Sicherung und ist diese älter als drei Tage? Warum, weshalb, wo, wie, was… Ist mir im ersten Schritt egal. Ich möchte nur informiert sein, wenn es keine aktuelle Datensicherung gibt.
Nun bin ich eher in der Unixwelt zuhause aber die Windows PowerShell sollte da doch was können, richtig?
Wie ich gesehen habe gibt es ein Snapin für das Windows ServerBackup. Wenn ich dieses hinzufüge kann ich über Get-WBSummary mir eine Art Zusammenfassung anschauen.
In dieser finde ich unter dem Punkt LastSuccessfulBackupTime das Datum der letzten erfolgreichen Sicherung. In meinem Fall also jeweils das Datum meiner letzten Vollsicherung. Daraus kann man doch sicher was basteln, oder?
Ich habe mir also ein kleines Script zusammengeworfen welches folgendes tut:
Es greift sich die Information über die letzte erfolgreiche Sicherung ab und vergleicht sie mit dem aktuellen Datum. Ist es gleich, war die letzte Sicherung heute und alles ist gut. Ist es von gestern, ist auch noch alles gut und Nagios bekommt ein OK zurück. Wenn es aber älter ist (2 – 3 Tage) gibt es eine Warnung an Nagios zurück und wenn es älter ist als 3 Tage gibt es die Meldung critical an Nagios weiter. Nagios kümmert sich dann wie gewohnt darum mich passend zu informieren.
Aktuell greift das Script keinerlei Exeptions ab und es ist nicht… sagen wir mal schön 😀 Ich werde es, je nach Zeit, immer mal etwas erweitern. Seine eigentliche Aufgabe erfüllt es denn noch jetzt schon!

Download:
>>Das Script kann hier in der letzten Version heruntergeladen werden<<

Damit einem nicht schon beim ersten Start des Scriptes die folgende Fehlermeldung anspringt:

Das Windows PowerShell-Snap-In „Windows.ServerBackup“ ist auf diesem Computer nicht installiert.

Muss über den Server-Manager ein weiteres Feature hinzugefügt werden. Hier sind unter Windows Server-Sicherungsfeatures noch die Befehlszeilentools zu installieren. Zusätzlich muss die Policy so geändert werden, dass dieses Script auch ausgeführt werden darf. Dazu einfach in die PowerShell folgendes eingeben:

# Set-ExecutionPolicy RemoteSigned

Ich lege das Script nun im Root des primären Filsystems in den Ordner c:\scripte\
Nun kann ich im NSClient++ die Sektion NRPE Handlers erstellen und dort ein Kommando für den Aufruf des Scriptes erstellen. Möchte man über den NSClient++ Windows PowerShell Scripte ausführen, schaut der Aufruf beim ersten hinschauen etwas seltsam aus:

[NRPE Handlers]
command[check_windowsbackup]=cmd /c echo C:\scripte\backuptest.ps1 | powershell.exe -command -

Natürlich muss der NSClient++ so konfiguriert sein, dass er auch als NRPE arbeitet:

[modules]
NRPEListener.dll
NRPEClient.dll
.....

[NRPE]
port=5666
command_timeout=120
allowed_hosts=1.2.3.4
socket_timeout=120
....

Nach einem Neustart des Clientdienstes sollte man nun auch schon vom Nagiossystem aus einen Test starten können:

$ check_nrpe -H 4.3.2.1 -p 5666 -t 120 -c check_windowsbackup
OK: Backup von gestern

Die restliche Einrichtung in Nagios sollte bekannt sein, sonst fragen 🙂


* UPDATE *

Die Version 0.2 fängt nun zusätzlich den Fehler ab, wenn die Befehlzeilentools nicht installiert sind. Ich dachte erst wäre nicht so wichtig… Aber nachdem ich es auf 10 Systeme gepackt hatte und immer nachgeschat habe 😛 Nun greift es dieses also ebenfals ab und gibt eine CRITICAL Meldung an Nagios weiter!


* UPDATE *

Die Version 0.3 fängt nun auch ab ob eine Sicherung über einen Tageswechsel hin noch läuft.

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑