diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index 226665dbf..c94a82a87 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -30,6 +30,22 @@ #include "../lib/u_async.h" #include "../lib/debug_config.h" #include "etcp_loadbalancer.h" + +/* Вызывать только после аутентификации ciphertext/STCP, под active_users/callbacks_running. + * Новый handshake перепроверяет членство; обычные DATA используют положительный кэш этого линка. */ +static int admit_peer(struct ETCP_LINK* link, int handshake) { + struct ETCP_CONN* c = link->etcp; + if (!c->require_known_node && !link->require_known_node) return 1; + if (!handshake && link->peer_admitted) return 1; + if (c->peer_node_id != sc_derive_node_id_from_pubkey(c->crypto_ctx.peer_public_key) + || !topo_groups_peer_key_known(c->instance, c->crypto_ctx.peer_public_key)) { + DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] authenticated handshake denied: unknown peer key path=%u", c->log_name, link->local_link_id); + etcp_link_close(link); return 0; + } + link->peer_admitted = 1; + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[%s] authenticated known peer admitted path=%u", c->log_name, link->local_link_id); + return 1; +} #include "etcp_keepalive.h" #ifdef UTUN_HAVE_STANDBY #include "standby.h" @@ -1408,6 +1424,8 @@ void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) { etcp->callbacks_running++; link->active_users++; + if (!admit_peer(link, 1)) goto done; + /* reinit только при смене reset_id пира — синхронизация через etcp_conn_apply_peer_reset_id */ if (link->tcp_link) { uint64_t peer_rid = stcp_link_get_peer_reset_id(link->tcp_link); @@ -2411,6 +2429,8 @@ static void bound_receive(struct ETCP_LINK* link, struct ll_entry* entry) { DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] packet channel authentication/format failed: result=%d bytes=%zu", conn->log_name, result, length); goto done; } + if (!admit_peer(link, !link->initialized || pkt->data[0] == ETCP_INIT_REQUEST + || pkt->data[0] == ETCP_INIT_REQUEST_NOINIT)) goto done; pkt->data_len = length - 3; pkt->noencrypt_len = 0; pkt->link = link; DEBUG_TRACE(DEBUG_CATEGORY_DEBUG, "[%s] packet channel RX path=%u wire=%u plain=%zu code=%02x up=%u", conn->log_name, link->local_link_id, entry->len, length, pkt->data[0], pkt->flag_up); @@ -2698,6 +2718,11 @@ static void etcp_process_packet_direct(struct ETCP_SOCKET* e_sock, uint8_t* data }// коллизия - peer id совпал а ключи разные. } + if (conn->require_known_node && !topo_groups_peer_key_known(conn->instance, sc.peer_public_key)) { + DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] authenticated UDP INIT denied: unknown peer key", conn->log_name); + errorcode = 8; goto ec_fr; + } + if (conn->fin_wait) { DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] received INIT during fin_wait, clearing", conn->log_name); conn->fin_wait = 0; @@ -2911,6 +2936,9 @@ int etcp_packet_decrypted(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, pkt->link=link; if (!pkt->data_len) { DEBUG_WARN(DEBUG_CATEGORY_ETCP,"empty decrypted ETCP packet"); result = 46; goto done; } if (conn->close_requested) { memory_pool_free(conn->instance->pkt_pool, pkt); goto done; } + if (!admit_peer(link, pkt->data[0] == ETCP_INIT_RESPONSE || pkt->data[0] == ETCP_INIT_RESPONSE_NOINIT)) { + result = 8; goto done; + } if (etcp_session_receive(link->etcp,pkt->data,pkt->data_len)) { memory_pool_free(conn->instance->pkt_pool,pkt); goto done; }