feat(NetworkConfigManager): improve IP address generation by passing used IPs to ensure uniqueness across tunnel creations; enhance error messaging for IP allocation failures
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m46s

This commit is contained in:
2026-01-22 21:17:50 +07:00
parent cd2c0d275e
commit ba0f0273e3
+9 -6
View File
@@ -536,7 +536,7 @@ function NetworkConfigManager() {
}
const newInterfaces = [];
const usedIps = new Set(getAllUsedIpsSet);
const usedIps = new Set(getAllUsedIpsSet); // Создаем Set с уже использованными IP из существующих интерфейсов
// Создаем туннели для каждой пары
templateServerPairs.forEach((pair, index) => {
@@ -560,15 +560,16 @@ function NetworkConfigManager() {
// Генерируем IP адреса (учитываем уже использованные в этой итерации)
// Важно: Local IP и Remote IP должны быть разными и в одной сети /30
// Передаем usedIps в функцию, чтобы она учитывала IP, выделенные для предыдущих туннелей
let localIp = null;
let remoteIp = null;
let attempts = 0;
const maxAttempts = 1000;
while ((!localIp || !remoteIp || localIp === remoteIp) && attempts < maxAttempts) {
const candidateLocal = generateFreePrivateIp(null, false, null, pairIpPoolId || null);
const candidateLocal = generateFreePrivateIp(null, false, null, pairIpPoolId || null, usedIps);
if (candidateLocal && !usedIps.has(candidateLocal)) {
const candidateRemote = generateFreePrivateIp(null, true, candidateLocal, pairIpPoolId || null);
const candidateRemote = generateFreePrivateIp(null, true, candidateLocal, pairIpPoolId || null, usedIps);
if (candidateRemote && !usedIps.has(candidateRemote) && candidateRemote !== candidateLocal) {
localIp = candidateLocal;
remoteIp = candidateRemote;
@@ -581,7 +582,7 @@ function NetworkConfigManager() {
}
if (!localIp || !remoteIp || localIp === remoteIp) {
notify.error(`Не удалось найти свободные IP адреса для туннеля ${index + 1} (${server1.dns || server1.ip}${server2.dns || server2.ip})`);
notify.error(`Не удалось найти свободные IP адреса для туннеля ${index + 1} (${server1.dns || server1.ip}${server2.dns || server2.ip}). Возможно, в пуле закончились свободные адреса.`);
return;
}
@@ -781,8 +782,10 @@ function NetworkConfigManager() {
// === Генерация свободного IP адреса из приватных диапазонов ===
// Генерирует IP в сетях /30 (четные базовые адреса)
// Если указан ipPoolId, использует IP пул, иначе использует приватные диапазоны RFC 1918
const generateFreePrivateIp = (excludeIp = null, forRemote = false, pairedLocalIp = null, ipPoolId = null) => {
const usedIps = new Set(getAllUsedIpsSet);
// usedIpsOverride - опциональный Set уже использованных IP (если не передан, создается копия getAllUsedIpsSet)
const generateFreePrivateIp = (excludeIp = null, forRemote = false, pairedLocalIp = null, ipPoolId = null, usedIpsOverride = null) => {
// Создаем копию Set, чтобы не модифицировать оригинальный
const usedIps = usedIpsOverride || new Set(getAllUsedIpsSet);
if (excludeIp) {
usedIps.delete(excludeIp.trim());
}