diff --git a/frontend/src/NetworkConfigManager.jsx b/frontend/src/NetworkConfigManager.jsx index 17f356d..93fd29e 100644 --- a/frontend/src/NetworkConfigManager.jsx +++ b/frontend/src/NetworkConfigManager.jsx @@ -982,15 +982,13 @@ function NetworkConfigManager() { // Проверяем, что IP входят в диапазон пула и отличаются if (!isIpInCidr(localIp, cidr)) continue; - if (isIpInCidr(remoteIp, cidr) && localIp !== remoteIp) { - if (prefix >= 30) { - if (!usedIps.has(localIp) && !usedIps.has(remoteIp)) { - return forRemote ? remoteIp : localIp; - } - } else { - if (!usedIps.has(localIp)) { - return localIp; - } + if (localIp === remoteIp) continue; + + // Для всех префиксов проверяем, что оба IP свободны (для туннелей нужны пары) + if (!usedIps.has(localIp) && !usedIps.has(remoteIp)) { + // Проверяем, что Remote IP тоже входит в пул (для префиксов >= 30 это всегда true) + if (prefix >= 30 || isIpInCidr(remoteIp, cidr)) { + return forRemote ? remoteIp : localIp; } } } @@ -3696,129 +3694,85 @@ function NetworkConfigManager() { ); })()} - {templateServer1 && templateServer2 && templateServer1 !== templateServer2 && (() => { - const server1 = getServerInfo(templateServer1); - const server2 = getServerInfo(templateServer2); - if (!server1 || !server2) return null; - - const autoName1 = generateInterfaceName(server1, server2, templateType, templateNamePrefix); - const autoName2 = generateInterfaceName(server2, server1, templateType, templateNamePrefix); - const previewName1 = templateName1.trim() || autoName1; - const previewName2 = templateName2.trim() || autoName2; - const previewLocalIp = generateFreePrivateIp(null, false, null, templateIpPoolId || null); - const previewRemoteIp = previewLocalIp ? generateFreePrivateIp(null, true, previewLocalIp, templateIpPoolId || null) : null; - - return ( - <> -
- - setTemplateName1(e.target.value)} - placeholder={autoName1} - /> -
Оставьте пустым для автогенерации
-
-
- - setTemplateName2(e.target.value)} - placeholder={autoName2} - /> -
Оставьте пустым для автогенерации
-
- {(templateType === 'IPSec' || templateType === 'GRE') && ( -
- -
- - -
-
- Выберите сохраненный IPSec пароль или создайте новый (опционально для GRE) -
-
- )} -
- - -
- Выберите IP пул для подбора адресов или оставьте автоматический подбор -
-
-
-
-
-
Предпросмотр интерфейса:
-
-
-
Сервер 1 ({server1.dns || server1.ip}):
-
Имя: {previewName1}
-
Local IP: {previewLocalIp || '—'}
-
-
-
Сервер 2 ({server2.dns || server2.ip}):
-
Имя: {previewName2}
-
Local IP: {previewRemoteIp || '—'}
-
- {previewLocalIp && previewRemoteIp && ( -
-
- {previewLocalIp} ↔ {previewRemoteIp} + {templateTunnelCount > 1 && templateServerPairs.length === templateTunnelCount && ( +
+ +
+ {templateServerPairs.map((pair, index) => { + const server1 = getServerInfo(pair.server1); + const server2 = getServerInfo(pair.server2); + if (!server1 || !server2 || !pair.server1 || !pair.server2 || pair.server1 === pair.server2) { + return null; + } + + const baseName1 = generateInterfaceName(server1, server2, templateType, templateNamePrefix); + const baseName2 = generateInterfaceName(server2, server1, templateType, templateNamePrefix); + const previewName1 = pair.name1?.trim() || baseName1; + const previewName2 = pair.name2?.trim() || baseName2; + + // Используем настройки из пары или глобальные для предпросмотра + const pairIpPoolId = pair.ipPoolId || templateIpPoolId; + + // Генерируем предпросмотр IP (используем временный Set для предпросмотра) + const previewUsedIps = new Set(getAllUsedIpsSet); + // Добавляем IP из предыдущих туннелей в предпросмотре + for (let i = 0; i < index; i++) { + const prevPair = templateServerPairs[i]; + if (prevPair.server1 && prevPair.server2) { + const prevPairIpPoolId = prevPair.ipPoolId || templateIpPoolId; + const prevPreviewLocal = generateFreePrivateIp(null, false, null, prevPairIpPoolId || null, previewUsedIps); + if (prevPreviewLocal) { + const prevPreviewRemote = generateFreePrivateIp(null, true, prevPreviewLocal, prevPairIpPoolId || null, previewUsedIps); + if (prevPreviewRemote && prevPreviewRemote !== prevPreviewLocal) { + previewUsedIps.add(prevPreviewLocal); + previewUsedIps.add(prevPreviewRemote); + } + } + } + } + + const previewLocalIp = generateFreePrivateIp(null, false, null, pairIpPoolId || null, previewUsedIps); + const previewRemoteIp = previewLocalIp ? generateFreePrivateIp(null, true, previewLocalIp, pairIpPoolId || null, previewUsedIps) : null; + + return ( +
+
+ Туннель {index + 1}: +
+
+
+
+
+ Сервер 1 ({server1.dns || server1.ip}): +
+
Имя: {previewName1}
+
Local IP: {previewLocalIp || '—'}
+
- )} +
+
+ Сервер 2 ({server2.dns || server2.ip}): +
+
Имя: {previewName2}
+
Local IP: {previewRemoteIp || '—'}
+
+
+
+ {previewLocalIp && previewRemoteIp && ( +
+ + {previewLocalIp} ↔ {previewRemoteIp} +
+ )} +
-
-
- - ); - })()} + ); + })} +
+
+ )}