Skip to main content

NTP Server abfragen und Netzwerk prüfen

NTP nutzt UDP Port 123. Ein normaler TCP-Portcheck ist daher nicht ausreichend. Wenn bestimmte NTP-Server per IP-Adresse getestet werden sollen, muss eine echte NTP-Anfrage an diese IP gesendet werden.


Keine Zusatzpakete notwendig

Der folgende Test benötigt keine zusätzlichen NTP-Tools wie ntpdig, sntp oder ntpdate. Er verwendet nur python3, falls es auf dem System vorhanden ist.

Auf normalen Debian-Systemen ist python3 häufig vorhanden. Auf sehr minimalen Systemen ist das aber nicht garantiert. Ohne python3 oder ein NTP-Tool ist ein sauberer direkter NTP-Test gegen beliebige IP-Adressen nicht sinnvoll möglich.


1. Einzelne NTP-IP testen

Beispiel-IP anpassen:

python3 - 192.168.10.10 <<'PY'
import datetime
import ipaddress
import socket
import struct
import sys

if len(sys.argv) != 2:
    print("FEHLER: Bitte genau eine IP-Adresse angeben.")
    sys.exit(2)

host = sys.argv[1].strip()

try:
    ipaddress.ip_address(host)
except ValueError:
    print(f"FEHLER {host}: Keine gültige IP-Adresse.")
    sys.exit(2)

packet = bytearray(48)
packet[0] = 0x23

try:
    infos = socket.getaddrinfo(host, 123, type=socket.SOCK_DGRAM)
    family, socktype, proto, _, sockaddr = infos[0]

    with socket.socket(family, socktype, proto) as sock:
        sock.settimeout(3)
        sock.sendto(packet, sockaddr)
        data, addr = sock.recvfrom(512)

    if len(data) < 48:
        print(f"FEHLER {host}: Antwort zu kurz, keine gültige NTP-Antwort.")
        sys.exit(1)

    stratum = data[1]
    tx_seconds, tx_fraction = struct.unpack("!II", data[40:48])
    unix_time = tx_seconds - 2208988800 + tx_fraction / 2**32
    server_time = datetime.datetime.fromtimestamp(unix_time, datetime.timezone.utc)

    if stratum == 0:
        print(f"WARNUNG {host}: Antwort erhalten, aber Stratum 0. Server lehnt die Anfrage möglicherweise ab.")
    else:
        print(f"OK {host}: NTP-Antwort erhalten, Stratum {stratum}, Serverzeit {server_time.isoformat()}")

except socket.timeout:
    print(f"FEHLER {host}: Timeout. Keine NTP-Antwort über UDP Port 123.")
    sys.exit(1)
except OSError as e:
    print(f"FEHLER {host}: Netzwerkfehler: {e}")
    sys.exit(1)
PY

2. Mehrere NTP-IPs testen

Die IP-Adressen in der ersten Zeile anpassen:

for ip in 192.168.10.10 192.168.10.11 192.168.10.12; do
  python3 - "$ip" <<'PY'
import datetime
import ipaddress
import socket
import struct
import sys

host = sys.argv[1].strip()

try:
    ipaddress.ip_address(host)
except ValueError:
    print(f"FEHLER {host}: Keine gültige IP-Adresse.")
    sys.exit(2)

packet = bytearray(48)
packet[0] = 0x23

try:
    infos = socket.getaddrinfo(host, 123, type=socket.SOCK_DGRAM)
    family, socktype, proto, _, sockaddr = infos[0]

    with socket.socket(family, socktype, proto) as sock:
        sock.settimeout(3)
        sock.sendto(packet, sockaddr)
        data, addr = sock.recvfrom(512)

    if len(data) < 48:
        print(f"FEHLER {host}: Antwort zu kurz, keine gültige NTP-Antwort.")
        sys.exit(1)

    stratum = data[1]
    tx_seconds, tx_fraction = struct.unpack("!II", data[40:48])
    unix_time = tx_seconds - 2208988800 + tx_fraction / 2**32
    server_time = datetime.datetime.fromtimestamp(unix_time, datetime.timezone.utc)

    if stratum == 0:
        print(f"WARNUNG {host}: Antwort erhalten, aber Stratum 0. Server lehnt die Anfrage möglicherweise ab.")
    else:
        print(f"OK {host}: NTP-Antwort erhalten, Stratum {stratum}, Serverzeit {server_time.isoformat()}")

except socket.timeout:
    print(f"FEHLER {host}: Timeout. Keine NTP-Antwort über UDP Port 123.")
except OSError as e:
    print(f"FEHLER {host}: Netzwerkfehler: {e}")
PY
done

3. Prüfen, ob Python vorhanden ist

python3 --version

Wenn eine Versionsnummer angezeigt wird, kann der Test verwendet werden. Wenn python3: command not found erscheint, ist Python auf diesem System nicht installiert.


Warum nicht curl oder wget?

curl und wget können keine echte NTP-Abfrage machen. NTP läuft über UDP Port 123, nicht über HTTP oder HTTPS.

Mit curl oder wget kann man nur prüfen, ob HTTP/HTTPS funktioniert:

curl -I https://www.debian.org
wget --spider https://www.debian.org

Das sagt aber nichts Sicheres darüber aus, ob NTP über UDP Port 123 erlaubt ist. Denn natürlich kann Netzwerkdiagnose nicht einfach mal logisch sein.


Warum nicht nur Bash mit /dev/udp?

Bash kann zwar Daten an /dev/udp/IP/PORT senden, aber UDP hat keinen Verbindungsaufbau wie TCP. Nur weil ein UDP-Paket gesendet wurde, weiß man noch nicht, ob ein NTP-Server geantwortet hat.

Für einen brauchbaren Test muss eine echte NTP-Anfrage gesendet und die Antwort ausgewertet werden. Genau das macht der Python-Test oben.


Ergebnis bewerten

Ergebnis Bedeutung
OK ... NTP-Antwort erhalten Die IP-Adresse antwortet auf NTP über UDP Port 123.
WARNUNG ... Stratum 0 Der Server hat geantwortet, lehnt die Anfrage aber möglicherweise ab oder liefert keine nutzbare Zeit.
Timeout Keine Antwort erhalten. UDP Port 123 wird möglicherweise blockiert oder der Server antwortet nicht.
Netzwerkfehler Es gibt ein lokales Netzwerkproblem, Routingproblem oder ein Problem mit der Adresse.
Keine gültige IP-Adresse Der angegebene Wert ist keine gültige IPv4- oder IPv6-Adresse.

Kurzfazit

Wenn bestimmte IP-Adressen getestet werden sollen, reicht timedatectl nicht aus. Für einen direkten Test braucht man entweder ein NTP-Tool wie ntpdig oder einen kleinen UDP-NTP-Test wie oben mit python3.

Ohne python3, ntpdig, sntp oder ntpdate ist ein sauberer direkter NTP-Test gegen beliebige IP-Adressen nicht realistisch möglich.