Falsche Uhrzeit auf Android / Chrony in Termux

mk16.de

Ich habe neulich sping in Termux ausprobiert. sping ist ein Protokoll, welches asymmetrische Latenzen und asymmetrischen Paketverlust messen kann. Dies bedeutet, dass sping mir die Zeit mitteilen kann, wie lange ein Paket zum anderen Peer braucht und wie lange es vom Peer zu mir zurück braucht. Außerdem kann mir sping wenn ein Paket verloren geht mitteilen, auf welcher dieser zwei Strecken - Hin- oder Rückweg - es verloren gegangen ist. Dies ist besonders hilfreich, wenn die Wege zum Peer Hin- und Zurück unterschiedlich sind. Das Phänomen, dass die Hin- und Rückwege unterschiedlich sind, wird auch als “asymmetrisches Routing” bezeichnet.

Nun wollte ich das ganze auf meinem Smartphone in Termux ausprobieren. Also habe ich eine sping-Implementation heruntergeladen und an meinem Server getestet. Das Resultat war Folgendes:

[fd00:8e13:ce5d::1] RX: -594.034314ms TX: 650.83909ms [Loss RX: 1/32 | Loss TX: 0/32]

Wenn man das Resultat interpretiert, bedeutet dies, dass mein Smartphone das Antwortpaket etwa eine halbe Sekunde bekommen hat, bevor der Server dieses überhaupt abgesendet hat. Dies ist natürlich nicht möglich. Im Allgemeinen deutet eine solche Ausgabe darauf hin, dass die Uhren der beiden Peers nicht synchron sind. Da nur die Zeitdifferenz gemessen wird, ist es dabei irrelevant, ob die Uhren richtig gehen - solange beide synchron sind. Das Phänomen entsteht, da das Antwortpaket die Uhrzeit enthält, wann der Server das Paket verarbeitet und gesendet hat. Beim anderen Peer angekommen, wird dann die Differenz der Uhrzeit der Ankunft des Paketes und der Uhrzeit, wann dieses gesendet wurde (die Information in im Paket selber vorhanden) berechnet. Eine solche falsche Uhr hat in diesem Fall auch dazu geführt, dass ein Paket als “verloren” markiert wurden ist.

Welche Uhr geht falsch?

Auf meinem Server, auf welchem ich meinen sping-Server installiert hatte, habe ich chrony - einen bekannten NTP-Daemon - laufen. Nachdem ich überprüft habe, dass dieser wie gewünscht läuft, habe ich mir die Uhrzeit auf meinem Smartphone näher angeschaut. Auf diesem läuft LineageOS (Android). Ich wollte nun herausfinden, ob die Uhr auf meinem Smartphone falsch geht und wenn ja, um wie viele Sekunden.

Um dies zu tun, habe ich chrony installiert. Ich habe später dazu auch ein Skript für die Installtion geschrieben und eine Anfrage an Termux gesendet, ob chrony in das Termux Paket Repository aufgenommen werden kann.

Folgendes war das Ergebnis:

$ chronyd -Q -t 3 'server ptbtime1.ptb.de iburst maxsamples 1'
2023-11-14T17:34:36Z chronyd version 4.4 starting (+CMDMON +NTP -REFCLOCK +RTC -PRIVDROP -SCFILTER -SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
2023-11-14T17:34:36Z Disabled control of system clock
2023-11-14T17:34:40Z System clock wrong by -1.282094 seconds (ignored)
2023-11-14T17:34:40Z chronyd exiting
$ chronyd -Q -t 3 'server ptbtime4.ptb.de iburst maxsamples 1'
2023-11-14T17:34:53Z chronyd version 4.4 starting (+CMDMON +NTP -REFCLOCK +RTC -PRIVDROP -SCFILTER -SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
2023-11-14T17:34:53Z Disabled control of system clock
2023-11-14T17:34:57Z System clock wrong by -1.275957 seconds (ignored)
2023-11-14T17:34:57Z chronyd exiting
$ chronyd -Q -t 3 'server time.cloudflare.com iburst maxsamples 1'
2023-11-14T17:35:02Z chronyd version 4.4 starting (+CMDMON +NTP -REFCLOCK +RTC -PRIVDROP -SCFILTER -SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
2023-11-14T17:35:02Z Disabled control of system clock
2023-11-14T17:35:06Z System clock wrong by -1.281283 seconds (ignored)
2023-11-14T17:35:06Z chronyd exiting

Ich habe chrony die Zeit mit verschiedenen Servern als Referenz überprüfen lassen. Man sieht, dass die Uhr auf meinem Smartphone um etwa 1.2 Sekunden vorgeht, was die Ausgabe von sping erklärt.

Skript

CHRONY_VERSION wird durch die aktuelle Version von chrony ersetzt.

#!/data/data/com.termux/files/usr/bin/bash

CHRONY_VERSION=4.4

die () {
    >&2 echo "$1"
    exit 1
}

pkg install -y build-essential clang pkg-config readline libtomcrypt libnettle libnss libgnutls libcap gnupg || die "Could not install all required packages."

curl "https://chrony-project.org/releases/chrony-${CHRONY_VERSION}.tar.gz" --output "chrony-${CHRONY_VERSION}.tar.gz" || die "Could not download chrony."
curl "https://chrony-project.org/releases/chrony-${CHRONY_VERSION}-tar-gz-asc.txt" --output "chrony-${CHRONY_VERSION}-tar-gz-asc.txt" || die "Could not download the GPG signature from chrony."

gpg --keyserver "keyserver.ubuntu.com" --recv-keys "8F375C7E8D0EE125A3D3BD51537E2B76F7680DAC" || die "Could not download the GPG key to verify the signature."

gpg --verify "chrony-${CHRONY_VERSION}-tar-gz-asc.txt" "chrony-${CHRONY_VERSION}.tar.gz" || die "Could not verify the signature."

tar xzf "chrony-${CHRONY_VERSION}.tar.gz" || die "Could not extract the chrony download."
# x = extract
# z = gzip
# f = file

(
    cd "chrony-${CHRONY_VERSION}/" || die "Could not change to the downloaded directory of chrony."

    # chrony can currently (not yet) adjust the time on Android, see https://gitlab.com/chrony/chrony/-/issues/1
    # For the build to be successful, this functionality must be deactivated with `--disable-refclock`.
    ./configure \
        --disable-refclock \
        --prefix="/data/data/com.termux/files/usr/" \
        --sysconfdir="/data/data/com.termux/files/usr/etc" \
        --localstatedir="/data/data/com.termux/files/usr/var" \
            || die "Could not successfully perform the preparation of the compilation of chrony."
    make -j "$(nproc)" || die "Could not compile chrony successfully."
    make install || die "Could not install chrony successfully."
)

Update zu chrony in Termux Package Repository: @sylirre hat es hinbekommen, ein Build-Script für Termux zu bauen. Es ist nun in den Paketquellen vorhanden.