{"id":9422,"date":"2026-08-10T13:37:14","date_gmt":"2026-08-10T11:37:14","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/"},"modified":"2026-08-10T13:45:06","modified_gmt":"2026-08-10T11:45:06","slug":"wireguard-allowedips-split-tunnel-calculator","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/","title":{"rendered":"Kalkulator AllowedIPs i tunelu dzielonego dla WireGuard"},"content":{"rendered":"<div class=\"gtm-analyser-container\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<p style=\"color: var(--text-secondary, #9aa0aa); margin-bottom: 20px;\">Ka\u017cdy peer WireGuard odpowiada na jedno pytanie: kt\u00f3re adresy docelowe nale\u017c\u0105 do tunelu. B\u0142\u0119dne AllowedIPs sprawiaj\u0105, \u017ce ruch albo wycieka poza tunel, albo znika w niew\u0142a\u015bciwym, zwykle bez \u017cadnego komunikatu o b\u0142\u0119dzie. Ten kalkulator obejmuje trzy cz\u0119\u015bci tego zadania.<\/p>\n<h3 style=\"color: var(--text-primary, #e8e8ee); font-size: 1.1rem; margin: 0 0 8px 0;\">1. Tunel dzielony: wycinanie sieci z zakresu<\/h3>\n<p style=\"color: var(--text-secondary, #9aa0aa); margin-bottom: 15px; font-size: 0.9rem;\">Podany zakres to ruch, kt\u00f3ry ma i\u015b\u0107 przez tunel, a wskazane sieci pozostaj\u0105 poza nim. Wynikiem jest najmniejszy mo\u017cliwy zbi\u00f3r blok\u00f3w CIDR obejmuj\u0105cy ca\u0142\u0105 reszt\u0119, gotowy do wklejenia za AllowedIPs.<\/p>\n<div style=\"display: flex; gap: 10px; align-items: flex-start; flex-wrap: wrap; margin-bottom: 15px;\">\n<div style=\"flex: 1; min-width: 220px;\">\n            <label style=\"color: var(--text-secondary, #9aa0aa); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Zakres ca\u0142kowity<\/label><br \/>\n            <input type=\"text\" id=\"wg-gesamt\" value=\"0.0.0.0\/0\" class=\"form-control\" style=\"width: 100%; padding: 12px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace;\">\n        <\/div>\n<div style=\"flex: 2; min-width: 260px;\">\n            <label style=\"color: var(--text-secondary, #9aa0aa); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Sieci do wykluczenia, po jednej w wierszu<\/label><br \/>\n            <textarea id=\"wg-ausnahmen\" rows=\"4\" class=\"form-control\" style=\"width: 100%; padding: 12px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; resize: vertical;\">10.0.0.0\/8<br \/>\n172.16.0.0\/12<br \/>\n192.168.0.0\/16<\/textarea>\n        <\/div>\n<\/p><\/div>\n<p>    <button id=\"wg-btn1\" class=\"button\" style=\"background: var(--accent, #4ade80); color: #0b1114; border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Obliczanie AllowedIPs<\/button><\/p>\n<div id=\"wg-ergebnis1\" style=\"margin-top: 20px;\"><\/div>\n<hr style=\"border: none; border-top: 1px solid var(--border, #2a2a35); margin: 30px 0;\">\n<h3 style=\"color: var(--text-primary, #e8e8ee); font-size: 1.1rem; margin: 0 0 8px 0;\">2. Nak\u0142adanie si\u0119 peer\u00f3w<\/h3>\n<p style=\"color: var(--text-secondary, #9aa0aa); margin-bottom: 15px; font-size: 0.9rem;\">AllowedIPs ka\u017cdego peera, po jednym peerze w wierszu: nazwa, dwukropek, nast\u0119pnie sieci oddzielone przecinkami.<\/p>\n<p>    <label style=\"color: var(--text-secondary, #9aa0aa); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Peery i ich AllowedIPs<\/label><br \/>\n    <textarea id=\"wg-peers\" rows=\"5\" class=\"form-control\" style=\"width: 100%; padding: 12px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; resize: vertical; margin-bottom: 15px;\">office: 10.0.0.0\/8, 192.168.1.0\/24<br \/>\nhome: 192.168.0.0\/16<br \/>\ncloud: 172.16.0.0\/12, 10.10.0.0\/16<br \/>\nbackup: 203.0.113.0\/24<\/textarea><\/p>\n<p>    <button id=\"wg-btn2\" class=\"button\" style=\"background: var(--accent, #4ade80); color: #0b1114; border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Sprawdzanie nak\u0142adania si\u0119<\/button><\/p>\n<div id=\"wg-ergebnis2\" style=\"margin-top: 20px;\"><\/div>\n<hr style=\"border: none; border-top: 1px solid var(--border, #2a2a35); margin: 30px 0;\">\n<h3 style=\"color: var(--text-primary, #e8e8ee); font-size: 1.1rem; margin: 0 0 8px 0;\">3. MTU tunelu<\/h3>\n<p style=\"color: var(--text-secondary, #9aa0aa); margin-bottom: 15px; font-size: 0.9rem;\">Tunel opakowuje ka\u017cdy pakiet dodatkowymi nag\u0142\u00f3wkami. Zbyt du\u017ce MTU tunelu powoduje fragmentacj\u0119 lub ciche odrzucanie pakiet\u00f3w, co objawia si\u0119 zwykle stronami, kt\u00f3re \u0142aduj\u0105 si\u0119 do po\u0142owy i zatrzymuj\u0105.<\/p>\n<div style=\"display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 15px;\">\n<div style=\"flex: 1; min-width: 180px;\">\n            <label style=\"color: var(--text-secondary, #9aa0aa); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Fizyczne MTU po\u0142\u0105czenia zewn\u0119trznego<\/label><br \/>\n            <input type=\"text\" id=\"wg-mtu\" value=\"1500\" class=\"form-control\" style=\"width: 100%; padding: 12px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace;\">\n        <\/div>\n<div style=\"flex: 1; min-width: 180px;\">\n            <label style=\"color: var(--text-secondary, #9aa0aa); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Wersja IP po\u0142\u0105czenia zewn\u0119trznego<\/label><br \/>\n            <select id=\"wg-version\" class=\"form-control\" style=\"width: 100%; padding: 12px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace;\"><option value=\"ipv4\">IPv4<\/option><option value=\"ipv6\">IPv6<\/option><\/select>\n        <\/div>\n<p>        <button id=\"wg-btn3\" class=\"button\" style=\"background: var(--accent, #4ade80); color: #0b1114; border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Obliczanie MTU<\/button>\n    <\/div>\n<div id=\"wg-ergebnis3\"><\/div>\n<\/div>\n<p><script>\n(function () {\n    \/\/ --- reine Rechenlogik, ohne jeden DOM-Zugriff ---<\/p>\n<p>    function ipZuZahl(text) {\n        const teile = String(text).trim().split('.');\n        if (teile.length !== 4) { return null; }\n        let wert = 0;\n        for (let i = 0; i < 4; i++) {\n            if (!\/^\\d{1,3}$\/.test(teile[i])) { return null; }\n            const n = parseInt(teile[i], 10);\n            if (n > 255) { return null; }\n            wert = wert * 256 + n;\n        }\n        return wert >>> 0;\n    }<\/p>\n<p>    function zahlZuIp(n) {\n        const a = Math.floor(n \/ 16777216) % 256;\n        const b = Math.floor(n \/ 65536) % 256;\n        const c = Math.floor(n \/ 256) % 256;\n        const d = n % 256;\n        return a + '.' + b + '.' + c + '.' + d;\n    }<\/p>\n<p>    function cidrText(block) {\n        return zahlZuIp(block.basis) + '\/' + block.praefix;\n    }<\/p>\n<p>    function formatZahl(n) {\n        return String(Math.round(n)).replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, ',');\n    }<\/p>\n<p>    function parseCidr(text) {\n        const roh = String(text).trim();\n        if (roh.length === 0) { return { fehler: 'leer', roh: roh }; }\n        const teile = roh.split('\/');\n        if (teile.length > 2) { return { fehler: 'cidr', roh: roh }; }\n        const adresse = ipZuZahl(teile[0]);\n        if (adresse === null) { return { fehler: 'cidr', roh: roh }; }\n        let praefix = 32;\n        if (teile.length === 2) {\n            const p = teile[1].trim();\n            if (!\/^\\d{1,3}$\/.test(p)) { return { fehler: 'praefix', roh: roh }; }\n            praefix = parseInt(p, 10);\n            if (praefix > 32) { return { fehler: 'praefix', roh: roh }; }\n        }\n        const groesse = Math.pow(2, 32 - praefix);\n        const basis = Math.floor(adresse \/ groesse) * groesse;\n        return {\n            fehler: null,\n            roh: roh,\n            basis: basis,\n            praefix: praefix,\n            groesse: groesse,\n            ende: basis + groesse - 1,\n            normalisiert: basis !== adresse\n        };\n    }<\/p>\n<p>    \/\/ rekursives Halbieren: Haelfte ganz ausserhalb -> behalten,\n    \/\/ ganz innerhalb einer Ausnahme -> verwerfen, sonst weiter teilen\n    function subtrahiere(basis, praefix, ausnahmen) {\n        const ergebnis = [];\n        let zaehler = 0;\n        let abbruch = false;<\/p>\n<p>        function schritt(b, p) {\n            if (abbruch) { return; }\n            zaehler = zaehler + 1;\n            if (zaehler > 200000) { abbruch = true; return; }\n            const groesse = Math.pow(2, 32 - p);\n            const ende = b + groesse - 1;\n            let ueberlappt = false;\n            for (let i = 0; i < ausnahmen.length; i++) {\n                const a = ausnahmen[i];\n                if (b >= a.basis && ende <= a.ende) { return; }\n                if (b <= a.ende &#038;&#038; ende >= a.basis) { ueberlappt = true; }\n            }\n            if (!ueberlappt) { ergebnis.push({ basis: b, praefix: p }); return; }\n            if (p >= 32) { return; }\n            schritt(b, p + 1);\n            schritt(b + groesse \/ 2, p + 1);\n        }<\/p>\n<p>        schritt(basis, praefix);\n        return { bloecke: ergebnis, abbruch: abbruch };\n    }<\/p>\n<p>    \/\/ benachbarte gleich grosse Bloecke wieder zusammenfassen\n    function fasseZusammen(bloecke) {\n        let liste = bloecke.slice().sort(function (x, y) {\n            if (x.basis !== y.basis) { return x.basis - y.basis; }\n            return x.praefix - y.praefix;\n        });\n        let geaendert = true;\n        while (geaendert) {\n            geaendert = false;\n            const neu = [];\n            let i = 0;\n            while (i < liste.length) {\n                const a = liste[i];\n                const b = i + 1 < liste.length ? liste[i + 1] : null;\n                if (b &#038;&#038; a.praefix === b.praefix &#038;&#038; a.praefix > 0) {\n                    const groesse = Math.pow(2, 32 - a.praefix);\n                    if (a.basis % (groesse * 2) === 0 && b.basis === a.basis + groesse) {\n                        neu.push({ basis: a.basis, praefix: a.praefix - 1 });\n                        i = i + 2;\n                        geaendert = true;\n                        continue;\n                    }\n                }\n                neu.push(a);\n                i = i + 1;\n            }\n            liste = neu;\n        }\n        return liste;\n    }<\/p>\n<p>    function formatiere(bloecke) {\n        return bloecke.map(cidrText).join(', ');\n    }<\/p>\n<p>    function berechne(gesamtText, ausnahmenText) {\n        const g = parseCidr(gesamtText);\n        if (g.fehler === 'leer') { return { fehler: { typ: 'leer' } }; }\n        if (g.fehler === 'praefix') { return { fehler: { typ: 'praefix', wert: g.roh } }; }\n        if (g.fehler) { return { fehler: { typ: 'cidr', wert: g.roh } }; }<\/p>\n<p>        const zeilen = String(ausnahmenText === undefined || ausnahmenText === null ? '' : ausnahmenText)\n            .split(\/[\\n\\r,;]+\/)\n            .map(function (t) { return t.trim(); })\n            .filter(function (t) { return t.length > 0; });<\/p>\n<p>        const ausnahmen = [];\n        const ignoriert = [];\n        const normalisiert = [];\n        if (g.normalisiert) { normalisiert.push({ von: g.roh, nach: cidrText(g) }); }<\/p>\n<p>        for (let i = 0; i < zeilen.length; i++) {\n            const a = parseCidr(zeilen[i]);\n            if (a.fehler === 'praefix') { return { fehler: { typ: 'praefix', wert: a.roh } }; }\n            if (a.fehler) { return { fehler: { typ: 'cidr', wert: a.roh } }; }\n            if (a.normalisiert) { normalisiert.push({ von: a.roh, nach: cidrText(a) }); }\n            if (a.ende < g.basis || a.basis > g.ende) { ignoriert.push(cidrText(a)); continue; }\n            ausnahmen.push(a);\n        }<\/p>\n<p>        const roh = subtrahiere(g.basis, g.praefix, ausnahmen);\n        if (roh.abbruch) { return { fehler: { typ: 'zuviel' } }; }\n        const bloecke = fasseZusammen(roh.bloecke);<\/p>\n<p>        let abgedeckt = 0;\n        for (let k = 0; k < bloecke.length; k++) {\n            abgedeckt = abgedeckt + Math.pow(2, 32 - bloecke[k].praefix);\n        }\n\n        return {\n            fehler: null,\n            gesamt: cidrText(g),\n            bloecke: bloecke,\n            allowedIPs: formatiere(bloecke),\n            anzahl: bloecke.length,\n            abgedeckt: abgedeckt,\n            gesamtGroesse: g.groesse,\n            ignoriert: ignoriert,\n            normalisiert: normalisiert\n        };\n    }\n\n    function lesePeers(text) {\n        const zeilen = String(text === undefined || text === null ? '' : text)\n            .split(\/[\\n\\r]+\/)\n            .map(function (t) { return t.trim(); })\n            .filter(function (t) { return t.length > 0; });<\/p>\n<p>        const peers = [];\n        for (let i = 0; i < zeilen.length; i++) {\n            const zeile = zeilen[i];\n            const pos = zeile.indexOf(':');\n            if (pos < 1) { return { fehler: { typ: 'name', wert: zeile } }; }\n            const name = zeile.slice(0, pos).trim();\n            if (name.length === 0) { return { fehler: { typ: 'name', wert: zeile } }; }\n            const teile = zeile.slice(pos + 1).split(',')\n                .map(function (t) { return t.trim(); })\n                .filter(function (t) { return t.length > 0; });\n            if (teile.length === 0) { return { fehler: { typ: 'ohnebereich', wert: name } }; }\n            const bereiche = [];\n            for (let j = 0; j < teile.length; j++) {\n                const c = parseCidr(teile[j]);\n                if (c.fehler === 'praefix') { return { fehler: { typ: 'praefix', wert: c.roh } }; }\n                if (c.fehler) { return { fehler: { typ: 'cidr', wert: c.roh } }; }\n                bereiche.push(c);\n            }\n            peers.push({ name: name, bereiche: bereiche });\n        }\n        if (peers.length < 2) { return { fehler: { typ: 'wenigpeers' } }; }\n        return { fehler: null, peers: peers };\n    }\n\n    \/\/ zwei IPv4-Bloecke sind entweder verschachtelt oder disjunkt:\n    \/\/ die Schnittmenge ist immer der spezifischere Block\n    function ueberschneidungen(peers) {\n        const paare = [];\n        for (let i = 0; i < peers.length; i++) {\n            for (let j = i + 1; j < peers.length; j++) {\n                const teile = [];\n                for (let x = 0; x < peers[i].bereiche.length; x++) {\n                    for (let y = 0; y < peers[j].bereiche.length; y++) {\n                        const a = peers[i].bereiche[x];\n                        const b = peers[j].bereiche[y];\n                        if (a.basis <= b.ende &#038;&#038; b.basis <= a.ende) {\n                            const enger = a.praefix >= b.praefix ? a : b;\n                            const t = cidrText(enger);\n                            if (teile.indexOf(t) === -1) { teile.push(t); }\n                        }\n                    }\n                }\n                if (teile.length > 0) {\n                    paare.push({ a: peers[i].name, b: peers[j].name, teile: teile });\n                }\n            }\n        }\n        return paare;\n    }<\/p>\n<p>    function mtuBerechnung(physisch, version) {\n        const roh = String(physisch === undefined || physisch === null ? '' : physisch).trim();\n        if (!\/^\\d{1,5}$\/.test(roh)) { return { fehler: { typ: 'mtu' } }; }\n        const n = parseInt(roh, 10);\n        if (n < 576 || n > 9200) { return { fehler: { typ: 'mtu' } }; }\n        const ipKopf = version === 'ipv6' ? 40 : 20;\n        const overhead = ipKopf + 8 + 32;\n        return {\n            fehler: null,\n            physisch: n,\n            ipKopf: ipKopf,\n            overhead: overhead,\n            tunnel: n - overhead,\n            version: version === 'ipv6' ? 'IPv6' : 'IPv4'\n        };\n    }<\/p>\n<p>    \/\/ fuer die Pruefung von aussen erreichbar\n    if (typeof window !== 'undefined') {\n        window.LW_TEST = window.LW_TEST || {};\n        window.LW_TEST.wg = {\n            berechne: berechne,\n            formatiere: formatiere,\n            ipZuZahl: ipZuZahl,\n            zahlZuIp: zahlZuIp,\n            parseCidr: parseCidr,\n            subtrahiere: subtrahiere,\n            fasseZusammen: fasseZusammen,\n            lesePeers: lesePeers,\n            ueberschneidungen: ueberschneidungen,\n            mtuBerechnung: mtuBerechnung\n        };\n    }<\/p>\n<p>    \/\/ --- DOM-Anbindung, sauber abgesichert ---<\/p>\n<p>    function esc(t) {\n        return String(t)\n            .replace(\/&\/g, '&amp;')\n            .replace(\/<\/g, '&lt;')\n            .replace(\/>\/g, '&gt;')\n            .replace(\/\"\/g, '&quot;');\n    }<\/p>\n<p>    const KASTEN = 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 6px; padding: 15px; margin-bottom: 12px;';\n    const MONO = 'font-family: monospace; color: var(--text-primary, #e8e8ee); word-break: break-all; line-height: 1.7;';\n    const KLEIN = 'color: var(--text-secondary, #9aa0aa); font-size: 0.8rem; margin: 0 0 6px 0; text-transform: uppercase; letter-spacing: 0.05em;';<\/p>\n<p>    function meldung(text) {\n        return '<\/p>\n<div style=\"' + KASTEN + ' border-color: var(--accent, #4ade80);\">' +\n            '<\/p>\n<p style=\"margin: 0; color: var(--text-primary, #e8e8ee);\">' + esc(text) + '<\/p>\n<\/div>\n<p>';\n    }<\/p>\n<p>    function fehlerText(f) {\n        if (f.typ === 'leer') { return 'Nale\u017cy poda\u0107 zakres ca\u0142kowity, na przyk\u0142ad 0.0.0.0\/0.'; }\n        if (f.typ === 'cidr') { return 'Nieprawid\u0142owy blok CIDR IPv4:' + ' ' + f.wert; }\n        if (f.typ === 'praefix') { return 'Prefiks musi by\u0107 liczb\u0105 od 0 do 32:' + ' ' + f.wert; }\n        if (f.typ === 'zuviel') { return 'Powstaje zbyt wiele blok\u00f3w do obliczenia. Potrzeba mniejszej liczby wyklucze\u0144 albo wyklucze\u0144 wi\u0119kszych.'; }\n        if (f.typ === 'name') { return 'Wiersz wymaga nazwy peera zako\u0144czonej dwukropkiem, na przyk\u0142ad office: 10.0.0.0\/8. Ten wiersz jej nie ma:' + ' ' + f.wert; }\n        if (f.typ === 'ohnebereich') { return 'Ten peer nie ma \u017cadnych sieci:' + ' ' + f.wert; }\n        if (f.typ === 'wenigpeers') { return 'Nale\u017cy poda\u0107 co najmniej dwa peery, po jednym w wierszu.'; }\n        if (f.typ === 'mtu') { return 'Fizyczne MTU nale\u017cy poda\u0107 jako liczb\u0119 ca\u0142kowit\u0105 od 576 do 9200.'; }\n        return 'Nieprawid\u0142owy blok CIDR IPv4:';\n    }<\/p>\n<p>    const btn = document.getElementById('wg-btn1');\n    const out = document.getElementById('wg-ergebnis1');\n    if (!btn || !out) { return; }\n    const btn2 = document.getElementById('wg-btn2');\n    const out2 = document.getElementById('wg-ergebnis2');\n    if (!btn2 || !out2) { return; }\n    const btn3 = document.getElementById('wg-btn3');\n    const out3 = document.getElementById('wg-ergebnis3');\n    if (!btn3 || !out3) { return; }<\/p>\n<p>    const feldGesamt = document.getElementById('wg-gesamt');\n    const feldAusnahmen = document.getElementById('wg-ausnahmen');\n    const feldPeers = document.getElementById('wg-peers');\n    const feldMtu = document.getElementById('wg-mtu');\n    const feldVersion = document.getElementById('wg-version');\n    if (!feldGesamt || !feldAusnahmen || !feldPeers || !feldMtu || !feldVersion) { return; }<\/p>\n<p>    btn.addEventListener('click', function () {\n        const r = berechne(feldGesamt.value, feldAusnahmen.value);\n        if (r.fehler) { out.innerHTML = meldung(fehlerText(r.fehler)); return; }\n        if (r.anzahl === 0) { out.innerHTML = meldung('Wykluczenia obejmuj\u0105 ca\u0142y zakres. Dla AllowedIPs nic nie pozostaje.'); return; }<\/p>\n<p>        let html = '<\/p>\n<div style=\"' + KASTEN + '\">' +\n            '<\/p>\n<p style=\"' + KLEIN + '\">AllowedIPs<\/p>\n<p>' +\n            '<\/p>\n<div style=\"' + MONO + '\">' + esc(r.allowedIPs) + '<\/div>\n<\/div>\n<p>';<\/p>\n<p>        const anteil = (r.abgedeckt \/ r.gesamtGroesse) * 100;\n        html += '<\/p>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap;\">' +\n            '<\/p>\n<div style=\"' + KASTEN + ' flex: 1; min-width: 150px;\">' +\n            '<\/p>\n<p style=\"' + KLEIN + '\">Bloki<\/p>\n<p>' +\n            '<\/p>\n<div style=\"' + MONO + ' font-size: 1.4rem;\">' + r.anzahl + '<\/div>\n<\/div>\n<p>' +\n            '<\/p>\n<div style=\"' + KASTEN + ' flex: 2; min-width: 220px;\">' +\n            '<\/p>\n<p style=\"' + KLEIN + '\">Obj\u0119te adresy<\/p>\n<p>' +\n            '<\/p>\n<div style=\"' + MONO + '\">' + formatZahl(r.abgedeckt) + ' \/ ' + formatZahl(r.gesamtGroesse) +\n            ' (' + anteil.toFixed(2) + ' %)<\/div>\n<\/div>\n<\/div>\n<p>';<\/p>\n<p>        if (r.normalisiert.length > 0) {\n            let zeilen = '';\n            for (let i = 0; i < r.normalisiert.length; i++) {\n                zeilen += '\n\n<div style=\"' + MONO + '\">' + esc(r.normalisiert[i].von) + ' &rarr; ' +\n                    esc(r.normalisiert[i].nach) + '<\/div>\n<p>';\n            }\n            html += '<\/p>\n<div style=\"' + KASTEN + '\">\n<p style=\"' + KLEIN + '\">Bity hosta wyzerowane<\/p>\n<p>' + zeilen + '<\/p><\/div>\n<p>';\n        }<\/p>\n<p>        if (r.ignoriert.length > 0) {\n            html += '<\/p>\n<div style=\"' + KASTEN + '\">\n<p style=\"' + KLEIN + '\">Pomini\u0119te, poza zakresem ca\u0142kowitym<\/p>\n<p>' +\n                '<\/p>\n<div style=\"' + MONO + '\">' + esc(r.ignoriert.join(', ')) + '<\/div>\n<\/div>\n<p>';\n        }<\/p>\n<p>        out.innerHTML = html;\n    });<\/p>\n<p>    btn2.addEventListener('click', function () {\n        const gelesen = lesePeers(feldPeers.value);\n        if (gelesen.fehler) { out2.innerHTML = meldung(fehlerText(gelesen.fehler)); return; }<\/p>\n<p>        const paare = ueberschneidungen(gelesen.peers);\n        if (paare.length === 0) { out2.innerHTML = meldung('Brak nak\u0142adania si\u0119. Ka\u017cdy adres pasuje najwy\u017cej do jednego peera.'); return; }<\/p>\n<p>        let html = '<\/p>\n<div style=\"' + KASTEN + '\">\n<p style=\"' + KLEIN + '\">Nak\u0142adaj\u0105ce si\u0119 peery<\/p>\n<p>';\n        html += '<\/p>\n<div style=\"display: flex; gap: 12px; ' + KLEIN + ' margin-top: 12px;\">' +\n            '<\/p>\n<div style=\"flex: 1;\">Para peer\u00f3w<\/div>\n<div style=\"flex: 1;\">Wsp\u00f3lne sieci<\/div>\n<\/div>\n<p>';\n        for (let i = 0; i < paare.length; i++) {\n            html += '\n\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap; padding: 8px 0; border-top: 1px solid var(--border, #2a2a35);\">' +\n                '<\/p>\n<div style=\"flex: 1; min-width: 160px; ' + MONO + '\">' + esc(paare[i].a) + ' &harr; ' + esc(paare[i].b) + '<\/div>\n<p>' +\n                '<\/p>\n<div style=\"flex: 1; min-width: 160px; ' + MONO + ' color: var(--accent, #4ade80);\">' +\n                esc(paare[i].teile.join(', ')) + '<\/div>\n<\/div>\n<p>';\n        }\n        html += '<\/p><\/div>\n<p>';\n        html += '<\/p>\n<div style=\"' + KASTEN + ' border-color: var(--accent, #4ade80);\">' +\n            '<\/p>\n<p style=\"' + KLEIN + '\">Dlaczego to wa\u017cne<\/p>\n<p>' +\n            '<\/p>\n<p style=\"margin: 0; color: var(--text-secondary, #9aa0aa);\">WireGuard wybiera peera, kt\u00f3rego AllowedIPs pasuj\u0105 jako ostatnie, a nie tego z najbardziej szczeg\u00f3\u0142owym dopasowaniem. Gdy dwa peery obejmuj\u0105 te same adresy, ruch po cichu trafia do niew\u0142a\u015bciwego tunelu i nic nie zg\u0142asza b\u0142\u0119du. Zakresy musz\u0105 by\u0107 roz\u0142\u0105czne.<\/p>\n<\/div>\n<p>';<\/p>\n<p>        out2.innerHTML = html;\n    });<\/p>\n<p>    btn3.addEventListener('click', function () {\n        const r = mtuBerechnung(feldMtu.value, feldVersion.value);\n        if (r.fehler) { out3.innerHTML = meldung(fehlerText(r.fehler)); return; }<\/p>\n<p>        const kopf = r.version === 'IPv6' ? '40 (IPv6) + 8 (UDP) + 32 (WireGuard)' : '20 (IPv4) + 8 (UDP) + 32 (WireGuard)';\n        let html = '<\/p>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap;\">' +\n            '<\/p>\n<div style=\"' + KASTEN + ' flex: 1; min-width: 180px;\">' +\n            '<\/p>\n<p style=\"' + KLEIN + '\">Zalecane MTU tunelu<\/p>\n<p>' +\n            '<\/p>\n<div style=\"' + MONO + ' font-size: 1.4rem; color: var(--accent, #4ade80);\">' + r.tunnel + ' Byte<\/div>\n<\/div>\n<p>' +\n            '<\/p>\n<div style=\"' + KASTEN + ' flex: 2; min-width: 240px;\">' +\n            '<\/p>\n<p style=\"' + KLEIN + '\">Jak to si\u0119 sumuje<\/p>\n<p>' +\n            '<\/p>\n<div style=\"' + MONO + '\">' + kopf + ' = ' + r.overhead + ' Byte<\/div>\n<p>' +\n            '<\/p>\n<div style=\"' + MONO + '\">' + r.physisch + ' &minus; ' + r.overhead + ' = ' + r.tunnel + ' Byte<\/div>\n<p>' +\n            '<\/p><\/div>\n<\/div>\n<p>' +\n            '<\/p>\n<div style=\"' + KASTEN + '\">\n<p style=\"' + KLEIN + '\">Wiersz do sekcji interface<\/p>\n<p>' +\n            '<\/p>\n<div style=\"' + MONO + '\">[Interface]<br \/>MTU = ' + r.tunnel + '<\/div>\n<\/div>\n<p>';<\/p>\n<p>        out3.innerHTML = html;\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ka\u017cdy peer WireGuard odpowiada na jedno pytanie: kt\u00f3re adresy docelowe nale\u017c\u0105 do tunelu. B\u0142\u0119dne AllowedIPs sprawiaj\u0105, \u017ce ruch albo wycieka poza tunel, albo znika w niew\u0142a\u015bciwym, zwykle bez \u017cadnego komunikatu o b\u0142\u0119dzie. Ten kalkulator obejmuje trzy cz\u0119\u015bci tego zadania. 1. Tunel dzielony: wycinanie sieci z zakresu Podany zakres to ruch, kt\u00f3ry ma i\u015b\u0107 przez tunel, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":9284,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"class_list":["post-9422","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Kalkulator AllowedIPs i tunelu dzielonego dla WireGuard - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Kalkulator AllowedIPs i tunelu dzielonego dla WireGuard - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Ka\u017cdy peer WireGuard odpowiada na jedno pytanie: kt\u00f3re adresy docelowe nale\u017c\u0105 do tunelu. B\u0142\u0119dne AllowedIPs sprawiaj\u0105, \u017ce ruch albo wycieka poza tunel, albo znika w niew\u0142a\u015bciwym, zwykle bez \u017cadnego komunikatu o b\u0142\u0119dzie. Ten kalkulator obejmuje trzy cz\u0119\u015bci tego zadania. 1. Tunel dzielony: wycinanie sieci z zakresu Podany zakres to ruch, kt\u00f3ry ma i\u015b\u0107 przez tunel, [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-10T11:45:06+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/wireguard-allowedips-split-tunnel-calculator\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/wireguard-allowedips-split-tunnel-calculator\\\/\",\"name\":\"Kalkulator AllowedIPs i tunelu dzielonego dla WireGuard - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-08-10T11:37:14+00:00\",\"dateModified\":\"2026-08-10T11:45:06+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/wireguard-allowedips-split-tunnel-calculator\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/wireguard-allowedips-split-tunnel-calculator\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/wireguard-allowedips-split-tunnel-calculator\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/toolbox-3\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Kalkulator AllowedIPs i tunelu dzielonego dla WireGuard\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Kalkulator AllowedIPs i tunelu dzielonego dla WireGuard - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/","og_locale":"en_US","og_type":"article","og_title":"Kalkulator AllowedIPs i tunelu dzielonego dla WireGuard - Lukas Wojcik - Blog","og_description":"Ka\u017cdy peer WireGuard odpowiada na jedno pytanie: kt\u00f3re adresy docelowe nale\u017c\u0105 do tunelu. B\u0142\u0119dne AllowedIPs sprawiaj\u0105, \u017ce ruch albo wycieka poza tunel, albo znika w niew\u0142a\u015bciwym, zwykle bez \u017cadnego komunikatu o b\u0142\u0119dzie. Ten kalkulator obejmuje trzy cz\u0119\u015bci tego zadania. 1. Tunel dzielony: wycinanie sieci z zakresu Podany zakres to ruch, kt\u00f3ry ma i\u015b\u0107 przez tunel, [&hellip;]","og_url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/","og_site_name":"Lukas Wojcik - Blog","article_modified_time":"2026-08-10T11:45:06+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/","url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/","name":"Kalkulator AllowedIPs i tunelu dzielonego dla WireGuard - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-08-10T11:37:14+00:00","dateModified":"2026-08-10T11:45:06+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/wireguard-allowedips-split-tunnel-calculator\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/toolbox-3\/"},{"@type":"ListItem","position":3,"name":"Kalkulator AllowedIPs i tunelu dzielonego dla WireGuard"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9422","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=9422"}],"version-history":[{"count":1,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9422\/revisions"}],"predecessor-version":[{"id":9440,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9422\/revisions\/9440"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9284"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=9422"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}