
Figura 1: Topologia em camadas (estratos)
O estrato 0, ou relógio de referência, fornece o tempo correto para o estrato 1, que por sua vez fornece o tempo para o estrato 2 e assim por diante. O NTP é então, simultaneamente, servidor (fornece o tempo) e cliente (consulta o tempo). A topologia está ilustrada na Figura 1. De forma geral, quanto mais perto da raiz, ou seja, do estrato 0, maior a exatidão do tempo. O estrato ao qual o servidor pertence é a principal métrica utilizada pelo NTP para escolher dentre vários, qual o melhor servidor para fornecer o tempo. Por outro lado, normalmente as diferenças de exatidão entre os estratos não são expressivas e há, no momento de escolher-se um conjunto de servidores de tempo para configurar um determinado cliente, outros fatores a se considerar, como por exemplo a carga à qual os servidores estão submetidos, e o atraso de rede. O estrato de um servidor não é uma característica estática. Se houver perda de conexão com as fontes de tempo, ou outros fatores que modifiquem a topologia da rede, o estrato pode variar. Ao consultar-se a lista de servidores no daemon NTP, o estrato (st) é informado:
usuario@cliente.local:~$ ntpq -c pe
remote refid st t when poll reach delay offset jitter
======================================================================
-servidor1 .IRIG. 1 u 8 32 377 0.407 0.248 0.016
-servidor2 .GPS. 1 u - 32 377 0.474 0.213 0.019
+servidor3 .GPS. 1 u 9 64 377 15.680 -0.005 0.026
+servidor4 .IRIG. 1 u 30 64 377 15.582 0.004 0.100
*servidor5 .GPS. 1 u 10 32 377 0.400 -0.026 0.049
xservidor6 .IRIG. 1 u 26 64 377 7.824 9.923 0.367
As relações entre os diferentes dispositivos NTP são normalmente chamadas de Associações. Elas podem ser:
No processo, então, o cliente envia um pacote ao servidor a aguarda a resposta, que vem em seguida. Isso pode ser descrito também como uma operação do tipo pull, dizendo que o cliente busca os dados necessários sobre o tempo no servidor.
Para configurar o cliente dessa forma é usado o parâmetro server no arquivo de configuração, seguido do nome ou endereço do servidor. É recomendável também usar adicionalmente o parâmetro iburst no comando, que serve para acelerar a sincronização inicial.
Um cliente pode criar associações com vários servidores simultaneamente (na verdade é recomendável que seja assim), e um servidor pode fornecer tempo a diversos clientes simultaneamente.
Um dispositivo (host) NTP normalmente é cliente e servidor ao mesmo tempo.
Esse modo é particularmente susceptível a ataques, onde um dispositivo intruso pode estar configurado no modo simétrico ativo e fornecer informações de tempo falsas para outro. Por isso deve sempre ser usado com criptografia.
Para configurar um dispositivo no modo simétrico utiliza-se o parâmetropeer, seguido do nome ou IP do par. Com o modo simétrico não deve-se utilizar os parâmetros burst ou iburst.
Para evitar a falha de segurança descrita no modo simétrico passivo, deve-se sempre manter a autenticação habilitada. Isso é o padrão do sistema. Para desabilitar a autenticação inclui-se o parâmetro disable auth no arquivo de configuração: isso não deve ser feito, a menos que se entenda muito bem as conseqüências e haja uma razão muito forte.
O cliente NTP no modo broadcast ou multicast (à partir da versão 4), ao receber o primeiro pacote de um servidor, busca os dados por um curto período de tempo, como se estivesse no modo cliente - servidor, a fim de conhecer o atraso envolvido. Ou seja, durante alguns instantes há troca de pacotes entre cliente e servidor, depois disso o cliente passa apenas a receber os pacotes broadcast ou multicast do servidor.
Para configurar um servidor utiliza-se o parâmetro broadcast, seguido do endereço IP de broadcast da interface de rede, ou de um endereço multicast. O IANA reservou os endereços multicast 224.0.1.1 (IPv4) e ff05::101 (IPv6 - site local) para o NTP, mas outros endereços podem ser utilizados. O parâmetro minpoll controla o tempo entre pacotes e o parâmetro ttl o número de saltos máximo de cada um deles.
Para configurar o cliente utiliza-se o parâmetro broadcastclient. Na versão 3 do NTP era necessário também utilizar o parâmetro broadcastdelay para definir o atraso de rede envolvido.
Como no caso do modo simétrico passivo, há aqui uma questão de segurança, porque um intruso pode facilmente enviar pacotes NTP falsos em modo broadcast. Então a autenticação deve sempre estar habilitada. Isso é o padrão do sistema. Para desabilitar a autenticação inclui-se o parâmetro disable auth no arquivo de configuração: isso não deve ser feito, a menos que se entenda muito bem as conseqüências e haja uma razão muito forte.
usuario@cliente.local:~$ ntpq -c pe
remote refid st t when poll reach delay offset jitter
======================================================================
-servidor1 .IRIG. 1 u 8 32 377 0.407 0.248 0.016
-servidor2 .GPS. 1 u - 32 377 0.474 0.213 0.019
+servidor3 .GPS. 1 u 9 64 377 15.680 -0.005 0.026
+servidor4 .IRIG. 1 u 30 64 377 15.582 0.004 0.100
*servidor5 .GPS. 1 u 10 32 377 0.400 -0.026 0.049
xservidor6 .IRIG. 1 u 26 64 377 7.824 9.923 0.367

