From 27b591daee49326b551d34ca85dede265ed6343d Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 15 Sep 2026 05:39:28 +0300 Subject: [PATCH] =?UTF-8?q?reality:=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20NTP-=D0=B2=D1=80=D0=B5?= =?UTF-8?q?=D0=BC=D1=8F=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20time(NULL?= =?UTF-8?q?)=20=D0=B2=20=D0=B0=D0=BD=D1=82=D0=B8-=D1=80=D0=B5=D0=BF=D0=BB?= =?UTF-8?q?=D0=B5=D0=B9=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B5?= =?UTF-8?q?=20timestamp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Часы colo2 отстают на ~52с (ntpd выключен), что ломало reality auth (diff < -30с = time_window). Теперь клиент и сервер передают ntp_time_get_seconds() в reality_client_hello_build_at / reality_server_hello_build_at вместо сырого системного времени. --- src/transport_layer/reality.c | 14 ++++++++++---- src/transport_layer/reality.h | 7 +++++++ src/transport_layer/stcp_client.c | 5 ++++- src/transport_layer/stcp_server.c | 4 +++- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/transport_layer/reality.c b/src/transport_layer/reality.c index f16156ef..d2431fde 100644 --- a/src/transport_layer/reality.c +++ b/src/transport_layer/reality.c @@ -488,9 +488,9 @@ static int reality_parse_client_hello(const uint8_t *ch, size_t ch_len, return REALITY_OK; } -int reality_server_hello_build(const struct reality_server_config *cfg, - const uint8_t *ch, size_t ch_len, - uint8_t *out, size_t out_cap, size_t *out_len) { +int reality_server_hello_build_at(const struct reality_server_config *cfg, uint32_t now_sec, + const uint8_t *ch, size_t ch_len, + uint8_t *out, size_t out_cap, size_t *out_len) { if (!cfg || !ch || !out || !out_len || out_cap < REALITY_MAX_SH_SIZE) { DEBUG_ERROR(DEBUG_CATEGORY_REALITY, "reality_server_hello_build: invalid args"); return REALITY_ERR_ARG; @@ -546,7 +546,7 @@ int reality_server_hello_build(const struct reality_server_config *cfg, // сверка timestamp uint32_t ts = ((uint32_t)plain[4] << 24) | ((uint32_t)plain[5] << 16) | ((uint32_t)plain[6] << 8) | plain[7]; - int64_t now = (int64_t)time(NULL); + int64_t now = (int64_t)now_sec; int64_t diff = now - (int64_t)ts; if (diff < -(int64_t)cfg->time_window_sec || diff > (int64_t)cfg->time_window_sec) { DEBUG_WARN(DEBUG_CATEGORY_REALITY, "reality_server_hello_build: timestamp out of window ts=%u now=%lld diff=%lld", @@ -623,3 +623,9 @@ int reality_server_hello_build(const struct reality_server_config *cfg, DEBUG_INFO(DEBUG_CATEGORY_REALITY, "server hello built: total=%zu", *out_len); return REALITY_OK; } + +int reality_server_hello_build(const struct reality_server_config *cfg, + const uint8_t *ch, size_t ch_len, + uint8_t *out, size_t out_cap, size_t *out_len) { + return reality_server_hello_build_at(cfg, (uint32_t)time(NULL), ch, ch_len, out, out_cap, out_len); +} diff --git a/src/transport_layer/reality.h b/src/transport_layer/reality.h index 2b3645d6..458fd4c9 100644 --- a/src/transport_layer/reality.h +++ b/src/transport_layer/reality.h @@ -105,6 +105,13 @@ int reality_server_hello_build(const struct reality_server_config *cfg, const uint8_t *ch, size_t ch_len, uint8_t *out, size_t out_cap, size_t *out_len); +// То же, но с явным now (unix-секунды) для анти-реплей проверки timestamp. +// Вызывающий код передаёт синхронизированное время (ntp_time_get_seconds), +// чтобы не зависеть от сырого time(NULL) при рассинхроне системных часов. +int reality_server_hello_build_at(const struct reality_server_config *cfg, uint32_t now_sec, + const uint8_t *ch, size_t ch_len, + uint8_t *out, size_t out_cap, size_t *out_len); + // Сгенерировать X25519 пару ключей (для конфигурации: сервер хранит privkey, // клиент — pubkey сервера). Возвращает REALITY_OK / REALITY_ERR_CRYPTO. int reality_generate_keypair(uint8_t priv[REALITY_AUTH_KEY_SIZE], diff --git a/src/transport_layer/stcp_client.c b/src/transport_layer/stcp_client.c index 2940a30d..b61a7835 100644 --- a/src/transport_layer/stcp_client.c +++ b/src/transport_layer/stcp_client.c @@ -3,6 +3,7 @@ #include "secure_channel.h" #include "crc32.h" #include "etcp.h" +#include "../ntp_time.h" #include "../lib/u_async.h" #include "../lib/socket_compat.h" #include "../lib/ll_queue.h" @@ -173,7 +174,9 @@ static void client_after_connect(struct stcp_conn *c) { int opt = 1; setsockopt(c->sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&opt, sizeof(opt)); if (cli->reality_enabled) { uint8_t ch[REALITY_MAX_CH_SIZE]; size_t ch_len = 0; - if (reality_client_hello_build(&cli->reality_cfg, ch, sizeof(ch), &ch_len) != REALITY_OK) { + uint32_t now_sec = (c->etcp_conn && c->etcp_conn->instance) + ? (uint32_t)ntp_time_get_seconds(c->etcp_conn->instance) : (uint32_t)time(NULL); + if (reality_client_hello_build_at(&cli->reality_cfg, now_sec, ch, sizeof(ch), &ch_len) != REALITY_OK) { DEBUG_ERROR(DEBUG_CATEGORY_REALITY, "stcp_client: ClientHello build failed"); stcp_conn_do_close(c, 1); return; } diff --git a/src/transport_layer/stcp_server.c b/src/transport_layer/stcp_server.c index a21f7492..b6a6df9b 100644 --- a/src/transport_layer/stcp_server.c +++ b/src/transport_layer/stcp_server.c @@ -11,6 +11,7 @@ #include "../lib/debug_config.h" #include "../lib/platform_compat.h" #include "../utun_instance.h" +#include "../ntp_time.h" #include "etcp.h" #include #include @@ -232,7 +233,8 @@ static void reality_ch_body_cb(struct stcp_conn *c, uint8_t *data, size_t len) { uint8_t sh[REALITY_MAX_SH_SIZE]; size_t sh_len = 0; - int rc = reality_server_hello_build(&c->reality_srv, full, 5 + len, sh, sizeof(sh), &sh_len); + uint32_t now_sec = c->inst ? (uint32_t)ntp_time_get_seconds(c->inst) : (uint32_t)time(NULL); + int rc = reality_server_hello_build_at(&c->reality_srv, now_sec, full, 5 + len, sh, sizeof(sh), &sh_len); if (rc == REALITY_OK) { uint8_t *shbuf = u_malloc(sh_len); if (!shbuf) { stcp_conn_do_close(c, ENOMEM); return; }