add CFG_SERVER_TYPE_LOCAL (type=local) and UNKNOWN semantics: PRIVATE/LOCAL hidden from nodeinfo, PRIVATE blocks incoming INIT, LOCAL accepts; UNKNOWN treated as PUBLIC; self-detection of PUBLIC IP on incoming INIT; filter LOCAL from NAT checks and connectivity
This commit is contained in:
1 parent
987c3ab01c
commit
efefe8ffaa
10 files changed
+77
-24
No files matched your search
@@ -136,7 +136,7 @@ link_state: 0=just init, 1=handshake, 2=reconnect, 3=connected.
|
||||
- local_link_id: uint8_t (0-255), назначается отправителем
|
||||
- sock_id: uint8_t, уникальный ID сокета отправителя
|
||||
- only_local: uint8_t, флаг "только локальные подключения"
|
||||
- type: uint8_t, тип сокета (CFG_SERVER_TYPE_PUBLIC/NAT/PRIVATE)
|
||||
- type: uint8_t, тип сокета (CFG_SERVER_TYPE_UNKNOWN=0/PUBLIC=1/NAT=2/PRIVATE=3/LOCAL=4)
|
||||
- random_padding: случайные байты до размера handshake (защита от fingerprinting)
|
||||
- salt + obfuscated_pubkey: публичный ключ с обфускацией (не шифруется AES,
|
||||
но скрывается XOR с salt и собственным публичным ключом). Передаётся в конце пакета
|
||||
|
||||
@@ -650,6 +650,8 @@ static int parse_server(const char *key, const char *value, struct CFG_SERVER *s
|
||||
srv->type = CFG_SERVER_TYPE_NAT;
|
||||
} else if (strcmp(value, "private") == 0) {
|
||||
srv->type = CFG_SERVER_TYPE_PRIVATE;
|
||||
} else if (strcmp(value, "local") == 0) {
|
||||
srv->type = CFG_SERVER_TYPE_LOCAL;
|
||||
} else {
|
||||
srv->type = CFG_SERVER_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
+3
-2
@@ -24,9 +24,10 @@ struct IP {
|
||||
};
|
||||
|
||||
#define CFG_SERVER_TYPE_UNKNOWN 0
|
||||
#define CFG_SERVER_TYPE_PUBLIC 1
|
||||
#define CFG_SERVER_TYPE_NAT 2
|
||||
#define CFG_SERVER_TYPE_PUBLIC 1
|
||||
#define CFG_SERVER_TYPE_NAT 2
|
||||
#define CFG_SERVER_TYPE_PRIVATE 3
|
||||
#define CFG_SERVER_TYPE_LOCAL 4
|
||||
|
||||
#define CFG_IPV6_MODE_NONE 0 // normal explicit address
|
||||
#define CFG_IPV6_MODE_TEMPORARY 1 // temporary IPv6 from interface
|
||||
|
||||
+12
-8
@@ -336,10 +336,10 @@ static void cm_idle_timer_cb(void* arg) {
|
||||
static int cm_nat_compatible(struct ETCP_SOCKET* our, uint8_t target_config_type, uint8_t target_nat_type) {
|
||||
uint8_t tt = target_nat_type >= NAT_VERIFIED_UNKNOWN ? CFG_SERVER_TYPE_PUBLIC : target_config_type;
|
||||
uint8_t ot = our->type;
|
||||
if (ot == CFG_SERVER_TYPE_PUBLIC) return 1;
|
||||
if (ot == CFG_SERVER_TYPE_PUBLIC || ot == CFG_SERVER_TYPE_UNKNOWN) return 1;
|
||||
if (ot == CFG_SERVER_TYPE_NAT && our->nat_type == NAT_VERIFIED_EIM && tt == CFG_SERVER_TYPE_PUBLIC) return 1;
|
||||
if (ot == CFG_SERVER_TYPE_NAT && our->nat_type == NAT_VERIFIED_EIM && tt == CFG_SERVER_TYPE_NAT) return 1;
|
||||
if (ot == CFG_SERVER_TYPE_PRIVATE && tt == CFG_SERVER_TYPE_PRIVATE) return 2;
|
||||
if ((ot == CFG_SERVER_TYPE_PRIVATE || ot == CFG_SERVER_TYPE_LOCAL) && tt == CFG_SERVER_TYPE_PRIVATE) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -376,7 +376,8 @@ static int cm_has_direct_ip(struct NODEINFO_Q* nq) {
|
||||
if (addrs[i].type == ADDR_TYPE_REAL || addrs[i].type == ADDR_TYPE_NAT) {
|
||||
for (int j = 0; j < meta_count; j++) {
|
||||
if (metas[j].id == addrs[i].socket_id &&
|
||||
(metas[j].config_type == CFG_SERVER_TYPE_PUBLIC || metas[j].nat_type == NAT_VERIFIED_EIM || metas[j].nat_type == NAT_VERIFIED_DIRECT))
|
||||
(metas[j].config_type == CFG_SERVER_TYPE_PUBLIC || metas[j].config_type == CFG_SERVER_TYPE_UNKNOWN
|
||||
|| metas[j].nat_type == NAT_VERIFIED_EIM || metas[j].nat_type == NAT_VERIFIED_DIRECT))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -393,7 +394,8 @@ static int cm_has_local_addr(struct NODEINFO_Q* nq) {
|
||||
for (int i = 0; i < addr_count; i++) {
|
||||
if (addrs[i].type == ADDR_TYPE_INTERFACE) {
|
||||
for (int j = 0; j < meta_count; j++) {
|
||||
if (metas[j].id == addrs[i].socket_id && metas[j].config_type == CFG_SERVER_TYPE_PRIVATE)
|
||||
if (metas[j].id == addrs[i].socket_id &&
|
||||
(metas[j].config_type == CFG_SERVER_TYPE_PRIVATE || metas[j].config_type == CFG_SERVER_TYPE_LOCAL))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -424,10 +426,11 @@ static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) {
|
||||
for (int i = 0; i < addr_count; i++) {
|
||||
if (addrs[i].type != ADDR_TYPE_INTERFACE) continue;
|
||||
for (int j = 0; j < meta_count; j++) {
|
||||
if (metas[j].id != addrs[i].socket_id || metas[j].config_type != CFG_SERVER_TYPE_PRIVATE) continue;
|
||||
if (metas[j].id != addrs[i].socket_id ||
|
||||
(metas[j].config_type != CFG_SERVER_TYPE_PRIVATE && metas[j].config_type != CFG_SERVER_TYPE_LOCAL)) continue;
|
||||
struct ETCP_SOCKET* s = entry->mgr->instance->etcp_sockets;
|
||||
while (s) {
|
||||
if (s->type == CFG_SERVER_TYPE_PRIVATE && s->local_addr.ss_family == AF_INET) {
|
||||
if ((s->type == CFG_SERVER_TYPE_PRIVATE || s->type == CFG_SERVER_TYPE_LOCAL) && s->local_addr.ss_family == AF_INET) {
|
||||
struct sockaddr_in sin;
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
@@ -589,7 +592,8 @@ static void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry) {
|
||||
if (addrs[i].type != ADDR_TYPE_REAL && addrs[i].type != ADDR_TYPE_NAT) continue;
|
||||
for (int j = 0; j < meta_count; j++) {
|
||||
if (metas[j].id == addrs[i].socket_id &&
|
||||
(metas[j].config_type == CFG_SERVER_TYPE_PUBLIC || metas[j].nat_type == NAT_VERIFIED_EIM || metas[j].nat_type == NAT_VERIFIED_DIRECT)) {
|
||||
(metas[j].config_type == CFG_SERVER_TYPE_PUBLIC || metas[j].config_type == CFG_SERVER_TYPE_UNKNOWN
|
||||
|| metas[j].nat_type == NAT_VERIFIED_EIM || metas[j].nat_type == NAT_VERIFIED_DIRECT)) {
|
||||
out_addrs[direct_count].type = addrs[i].type;
|
||||
memcpy(out_addrs[direct_count].ip, addrs[i].addr, 4);
|
||||
out_addrs[direct_count].port = htons(addrs[i].port);
|
||||
@@ -852,7 +856,7 @@ static void cm_handle_direct_req(struct ETCP_CONN* conn, const uint8_t* data, si
|
||||
(void)sock_id; (void)type;
|
||||
struct ETCP_SOCKET* s = conn->instance->etcp_sockets;
|
||||
while (s) {
|
||||
if (s->type == CFG_SERVER_TYPE_PUBLIC && s->local_addr.ss_family == AF_INET) {
|
||||
if ((s->type == CFG_SERVER_TYPE_PUBLIC || s->type == CFG_SERVER_TYPE_UNKNOWN) && s->local_addr.ss_family == AF_INET) {
|
||||
struct sockaddr_in sin;
|
||||
memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET;
|
||||
memcpy(&sin.sin_addr.s_addr, ip, 4); sin.sin_port = port;
|
||||
|
||||
@@ -1294,6 +1294,33 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk
|
||||
link->etcp->log_name);
|
||||
}
|
||||
}
|
||||
/* Self-detection: if my IP is non-local, I'm on a public IP */
|
||||
if (e_sock->nat_type != NAT_VERIFIED_DIRECT && e_sock->local_addr.ss_family == AF_INET) {
|
||||
uint32_t my_ip = ((struct sockaddr_in*)&e_sock->local_addr)->sin_addr.s_addr;
|
||||
if (my_ip != 0 && !is_local_subnet(my_ip)) {
|
||||
e_sock->nat_type = NAT_VERIFIED_DIRECT;
|
||||
struct sockaddr_in* nat_sin = (struct sockaddr_in*)&e_sock->nat_addr;
|
||||
nat_sin->sin_family = AF_INET;
|
||||
nat_sin->sin_addr.s_addr = my_ip;
|
||||
nat_sin->sin_port = ((struct sockaddr_in*)&e_sock->local_addr)->sin_port;
|
||||
if (link->etcp->instance->bgp) {
|
||||
route_bgp_update_my_nodeinfo(link->etcp->instance->bgp->instance, link->etcp->instance->bgp);
|
||||
struct ROUTE_BGP* bgp = link->etcp->instance->bgp;
|
||||
if (bgp->local_node && bgp->senders_list) {
|
||||
bgp->local_node->node.ver = (bgp->local_node->node.ver % 255) + 1;
|
||||
bgp->local_node->dirty = 1;
|
||||
struct ll_entry* se = bgp->senders_list->head;
|
||||
while (se) {
|
||||
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data;
|
||||
if (item && item->conn) route_bgp_send_nodeinfo(bgp->local_node, item->conn);
|
||||
se = se->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "Self-detected PUBLIC IP: %s on socket %s (id=%d)",
|
||||
ip_to_str(&my_ip, AF_INET).str, e_sock->name, e_sock->sock_id);
|
||||
}
|
||||
}
|
||||
pkt->noencrypt_len=0;
|
||||
pkt->link=link;
|
||||
link->recv_keepalive = 1;
|
||||
@@ -1565,6 +1592,11 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
|
||||
errorcode=4;
|
||||
goto ec_fr;
|
||||
}// не init
|
||||
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "INIT rejected: socket %s (type=PRIVATE) does not accept incoming connections", e_sock->name);
|
||||
errorcode=8;
|
||||
goto ec_fr;
|
||||
}
|
||||
if (pkt_len < ETCP_INIT_REQ_V1_SIZE) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "INIT REQUEST too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(&addr).str);
|
||||
errorcode=7;
|
||||
|
||||
+4
-3
@@ -645,7 +645,8 @@ static struct ETCP_CONN* route_bgp_find_third_node(struct ROUTE_BGP* bgp, struct
|
||||
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data;
|
||||
if (item && item->conn && item->conn != exclude && item->conn->links && item->conn->links->remote_only_local==0) {
|
||||
// Skip nodes with private socket type - they can't help with NAT detection
|
||||
if (item->conn->links->remote_type != CFG_SERVER_TYPE_PRIVATE) return item->conn;
|
||||
if (item->conn->links->remote_type != CFG_SERVER_TYPE_PRIVATE
|
||||
&& item->conn->links->remote_type != CFG_SERVER_TYPE_LOCAL) return item->conn;
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
@@ -671,8 +672,8 @@ void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* lin
|
||||
if (link->nat_type == NAT_TYPE_DIRECT) return;
|
||||
if (link->nat_check_status == NAT_CHECK_IN_PROGRESS) return;
|
||||
// Skip NAT check for private sockets - they are not reachable from outside
|
||||
if (link->conn->type == CFG_SERVER_TYPE_PRIVATE) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "skip nat check for private socket link");
|
||||
if (link->conn->type == CFG_SERVER_TYPE_PRIVATE || link->conn->type == CFG_SERVER_TYPE_LOCAL) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "skip nat check for private/local socket link");
|
||||
return;
|
||||
}
|
||||
// Find third node to send ping through
|
||||
|
||||
@@ -124,14 +124,15 @@ static int conn_match_candidate_sockets(struct UTUN_INSTANCE* instance,
|
||||
uint32_t if_ip = if_sin->sin_addr.s_addr;
|
||||
|
||||
if (addr_type == ADDR_TYPE_INTERFACE) {
|
||||
// предпочитаем PRIVATE сокеты в той же /24 подсети
|
||||
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE && (if_ip & 0x00FFFFFF) == (target_ip & 0x00FFFFFF))
|
||||
// предпочитаем PRIVATE/LOCAL сокеты в той же /24 подсети
|
||||
if ((e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL)
|
||||
&& (if_ip & 0x00FFFFFF) == (target_ip & 0x00FFFFFF))
|
||||
match = 1;
|
||||
} else {
|
||||
// NAT или REAL: предпочитаем DIRECT > EIM > PUBLIC
|
||||
// NAT или REAL: предпочитаем DIRECT > EIM > PUBLIC/UNKNOWN
|
||||
if (e_sock->nat_type == NAT_VERIFIED_DIRECT) match = 1;
|
||||
else if (e_sock->nat_type == NAT_VERIFIED_EIM) match = 1;
|
||||
else if (e_sock->type == CFG_SERVER_TYPE_PUBLIC) match = 1;
|
||||
else if (e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) match = 1;
|
||||
}
|
||||
|
||||
if (match) {
|
||||
@@ -150,10 +151,12 @@ static int conn_match_candidate_sockets(struct UTUN_INSTANCE* instance,
|
||||
for (int i = 0; i < found; i++) if (out_sockets[i] == e_sock) { dup = 1; break; }
|
||||
if (!dup) {
|
||||
if (addr_type == ADDR_TYPE_INTERFACE) {
|
||||
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE) out_sockets[found++] = e_sock;
|
||||
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL)
|
||||
out_sockets[found++] = e_sock;
|
||||
} else {
|
||||
// любой не-private
|
||||
if (e_sock->type != CFG_SERVER_TYPE_PRIVATE) out_sockets[found++] = e_sock;
|
||||
// любой не-private и не-local
|
||||
if (e_sock->type != CFG_SERVER_TYPE_PRIVATE && e_sock->type != CFG_SERVER_TYPE_LOCAL)
|
||||
out_sockets[found++] = e_sock;
|
||||
}
|
||||
}
|
||||
e_sock = e_sock->next;
|
||||
|
||||
+9
-2
@@ -444,6 +444,7 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
|
||||
int sock6_count = 0, addr6_count = 0;
|
||||
struct ETCP_SOCKET* e_sock = instance->etcp_sockets;
|
||||
while (e_sock) {
|
||||
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; }
|
||||
if (e_sock->local_addr.ss_family == AF_INET) {
|
||||
sock_count++;
|
||||
addr_count++; // INTERFACE
|
||||
@@ -454,7 +455,8 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
|
||||
}
|
||||
}
|
||||
if (e_sock->nat_type == NAT_VERIFIED_DIRECT ||
|
||||
(e_sock->type == CFG_SERVER_TYPE_PUBLIC && e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) addr_count++;
|
||||
((e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN)
|
||||
&& e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) addr_count++;
|
||||
} else if (e_sock->local_addr.ss_family == AF_INET6) {
|
||||
sock6_count++;
|
||||
addr6_count++; // INTERFACE only (no NAT for IPv6)
|
||||
@@ -516,6 +518,7 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
|
||||
e_sock = instance->etcp_sockets;
|
||||
int midx = 0;
|
||||
while (e_sock) {
|
||||
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; }
|
||||
if (e_sock->local_addr.ss_family == AF_INET) {
|
||||
meta[midx].id = e_sock->sock_id;
|
||||
meta[midx].config_type = e_sock->type;
|
||||
@@ -531,6 +534,7 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
|
||||
int aidx = 0;
|
||||
e_sock = instance->etcp_sockets;
|
||||
while (e_sock) {
|
||||
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; }
|
||||
if (e_sock->local_addr.ss_family == AF_INET) {
|
||||
struct sockaddr_in* if_sin = (struct sockaddr_in*)&e_sock->interface_addr;
|
||||
struct sockaddr_in* nat_sin = (struct sockaddr_in*)&e_sock->nat_addr;
|
||||
@@ -551,7 +555,8 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
|
||||
}
|
||||
}
|
||||
if (e_sock->nat_type == NAT_VERIFIED_DIRECT ||
|
||||
(e_sock->type == CFG_SERVER_TYPE_PUBLIC && e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) {
|
||||
((e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN)
|
||||
&& e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) {
|
||||
memcpy(addrs[aidx].addr, &if_sin->sin_addr.s_addr, 4);
|
||||
addrs[aidx].port = ntohs(if_sin->sin_port);
|
||||
addrs[aidx].type = ADDR_TYPE_REAL;
|
||||
@@ -568,6 +573,7 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
|
||||
e_sock = instance->etcp_sockets;
|
||||
int m6idx = 0;
|
||||
while (e_sock) {
|
||||
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; }
|
||||
if (e_sock->local_addr.ss_family == AF_INET6) {
|
||||
meta6[m6idx].id = e_sock->sock_id;
|
||||
meta6[m6idx].config_type = e_sock->type;
|
||||
@@ -583,6 +589,7 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG
|
||||
int a6idx = 0;
|
||||
e_sock = instance->etcp_sockets;
|
||||
while (e_sock) {
|
||||
if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; }
|
||||
if (e_sock->local_addr.ss_family == AF_INET6) {
|
||||
struct sockaddr_in6* if_sin6 = (struct sockaddr_in6*)&e_sock->interface_addr;
|
||||
memcpy(addrs6[a6idx].addr, &if_sin6->sin6_addr, 16);
|
||||
|
||||
@@ -1535,7 +1535,9 @@ static const char* config_type_to_string(uint8_t config_type) {
|
||||
case CFG_SERVER_TYPE_PUBLIC: return "PUBLIC";
|
||||
case CFG_SERVER_TYPE_NAT: return "NAT";
|
||||
case CFG_SERVER_TYPE_PRIVATE: return "Private";
|
||||
default: return "Unknown";
|
||||
case CFG_SERVER_TYPE_LOCAL: return "Local";
|
||||
case CFG_SERVER_TYPE_UNKNOWN: return "Unknown";
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ extern "C" {
|
||||
#define CFG_SERVER_TYPE_PUBLIC 1
|
||||
#define CFG_SERVER_TYPE_NAT 2
|
||||
#define CFG_SERVER_TYPE_PRIVATE 3
|
||||
#define CFG_SERVER_TYPE_LOCAL 4
|
||||
#define ETCPMON_MAX_MSG_SIZE 32768
|
||||
#define ETCPMON_MAX_CONN_NAME 32
|
||||
#define ETCPMON_MAX_CONNECTIONS 250
|
||||
|
||||
Reference in new issue
Block a user