Figura 2: O funcionamento do NTP (1)
A Figura 2 mostra os principais componentes do NTP, que são apresentados e explicados de uma forma bastante simplificada no texto a seguir. Para informações mais precisas sobre como são calculadas as várias métricas do sistema e sobre como devem funcionar os diversos algorítmos, recomenda-se a consulta direta às RFCs e à documentação oficial.
Figura 3: Troca de mensagens (1)
Ao receber a Mensagem 2, o Cliente passa a conhecer os instantes a, x, y e b. Mas a e b estão numa escala de tempo, enquanto x e y em outra. O valor do incremento dessas escalas é o mesmo, mas os relógios não estão sincronizados. Não é possível, então, calcular o tempo que a Mensagem 1 levou para ser transmitida (T-ida), nem o tempo que a Mensagem 2 gastou na rede (T-volta). Contudo, o tempo total de ida e volta, ou atraso (também conhecido por Round Trip Time ou RTT) que é a soma T-ida + T-volta pode ser calculado como:atraso (delay) = (b-a)-(y-x).
Considerando-se que o tempo de ida é igual ao tempo de volta, pode-se calcular o deslocamento entre o servidor e o relógio local como como:
deslocamento (offset) = x - (a + atraso/2) =
deslocamento (offset) = (x-a+y-b)/2.

Figura 4: Troca de mensagens - exemplo (1)
Ao olhar a Figura 4, é fácil observar que T-ida=2 e T-volta=2. Contudo, nem o Cliente nem o Servidor têm essa visão. O Servidor ao final da troca de mensagens descarta todas as informações sobre a mesma. O Cliente conhece as variáveis a=9, x=4, y=9 e b=18, mas à partir delas é impossível calcular T-ida ou T-volta. Contudo, é possível calcular o atraso e o deslocamento:
atraso = (b-a)-(y-x) = (18-9)-(9-4) = 9 - 5 = 4.
deslocamento = (x-a+y-b)/2 = (4-9+9-18)/2 = -14/2 = -7.
deslocamento - atraso/2 <= deslocamento verdadeiro <= deslocamento + atraso/2

Figura 5: Erro do deslocamento por causa da assimetria
Tome-se o seguinte exemplo numérico, ilustrando o pior caso. Os servidores são os mesmos da Figura 4, mas a primeira mensagem leva um tempo desprezível pra ser enviada, enquanto a segunda demora 4 unidades de tempo: a=9; x=2; y=7; b=18. Nesse caso T-ida=0 e T-volta=4. O exemplo está ilustrado na Figura 6.
Figura 6: Troca de mensagens - assimetria (1)
Calcula-se o atraso como:
atraso = (b-a)-(y-x) = (18-9)-(7-2) = 9 - 5 = 4.
deslocamento = (x-a+y-b)/2 = (2-9+7-18)/2 = -18/2 = -9.
deslocamento - 2 <= deslocamento verdadeiro <= deslocamento + 2
-9 -2 <= deslocamento verdadeiro <= -9 + 2
-11 <= deslocamento verdadeiro <= -7
minpoll e maxpoll definem o mínimo e o máximo, e são representadas em potência de 2. Ou seja, por padrão minpoll = 6 (26=64) e maxpoll = 10 (210=1024). Numa consulta à lista de servidores NTP, a variável poll representa o período e a variável when é um contador que indica quantos segundos se passaram desde a última consulta; quando poll = when uma nova consulta é realizada e a variável when é zerada. Se o parâmetro iburst é utilizado na configuração de um servidor, a taxa de envio de pacotes é acelerada no início da sincronização, de forma a se conseguir um conjunto de dados mais depressa. A variável reach representa um registrador de deslocamento de 8 bits, cujo valor é mostrado no formato octal. Um bit 1 significa que o cliente obteve resposta do servidor para uma consulta. Então o valor 377 = 11.111.111, significa que as últimas 8 consultas ao servidor foram bem sucedidas.
usuario@servidor:~$ ntpq -c pe
remote refid st t when poll reach delay offset jitter
======================================================================
*servidor1 .IRIG. 1 u 93 128 377 0.523 0.020 0.033
+servidor2 .GPS. 1 u 57 128 377 0.488 -0.054 0.025
-servidor3 .IRIG. 1 u 50 128 377 5.151 -0.386 0.382
+servidor4 .IRIG. 1 u 34 64 377 5.163 -0.360 0.559

