Distinguish LAN nonce failures from ordinary unknown devices
This commit is contained in:
1 parent
94a76e569e
commit
8dd28fb90a
3 files changed
+18
-9
No files matched your search
@@ -121,7 +121,7 @@ static int route_verify(void* arg, uint64_t peer, const uint8_t* data, size_t le
|
||||
struct TOPO_NODE* node = topo_node_registry_find(inst->topo_groups, peer);
|
||||
if (node && node->timestamp) memcpy(key, node->ed25519_public_key, sizeof(key));
|
||||
else if (!inst->topo_sqlite_db || topo_node_sqlite_get_ed25519_pubkey(inst->topo_sqlite_db, peer, key)) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DISCOVERY, "LAN route ignored peer=%016llx reason=unknown signing key", (unsigned long long)peer); return -1;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DISCOVERY, "LAN route ignored peer=%016llx reason=unknown signing key", (unsigned long long)peer); return 1;
|
||||
}
|
||||
if (sc_ed25519_verify(key, data, len, signature) != SC_OK) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DISCOVERY, "LAN route signature rejected peer=%016llx", (unsigned long long)peer); return -1;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
enum packet_drop {
|
||||
DROP_FOREIGN, DROP_NONLOCAL, DROP_HEADER, DROP_ANNOUNCE, DROP_IDENTITY,
|
||||
DROP_ENDPOINT, DROP_ACK, DROP_MESSAGE, DROP_CAPACITY, DROP_LIMIT, DROP_COUNT
|
||||
DROP_ENDPOINT, DROP_ACK, DROP_MESSAGE, DROP_CAPACITY, DROP_LIMIT, DROP_ROUTE_NONCE, DROP_ROUTE_ADDRESS, DROP_COUNT
|
||||
};
|
||||
|
||||
struct local_socket {
|
||||
@@ -98,7 +98,8 @@ static void drop_packet(struct local_transport* t, enum packet_drop reason) { t-
|
||||
static void reset_receive(struct local_transport* t) {
|
||||
static const char* reasons[DROP_COUNT] = {
|
||||
"foreign", "non-local source", "header/discovery type", "announcement/name", "identity/destination",
|
||||
"unknown/expired endpoint", "ACK payload", "message/application limit", "table capacity", "receive budget"
|
||||
"unknown/expired endpoint", "ACK payload", "message/application limit", "table capacity", "receive budget",
|
||||
"LAN proof nonce/epoch/destination", "LAN signed/source IP mismatch"
|
||||
};
|
||||
for (int i = 0; i < DROP_COUNT; i++) {
|
||||
if (t->dropped[i]) {
|
||||
@@ -273,13 +274,16 @@ static void receive_route(struct local_socket* s, const struct sockaddr_storage*
|
||||
if (destination || destination_epoch || memcmp(body, zero, 16)) { drop_packet(t, DROP_IDENTITY); return; }
|
||||
} else if (destination != t->node_id || destination_epoch != t->epoch ||
|
||||
!e->challenge_until || now >= e->challenge_until || epoch != e->route_epoch || memcmp(body, e->nonce, 16)) {
|
||||
drop_packet(t, DROP_IDENTITY); return;
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DISCOVERY, "LAN proof rejected peer=%016llx epoch=%016llx expected=%016llx pending=%d expired=%d",
|
||||
(unsigned long long)sender, (unsigned long long)epoch, (unsigned long long)e->route_epoch,
|
||||
e->challenge_until != 0, e->challenge_until != 0 && now >= e->challenge_until);
|
||||
drop_packet(t, DROP_ROUTE_NONCE); return;
|
||||
}
|
||||
const void* ip = source->ss_family == AF_INET ? (const void*)&((const struct sockaddr_in*)source)->sin_addr :
|
||||
(const void*)&((const struct sockaddr_in6*)source)->sin6_addr;
|
||||
size_t ip_size = source->ss_family == AF_INET ? 4 : 16;
|
||||
if (body[16] != (ip_size == 4 ? 4 : 6) || memcmp(body + 17, ip, ip_size) ||
|
||||
(ip_size == 4 && memcmp(body + 21, zero, 12))) { drop_packet(t, DROP_NONLOCAL); return; }
|
||||
(ip_size == 4 && memcmp(body + 21, zero, 12))) { drop_packet(t, DROP_ROUTE_ADDRESS); return; }
|
||||
struct local_route_socket sockets[LOCAL_ROUTE_SOCKETS_MAX] = {0};
|
||||
for (unsigned i = 0; i < body[33]; i++) {
|
||||
const uint8_t* p = body + LOCAL_ROUTE_HEADER_SIZE + i * LOCAL_ROUTE_SOCKET_SIZE;
|
||||
@@ -300,8 +304,10 @@ static void receive_route(struct local_socket* s, const struct sockaddr_storage*
|
||||
if (!t->routes_left) { drop_packet(t, DROP_LIMIT); return; }
|
||||
t->routes_left--;
|
||||
size_t signed_size = size - LOCAL_ROUTE_SIGNATURE_SIZE;
|
||||
if (t->callbacks.route_verify(t->arg, sender, data, signed_size, data + signed_size)) {
|
||||
drop_packet(t, DROP_IDENTITY); return;
|
||||
int verified = t->callbacks.route_verify(t->arg, sender, data, signed_size, data + signed_size);
|
||||
if (verified) {
|
||||
if (verified < 0) drop_packet(t, DROP_IDENTITY);
|
||||
return;
|
||||
}
|
||||
if (type == LOCAL_ROUTE_ANNOUNCE) {
|
||||
int equal = e->route_count == body[33] && e->route_epoch == epoch;
|
||||
@@ -363,8 +369,10 @@ static void receive_packet(struct local_socket* s, struct sockaddr_storage* sour
|
||||
p = &t->peers[t->peer_count++]; memset(p, 0, sizeof(*p)); p->peer.node_id = peer_id;
|
||||
}
|
||||
if (p->epoch != epoch) {
|
||||
int had_routes = 0;
|
||||
for (size_t i = 0; i < p->count; i++) if (p->endpoints[i].route_until) had_routes = 1;
|
||||
p->epoch = epoch; p->count = 0; changed = 1;
|
||||
if (t->callbacks.routes_changed) t->callbacks.routes_changed(t->arg, peer_id);
|
||||
if (had_routes && t->callbacks.routes_changed) t->callbacks.routes_changed(t->arg, peer_id);
|
||||
}
|
||||
if (strlen(p->peer.name) != len || memcmp(p->peer.name, payload, len)) {
|
||||
memcpy(p->peer.name, payload, len); p->peer.name[len] = 0; changed = 1;
|
||||
|
||||
@@ -55,7 +55,8 @@ struct local_transport_callbacks {
|
||||
void (*delivery)(void* arg, uint64_t request_id, uint64_t peer_id, int status); // один результат: enum local_delivery_status
|
||||
void (*activity_changed)(void* arg, int active); // сокеты включаются/выключаются, в том числе при ошибке таймера
|
||||
/* Необязательный LAN transport: задать все пять callbacks либо ни одного.
|
||||
* sockets возвращает 0..capacity или -1; sign/verify — 0/-1, подпись Ed25519 ровно 64 байта.
|
||||
* sockets возвращает 0..capacity или -1; sign — 0/-1; verify — 0 (верна), 1 (ключ неизвестен), -1 (неверна/ошибка).
|
||||
* Подпись Ed25519 ровно 64 байта.
|
||||
* Подписываются полный wire-заголовок и тело без подписи; verify использует только известный ключ peer.
|
||||
* offline возвращает 1 при отсутствии прямого UP и живого BGP-пути во всех группах.
|
||||
* routes_changed вызывается после применения/удаления адресов; не останавливать транспорт из callback. */
|
||||
|
||||
Reference in new issue
Block a user