nat: reject local probe sources and preserve internet profiles on LAN
This commit is contained in:
1 parent
308eb07742
commit
83efa229ed
3 files changed
+112
-18
No files matched your search
@@ -517,6 +517,21 @@ void nat_detection_record_observation(struct NAT_DETECTION *detector, struct ETC
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT observation has invalid group/identity group=%016llx owner=%016llx",
|
||||
(unsigned long long)group_id, (unsigned long long)owner); return;
|
||||
}
|
||||
int eligible = public_address(detector, source);
|
||||
if (!eligible) DEBUG_WARN(DEBUG_CATEGORY_NAT,
|
||||
"NAT observation rejected by receiver group=%016llx owner=%016llx round=%016llx source=%s reason=non_public_source",
|
||||
(unsigned long long)group_id, (unsigned long long)owner, (unsigned long long)round, sockaddr_storage_to_str(source).str);
|
||||
if (length == NAT_QUERY_TAG_SIZE) {
|
||||
struct nat_wire report = {.command = NAT_OBSERVATION, .owner_socket = tag[8], .step = tag[ROUTE_OBSERVE_TAG_SIZE],
|
||||
.reason = eligible ? NAT_REASON_NONE : NAT_REASON_INVALID_OBSERVATION};
|
||||
write64(report.owner, owner); write64(report.generation, generation); write64(report.round, round);
|
||||
write64(report.token, read64(tag + ROUTE_OBSERVE_TAG_SIZE + 1));
|
||||
write64(report.observer, detector->instance->node_id); write64(report.helper, detector->instance->node_id);
|
||||
if (route_ping_addr_encode(report.target, source) || send_control(detector, group_id, owner, &report))
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT routed observation delivery failed group=%016llx owner=%016llx round=%016llx",
|
||||
(unsigned long long)group_id, (unsigned long long)owner, (unsigned long long)round);
|
||||
}
|
||||
if (!eligible) return;
|
||||
struct nat_binding *binding = binding_find(detector, group_id, owner, generation, round);
|
||||
if (!binding) {
|
||||
unsigned count = 0;
|
||||
@@ -532,15 +547,6 @@ void nat_detection_record_observation(struct NAT_DETECTION *detector, struct ETC
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT observation group=%016llx owner=%016llx socket=%u generation=%016llx round=%016llx observed=%s via=%s",
|
||||
(unsigned long long)group_id, (unsigned long long)owner, tag[8], (unsigned long long)generation, (unsigned long long)round,
|
||||
sockaddr_storage_to_str(source).str, socket->name);
|
||||
if (length == NAT_QUERY_TAG_SIZE) {
|
||||
struct nat_wire report = {.command = NAT_OBSERVATION, .owner_socket = tag[8], .step = tag[ROUTE_OBSERVE_TAG_SIZE]};
|
||||
write64(report.owner, owner); write64(report.generation, generation); write64(report.round, round);
|
||||
write64(report.token, read64(tag + ROUTE_OBSERVE_TAG_SIZE + 1));
|
||||
write64(report.observer, detector->instance->node_id); write64(report.helper, detector->instance->node_id);
|
||||
if (route_ping_addr_encode(report.target, source) || send_control(detector, group_id, owner, &report))
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT routed observation delivery failed group=%016llx owner=%016llx round=%016llx",
|
||||
(unsigned long long)group_id, (unsigned long long)owner, (unsigned long long)round);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_profile(struct nat_socket *state, uint8_t reason) {
|
||||
@@ -669,7 +675,8 @@ static void owner_heartbeat_cb(int success, uint16_t rtt, void *arg, uint64_t no
|
||||
struct nat_socket *state = arg; state->heartbeat_active = 0;
|
||||
if (!state->phase) return;
|
||||
struct sockaddr_storage observed;
|
||||
if (success && !route_ping_observation(data, length, state->socket, state->group_id, state->round, &observed)) {
|
||||
if (success && !route_ping_observation(data, length, state->socket, state->group_id, state->round, &observed) &&
|
||||
public_address(state->detector, &observed)) {
|
||||
if (state->baseline.ss_family && !route_ping_addr_equal(&state->baseline, &observed, 1)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT anchor mapping changed socket=%s round=%016llx previous=%s current=%s",
|
||||
state->socket->name, (unsigned long long)state->round,
|
||||
@@ -697,6 +704,11 @@ static void owner_ping_cb(int success, uint16_t rtt, void *arg, uint64_t nonce,
|
||||
if (++state->retries < NAT_PROBE_COUNT) { state->due = get_time_tb() + 1000; return; }
|
||||
owner_finish(state, success ? NAT_REASON_INVALID_OBSERVATION : NAT_REASON_TIMEOUT); return;
|
||||
}
|
||||
if (!public_address(state->detector, &observed)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT observation unusable socket=%s phase=%u round=%016llx observed=%s reason=non_public_source",
|
||||
state->socket->name, state->phase, (unsigned long long)state->round, sockaddr_storage_to_str(&observed).str);
|
||||
owner_finish(state, NAT_REASON_INVALID_OBSERVATION); return;
|
||||
}
|
||||
state->retries = 0;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT own observation socket=%s phase=%u round=%016llx observed=%s",
|
||||
state->socket->name, state->phase, (unsigned long long)state->round, sockaddr_storage_to_str(&observed).str);
|
||||
@@ -757,11 +769,20 @@ void nat_detection_receive_ingress(struct NAT_DETECTION *detector, struct ETCP_S
|
||||
if (!step || memcmp(tag, expected, sizeof(expected)) || tag[ROUTE_OBSERVE_TAG_SIZE] != step ||
|
||||
read64(tag + ROUTE_OBSERVE_TAG_SIZE + 1) != state->token ||
|
||||
sc_derive_node_id_from_pubkey(peer_key) != state->helper || memcmp(peer_key, state->helper_key, 32) ||
|
||||
source->ss_family != state->local.ss_family || !public_address(detector, source) ||
|
||||
((step == NAT_STEP_POST || state->pre_received) && !route_ping_addr_equal(source, &state->helper_address, 1))) {
|
||||
source->ss_family != state->local.ss_family) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT ingress correlation/source mismatch socket=%s phase=%u round=%016llx source=%s",
|
||||
socket->name, state->phase, (unsigned long long)state->round, sockaddr_storage_to_str(source).str); return;
|
||||
}
|
||||
if (!public_address(detector, source)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT helper rejected by receiver socket=%s round=%016llx helper=%016llx source=%s reason=non_public_source",
|
||||
socket->name, (unsigned long long)state->round, (unsigned long long)state->helper, sockaddr_storage_to_str(source).str);
|
||||
owner_finish(state, NAT_REASON_NO_HELPER); return;
|
||||
}
|
||||
if ((step == NAT_STEP_POST || state->pre_received) && !route_ping_addr_equal(source, &state->helper_address, 1)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT ingress endpoint mismatch socket=%s phase=%u round=%016llx source=%s expected=%s",
|
||||
socket->name, state->phase, (unsigned long long)state->round,
|
||||
sockaddr_storage_to_str(source).str, sockaddr_storage_to_str(&state->helper_address).str); return;
|
||||
}
|
||||
if (route_ping_addr_equal(source, &state->observer_address, 0) || route_ping_addr_equal(source, &state->baseline, 0)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT helper rejected by receiver socket=%s round=%016llx helper=%016llx source=%s reason=%s",
|
||||
socket->name, (unsigned long long)state->round, (unsigned long long)state->helper,
|
||||
@@ -859,7 +880,7 @@ static void helper_ping_cb(int success, uint16_t rtt, void *arg, uint64_t nonce,
|
||||
struct ETCP_SOCKET *socket = find_socket(probe->detector, probe->io_socket, probe->io_generation);
|
||||
struct sockaddr_storage mapped;
|
||||
if (success && socket && !route_ping_observation(data, length, socket, probe->group_id,
|
||||
read64(probe->message.round), &mapped)) {
|
||||
read64(probe->message.round), &mapped) && public_address(probe->detector, &mapped)) {
|
||||
if (route_ping_addr_encode(probe->message.primary, &mapped)) { helper_finish(probe, NAT_REASON_INVALID_OBSERVATION); return; }
|
||||
probe->message.received++;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT helper endpoint measured group=%016llx owner=%016llx step=%u socket=%s mapped=%s fallback=%u",
|
||||
@@ -1089,6 +1110,7 @@ static void receive_observation(struct NAT_DETECTION *detector, uint64_t group,
|
||||
probe->io_generation != socket->generation || read64(probe->message.round) != read64(message->round) ||
|
||||
read64(probe->message.token) != read64(message->token) || read64(probe->message.observer) != sender) continue;
|
||||
etcp_cancel_pings(detector->instance, helper_ping_cb, probe);
|
||||
if (message->reason) { helper_finish(probe, message->reason); return; }
|
||||
helper_ping_cb(1, 0, probe, 0, data, sizeof(data)); return;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT stale helper observation report ignored"); return;
|
||||
@@ -1101,6 +1123,7 @@ static void receive_observation(struct NAT_DETECTION *detector, uint64_t group,
|
||||
(unsigned long long)group, (unsigned long long)sender, message->step); return;
|
||||
}
|
||||
etcp_cancel_pings(detector->instance, owner_ping_cb, state);
|
||||
if (message->reason) { owner_finish(state, message->reason); return; }
|
||||
owner_ping_cb(1, 0, state, 0, data, sizeof(data));
|
||||
}
|
||||
|
||||
@@ -1514,6 +1537,10 @@ void nat_detection_link_ready(struct NAT_DETECTION *detector, struct ETCP_LINK *
|
||||
void nat_detection_observed_by_peer(struct NAT_DETECTION *detector, struct ETCP_LINK *link,
|
||||
const struct sockaddr_storage *observed) {
|
||||
if (!detector || !link || !link->conn || link->is_tcp || link->conn->socks_udp || !observed->ss_family) return;
|
||||
if (!public_address(detector, observed)) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT ignores LAN observation socket=%s peer=%016llx observed=%s",
|
||||
link->conn->name, (unsigned long long)link->etcp->peer_node_id, sockaddr_storage_to_str(observed).str); return;
|
||||
}
|
||||
struct nat_socket *state = socket_state(detector, link->conn, 1);
|
||||
if (!state) return;
|
||||
if ((state->measured_profile.mapping == ADDRESS_MAP_UNCHANGED &&
|
||||
|
||||
Reference in new issue
Block a user