Figura 7
usuario@cliente.local:~$ ntpq
ntpq> pe
remote refid st t when poll reach delay offset jitter
======================================================================
-servidor1 .IRIG. 1 u 8 32 377 0.407 0.248 0.016
-servidor2 .GPS. 1 u - 32 377 0.474 0.213 0.019
+servidor3 .GPS. 1 u 9 64 377 15.680 -0.005 0.026
+servidor4 .IRIG. 1 u 30 64 377 15.582 0.004 0.100
*servidor5 .GPS. 1 u 10 32 377 0.400 -0.026 0.049
xservidor6 .IRIG. 1 u 26 64 377 7.824 9.923 0.367
servidor7 .INIT. 16 u - 1024 0 0.000 0.000 4000.00
-servidor8 .ACTS. 1 u 13 64 377 202.274 2.459 0.309
LOCAL(0) LOCAL(0) 13 l 48 64 377 0.000 0.000 0.001
Detalhando os valores para o primeiro (&1) servidor da lista:
ntpq> rv &1
assID=47012 status=9314 reach, conf, sel_outlyer, 1 event, event_reach,
srcadr=servidor1, srcport=123, dstadr=cliente.local, dstport=123,
leap=00, stratum=1, precision=-19, rootdelay=0.000,
rootdispersion=0.351, refid=IRIG, reach=377, unreach=0, hmode=3,
pmode=4, hpoll=5, ppoll=5, flash=00 ok, keyid=0, ttl=0, offset=0.248,
delay=0.407, dispersion=0.059, jitter=0.016,
reftime=cacb6721.f903866e Thu, Oct 25 2007 17:04:01.972,
org=cacb6729.1e5c8d02 Thu, Oct 25 2007 17:04:09.118,
rec=cacb6729.1e5a1448 Thu, Oct 25 2007 17:04:09.118,
xmt=cacb6729.1e393ee5 Thu, Oct 25 2007 17:04:09.118,
filtdelay= 0.44 0.41 0.56 0.56 0.58 0.54 0.58 0.53,
filtoffset= 0.26 0.25 0.23 0.27 0.26 0.22 0.24 0.25,
filtdisp= 0.00 0.03 0.06 0.09 0.12 0.15 0.18 0.21
intervalo de confiança = (deslocamento/2) + dispersão.

