sdwdate Development Notes

From Kicksecure
< Dev
Jump to navigation Jump to search
Design Previous page: First Time Source Code Contributor Policy Index page: Design Next page: Dev/image creation sdwdate Development Notes

Fingerprinting versus Security

chrony as a replacement for sclockadj

[edit]

Introduction

[edit]

Idea: use sdwdate to fetch the time, but set the time using chrony (new method) instead of using sclockadj (current method).

Problem with sclockadjGitHub Logo is that it uses clock_settime, which is causing issues. chrony uses adjtimexarchive.org iconarchive.today icon, which will probably work better.

For that, chrony is configured in "offline mode", i.e., not contacting any remote servers to fetch the time. chrony is only supposed to set the time, which sdwdate should feed into chrony through its unix domain socket driver protocol.

Instructions

[edit]

1. Platform-specific.

  • Debian: No special steps required.
  • Qubes: Required in Qubes only.

sudo touch /var/run/qubes-service/clocksync

2. Remove all other time synchronization daemons.

This is to avoid other time synchronization daemons competing for any clock changes.

sudo apt purge ntp* sdwdate systemd-timesyncd

3. Install chrony.

Install package(s) chrony following these instructions

1 Platform specific notice.

2 Update the package lists and upgrade the system.

sudo apt update && sudo apt full-upgrade

3 Install the chrony package(s).

Using apt command line --no-install-recommends option is in most cases optional.

sudo apt install --no-install-recommends chrony

4 Platform specific notice.

  • Kicksecure: No special notice.
  • Kicksecure-Qubes: Shut down Template and restart App Qubes based on it as per Qubes Template Modification.

5 Done.

The procedure of installing package(s) chrony is complete.

4. Open file /etc/chrony/conf.d/30_sdwdate.conf in an editor with root rights.

Select your platform.

Kicksecure

See Open File with Root Rights for detailed instructions on why using sudoedit improves security and how to use it.

Note: Mousepad (or the chosen text editor) must be closed before running the sudoedit command.

sudoedit /etc/chrony/conf.d/30_sdwdate.conf

Kicksecure-Qubes

Notes:

sudoedit /etc/chrony/conf.d/30_sdwdate.conf

  • After applying this change, shut down the Template.
  • All App Qubes based on the Template need to be restarted if they were already running.
  • This is a general procedure required for Qubes and is unspecific to Kicksecure-Qubes.

Others and Alternatives

Notes:

  • This is just an example. Other tools could achieve the same goal.
  • If this example does not work for you, or if you are not using Kicksecure, please refer to Open File with Root Rights.

sudoedit /etc/chrony/conf.d/30_sdwdate.conf

5. Paste.

## Enable offline mode. ## Disable Debian default pool. ## Which is configured in /etc/chrony/chrony.conf ## Does not work. #pool 2.debian.pool.ntp.org offline ## Open the refclock unix domain socket. ## Tested. This is functional. When running "chronyc sources" ## the socket is shown. Versus without the following line, the ## socket is not shown. refclock SOCK /var/run/chrony.ttyS0.sock

6. Save and exit.

7. Open file /etc/chrony/chrony.conf in an editor with root rights.

Select your platform.

Kicksecure

See Open File with Root Rights for detailed instructions on why using sudoedit improves security and how to use it.

Note: Mousepad (or the chosen text editor) must be closed before running the sudoedit command.

sudoedit /etc/chrony/chrony.conf

Kicksecure-Qubes

Notes:

sudoedit /etc/chrony/chrony.conf

  • After applying this change, shut down the Template.
  • All App Qubes based on the Template need to be restarted if they were already running.
  • This is a general procedure required for Qubes and is unspecific to Kicksecure-Qubes.

Others and Alternatives

Notes:

  • This is just an example. Other tools could achieve the same goal.
  • If this example does not work for you, or if you are not using Kicksecure, please refer to Open File with Root Rights.

sudoedit /etc/chrony/chrony.conf

Out-comment or delete the following line.

pool 2.debian.pool.ntp.org iburst

Non-ideal. It would be nicer if offline mode configuration could be done with a drop-in snippet in folder /etc/chrony/conf.d, but this might not be possible.

8. Save and exit.

9. Restart chrony.

sudo systemctl restart chrony

10. No need to restart chronyd. [1]

11. Check if the unix domain socket file /var/run/chrony.ttyS0.sock exists.

ls /var/run/chrony.ttyS0.sock

12. Watch chrony journal log.

sudo journalctl -f -u chrony

13. Verify that the unix domain socket driver is the only time source.

chronyc sources

Expected printout:

MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
#? SOC0                          0   4     0     -     +0ns[   +0ns] +/-    0ns

14. chronyc

Might be helpful during development.

chronyc

chronyc help

chronyc tracking

15. See man pages.

