Browse Source

Invalidate changed endpoints and verify the Android address contract

master
evgeny 6 days ago
parent
commit
5429431567
  1. 19
      src/routing_layer/nat_detection.c
  2. 13
      tests/test_android_replies.c

19
src/routing_layer/nat_detection.c

@ -419,7 +419,8 @@ static void owner_finish(struct nat_socket *state, uint8_t reason) {
state->active_ping = 0; state->phase = NAT_IDLE; state->reason = reason;
if (reason == NAT_REASON_NO_OBSERVER || reason == NAT_REASON_NO_HELPER) state->fallback_allowed = 1;
state->preferred_observer = 0;
state->due = get_time_tb() + (state->socket->address_profile.source || !reason ? NAT_REFRESH_TB : NAT_RETRY_TB);
state->due = get_time_tb() + (reason == NAT_REASON_ADDRESS_CHANGED ? 2500 :
state->socket->address_profile.source || !reason ? NAT_REFRESH_TB : NAT_RETRY_TB);
if (reason) {
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT round incomplete socket=%s generation=%016llx round=%016llx reason=%s",
state->socket->name, (unsigned long long)state->socket->generation,
@ -496,7 +497,8 @@ static void owner_ping_cb(int success, uint16_t rtt, void *arg, uint64_t nonce,
state->socket->name, state->phase, (unsigned long long)state->round, sockaddr_storage_to_str(&observed).str);
if (state->phase == NAT_OBSERVE_B) {
state->baseline = observed;
if (state->socket->nat_addr.ss_family && !route_ping_addr_equal(&state->socket->nat_addr, &observed, 1))
if ((state->measured_profile.mapping == ADDRESS_MAP_UNCHANGED && !route_ping_addr_equal(&state->local, &observed, 1)) ||
(state->socket->nat_addr.ss_family && !route_ping_addr_equal(&state->socket->nat_addr, &observed, 1)))
clear_profile(state, NAT_REASON_ADDRESS_CHANGED);
if (owner_find(state)) owner_finish(state, NAT_REASON_CONTROL_LOST);
return;
@ -879,9 +881,13 @@ static void owner_start(struct nat_socket *state) {
}
if (select_observer(state)) {
if (state->reason != NAT_REASON_NO_OBSERVER)
DEBUG_INFO(DEBUG_CATEGORY_NAT, "NAT profile remains UNKNOWN: no live observer socket=%s", state->socket->name);
DEBUG_INFO(DEBUG_CATEGORY_NAT, "NAT recheck has no live observer socket=%s retained=%s/%s source=%s", state->socket->name,
address_mapping_name(state->socket->address_profile.mapping),
address_inbound_name(state->socket->address_profile.inbound),
address_profile_source_name(state->socket->address_profile.source));
state->reason = NAT_REASON_NO_OBSERVER; state->fallback_allowed = 1;
state->due = get_time_tb() + NAT_RETRY_TB; select_profile(state); return;
select_profile(state);
state->due = get_time_tb() + (state->socket->address_profile.source ? NAT_REFRESH_TB : NAT_RETRY_TB); return;
}
if (random_id(&state->round)) { state->reason = NAT_REASON_SEND_ERROR; state->due = get_time_tb() + NAT_RETRY_TB; return; }
history_load(state);
@ -972,8 +978,11 @@ void nat_detection_observed_by_peer(struct NAT_DETECTION *detector, struct ETCP_
if (!state) return;
if ((state->measured_profile.mapping == ADDRESS_MAP_UNCHANGED &&
!route_ping_addr_equal(&state->local, observed, 1)) ||
(link->conn->nat_addr.ss_family && !route_ping_addr_equal(&link->conn->nat_addr, observed, 1)))
(link->conn->nat_addr.ss_family && !route_ping_addr_equal(&link->conn->nat_addr, observed, 1))) {
if (state->phase) owner_finish(state, NAT_REASON_ADDRESS_CHANGED);
clear_profile(state, NAT_REASON_ADDRESS_CHANGED);
state->due = get_time_tb() + 2500;
}
}
void nat_detection_socket_removed(struct NAT_DETECTION *detector, struct ETCP_SOCKET *socket) {

13
tests/test_android_replies.c

@ -64,13 +64,16 @@ static int check_addresses(const char *channel) {
REQUIRE(!topo_node_sqlite_addrs_put(instance->topo_sqlite_db, instance->node_id, &node));
char *json = utun_bridge_get_member_detail_json(channel, instance->node_id);
char value[128];
REQUIRE(json && !extract(json, "$.adr[0].a", value, sizeof(value)) && !strcmp(value, "194.63.142.140"));
REQUIRE(!extract(json, "$.adr[0].p", value, sizeof(value)) && !strcmp(value, "1333"));
REQUIRE(json && !extract(json, "$.adr[0].ad", value, sizeof(value)) && !strcmp(value, "194.63.142.140"));
REQUIRE(!extract(json, "$.adr[0].po", value, sizeof(value)) && !strcmp(value, "1333"));
REQUIRE(!extract(json, "$.adr[0].at", value, sizeof(value)) && !strcmp(value, "4"));
REQUIRE(!extract(json, "$.adr[0].pr", value, sizeof(value)) && !strcmp(value, "UDP"));
REQUIRE(!extract(json, "$.adr[0].pt", value, sizeof(value)) && !strcmp(value, "UDP"));
REQUIRE(!extract(json, "$.adr[0].si", value, sizeof(value)) && !strcmp(value, "5"));
REQUIRE(!extract(json, "$.adr[1].ad", value, sizeof(value)) && !strcmp(value, "2a04:5200::f"));
REQUIRE(!extract(json, "$.adr[1].at", value, sizeof(value)) && !strcmp(value, "1"));
REQUIRE(!extract(json, "$.adr[1].pr", value, sizeof(value)) && !strcmp(value, "TCP"));
REQUIRE(!extract(json, "$.adr[1].p", value, sizeof(value)) && !strcmp(value, "443"));
REQUIRE(!extract(json, "$.adr[1].pt", value, sizeof(value)) && !strcmp(value, "TCP"));
REQUIRE(!extract(json, "$.adr[1].po", value, sizeof(value)) && !strcmp(value, "443"));
REQUIRE(!extract(json, "$.adr[1].si", value, sizeof(value)) && !strcmp(value, "6"));
u_free(json); return 0;
}

Loading…
Cancel
Save