Sign endpoint profile provenance and restrict external-address publication
This commit is contained in:
1 parent
6beae21ec4
commit
735ac36579
3 files changed
+24
-9
No files matched your search
@@ -19,11 +19,14 @@ enum address_inbound {
|
||||
ADDRESS_IN_CONTACT
|
||||
};
|
||||
|
||||
enum address_profile_source { ADDRESS_SOURCE_NONE, ADDRESS_SOURCE_ETCP, ADDRESS_SOURCE_STUN };
|
||||
|
||||
#define ADDRESS_PROFILE_TTL_US UINT64_C(300000000)
|
||||
|
||||
struct address_profile {
|
||||
uint8_t mapping;
|
||||
uint8_t inbound;
|
||||
uint8_t source; /* ETCP — этот endpoint; STUN — резервная оценка его IP/netif. */
|
||||
uint64_t evidence_id;
|
||||
uint64_t checked_at;
|
||||
};
|
||||
@@ -38,9 +41,16 @@ static inline const char *address_inbound_name(uint8_t value) {
|
||||
return value <= ADDRESS_IN_CONTACT ? names[value] : "INVALID";
|
||||
}
|
||||
|
||||
static inline const char *address_profile_source_name(uint8_t value) {
|
||||
static const char *const names[] = {"NONE", "ETCP", "STUN"};
|
||||
return value <= ADDRESS_SOURCE_STUN ? names[value] : "INVALID";
|
||||
}
|
||||
|
||||
static inline int address_profile_valid(const struct address_profile *profile) {
|
||||
return profile && profile->mapping <= ADDRESS_MAP_DEPENDENT && profile->inbound <= ADDRESS_IN_CONTACT &&
|
||||
((!profile->mapping && !profile->inbound) || (profile->evidence_id && profile->checked_at));
|
||||
profile->source <= ADDRESS_SOURCE_STUN &&
|
||||
((!profile->mapping && !profile->inbound && profile->source == ADDRESS_SOURCE_NONE) ||
|
||||
((profile->mapping || profile->inbound) && profile->source && profile->evidence_id && profile->checked_at));
|
||||
}
|
||||
|
||||
static inline int address_profile_fresh(const struct address_profile *profile, uint64_t now_us) {
|
||||
|
||||
@@ -92,6 +92,7 @@ void topo_node_apply_reality(struct ETCP_LINK* link, const struct TOPO_REALITY_S
|
||||
static int sockmeta4_list_equal(struct TOPO_SOCKMETA4* a, struct TOPO_SOCKMETA4* b) {
|
||||
while (a && b) {
|
||||
if (a->id != b->id || a->config_type != b->config_type ||
|
||||
a->address_profile.source != b->address_profile.source ||
|
||||
a->address_profile.mapping != b->address_profile.mapping || a->address_profile.inbound != b->address_profile.inbound ||
|
||||
a->address_profile.evidence_id != b->address_profile.evidence_id || a->address_profile.checked_at != b->address_profile.checked_at)
|
||||
return 0;
|
||||
@@ -110,6 +111,7 @@ static int addr4_list_equal(struct TOPO_ADDR4* a, struct TOPO_ADDR4* b) {
|
||||
static int sockmeta6_list_equal(struct TOPO_SOCKMETA6* a, struct TOPO_SOCKMETA6* b) {
|
||||
while (a && b) {
|
||||
if (a->id != b->id || a->config_type != b->config_type ||
|
||||
a->address_profile.source != b->address_profile.source ||
|
||||
a->address_profile.mapping != b->address_profile.mapping || a->address_profile.inbound != b->address_profile.inbound ||
|
||||
a->address_profile.evidence_id != b->address_profile.evidence_id || a->address_profile.checked_at != b->address_profile.checked_at)
|
||||
return 0;
|
||||
@@ -347,17 +349,19 @@ void topo_node_registry_unref(struct TOPO_GROUPS* groups, uint64_t node_id) {
|
||||
|
||||
static void sockmeta_wire_write(uint8_t *out, uint8_t id, uint8_t config, const struct address_profile *profile) {
|
||||
out[0] = id; out[1] = config; out[2] = profile->mapping; out[3] = profile->inbound;
|
||||
out[4] = profile->source;
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
out[4 + i] = (uint8_t)(profile->evidence_id >> (56 - i * 8));
|
||||
out[12 + i] = (uint8_t)(profile->checked_at >> (56 - i * 8));
|
||||
out[5 + i] = (uint8_t)(profile->evidence_id >> (56 - i * 8));
|
||||
out[13 + i] = (uint8_t)(profile->checked_at >> (56 - i * 8));
|
||||
}
|
||||
}
|
||||
|
||||
static int sockmeta_wire_read(const uint8_t *in, struct address_profile *profile) {
|
||||
memset(profile, 0, sizeof(*profile)); profile->mapping = in[2]; profile->inbound = in[3];
|
||||
profile->source = in[4];
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
profile->evidence_id = (profile->evidence_id << 8) | in[4 + i];
|
||||
profile->checked_at = (profile->checked_at << 8) | in[12 + i];
|
||||
profile->evidence_id = (profile->evidence_id << 8) | in[5 + i];
|
||||
profile->checked_at = (profile->checked_at << 8) | in[13 + i];
|
||||
}
|
||||
if (!address_profile_valid(profile)) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "invalid address profile in NODEINFO"); return -1; }
|
||||
return 0;
|
||||
@@ -1177,7 +1181,7 @@ int topo_node_update_my_addresses(struct UTUN_INSTANCE* instance) {
|
||||
/* Общий внешний адрес публикует только владелец после наблюдений EIM.
|
||||
Наличие ответа интернет-NTP не связано с работоспособностью этого endpoint. */
|
||||
if (e_sock->nat_addr.ss_family == AF_INET && nat_sin->sin_addr.s_addr != 0 &&
|
||||
e_sock->address_profile.mapping == ADDRESS_MAP_EIM) {
|
||||
e_sock->address_profile.mapping == ADDRESS_MAP_EIM && e_sock->address_profile.source == ADDRESS_SOURCE_ETCP) {
|
||||
struct TOPO_ADDR4* a = memory_pool_alloc(instance->topo_groups->v4_addr_pool);
|
||||
if (!a) goto allocation_failed;
|
||||
memcpy(a->addr, &nat_sin->sin_addr.s_addr, 4); a->port = ntohs(nat_sin->sin_port);
|
||||
@@ -1196,7 +1200,8 @@ int topo_node_update_my_addresses(struct UTUN_INSTANCE* instance) {
|
||||
memcpy(a6->addr, &if_sin6->sin6_addr, 16); a6->port = ntohs(if_sin6->sin6_port);
|
||||
a6->type = TOPO_ADDR_INTERFACE; a6->socket_id = e_sock->sock_id; a6->protocol = TOPO_PROTO_UDP;
|
||||
a6->next = v6_head; v6_head = a6; }
|
||||
if (e_sock->nat_addr.ss_family == AF_INET6 && e_sock->address_profile.mapping == ADDRESS_MAP_EIM) {
|
||||
if (e_sock->nat_addr.ss_family == AF_INET6 && e_sock->address_profile.mapping == ADDRESS_MAP_EIM &&
|
||||
e_sock->address_profile.source == ADDRESS_SOURCE_ETCP) {
|
||||
const struct sockaddr_in6 *mapped = (const struct sockaddr_in6 *)&e_sock->nat_addr;
|
||||
struct TOPO_ADDR6 *a6 = memory_pool_alloc(instance->topo_groups->v6_addr_pool);
|
||||
if (!a6) goto allocation_failed;
|
||||
|
||||
@@ -105,12 +105,12 @@ struct TOPO_CONNECTIVITY {
|
||||
#define PING_TTL_TB (86400ULL * 10000ULL)
|
||||
|
||||
struct TOPOMSG_SOCKMETA4 {
|
||||
uint8_t id, config_type, mapping, inbound;
|
||||
uint8_t id, config_type, mapping, inbound, source;
|
||||
uint8_t evidence_id[8], checked_at[8];
|
||||
} __attribute__((packed));
|
||||
struct TOPOMSG_ADDR4 { uint8_t addr[4]; uint16_t port; uint8_t type, socket_id, protocol; } __attribute__((packed));
|
||||
struct TOPOMSG_SOCKMETA6 {
|
||||
uint8_t id, config_type, mapping, inbound;
|
||||
uint8_t id, config_type, mapping, inbound, source;
|
||||
uint8_t evidence_id[8], checked_at[8];
|
||||
} __attribute__((packed));
|
||||
struct TOPOMSG_ADDR6 { uint8_t addr[16]; uint16_t port; uint8_t type, socket_id, protocol; } __attribute__((packed));
|
||||
|
||||
Reference in new issue
Block a user