Prefer untouched helper IPs and exercise NAT through real groups
This commit is contained in:
1 parent
8990574c1d
commit
0ee431b490
3 files changed
+30
-15
No files matched your search
@@ -63,7 +63,7 @@ struct nat_socket {
|
|||||||
uint8_t contacts[NAT_MAX_CONTACTS][17];
|
uint8_t contacts[NAT_MAX_CONTACTS][17];
|
||||||
unsigned contact_count, phase, reason, retries;
|
unsigned contact_count, phase, reason, retries;
|
||||||
uint8_t history_loaded, history_complete, history_incomplete, filter_clean, pre_received, post_received, pre_healthy;
|
uint8_t history_loaded, history_complete, history_incomplete, filter_clean, pre_received, post_received, pre_healthy;
|
||||||
uint8_t helper_socket, active_ping, forced, cycling, using_fallback;
|
uint8_t helper_socket, active_ping, forced, cycling, using_fallback, prefer_fresh;
|
||||||
uint32_t rounds, helper_reselections;
|
uint32_t rounds, helper_reselections;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -104,6 +104,7 @@ static void owner_finish(struct nat_socket *, uint8_t);
|
|||||||
static void helper_remove(struct nat_probe *);
|
static void helper_remove(struct nat_probe *);
|
||||||
static int helper_send(struct nat_probe *);
|
static int helper_send(struct nat_probe *);
|
||||||
static void owner_start(struct nat_socket *);
|
static void owner_start(struct nat_socket *);
|
||||||
|
static int contacted(struct nat_socket *, const struct sockaddr_storage *);
|
||||||
|
|
||||||
static uint64_t read64(const uint8_t *data) {
|
static uint64_t read64(const uint8_t *data) {
|
||||||
uint64_t value = 0;
|
uint64_t value = 0;
|
||||||
@@ -231,6 +232,7 @@ static int select_pair(struct nat_socket *state) {
|
|||||||
const struct TOPO_NODE *cn = group_node(detector, group->group_id, helper);
|
const struct TOPO_NODE *cn = group_node(detector, group->group_id, helper);
|
||||||
struct sockaddr_storage ca = {0}; uint8_t cs = 0;
|
struct sockaddr_storage ca = {0}; uint8_t cs = 0;
|
||||||
if (!state->socket->is_tcp && !node_udp_endpoint(detector, cn, state->local.ss_family, 1, &ca, &cs)) continue;
|
if (!state->socket->is_tcp && !node_udp_endpoint(detector, cn, state->local.ss_family, 1, &ca, &cs)) continue;
|
||||||
|
if (!state->socket->is_tcp && state->prefer_fresh && !state->using_fallback && contacted(state, &ca)) continue;
|
||||||
struct nat_pair candidate = {group->group_id, observer, helper};
|
struct nat_pair candidate = {group->group_id, observer, helper};
|
||||||
if (state->using_fallback) {
|
if (state->using_fallback) {
|
||||||
if (memcmp(&candidate, &state->fallback, sizeof(candidate))) continue;
|
if (memcmp(&candidate, &state->fallback, sizeof(candidate))) continue;
|
||||||
@@ -242,6 +244,9 @@ static int select_pair(struct nat_socket *state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!best.group) {
|
if (!best.group) {
|
||||||
|
if (state->prefer_fresh && !state->using_fallback) {
|
||||||
|
state->prefer_fresh = 0; state->cursor = (struct nat_pair){0}; return select_pair(state);
|
||||||
|
}
|
||||||
if (!state->using_fallback && state->fallback.group) { state->using_fallback = 1; return select_pair(state); }
|
if (!state->using_fallback && state->fallback.group) { state->using_fallback = 1; return select_pair(state); }
|
||||||
state->reason = observers ? NAT_REASON_NO_HELPER : NAT_REASON_NO_OBSERVER;
|
state->reason = observers ? NAT_REASON_NO_HELPER : NAT_REASON_NO_OBSERVER;
|
||||||
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT candidate cycle exhausted socket=%s groups=%u observers=%u reason=%s",
|
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT candidate cycle exhausted socket=%s groups=%u observers=%u reason=%s",
|
||||||
@@ -1051,11 +1056,12 @@ static void owner_start(struct nat_socket *state) {
|
|||||||
state->socket->name, sockaddr_storage_to_str(&state->local).str); return;
|
state->socket->name, sockaddr_storage_to_str(&state->local).str); return;
|
||||||
}
|
}
|
||||||
if (!state->cycling) {
|
if (!state->cycling) {
|
||||||
state->cycling = 1; state->cursor = (struct nat_pair){0}; state->fallback = (struct nat_pair){0}; state->using_fallback = 0;
|
state->cycling = 1; state->cursor = (struct nat_pair){0}; state->fallback = (struct nat_pair){0};
|
||||||
|
state->using_fallback = 0; state->prefer_fresh = 1;
|
||||||
}
|
}
|
||||||
|
history_load(state);
|
||||||
if (select_pair(state)) { owner_finish(state, state->reason); return; }
|
if (select_pair(state)) { owner_finish(state, state->reason); return; }
|
||||||
if (random_id(&state->round)) { owner_finish(state, NAT_REASON_SEND_ERROR); return; }
|
if (random_id(&state->round)) { owner_finish(state, NAT_REASON_SEND_ERROR); return; }
|
||||||
history_load(state);
|
|
||||||
state->rounds++;
|
state->rounds++;
|
||||||
memset(&state->helper_seen, 0, sizeof(state->helper_seen)); memset(&state->alternate_seen, 0, sizeof(state->alternate_seen));
|
memset(&state->helper_seen, 0, sizeof(state->helper_seen)); memset(&state->alternate_seen, 0, sizeof(state->alternate_seen));
|
||||||
state->retries = 0; state->pre_received = 0; state->post_received = 0; state->filter_clean = 0; state->pre_healthy = 0;
|
state->retries = 0; state->pre_received = 0; state->post_received = 0; state->filter_clean = 0; state->pre_healthy = 0;
|
||||||
|
|||||||
+14
-6
@@ -44,11 +44,11 @@ static inline struct UTUN_INSTANCE *nat_fixture_node(struct nat_fixture *fixture
|
|||||||
struct UTUN_INSTANCE *node = utun_instance_create_from_str(fixture->ua, config);
|
struct UTUN_INSTANCE *node = utun_instance_create_from_str(fixture->ua, config);
|
||||||
assert(node && fixture->node_count < 8 && utun_core_start(node) == 0);
|
assert(node && fixture->node_count < 8 && utun_core_start(node) == 0);
|
||||||
nat_detection_set_allow_local(node->nat_det, 1);
|
nat_detection_set_allow_local(node->nat_det, 1);
|
||||||
|
assert(topo_groups_create_group(node->topo_groups, TOPO_GROUP_UTUN, TOPO_GROUP_TYPE_UTUN, ""));
|
||||||
fixture->nodes[fixture->node_count++] = node; return node;
|
fixture->nodes[fixture->node_count++] = node; return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Без групповой автосвязности: A контактирует только с явно указанным B.
|
/* Без автосвязности: заданный UDP-транспорт присоединяется к группе; остальные узлы доступны через BGP. */
|
||||||
* NCD переносит настоящую подписанную запись, handshake идёт по UDP. */
|
|
||||||
static inline struct ETCP_CONN *nat_fixture_connect(struct nat_fixture *fixture, struct UTUN_INSTANCE *from,
|
static inline struct ETCP_CONN *nat_fixture_connect(struct nat_fixture *fixture, struct UTUN_INSTANCE *from,
|
||||||
const char *source, struct UTUN_INSTANCE *to) {
|
const char *source, struct UTUN_INSTANCE *to) {
|
||||||
assert(fixture->handle_count < 24);
|
assert(fixture->handle_count < 24);
|
||||||
@@ -60,12 +60,20 @@ static inline struct ETCP_CONN *nat_fixture_connect(struct nat_fixture *fixture,
|
|||||||
struct ETCP_CONN *connection = NULL;
|
struct ETCP_CONN *connection = NULL;
|
||||||
while (get_time_tb() < end) {
|
while (get_time_tb() < end) {
|
||||||
connection = node_conn_direct_get_conn(*handle);
|
connection = node_conn_direct_get_conn(*handle);
|
||||||
if (connection && connection->links_up) return connection;
|
if (connection && connection->links_up) break;
|
||||||
uasync_poll(fixture->ua, 10);
|
uasync_poll(fixture->ua, 10);
|
||||||
}
|
}
|
||||||
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "fixture connection timed out from=%016llx to=%016llx",
|
assert(connection && connection->links_up);
|
||||||
(unsigned long long)from->node_id, (unsigned long long)to->node_id);
|
struct TOPO_GROUP *group = topo_groups_find(from->topo_groups, TOPO_GROUP_UTUN);
|
||||||
abort();
|
struct TOPO_GROUP *remote = topo_groups_find(to->topo_groups, TOPO_GROUP_UTUN);
|
||||||
|
assert(group && remote && !topo_group_new_conn(group, connection));
|
||||||
|
end = get_time_tb() + 50000;
|
||||||
|
while (get_time_tb() < end) {
|
||||||
|
if (topo_group_peer_ready(group, to->node_id) && topo_group_peer_ready(remote, from->node_id)) return connection;
|
||||||
|
uasync_poll(fixture->ua, 10);
|
||||||
|
}
|
||||||
|
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "fixture group negotiation timed out from=%016llx to=%016llx",
|
||||||
|
(unsigned long long)from->node_id, (unsigned long long)to->node_id); abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void nat_fixture_cleanup(struct nat_fixture *fixture) {
|
static inline void nat_fixture_cleanup(struct nat_fixture *fixture) {
|
||||||
|
|||||||
@@ -65,30 +65,31 @@ int main(void) {
|
|||||||
struct ETCP_SOCKET *peer = test_etcp_bound_socket(observer, "udp");
|
struct ETCP_SOCKET *peer = test_etcp_bound_socket(observer, "udp");
|
||||||
const uint64_t round = UINT64_C(0x0102030405060708);
|
const uint64_t round = UINT64_C(0x0102030405060708);
|
||||||
struct result result = {0};
|
struct result result = {0};
|
||||||
assert(route_ping_observe(socket, observer->my_keys.public_key, &peer->local_addr, round, 500, ping_done, &result) == 0);
|
assert(route_ping_observe(socket, observer->my_keys.public_key, &peer->local_addr, TOPO_GROUP_UTUN, round, 500, ping_done, &result) == 0);
|
||||||
wait_result(&fixture, &result);
|
wait_result(&fixture, &result);
|
||||||
struct sockaddr_storage observed;
|
struct sockaddr_storage observed;
|
||||||
assert(result.success && route_ping_observation(result.data, result.length, socket, round, &observed) == 0);
|
assert(result.success && route_ping_observation(result.data, result.length, socket, TOPO_GROUP_UTUN, round, &observed) == 0);
|
||||||
assert(route_ping_addr_equal(&observed, &socket->local_addr, 1));
|
assert(route_ping_addr_equal(&observed, &socket->local_addr, 1));
|
||||||
assert(route_ping_observation(result.data, result.length, socket, round + 1, &observed) < 0);
|
assert(route_ping_observation(result.data, result.length, socket, TOPO_GROUP_UTUN, round + 1, &observed) < 0);
|
||||||
|
assert(route_ping_observation(result.data, result.length, socket, TOPO_GROUP_UTUN + 1, round, &observed) < 0);
|
||||||
assert(socket->address_profile.mapping == ADDRESS_MAP_UNKNOWN); /* один ответ не назначает NAT-тип */
|
assert(socket->address_profile.mapping == ADDRESS_MAP_UNKNOWN); /* один ответ не назначает NAT-тип */
|
||||||
|
|
||||||
memset(&result, 0, sizeof(result));
|
memset(&result, 0, sizeof(result));
|
||||||
struct ETCP_SOCKET *untrusted = test_etcp_bound_socket(foreign, "udp");
|
struct ETCP_SOCKET *untrusted = test_etcp_bound_socket(foreign, "udp");
|
||||||
assert(route_ping_observe(socket, observer->my_keys.public_key, &untrusted->local_addr,
|
assert(route_ping_observe(socket, observer->my_keys.public_key, &untrusted->local_addr,
|
||||||
round + 1, 300, ping_done, &result) == 0);
|
TOPO_GROUP_UTUN, round + 1, 300, ping_done, &result) == 0);
|
||||||
assert(owner->pending_pings);
|
assert(owner->pending_pings);
|
||||||
send_foreign_pong(foreign, socket, owner->pending_pings->nonce);
|
send_foreign_pong(foreign, socket, owner->pending_pings->nonce);
|
||||||
wait_result(&fixture, &result);
|
wait_result(&fixture, &result);
|
||||||
assert(!result.success && !owner->pending_pings);
|
assert(!result.success && !owner->pending_pings);
|
||||||
|
|
||||||
memset(&result, 0, sizeof(result));
|
memset(&result, 0, sizeof(result));
|
||||||
assert(route_ping_observe(socket, observer->my_keys.public_key, &peer->local_addr, round + 2, 300, ping_done, &result) == 0);
|
assert(route_ping_observe(socket, observer->my_keys.public_key, &peer->local_addr, TOPO_GROUP_UTUN, round + 2, 300, ping_done, &result) == 0);
|
||||||
uint64_t generation = socket->generation; socket->generation = generation == UINT64_MAX ? generation - 1 : generation + 1;
|
uint64_t generation = socket->generation; socket->generation = generation == UINT64_MAX ? generation - 1 : generation + 1;
|
||||||
wait_result(&fixture, &result); assert(!result.success); socket->generation = generation;
|
wait_result(&fixture, &result); assert(!result.success); socket->generation = generation;
|
||||||
|
|
||||||
memset(&result, 0, sizeof(result));
|
memset(&result, 0, sizeof(result));
|
||||||
assert(route_ping_observe(socket, observer->my_keys.public_key, &peer->local_addr, round + 3, 500, ping_done, &result) == 0);
|
assert(route_ping_observe(socket, observer->my_keys.public_key, &peer->local_addr, TOPO_GROUP_UTUN, round + 3, 500, ping_done, &result) == 0);
|
||||||
etcp_cancel_pings(owner, ping_done, &result); assert(!owner->pending_pings);
|
etcp_cancel_pings(owner, ping_done, &result); assert(!owner->pending_pings);
|
||||||
uint64_t end = get_time_tb() + 6000;
|
uint64_t end = get_time_tb() + 6000;
|
||||||
while (get_time_tb() < end) uasync_poll(fixture.ua, 10);
|
while (get_time_tb() < end) uasync_poll(fixture.ua, 10);
|
||||||
|
|||||||
Reference in new issue
Block a user