Test stable published profiles across repeated NAT measurements
This commit is contained in:
1 parent
61132a3e84
commit
ba29adf6ef
2 files changed
+29
-34
No files matched your search
+17
-15
@@ -6,7 +6,7 @@
|
|||||||
static void wait_profile(struct nat_fixture *fixture, struct ETCP_SOCKET *socket, uint8_t mapping, uint8_t inbound) {
|
static void wait_profile(struct nat_fixture *fixture, struct ETCP_SOCKET *socket, uint8_t mapping, uint8_t inbound) {
|
||||||
uint64_t end = get_time_tb() + 180000;
|
uint64_t end = get_time_tb() + 180000;
|
||||||
while (get_time_tb() < end) {
|
while (get_time_tb() < end) {
|
||||||
if (socket->address_profile.evidence_id && socket->address_profile.mapping == mapping &&
|
if (socket->address_profile.source && socket->address_profile.mapping == mapping &&
|
||||||
socket->address_profile.inbound == inbound) return;
|
socket->address_profile.inbound == inbound) return;
|
||||||
uasync_poll(fixture->ua, 10);
|
uasync_poll(fixture->ua, 10);
|
||||||
}
|
}
|
||||||
@@ -23,13 +23,11 @@ static void check_snapshot(struct UTUN_INSTANCE *owner, struct ETCP_SOCKET *sock
|
|||||||
assert(node && topo_node_verify(node) == 0);
|
assert(node && topo_node_verify(node) == 0);
|
||||||
struct TOPO_SOCKMETA4 *meta = node->v4_sock_meta;
|
struct TOPO_SOCKMETA4 *meta = node->v4_sock_meta;
|
||||||
while (meta && meta->id != socket->sock_id) meta = meta->next;
|
while (meta && meta->id != socket->sock_id) meta = meta->next;
|
||||||
assert(meta && meta->address_profile.evidence_id == socket->address_profile.evidence_id &&
|
assert(meta && meta->address_profile.mapping == socket->address_profile.mapping &&
|
||||||
meta->address_profile.checked_at == socket->address_profile.checked_at &&
|
|
||||||
meta->address_profile.mapping == socket->address_profile.mapping &&
|
|
||||||
meta->address_profile.inbound == socket->address_profile.inbound &&
|
meta->address_profile.inbound == socket->address_profile.inbound &&
|
||||||
meta->address_profile.source == ADDRESS_SOURCE_ETCP);
|
meta->address_profile.source == ADDRESS_SOURCE_ETCP);
|
||||||
struct address_profile saved = meta->address_profile;
|
struct address_profile saved = meta->address_profile;
|
||||||
meta->address_profile.checked_at++;
|
meta->address_profile.mapping = ADDRESS_MAP_DEPENDENT;
|
||||||
assert(topo_node_verify(node) < 0);
|
assert(topo_node_verify(node) < 0);
|
||||||
meta->address_profile = saved;
|
meta->address_profile = saved;
|
||||||
meta->address_profile.source = ADDRESS_SOURCE_STUN;
|
meta->address_profile.source = ADDRESS_SOURCE_STUN;
|
||||||
@@ -41,14 +39,12 @@ static void check_snapshot(struct UTUN_INSTANCE *owner, struct ETCP_SOCKET *sock
|
|||||||
|
|
||||||
sqlite3_stmt *statement = NULL;
|
sqlite3_stmt *statement = NULL;
|
||||||
assert(sqlite3_prepare_v2(owner->topo_sqlite_db,
|
assert(sqlite3_prepare_v2(owner->topo_sqlite_db,
|
||||||
"SELECT nat_mapping,nat_inbound,nat_evidence,nat_checked,nat_source FROM node_addresses WHERE node_id=? AND socket_id=?",
|
"SELECT nat_mapping,nat_inbound,nat_source FROM node_addresses WHERE node_id=? AND socket_id=?",
|
||||||
-1, &statement, NULL) == SQLITE_OK);
|
-1, &statement, NULL) == SQLITE_OK);
|
||||||
sqlite3_bind_int64(statement, 1, (sqlite3_int64)owner->node_id); sqlite3_bind_int(statement, 2, socket->sock_id);
|
sqlite3_bind_int64(statement, 1, (sqlite3_int64)owner->node_id); sqlite3_bind_int(statement, 2, socket->sock_id);
|
||||||
assert(sqlite3_step(statement) == SQLITE_ROW);
|
assert(sqlite3_step(statement) == SQLITE_ROW);
|
||||||
assert(sqlite3_column_int(statement, 0) == saved.mapping && sqlite3_column_int(statement, 1) == saved.inbound);
|
assert(sqlite3_column_int(statement, 0) == saved.mapping && sqlite3_column_int(statement, 1) == saved.inbound);
|
||||||
assert((uint64_t)sqlite3_column_int64(statement, 2) == saved.evidence_id);
|
assert(sqlite3_column_int(statement, 2) == ADDRESS_SOURCE_ETCP);
|
||||||
assert((uint64_t)sqlite3_column_int64(statement, 3) == saved.checked_at);
|
|
||||||
assert(sqlite3_column_int(statement, 4) == ADDRESS_SOURCE_ETCP);
|
|
||||||
sqlite3_finalize(statement);
|
sqlite3_finalize(statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +86,9 @@ int main(void) {
|
|||||||
struct nat_check_status status;
|
struct nat_check_status status;
|
||||||
assert(nat_detection_get_status(owner->nat_det, socket, &status) == 0);
|
assert(nat_detection_get_status(owner->nat_det, socket, &status) == 0);
|
||||||
assert(status.helper_reselections > 0 && status.helper == helper->node_id && status.observer == observer->node_id);
|
assert(status.helper_reselections > 0 && status.helper == helper->node_id && status.observer == observer->node_id);
|
||||||
assert(socket->address_profile.evidence_id != second_socket->address_profile.evidence_id);
|
struct nat_check_status second_status;
|
||||||
|
assert(nat_detection_get_status(owner->nat_det, second_socket, &second_status) == 0);
|
||||||
|
assert(status.round != second_status.round);
|
||||||
check_snapshot(owner, socket);
|
check_snapshot(owner, socket);
|
||||||
check_snapshot(owner, second_socket);
|
check_snapshot(owner, second_socket);
|
||||||
check_snapshot(owner, tcp);
|
check_snapshot(owner, tcp);
|
||||||
@@ -99,13 +97,17 @@ int main(void) {
|
|||||||
assert(!route_ping_addr_equal(&socket->local_addr, &observer_socket->local_addr, 1));
|
assert(!route_ping_addr_equal(&socket->local_addr, &observer_socket->local_addr, 1));
|
||||||
assert(!route_ping_addr_equal(&socket->local_addr, &test_etcp_bound_socket(helper, "udp")->local_addr, 1));
|
assert(!route_ping_addr_equal(&socket->local_addr, &test_etcp_bound_socket(helper, "udp")->local_addr, 1));
|
||||||
|
|
||||||
/* Повторная проверка не объявляет старый контакт независимым. */
|
/* Неполный повторный ingress сохраняет успех и не изменяет подписанный NODEINFO. */
|
||||||
uint64_t old_evidence = socket->address_profile.evidence_id;
|
uint64_t old_round = status.round;
|
||||||
|
struct TOPO_NODE *snapshot = topo_node_registry_find(owner->topo_groups, owner->node_id);
|
||||||
|
uint64_t old_timestamp = snapshot->timestamp;
|
||||||
nat_detection_request_check_all(owner->nat_det);
|
nat_detection_request_check_all(owner->nat_det);
|
||||||
uint64_t end = get_time_tb() + 180000;
|
uint64_t end = get_time_tb() + 180000;
|
||||||
while (get_time_tb() < end && socket->address_profile.evidence_id == old_evidence) uasync_poll(fixture.ua, 10);
|
do { uasync_poll(fixture.ua, 10); assert(!nat_detection_get_status(owner->nat_det, socket, &status)); }
|
||||||
assert(socket->address_profile.evidence_id != old_evidence);
|
while (get_time_tb() < end && (status.round == old_round || status.phase));
|
||||||
assert(socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && socket->address_profile.inbound == ADDRESS_IN_UNKNOWN);
|
assert(status.round != old_round && !status.phase && status.reason == NAT_REASON_CONTACT_HISTORY);
|
||||||
|
assert(socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && socket->address_profile.inbound == ADDRESS_IN_OPEN);
|
||||||
|
assert(snapshot->timestamp == old_timestamp && topo_node_verify(snapshot) == 0);
|
||||||
|
|
||||||
/* Закрытие endpoint посреди запроса и переиспользование ID/порта: старые ответы не применяются. */
|
/* Закрытие endpoint посреди запроса и переиспользование ID/порта: старые ответы не применяются. */
|
||||||
nat_detection_request_check_all(owner->nat_det);
|
nat_detection_request_check_all(owner->nat_det);
|
||||||
|
|||||||
+12
-19
@@ -9,29 +9,25 @@
|
|||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
|
||||||
const uint64_t now = UINT64_C(1700000000000000);
|
|
||||||
const uint32_t public_ip = htonl(UINT32_C(0xc633640b));
|
const uint32_t public_ip = htonl(UINT32_C(0xc633640b));
|
||||||
const uint32_t private_ip = htonl(UINT32_C(0x0a400102));
|
const uint32_t private_ip = htonl(UINT32_C(0x0a400102));
|
||||||
struct address_profile unknown = {0};
|
struct address_profile unknown = {0};
|
||||||
struct address_profile open = {.mapping = ADDRESS_MAP_EIM, .inbound = ADDRESS_IN_OPEN, .source = ADDRESS_SOURCE_ETCP,
|
struct address_profile open = {.mapping = ADDRESS_MAP_EIM, .inbound = ADDRESS_IN_OPEN, .source = ADDRESS_SOURCE_ETCP};
|
||||||
.evidence_id = 1, .checked_at = now};
|
|
||||||
struct address_profile contact = open; contact.inbound = ADDRESS_IN_CONTACT;
|
struct address_profile contact = open; contact.inbound = ADDRESS_IN_CONTACT;
|
||||||
struct address_profile dependent = open; dependent.mapping = ADDRESS_MAP_DEPENDENT; dependent.inbound = ADDRESS_IN_UNKNOWN;
|
struct address_profile dependent = open; dependent.mapping = ADDRESS_MAP_DEPENDENT; dependent.inbound = ADDRESS_IN_UNKNOWN;
|
||||||
|
|
||||||
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_PUBLIC, &unknown, 1, now) == SOCK_TC_PROBE);
|
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_PUBLIC, &unknown, 1) == SOCK_TC_PROBE);
|
||||||
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_PUBLIC, &open, 0, now) == SOCK_TC_PRIV);
|
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_PUBLIC, &open, 0) == SOCK_TC_PRIV);
|
||||||
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &open, 1, now) == SOCK_TC_PUB);
|
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &open, 1) == SOCK_TC_PUB);
|
||||||
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &contact, 1, now) == SOCK_TC_CONTACT);
|
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &contact, 1) == SOCK_TC_CONTACT);
|
||||||
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &unknown, 1, now) == SOCK_TC_PROBE);
|
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &unknown, 1) == SOCK_TC_PROBE);
|
||||||
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &dependent, 1, now) == SOCK_TC_UNREACH);
|
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &dependent, 1) == SOCK_TC_UNREACH);
|
||||||
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_NAT, &dependent, 0, now) == SOCK_TC_PRIV);
|
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_NAT, &dependent, 0) == SOCK_TC_PRIV);
|
||||||
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_LOCAL, &open, 1, now) == SOCK_TC_PRIV);
|
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_LOCAL, &open, 1) == SOCK_TC_PRIV);
|
||||||
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_PRIVATE, &open, 1, now) == SOCK_TC_PRIV);
|
assert(sock_target_class(TOPO_ADDR_INTERFACE, CFG_SERVER_TYPE_PRIVATE, &open, 1) == SOCK_TC_PRIV);
|
||||||
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &open, 1, now + ADDRESS_PROFILE_TTL_US + 1) == SOCK_TC_PROBE);
|
|
||||||
assert(sock_target_class(TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &open, 1, now - 1) == SOCK_TC_PROBE);
|
|
||||||
|
|
||||||
struct sock_view outgoing = {.has_inet = 1, .has_priv = 1, .now_us = now, .public_ip4 = public_ip};
|
struct sock_view outgoing = {.has_inet = 1, .has_priv = 1, .public_ip4 = public_ip};
|
||||||
struct sock_view local = {.has_priv = 1, .now_us = now};
|
struct sock_view local = {.has_priv = 1};
|
||||||
assert(sock_match(&outgoing, TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &open, public_ip));
|
assert(sock_match(&outgoing, TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &open, public_ip));
|
||||||
assert(sock_match(&outgoing, TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &contact, public_ip));
|
assert(sock_match(&outgoing, TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &contact, public_ip));
|
||||||
/* Совпадение публичного IP разрешает проверку hairpin. */
|
/* Совпадение публичного IP разрешает проверку hairpin. */
|
||||||
@@ -45,8 +41,5 @@ int main(void) {
|
|||||||
assert(address_profile_valid(&dependent));
|
assert(address_profile_valid(&dependent));
|
||||||
dependent.source = ADDRESS_SOURCE_NONE;
|
dependent.source = ADDRESS_SOURCE_NONE;
|
||||||
assert(!address_profile_valid(&dependent));
|
assert(!address_profile_valid(&dependent));
|
||||||
outgoing.now_us = now + ADDRESS_PROFILE_TTL_US + 1;
|
|
||||||
assert(sock_match(&outgoing, TOPO_ADDR_NAT, CFG_SERVER_TYPE_NAT, &open, public_ip));
|
|
||||||
/* Смена времени/давности снижает уверенность, сохраняя возможность реального handshake. */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user