16. GNU date usage examples:

Might be useful during development.

To show the current time in unixtime format:

date --utc "+%s"

Expected printout:

1654420510

To convert a specific time/date to unixtime, use:

date --utc "+%s" --date "Sun 05 Jun 2022 09:22:28 AM UTC"

Expected printout:

1654420948

17. TODO: task

Write a python3.9 or bash script that expects unixtime and writes it into the unix domain socket file /var/run/chrony.ttyS0.sock.

interface draft, TODO:

./unixtime-to-chrony-socket 1654420510

Or if the protocol also supports nanoseconds:

./unixtime-to-chrony-socket 1654420510.864804506

How can we write messages to the unix domain socket file?

maybe https://unix.stackexchange.com/questions/117037/how-to-send-data-to-a-serial-port-and-see-any-answerarchive.org iconarchive.today icon

does not work

Information

[edit]

Testing if chrony is really in "offline mode" is not trivial. pool 2.debian.pool.ntp.org offline did not work.

chrony needed 7 minutes between its start and showing that it is still communicating with remote time servers.

Jun 05 04:46:44 disp5211 systemd[1]: Starting chrony, an NTP client/server...
Jun 05 04:46:44 disp5211 chronyd[6133]: chronyd version 4.0 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
Jun 05 04:46:44 disp5211 chronyd[6133]: Frequency -0.343 +/- 9.106 ppm read from /var/lib/chrony/chrony.drift
Jun 05 04:46:44 disp5211 chronyd[6133]: Using right/UTC timezone to obtain leap second data
Jun 05 04:46:44 disp5211 chronyd[6133]: Loaded seccomp filter
Jun 05 04:46:44 disp5211 systemd[1]: Started chrony, an NTP client/server.
Jun 05 04:53:52 disp5211 chronyd[6133]: Selected source 172.107.94.157 (2.debian.pool.ntp.org)
Jun 05 04:53:52 disp5211 chronyd[6133]: System clock TAI offset set to 37 seconds

Fingerprinting versus Security

[edit]

An optimization problem. There are conflicting goals.

  • goal: Saving remote server resources → implementation: use HEAD (implemented)
  • goal: Fingerprinting resistance at the remote server level → implementation: Hide outdated user agent version numbers (not implemented)
    • similar to --user-agent curl or even a fake user agent.
    • Disadvantage: this user agent may make use really unique.
    • Hiding version numbers might not help with security either. If a user runs a vulnerable version, an adversary could try every exploit independent of the user agent version. The only solution is timely software upgrades by the user.
    • Tails-dev - Faking htpdate user agent worth it?archive.org iconarchive.today icon
  • goal: Maximization of security of sdwdate (implemented) → implementation: use the most remote code execution resistant backend (such as curl vs full web browser vs python3 requests) for url_to_unixtime
    • Use python3 requests (implemented in memory-safe python3) instead of curl (implemented in unsafe memory language C).
  • goal: Maximization of fingerprinting resistance from the viewpoint of the remote server → implementation: emulate being a full browser by using selenium or similar. (not implemented)
    • Convincingly emulating a browser is impossible. Changing the user agent is insufficient. The only way is to actually run a browser.
    • Running a full browser inside sdwdate would mess up security. Also very difficult to implement. Running a full browser GUI with an invisible X server and then somehow extracting only the HTTP DATE header. Might also worsen sdwdate's web fingerprint since it would run any tracking script (e.g., Google Analytics) present on the remote server. Then also, which browser? Tor Browser + selenium? Keep that browser updated? Too complex.

A compromise had to be made. Priority goals were chosen: maximizing sdwdate security and saving remote server resources.

sdwdate linux user account

[edit]
  • sdwdate is a daemon designed to be executed by an init system.
  • There is no hard dependency on systemd by sdwdate.
  • Currently, there is only a systemd unit file in the sdwdate GitHub repository.
  • Other systems could be supported in principle, but this is currently unsupported as no contributor has added that functionality.
  • sdwdate is designed to run under the linux user account sdwdate.
  • Running sdwdate as root is neither desired nor required.
  • Thanks to systemd, sdwdate can benefit from systemd sandboxing, which would be unavailable if started manually with user privileges.
    • Using Linux capabilities. Has AmbientCapabilities=CAP_SYS_TIME and CapabilityBoundingSet=CAP_SYS_TIME. Therefore, the linux user account sdwdate can set the time without root.

Footnotes

[edit]
  1. Since it is just an alias in /lib/systemd/systemchrony.service.
    Alias=chronyd.service
    

Design Previous page: First Time Source Code Contributor Policy Index page: Design Next page: Dev/image creation

Notification image

We believe security software like Kicksecure needs to remain Open Source and independent. Would you help sustain and grow the project? Learn more about our 13 year success story and maybe DONATE!