etcp: exchange observed IPs on established TCP links
This commit is contained in:
1 parent
95f209d098
commit
5eb3526186
2 files changed
+52
No files matched your search
@@ -1262,6 +1262,29 @@ void etcp_link_close(struct ETCP_LINK* link) {
|
||||
|
||||
// ====== TCP link helpers ======
|
||||
|
||||
/* По готовому STCP сообщает пиру его фактический IP; исходящий порт не является портом listener. */
|
||||
static void tcp_send_observed_ip(struct ETCP_LINK *link) {
|
||||
struct UTUN_INSTANCE *inst = link->etcp->instance;
|
||||
if (!link->tcp_link || (!link->is_server && inst->config && inst->config->global.socks_enabled)) return;
|
||||
const struct sockaddr_storage *peer = stcp_link_get_peer_addr(link->tcp_link);
|
||||
if (!peer) { DEBUG_WARN(DEBUG_CATEGORY_NAT, "TCP IP report cannot read peer socket=%s", link->etcp->log_name); return; }
|
||||
struct ETCP_DGRAM *pkt = memory_pool_alloc(inst->pkt_pool);
|
||||
if (!pkt) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "TCP IP report allocation failed peer=%s", link->etcp->log_name); return; }
|
||||
pkt->link = link; pkt->data_len = 18; pkt->noencrypt_len = 0;
|
||||
memset(pkt->data, 0, pkt->data_len); pkt->data[0] = ETCP_TCP_ADDRESS;
|
||||
if (peer->ss_family == AF_INET) {
|
||||
pkt->data[1] = 4; memcpy(pkt->data + 2, &((const struct sockaddr_in *)peer)->sin_addr, 4);
|
||||
} else if (peer->ss_family == AF_INET6) {
|
||||
pkt->data[1] = 6; memcpy(pkt->data + 2, &((const struct sockaddr_in6 *)peer)->sin6_addr, 16);
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "TCP IP report unsupported family=%d", peer->ss_family);
|
||||
memory_pool_free(inst->pkt_pool, pkt); return;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "TCP IP report peer=%s observed=%s", link->etcp->log_name, sockaddr_storage_to_str(peer).str);
|
||||
if (etcp_encrypt_send(pkt) < 0) DEBUG_WARN(DEBUG_CATEGORY_NAT, "TCP IP report send failed");
|
||||
memory_pool_free(inst->pkt_pool, pkt);
|
||||
}
|
||||
|
||||
// Поднять TCP-линк в ready: синхронизация reset-эпохи (gop/rid), keepalive, ed25519,
|
||||
// mark initialized + link_status=1, уведомить коннект и loadbalancer.
|
||||
void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) {
|
||||
@@ -1297,6 +1320,7 @@ void etcp_link_enter_ready_tcp(struct ETCP_LINK *link) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[%s] TCP link %d UP (mtu=%d init=%d up=%d tcp_links=%d)",
|
||||
etcp->log_name, link->local_link_id, link->mtu,
|
||||
etcp->initialized, etcp->links_up, etcp->tcp_link_count);
|
||||
tcp_send_observed_ip(link);
|
||||
}
|
||||
|
||||
// Повторная попытка STCP-подключения с экспоненциальным backoff (до 30 с).
|
||||
@@ -2636,6 +2660,33 @@ int etcp_packet_decrypted(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt,
|
||||
|
||||
uint8_t pkt_code = pkt->data[0];
|
||||
|
||||
if (pkt_code == ETCP_TCP_ADDRESS) {
|
||||
struct UTUN_INSTANCE *inst = link->etcp->instance;
|
||||
static const uint8_t zero[12];
|
||||
if (!link->is_tcp || pkt->data_len != 18 ||
|
||||
(pkt->data[1] != 4 && pkt->data[1] != 6) ||
|
||||
(pkt->data[1] == 4 && memcmp(pkt->data + 6, zero, sizeof(zero)))) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_NAT, "TCP IP report invalid transport/format peer=%s size=%u",
|
||||
link->etcp->log_name, pkt->data_len);
|
||||
memory_pool_free(inst->pkt_pool, pkt); return 0;
|
||||
}
|
||||
if (!link->is_server && inst->config && inst->config->global.socks_enabled) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "TCP IP report ignored through SOCKS peer=%s", link->etcp->log_name);
|
||||
memory_pool_free(inst->pkt_pool, pkt); return 0;
|
||||
}
|
||||
struct sockaddr_storage observed = {0};
|
||||
if (pkt->data[1] == 4) {
|
||||
observed.ss_family = AF_INET; memcpy(&((struct sockaddr_in *)&observed)->sin_addr, pkt->data + 2, 4);
|
||||
} else {
|
||||
observed.ss_family = AF_INET6; memcpy(&((struct sockaddr_in6 *)&observed)->sin6_addr, pkt->data + 2, 16);
|
||||
}
|
||||
link->local_as_seen_by_peer = observed;
|
||||
const struct sockaddr_storage *local = stcp_link_get_local_addr(link->tcp_link);
|
||||
if (local && inst->nat_det && link->conn) nat_detection_tcp_observed(inst->nat_det, link, local, &observed);
|
||||
else if (!local) DEBUG_WARN(DEBUG_CATEGORY_NAT, "TCP IP report cannot read local socket peer=%s", link->etcp->log_name);
|
||||
memory_pool_free(inst->pkt_pool, pkt); return 0;
|
||||
}
|
||||
|
||||
#ifdef UTUN_HAVE_STANDBY
|
||||
{
|
||||
char who[256];
|
||||
|
||||
@@ -44,6 +44,7 @@ extern "C" {
|
||||
#define ETCP_PING 0x06
|
||||
#define ETCP_PONG 0x07
|
||||
#define ETCP_KEEPALIVE 0x08
|
||||
#define ETCP_TCP_ADDRESS 0x0d // STCP control: code + family(4/6) + observed IP(16), без порта
|
||||
|
||||
#define ETCP_PING_FLAG_WANT_RTT 0x01 // в PONG: хочу получить RTT от пингера
|
||||
#define ETCP_PING_FLAG_SEND_RTT 0x02 // в PING: несу RTT для получателя
|
||||
|
||||
Reference in new issue
Block a user