Figura 8
A Seleção de relógios busca um intervalo de intersecção para os valores de deslocamento de cada servidor, considerados os intervalos de confiança. Os servidores cujos deslocamentos ficam fora da intersecção são relógios falsos. A Figura 9 ilustra isso para 4 servidores, A, B e C são relógios verdadeiros, e D é um relógio falso:
Figura 9
Ao consultar-se a lista de servidores do NTP, os relógios falsos são identificados por um "x". No exemplo abaixo, o servidor6 é um relógio falso (esses símbolos, como o "x", usados para diferenciar os servidores, são chamados de tally-codes, para mais detalhes deve-se consultar a seção Utilizando.):
usuario@cliente.local:~$ ntpq
ntpq> pe
remote refid st t when poll reach delay offset jitter
======================================================================
-servidor1 .IRIG. 1 u 8 32 377 0.407 0.248 0.016
-servidor2 .GPS. 1 u - 32 377 0.474 0.213 0.019
+servidor3 .GPS. 1 u 9 64 377 15.680 -0.005 0.026
+servidor4 .IRIG. 1 u 30 64 377 15.582 0.004 0.100
*servidor5 .GPS. 1 u 10 32 377 0.400 -0.026 0.049
xservidor6 .IRIG. 1 u 26 64 377 7.824 9.923 0.367
servidor7 .INIT. 16 u - 1024 0 0.000 0.000 4000.00
-servidor8 .ACTS. 1 u 13 64 377 202.274 2.459 0.309
LOCAL(0) LOCAL(0) 13 l 48 64 377 0.000 0.000 0.001
usuario@cliente.local:~$ ntpq
ntpq> pe
remote refid st t when poll reach delay offset jitter
======================================================================
-servidor1 .IRIG. 1 u 8 32 377 0.407 0.248 0.016
-servidor2 .GPS. 1 u - 32 377 0.474 0.213 0.019
+servidor3 .GPS. 1 u 9 64 377 15.680 -0.005 0.026
+servidor4 .IRIG. 1 u 30 64 377 15.582 0.004 0.100
*servidor5 .GPS. 1 u 10 32 377 0.400 -0.026 0.049
xservidor6 .IRIG. 1 u 26 64 377 7.824 9.923 0.367
servidor7 .INIT. 16 u - 1024 0 0.000 0.000 4000.00
-servidor8 .ACTS. 1 u 13 64 377 202.274 2.459 0.309
LOCAL(0) LOCAL(0) 13 l 48 64 377 0.000 0.000 0.001
prefer na configuração de um servidor e este estiver dentre os sobreviventes, ele será considerado como par do sistema e, mesmo que existam outros sobreviventes, estes serão ignorados. Nesses casos, o algorítmo de Combinação de Relógios não é utilizado.
Para os demais casos, quando há mais do que um sobrevivente e nenhum deles foi configurado com a palavra chave prefer, o algorítmo de Combinação de Relógios calcula uma média ponderada dos deslocamentos dos relógios, com o objetivo de aumentar a exatidão.
No exemplo abaixo os 3 servidores destacados contribuem para o valor de deslocamento de -0,119ms, mostrado nas variáveis do sistema.
usuario@cliente.local:~$ ntpq
ntpq> pe
remote refid st t when poll reach delay offset jitter
==========================================================================
+servidor1 .IRIG. 1 u 7 16 377 0.410 -0.087 0.022
*servidor2 .GPS. 1 u 7 16 377 0.380 -0.128 0.052
+servidor3 .IRIG. 1 u 5 16 377 14.750 -0.166 0.076
-servidor4 200.1.2.123 2 u 15 16 377 0.449 -0.466 0.009
xservidor5 .IRIG. 1 u 17 64 377 7.772 9.447 0.186
xservidor6 .ACTS. 1 u 52 64 377 193.471 5.779 5.444
-servidor .GPS. 1 u 9 16 377 0.344 -0.486 0.071
-servidor 200.1.2.123 2 u 45 64 377 4.437 1.423 0.723
ntpq> rl
assID=0 status=06f4 leap_none, sync_ntp, 15 events, event_peer/strat_chg,
version="ntpd 4.2.2p4@1.1585-o Wed Mar 7 20:43:30 UTC 2007 (1)",
processor="i686", system="Linux/2.6.20-16-generic", leap=00, stratum=2,
precision=-20, rootdelay=0.380, rootdispersion=5.864, peer=40768,
refid=servidor2,
reftime=cad0765f.9bd22b77 Mon, Oct 29 2007 13:10:23.608, poll=4,
clock=cad07677.9bbc05c3 Mon, Oct 29 2007 13:10:47.608, state=4,
offset=-0.119, frequency=55.279, jitter=0.060, noise=0.014,
stability=0.009, tai=0
No exemplo a seguir, apesar de haver 3 sobreviventes, foi usada a palavra chave prefer na configuração do servidor5. Como ele é um dos sobreviventes, foi escolhido como par do sistema e é o único responsável pelos parâmetros de sincronização. Nesse caso, o algorítmo de Combinação de Relógios não é utilizado:
usuario@cliente.local:~$ ntpq
ntpq> pe
remote refid st t when poll reach delay offset jitter
======================================================================
-servidor1 .IRIG. 1 u 6 32 377 0.364 0.393 0.032
-servidor2 .GPS. 1 u 1 32 377 0.415 0.357 0.012
+servidor3 .GPS. 1 u 40 64 377 19.990 0.002 0.019
+servidor4 .IRIG. 1 u 11 64 377 14.804 0.318 0.172
*servidor5 .GPS. 1 u 5 32 377 0.366 -0.001 0.017
xservidor6 .IRIG. 1 u 19 64 377 7.779 9.969 0.235
ntpq> rl
assID=0 status=0654 leap_none, sync_ntp, 5 events, event_peer/strat_chg,
version="ntpd 4.2.0a@1:4.2.0a+stable-8-r Mon Sep 18 19:09:33 UTC 2006 (1)",
processor="i686", system="Linux/2.6.17-12-generic", leap=00, stratum=2,
precision=-20, rootdelay=0.366, rootdispersion=12.913, peer=29992,
refid=servidor5,
reftime=cad07802.aea704bc Mon, Oct 29 2007 13:17:22.682, poll=5,
clock=cad0780b.f47980f5 Mon, Oct 29 2007 13:17:31.954, state=4,
offset=-0.001, frequency=-23.914, noise=0.015, jitter=0.017,
stability=0.037
driftfile (geralmente /var/lib/ntp/ntp.drift) na configuração armazena o erro esperado de freqüência para o relógio.
Algumas características importantes desse algorítmo:
ntpq e ntpdc.
keys no arquivo de configuração e armazena-as num cache. Cada chave deve ser ativada com o comando trustedkey antes de ser usada. Isso pode ser feito com o programa em funcionamento, utilizando o ntpdc. Os comandos requestkey e controlkey selecionam as chaves utilizadas para autenticar os programas ntpdc e ntpq.
O arquivo de chaves pode conter várias chaves, uma em cada linha. Cada linha tem 3 colunas. A primeira é o número da chave, entre 1 e 65535. A segunda é o tipo da chave; recomenda-se utilizar M para MD5, que é representada por uma seqüência de até 31 caracteres ASCII (A versão 3 do NTP suportava também DES, mas além de ser pior, há problemas legais nos Estados Unidos, que consideram programas utilizando DES como munição, proibindo sua exportação). A terceira é a chave em si.
Exemplo de arquivo com chaves:
1 M ABCDEFGHIJLMJNOPQRST
2 M ESSAEHUMACHAVEMD5VALIDA
3 M ESSAEHUMACHAVEMD5VALIDATB
15 M 1234ACDAS@#$LKAS)KJDKASH
498 M NTPv4.98
Exemplo de utilização das chaves simétricas na configuração do ntp:
server servidor1.dominio1 key 498
server servidor2.dominio2 key 2
peer servidor3.dominio3 key 3
# caminho para o arquivo com as chaves
keys /etc/ntp.keys
# define quais chaves são confiáveis
trustedkey 2 15 498
requestkey 15 # chave para utilizar o ntpq
controlkey 15 # chave para utilizar o ntpqc
Autenticação por Chave Pública (Autokey)
Na versão 4 do NTP uma nova forma de autenticação é suportada, baseada em chaves públicas e num protocolo que foi chamado de autokey. A integridade dos pacotes é verificada através de chaves MD5 e a autenticidade das fontes de tempo é averiguada por meio de assinaturas digitais e vários esquemas de autenticação. Esquemas de identificação (identity schemes) baseados em trocas do tipo desafio/resposta são usados para evitar vários tipos de ataques aos quais o método de chaves simétricas é potencialmente vulnerável.
A autenticação é baseada em grupos de segurança (security groups). Pode-se entender um grupo de segurança como um conjunto de servidores e clientes NTP que compartilha os mesmos métodos de autenticação, tendo em sua raiz um ou mais servidores considerados confiáveis, e administrados por uma mesma entidade. Um grupo não necessariamente precisa ter servidores estrato 1 em sua raiz, mas pode ser cliente de outros grupos de segurança.
O número de opções que há para configurar-se o autokey é assustador. Contudo a configuração necessária para a maioria das situações é relativamente simples. Pode-se configurar um grupo de segurança com um ou mais servidores confiáveis (TH - Trusted Hosts) no estrato mais baixo. Elege-se um desses servidores para ser o agente confiável (TA - trusted agent) e gerar os certificados privados, um certificado público auto assinado, e chaves de identificação privadas. Se houver mais de um servidor confiável, esses certificados e chaves são copiados para os demais manualmente.
Os demais clientes e servidores geram chaves privadas e certificados auto assinados considerados não confiáveis. Cada um deles fornece sua senha ao agente confiável e requisita as chaves e certificados do grupo (isso pode ser feito por email ou por um formulário web, por exemplo). Para os servidores são fornecidas chaves cifradas. Para os clientes somente um subconjunto de parâmetros de identificação não criptografados é fornecido.
O autokey se encarrega de resgatar os certificados ao longo da cadeia de servidores NTP até chegar a um servidor confiável, garantindo que toda a cadeia de servidores é confiável.
Para garantir a integridade dos pacotes assinaturas baseadas no endereço IP são utilizadas. O endereço tem de ser o mesmo, então, para o cliente e para o servidor, o que significa que a autenticação baseada em chave pública não funciona em conjunto com NAT.
Mais detalhes de configuração do autokey podem ser obtidos na documentação oficial do NTP.