O processo está bastante envolvido, mas note que uma sincronização de NTP é uma conversa e, como você suspeita, ela precisa calcular o tempo de ida e volta para sincronizar efetivamente levando em consideração quanto tempo os pacotes levam.
Embora o cliente possa não saber a hora com precisão quando solicita uma atualização de hora, ele sabe pelo menos quando enviou o pacote. O servidor sabe a hora exata em que recebe um pacote, mais a hora exata em que envia uma resposta. O cliente sabe o tempo de intervalo entre o momento em que enviou um pacote e o recebimento da resposta.
Assim, a partir desses números, é fácil calcular a hora correta, desde que o atraso seja consistente em toda a conversa.
Nem sempre é consistente, é claro, razão pela qual vários servidores geralmente são configurados para que os erros possam ser calculados, juntamente com o cliente mantendo as informações de rastreamento de estado para que ele possa ignorar quaisquer resultados malucos.
Wikipedia é uma boa fonte de detalhes.