# How to Debug NTS Connection Problems with chrony or ntpd-rs

> Debug NTS connection problems with chrony or ntpd-rs. Verify DNS, test connectivity, validate configs, and use verbose logging to fix TLS handshake and certificate issues.

- Repository: [Jauder Ho/nts-servers](https://github.com/jauderho/nts-servers)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Debug NTS connection problems by verifying DNS resolution, testing UDP/TCP connectivity, validating configuration syntax in [`chrony.conf`](https://github.com/jauderho/nts-servers/blob/main/chrony.conf) or [`ntp.toml`](https://github.com/jauderho/nts-servers/blob/main/ntp.toml), and using verbose logging to isolate TLS handshake and certificate failures.**

The `jauderho/nts-servers` repository maintains a curated list of Network Time Security (NTS) capable NTP servers, but clients like **chrony** and **ntpd-rs** can fail to connect due to DNS misconfiguration, firewall rules, or certificate issues. Understanding how to debug NTS connection problems requires a systematic approach across the network stack, from basic connectivity tests to deep TLS handshake inspection. This guide walks through the exact commands, configuration files, and verification scripts provided in the repository to diagnose and resolve connection failures.

## Verify DNS and Network Connectivity First

Before debugging NTS-specific protocol issues, confirm that the underlying network path is clear.

### Check DNS Resolution

NTS failures often stem from hostname resolution problems. Use standard DNS tools to verify the server resolves correctly:

```bash
dig +short time.cloudflare.com
host time.cloudflare.com

```

If these commands return no IP addresses, the issue lies with your local resolver or the server's DNS records, not the NTS implementation.

### Test UDP Port 123

Chrony uses UDP port 123 for NTP traffic. Verify basic reachability with netcat:

```bash
nc -vz -u time.cloudflare.com 123

```

A *Connection timed out* error indicates that firewalls, NAT rules, or routing problems are blocking UDP traffic before it reaches the NTS server.

## Validate Configuration Files

NTS requires explicit configuration keywords that differ between chrony and ntpd-rs.

### Inspect chrony.conf

The repository provides [`chrony.conf`](https://github.com/jauderho/nts-servers/blob/main/chrony.conf), which lists servers with the **nts** keyword required to enable NTS. According to the source analysis, each server entry must include the `nts` flag:

```bash

# Example entry in chrony.conf

server time.cloudflare.com iburst nts

```

Missing the `nts` keyword causes chrony to attempt standard NTP authentication rather than NTS, resulting in connection failures or "NTS not supported" errors.

### Inspect ntp.toml

For **ntpd-rs**, the repository generates [`ntp.toml`](https://github.com/jauderho/nts-servers/blob/main/ntp.toml) from the same source list. This TOML configuration file contains the server definitions used by the Rust daemon. Verify that your local copy matches the repository version, as the file is kept up-to-date via [`scripts/ntpServerConverter.py`](https://github.com/jauderho/nts-servers/blob/main/scripts/ntpServerConverter.py) processing [`nts-sources.yml`](https://github.com/jauderho/nts-servers/blob/main/nts-sources.yml).

## Test NTS Connections with Command-Line Tools

The repository includes purpose-built scripts to test NTS functionality without modifying your system configuration.

### Single-Shot Tests Using chronyd

The [`scripts/ntsCheck.sh`](https://github.com/jauderho/nts-servers/blob/main/scripts/ntsCheck.sh) file provides a wrapper around chrony's built-in NTS client. It executes:

```bash
chronyd -Q -t 5 "server time.cloudflare.com iburst nts maxsamples 1"

```

Run the script directly to test any server:

```bash
./scripts/ntsCheck.sh time.cloudflare.com

```

The `-Q` flag performs a one-shot query and exits, printing specific error messages such as `NTS handshake successful`, `NTS not supported`, or `Network unreachable` directly to the terminal.

### Batch Verification with verifyNTSServers.py

To test the entire server list at once, use the Python verification script which processes [`nts-sources.yml`](https://github.com/jauderho/nts-servers/blob/main/nts-sources.yml):

```bash
python3 scripts/verifyNTSServers.py nts-sources.yml

```

As implemented in [`scripts/verifyNTSServers.py`](https://github.com/jauderho/nts-servers/blob/main/scripts/verifyNTSServers.py), the script extracts hostnames from the YAML file (handling both plain text and markdown links) and runs the same `chronyd` query for every entry. Output is grouped into *Good* and *Failed* sections, making it easy to identify problematic servers across the entire list.

## Enable Verbose Logging for TLS and NTS Handshake Debugging

When basic connectivity tests fail, verbose logging reveals whether the problem occurs during the TLS handshake or the NTS extension negotiation.

### Debug chrony with Foreground Mode

Start chrony in debug mode to view protocol-level details:

```bash
sudo chronyd -d -q -n -f chrony.conf

```

**Key flags explained:**
- `-d` enables debug output showing TLS and NTS protocol steps
- `-q` quits after the first successful poll
- `-n` runs in the foreground without daemonizing

Watch the output for specific error patterns:
- `NTS: TLS handshake failed (error 0x80000000)` indicates certificate or TLS version issues
- `NTS: Server does not support NTS extension` means the server offers HTTPS but lacks the NTS-KE (Network Time Security Key Establishment) service

### Debug ntpd-rs with RUST_LOG

For the Rust implementation, enable debug tracing via environment variables:

```bash
RUST_LOG=debug ntpd-rs -c ntp.toml -n

```

The debug log includes entries such as:

```

[DEBUG ntpd_rs::nts] TLS handshake completed, NTS ready
[ERROR ntpd_rs::nts] NTS handshake failed: certificate verification error

```

If you encounter *certificate verification error*, update your system's CA certificate bundle (`update-ca-certificates` on Debian/Ubuntu systems) to ensure the client recognizes the server's certificate authority.

## Cross-Check with Legacy NTP Tools

Although NTS uses TCP/443 for the initial handshake, the underlying time synchronization relies on UDP/123. Verify basic NTP functionality to isolate transport layer issues:

```bash
ntpdate -q time.cloudflare.com
ntpq -p time.cloudflare.com

```

Success here confirms that UDP traffic flows correctly; failure usually indicates network blocking rather than NTS-specific configuration problems.

## Summary

Debugging NTS connections requires methodical verification across multiple layers:
- Use `dig` and `nc` to confirm DNS resolution and UDP connectivity before troubleshooting NTS protocols
- Reference [`chrony.conf`](https://github.com/jauderho/nts-servers/blob/main/chrony.conf) and [`ntp.toml`](https://github.com/jauderho/nts-servers/blob/main/ntp.toml) to ensure the **nts** keyword or equivalent configuration is present
- Run [`scripts/ntsCheck.sh`](https://github.com/jauderho/nts-servers/blob/main/scripts/ntsCheck.sh) for quick single-server tests using `chronyd -Q`
- Execute [`scripts/verifyNTSServers.py`](https://github.com/jauderho/nts-servers/blob/main/scripts/verifyNTSServers.py) against [`nts-sources.yml`](https://github.com/jauderho/nts-servers/blob/main/nts-sources.yml) to batch-check the entire curated list
- Enable `chronyd -d` or `RUST_LOG=debug` to inspect TLS handshake details and certificate validation
- Update system CA bundles when `ntpd-rs` reports certificate verification errors

## Frequently Asked Questions

### Why does chrony report "NTS handshake failed"?

This error typically indicates a TLS layer problem, such as an expired server certificate, unsupported TLS version, or missing intermediate certificates. Run `sudo chronyd -d -q` to view the specific TLS error code. If the server uses a modern certificate chain, ensure your system's CA certificates are current by running `update-ca-certificates`.

### How do I test if my firewall is blocking NTS traffic?

First, test UDP port 123 with `nc -vz -u <hostname> 123`. Then test TCP port 443 (used for the NTS-KE handshake) with `nc -vz <hostname> 443`. If the UDP test fails but TCP succeeds, your firewall is likely blocking standard NTP traffic while allowing HTTPS. Both protocols must be open for NTS to function.

### What's the difference between the chrony.conf and ntp.toml files in the repository?

Both files contain the same curated server list from [`nts-sources.yml`](https://github.com/jauderho/nts-servers/blob/main/nts-sources.yml), but [`chrony.conf`](https://github.com/jauderho/nts-servers/blob/main/chrony.conf) uses chrony's native configuration syntax with the `server` and `nts` keywords, while [`ntp.toml`](https://github.com/jauderho/nts-servers/blob/main/ntp.toml) uses TOML format required by ntpd-rs. The repository keeps both synchronized via [`scripts/ntpServerConverter.py`](https://github.com/jauderho/nts-servers/blob/main/scripts/ntpServerConverter.py), which regenerates the files whenever [`nts-sources.yml`](https://github.com/jauderho/nts-servers/blob/main/nts-sources.yml) is updated.

### Can I use verifyNTSServers.py to test custom NTS servers?

Yes, the script accepts any YAML file following the [`nts-sources.yml`](https://github.com/jauderho/nts-servers/blob/main/nts-sources.yml) structure. Create a file listing your custom hostnames and run `python3 scripts/verifyNTSServers.py your-file.yml`. The script will attempt NTS handshakes with each entry using the same `chronyd -Q` command used for the official repository list.