NAT/PAT Table Visualizer

NAT/PAT 表格視覺化器

模擬 PAT 負載映射、計算 NAT 表容量並可視化埠耗盡臨界值。

PAT 項目模擬器

模擬新增 NAT 項目,查看轉譯表如何增長。

埠耗盡參考
平台 PAT 埠範圍 每 IP 埠數 最大轉譯次數
Cisco IOS/IOS-XE 1024–65535 64,512 64,512 × outside IPs
Cisco ASA 1024–65535 (default) 64,512 受限於 xlate 表記憶體
Linux iptables/nftables 1024–65535 (default) 64,512 受限於 conntrack 表大小
Windows Server NAT 1025–5000 (legacy) / 1024–65535 63,511 透過登錄檔設定
RFC 4787 (BEHAVE) 建議保留來源埠 每個終端機對應埠
const PAT_PORTS = 64512; // 65535 - 1024 + 1 (ports 1024-65535) let natEntries = []; let nextPatPort = 1024; function calcPat() { const hosts = parseInt(document.getElementById('insideHosts').value); const ips = parseInt(document.getElementById('outsideIps').value); const sessPerHost = parseInt(document.getElementById('sessPerHost').value); const proto = document.getElementById('natProto').value; const section = document.getElementById('patResult'); const content = document.getElementById('patResultContent'); section.style.display = 'block'; if (isNaN(hosts) || isNaN(ips) || isNaN(sessPerHost) || hosts < 1 || ips < 1 || sessPerHost < 1) { content.innerHTML = '
Invalid input. All fields must be positive numbers.
'; return; } const poolSize = proto === 'both' ? PAT_PORTS * 2 * ips : PAT_PORTS * ips; const totalSessions = hosts * sessPerHost; const utilPct = Math.min((totalSessions / poolSize) * 100, 100); const isExhausted = totalSessions > poolSize; const overflow = isExhausted ? totalSessions - poolSize : 0; const barColor = utilPct > 90 ? '#dc3545' : utilPct > 70 ? '#f7971e' : '#4CAF50'; content.innerHTML = `
${poolSize.toLocaleString()}
Total PAT slots (pool)
${totalSessions.toLocaleString()}
Sessions required
${utilPct.toFixed(1)}%
Pool utilization
${isExhausted ? `
${overflow.toLocaleString()}
Sessions DROPPED (overflow)
` : ''}
${utilPct.toFixed(1)}%
${isExhausted ? `Port exhaustion! Need ${Math.ceil(totalSessions / PAT_PORTS)} outside IPs to support current session load.` : `Sufficient capacity. ${(poolSize - totalSessions).toLocaleString()} PAT slots remaining.`}
Formula: ${ips} IP(s) × ${proto === 'both' ? '2 × ' : ''}64,512 ports = ${poolSize.toLocaleString()} slots
`; } function addNatEntry() { const insideIp = document.getElementById('simInsideIp').value.trim(); const insidePort = parseInt(document.getElementById('simInsidePort').value); const outsideIp = document.getElementById('simOutsideIp').value.trim(); const dstIpPort = document.getElementById('simDstIpPort').value.trim(); if (!insideIp || !outsideIp || !dstIpPort || isNaN(insidePort)) { alert('Fill in all simulator fields.'); return; } const patPort = nextPatPort++; if (patPort > 65535) { alert('PAT pool exhausted (port 65535 reached).'); return; } natEntries.push({ insideIp, insidePort, outsideIp, patPort, dstIpPort, proto: 'TCP' }); renderNatTable(); // Auto-increment inside port for easy demo document.getElementById('simInsidePort').value = insidePort + 1; } function clearNatTable() { natEntries = []; nextPatPort = 1024; renderNatTable(); } function renderNatTable() { const div = document.getElementById('natTable'); const section = document.getElementById('natTableSection'); if (!natEntries.length) { section.style.display = 'none'; div.innerHTML = ''; return; } section.style.display = 'block'; let rows = natEntries.map((e, i) => ` ${i + 1} ${e.insideIp}:${e.insidePort} ${e.outsideIp}:${e.patPort} ${e.dstIpPort} ${e.proto} `).join(''); div.innerHTML = ` ${rows}
# Inside Local Inside Global (PAT) Destination Proto
${natEntries.length} entries | Next PAT port: ${nextPatPort}
`; }