Browse Source

Admit reverse-capable providers without requiring an outgoing-compatible address

master
evgeny 5 days ago
parent
commit
aa3fb9cac7
  1. 41
      src/transport_layer/node_conn_direct.c
  2. 5
      src/transport_layer/node_conn_direct.h

41
src/transport_layer/node_conn_direct.c

@ -361,7 +361,46 @@ int node_conn_direct_compatible(struct UTUN_INSTANCE* inst, uint64_t node_id) {
if (conn && conn->state != 2 && !conn->close_requested && conn->links_up) return 1;
struct TOPO_NODE* node = topo_node_registry_find(inst->topo_groups, node_id);
if (!node) { DEBUG_DEBUG(DEBUG_CATEGORY_NCD, "[ncd] compatibility unknown snapshot node=%016llx", (unsigned long long)node_id); return 0; }
return ncd_create_links(NULL, node, NULL, inst) > 0;
if (ncd_create_links(NULL, node, NULL, inst) > 0) return 1;
/* Входящее подключение тоже допустимо: REVERSE_REQ просит пира открыть наш опубликованный адрес.
* TCP имеет собственный исходящий socket fallback; для UDP нужен известный UDP-сокет пира.
* Это возможность попытки, не подтверждение маршрута/работоспособности скрытых сокетов пира. */
const struct TOPO_NODE* self = topo_node_registry_find(inst->topo_groups, inst->node_id);
if (!self) return 0;
for (const struct TOPO_ADDR4* a = self->v4_addrs; a; a = a->next) {
uint32_t ip; memcpy(&ip, a->addr, 4);
if (!ip || !a->port) continue;
const struct TOPO_SOCKMETA4* meta = self->v4_sock_meta;
while (meta && meta->id != a->socket_id) meta = meta->next;
uint8_t cfg = meta ? meta->config_type : CFG_SERVER_TYPE_UNKNOWN, nat = meta ? meta->nat_type : NAT_TYPE_UNKNOWN;
if (sock_target_class(a->type, cfg, nat) != SOCK_TC_PUB) continue;
if ((a->protocol & TOPO_PROTO_REALITY) && !topo_node_find_reality_sock(self, a->socket_id)) continue;
if (a->protocol & TOPO_PROTO_TCP) return 1;
if (!(a->protocol & TOPO_PROTO_UDP)) continue;
for (const struct TOPO_ADDR4* remote = node->v4_addrs; remote; remote = remote->next) {
if (!(remote->protocol & TOPO_PROTO_UDP)) continue;
const struct TOPO_SOCKMETA4* rm = node->v4_sock_meta;
while (rm && rm->id != remote->socket_id) rm = rm->next;
struct sock_view view = {.has_inet = 1};
view.is_eim = rm && (rm->nat_type == NAT_TYPE_EIM || rm->nat_type == NAT_VERIFIED_EIM);
for (const struct TOPO_ADDR4* ra = node->v4_addrs; ra; ra = ra->next)
if (ra->socket_id == remote->socket_id && ra->type == TOPO_ADDR_NAT) memcpy(&view.public_ip4, ra->addr, 4);
if (sock_match(&view, a->type, cfg, nat, ip)) return 1;
}
}
for (const struct TOPO_ADDR6* a = self->v6_addrs; a; a = a->next) {
int nonzero = 0; for (unsigned i = 0; i < 16; i++) nonzero |= a->addr[i];
if (!nonzero || !a->port || (a->addr[0] == 0xfe && (a->addr[1] & 0xc0) == 0x80)) continue;
const struct TOPO_SOCKMETA6* meta = self->v6_sock_meta;
while (meta && meta->id != a->socket_id) meta = meta->next;
if (meta && (meta->config_type == CFG_SERVER_TYPE_PRIVATE || meta->config_type == CFG_SERVER_TYPE_LOCAL)) continue;
if ((a->protocol & TOPO_PROTO_REALITY) && !topo_node_find_reality_sock(self, a->socket_id)) continue;
if (a->protocol & TOPO_PROTO_TCP) return 1;
if (!(a->protocol & TOPO_PROTO_UDP)) continue;
for (const struct TOPO_ADDR6* remote = node->v6_addrs; remote; remote = remote->next)
if (remote->protocol & TOPO_PROTO_UDP) return 1;
}
return 0;
}
int node_conn_direct_update_node(struct UTUN_INSTANCE* inst, uint64_t node_id) {

5
src/transport_layer/node_conn_direct.h

@ -44,8 +44,9 @@ struct ETCP_SOCKET;
/* ─── Opaque handle ─── */
struct NODE_CONN_DIRECT;
/* Совместимая пара адрес/сокет либо рабочий ETCP; без линков, handles, таймеров и сетевых проб.
* Использует тот же обход, что open, включая IPv6 и TCP без слушающего сокета. Не доказывает достижимость. */
/* Рабочий ETCP, совместимая исходящая пара либо возможность reverse на наш опубликованный адрес.
* Без линков/handles/таймеров/проб. Исходящие пары — тот же обход, что open; reverse — sock_match/публикуемые адреса.
* Учитывает IPv6 и исходящий TCP fallback; возможность попытки не доказывает достижимость. */
int node_conn_direct_compatible(struct UTUN_INSTANCE* inst, uint64_t node_id);
/* ─── Callback events (единый callback на handle) ─── */

Loading…
Cancel
Save