সরাসরি পর্বে যান
পর্ব ৪৯ · ৬২-এর মধ্যে · মডিউল ৮

Firewall আর VPN — nftables, IPsec আর WireGuard

Firewalls and VPNs — ACLs, Stateful Inspection & Conntrack, DMZ, Linux nftables, IPsec (AH/ESP/IKEv2) & WireGuard

Taught in Bangla, this lesson covers firewalls and VPNs: what a firewall inspects, stateless packet filters and first-match ACLs, stateful inspection with conntrack states, proxies, NGFWs and DMZ placement, Linux netfilter hooks and nftables, VPN tunnels with overhead and MTU calculation, IPsec with AH, ESP, security associations and IKEv2, WireGuard peers and AllowedIPs, split tunnelling and DNS leaks.

এই পর্বে যা শিখবেন

  • Stateless ACL হাতে মেলানো (first match, implicit deny) আর stateful firewall-এর conntrack অবস্থাগুলো
  • Firewall কোথায় বসে — host, perimeter, DMZ, ভেতরের ভাগ — আর বাইরে যাওয়া ট্রাফিকের নিয়ম কেন জরুরি
  • Linux-এর netfilter hook আর একটি পূর্ণ, নিরাপদ nftables ruleset লাইন ধরে ধরে; iptables, ufw, Windows আর cloud-এর সমতুল্য
  • VPN-এর tunnel, overhead আর MTU/MSS-এর হিসাব; IPsec-এর AH, ESP, SA, IKEv2 আর NAT-T
  • WireGuard-এর cryptokey routing, একটি দুই-peer কনফিগারেশন, split tunnel, DNS leak আর zero trust

১ · Firewall কী দেখে সিদ্ধান্ত নেয়

একটি অফিস ভবনের গেটে দারোয়ান বসে আছেন। তাঁর হাতে একটি খাতা: “হিসাব বিভাগের লোক ঢুকবেন”, “বাইরের মানুষ শুধু রিসেপশন পর্যন্ত”, “রাত ১০টার পর কেউ নয়”। কেউ এলে তিনি দেখেন — কে, কোথা থেকে, কার কাছে যাবেন — তারপর খাতা মিলিয়ে ঢুকতে দেন বা ফেরত পাঠান। নেটওয়ার্কে এই দারোয়ানের নাম firewall, আর তাঁর খাতা হলো নিয়মের তালিকা (ruleset).

পর্ব ৪৬-এ (নেটওয়ার্ক নিরাপত্তার ভিত্তি) নিরাপত্তার স্তর, zone আর “যা স্পষ্টভাবে অনুমোদিত নয়, তা নিষিদ্ধ” নীতির কথা এসেছে। এই পর্বে দেখব সেই নীতি যন্ত্রে কীভাবে বসে। একটি firewall প্রতিটি packet নিয়ে সাধারণত চার ধরনের তথ্য দেখে:

ঠিকানা আর port

Protocol, উৎস IP, উৎস port, গন্তব্য IP, গন্তব্য port — 5-tuple. “কে, কাকে, কোন সেবায়”-এর উত্তর।

layer 3–4

Interface

Packet কোন interface দিয়ে ঢুকল আর কোনটি দিয়ে বেরোবে — LAN, WAN না DMZ. একই ঠিকানা ভুল দরজা দিয়ে এলে সন্দেহজনক।

কোন দরজা

দিক

ভেতরে আসছে (inbound), বাইরে যাচ্ছে (outbound), নাকি যন্ত্রটি শুধু পার করে দিচ্ছে (forward).

direction

অবস্থা

এটি কি নতুন কথোপকথনের প্রথম packet, নাকি আগে থেকে চলা কথোপকথনের উত্তর? এই প্রশ্নই stateful firewall-কে আলাদা করে (অংশ ৩)।

state

সিদ্ধান্তও মূলত তিন রকম: accept (যেতে দেওয়া), drop (নীরবে ফেলে দেওয়া — প্রেরক timeout পর্যন্ত অপেক্ষা করে), আর reject (ফেলে দিয়ে প্রেরককে TCP RST বা ICMP “unreachable” দিয়ে জানানো)। নিজের নেটওয়ার্কের ভেতরে reject ভুল তাড়াতাড়ি ধরায়; ইন্টারনেটমুখী দিকে অনেকে drop পছন্দ করেন — একমাত্র “সঠিক” উত্তর নেই।

১৯৮৮ সালের Morris worm কয়েক হাজার ইন্টারনেট-যুক্ত কম্পিউটার অচল করে দেয় — বোঝা গেল সব যন্ত্র সবার কাছে খোলা রাখা যায় না। নব্বইয়ের দশকের শুরুতে router-এ packet filter আর প্রথম বাণিজ্যিক firewall আসে; ১৯৯৪ সালে Cheswick আর Bellovin-এর বই “Firewalls and Internet Security” ধারণাগুলো গুছিয়ে দেয়, আর Check Point-এর FireWall-1 “stateful inspection” জনপ্রিয় করে। Linux-এ এসেছে ipfwadm, ipchains, তারপর Linux 2.4-এর (২০০১) netfilter/iptables, আর ২০১৪ সালে Linux 3.13-এ nftables.

২ · Stateless packet filter আর ACL — উপর থেকে নিচে, প্রথম মিলেই থামা

সবচেয়ে পুরোনো আর সরল firewall হলো stateless packet filter: প্রতিটি packet-কে আলাদাভাবে দেখে, আগের কোনো packet মনে রাখে না। Router আর switch-এ এর নিয়মের তালিকাকে বলে ACL (access control list). ACL পড়ার তিনটি সোনালি নিয়ম প্রায় সব vendor-এ এক:

  1. উপর থেকে নিচে: নিয়মগুলো লেখা ক্রমেই পরীক্ষা হয়।
  2. প্রথম মিলেই থামা (first match): যে নিয়ম প্রথম মেলে তার সিদ্ধান্তই চূড়ান্ত; নিচের নিয়ম আর দেখা হয় না।
  3. শেষে অদৃশ্য “সব বাতিল”: কোনো নিয়মই না মিললে packet বাতিল — একে বলে implicit deny. তালিকায় এটি লেখা থাকে না, কিন্তু থাকে।

ঢাকার একটি মোড়ে ট্রাফিক পুলিশের হাতে একটি তালিকা: “১. ট্রাক ঢুকবে না, ২. বাস ঢুকবে, ৩. সাদা গাড়ি ঢুকবে।” একটি সাদা ট্রাক এল — প্রথম লাইনেই “ট্রাক” মিলে গেল, তাই ফেরত। তিন নম্বর লাইনের “সাদা গাড়ি” তিনি দেখবেনই না। আর একটি রিকশা এলে? কোনো লাইনই মেলে না — তালিকায় না থাকা মানেই ঢোকা নিষেধ।

একটি পরীক্ষা-ধরনের ACL — হাতে মেলানো

একটি router-এর একটি interface-এ ঢোকা ট্রাফিকের জন্য এই পাঁচটি নিয়ম। সার্ভারগুলো 10.1.1.0/24-এ: ওয়েব সার্ভার 10.1.1.10, DNS সার্ভার 10.1.1.53.

#সিদ্ধান্তProtocolউৎসগন্তব্যগন্তব্য port
১denytcp192.168.10.0/2410.1.1.0/2423 (Telnet)
২permittcp192.168.10.0/2410.1.1.10/3280
৩permittcp192.168.0.0/16any443
৪denyip (সব)192.168.20.0/2410.1.1.0/24—
৫permitudpany10.1.1.53/3253
—deny (অদৃশ্য)সবanyany—

এবার একটি packet ধরি: TCP, উৎস 192.168.20.7, গন্তব্য 10.1.1.10:443. নিয়ম ৪ দেখে মনে হয় “192.168.20.x-এর সবকিছু বাতিল” — কিন্তু ক্রম মেনে দেখুন কী হয়।

  1. Packettcp .20.7 → .10:443ঢুকছে
  2. নিয়ম ১উৎস মেলে নাপরের নিয়ম
  3. নিয়ম ২উৎস মেলে নাপরের নিয়ম
  4. নিয়ম ৩সব মেলেPERMIT
  5. নিয়ম ৪, ৫দেখাই হয় নাথেমে গেছে
মেলানোর হিসাব
এখন দেখা হচ্ছে
Protocol │ উৎস │ গন্তব্য │ port
ফল
  1. Packet এল। TCP, উৎস 192.168.20.7, গন্তব্য 10.1.1.10, গন্তব্য port 443 (HTTPS). Router এখন তালিকার একদম ওপর থেকে শুরু করবে।
  2. নিয়ম ১ মেলে না। Protocol TCP মিলেছে, গন্তব্য 10.1.1.0/24-এর মধ্যেও আছে, কিন্তু উৎস 192.168.10.0/24 নয় (তৃতীয় অক্টেট ২০, ১০ নয়), আর port-ও ২৩ নয়। একটি শর্ত না মিললেই পুরো নিয়ম বাদ।
  3. নিয়ম ২-ও মেলে না। আবার উৎসের ব্লক আলাদা, আর port ৮০ নয়। এখনো কোনো সিদ্ধান্ত হয়নি।
  4. নিয়ম ৩ মিলে গেল — PERMIT. 192.168.0.0/16 মানে প্রথম দুই অক্টেট 192.168, বাকি যা খুশি — 192.168.20.7 এর মধ্যে পড়ে। গন্তব্য any, port 443 — সব শর্ত পূরণ। Packet অনুমতি পেল, আর মেলানো এখানেই থামল।
  5. নিয়ম ৪ কখনো দেখাই হলো না। লেখকের ইচ্ছা হয়তো ছিল “192.168.20.0/24 সার্ভারে কিছুই পাবে না” — কিন্তু নিয়ম ৩ আগে থাকায় তাদের HTTPS চলে যাচ্ছে। এই “ছায়া পড়া” নিয়ম (shadowed rule) বাস্তবের firewall-এ খুব সাধারণ ভুল। সমাধান: নির্দিষ্ট নিয়ম ওপরে, সাধারণ নিয়ম নিচে।

এবার পুরো পরীক্ষাটি একটি ছোট simulator-এ — সাতটি packet, প্রতিটির জন্য কোন নিয়ম মিলল আর কী সিদ্ধান্ত। খাতায় আগে নিজে উত্তর লিখে তারপর চালিয়ে দেখুন।

// Stateless ACL: rules checked top-down, first match wins, implicit deny at the end.
const ip = s => s.split(".").reduce((a, o) => a * 256 + Number(o), 0);
const inPfx = (addr, pfx) => {                       // "any" or "a.b.c.d/len"
  if (pfx === "any") return true;
  const [net, len] = pfx.split("/"), size = 2 ** (32 - Number(len));
  return Math.floor(ip(addr) / size) === Math.floor(ip(net) / size);
};
const ACL = [   // [action, proto, source, destination, dst port]
  ["deny",   "tcp", "192.168.10.0/24", "10.1.1.0/24",  23],
  ["permit", "tcp", "192.168.10.0/24", "10.1.1.10/32", 80],
  ["permit", "tcp", "192.168.0.0/16",  "any",          443],
  ["deny",   "ip",  "192.168.20.0/24", "10.1.1.0/24",  null],
  ["permit", "udp", "any",             "10.1.1.53/32", 53],
];
function check(proto, src, dst, dport) {
  for (let i = 0; i < ACL.length; i++) {
    const [act, p, s, d, port] = ACL[i];
    if ((p === "ip" || p === proto) && inPfx(src, s) && inPfx(dst, d) &&
        (port === null || port === dport))
      return `rule ${i + 1} -> ${act.toUpperCase()}`;
  }
  return "no match -> DENY (implicit deny)";
}
const packets = [
  ["a", "tcp", "192.168.10.5", "10.1.1.10", 80],  ["b", "tcp", "192.168.10.5", "10.1.1.10", 23],
  ["c", "tcp", "192.168.20.7", "10.1.1.10", 443], ["d", "tcp", "192.168.20.7", "10.1.1.10", 80],
  ["e", "udp", "172.16.5.5",   "10.1.1.53", 53],  ["f", "udp", "172.16.5.5",   "10.1.1.10", 161],
  ["g", "icmp", "192.168.10.5", "10.1.1.10", null],
];
for (const [id, proto, src, dst, dport] of packets)
  console.log(`${id}) ${proto.padEnd(4)} ${src.padEnd(13)} -> ${(dst + (dport ? ":" + dport : "")).padEnd(13)} ${check(proto, src, dst, dport)}`);

আউটপুট:

a) tcp  192.168.10.5  -> 10.1.1.10:80  rule 2 -> PERMIT
b) tcp  192.168.10.5  -> 10.1.1.10:23  rule 1 -> DENY
c) tcp  192.168.20.7  -> 10.1.1.10:443 rule 3 -> PERMIT
d) tcp  192.168.20.7  -> 10.1.1.10:80  rule 4 -> DENY
e) udp  172.16.5.5    -> 10.1.1.53:53  rule 5 -> PERMIT
f) udp  172.16.5.5    -> 10.1.1.10:161 no match -> DENY (implicit deny)
g) icmp 192.168.10.5  -> 10.1.1.10     no match -> DENY (implicit deny)

a আর b: শুধু port আলাদা — ৮০ পেল নিয়ম ২-এর অনুমতি, ২৩ (Telnet) আটকাল নিয়ম ১-এ। c: stepper-এর packet, নিয়ম ৩-এ PERMIT. d: নিয়ম ১–৩ মেলে না, তাই নিয়ম ৪-এ DENY. e: DNS সার্ভারে UDP 53 — নিয়ম ৫. f: UDP 161 (SNMP) কোনো নিয়মে নেই — implicit deny. g: সবচেয়ে শিক্ষণীয় — ping (ICMP)! কোনো নিয়ম ICMP-র কথা বলে না, তাই বাতিল। “ping কাজ করছে না” অভিযোগের বড় একটি কারণ এই অদৃশ্য নিয়ম।

Router-এ একই ACL — wildcard mask-সহ

Cisco-ধরনের router-এ একই নিয়ম লেখা হয় subnet mask-এর বদলে wildcard mask দিয়ে (mask-এর bit উল্টে: /24 → 0.0.0.255) — হিসাবটি পর্ব ১৭-এ (Subnetting) দেখেছেন। অন্য vendor-এর ভাষা আলাদা, নীতি একই।

ip access-list extended EDGE-IN
 10 deny   tcp 192.168.10.0 0.0.0.255 10.1.1.0 0.0.0.255 eq 23
 20 permit tcp 192.168.10.0 0.0.0.255 host 10.1.1.10 eq 80
 30 permit tcp 192.168.0.0 0.0.255.255 any eq 443
 40 deny   ip  192.168.20.0 0.0.0.255 10.1.1.0 0.0.0.255
 50 permit udp any host 10.1.1.53 eq 53
!
interface GigabitEthernet0/1
 ip access-group EDGE-IN in

শেষ লাইনটি বলে: ACL-টি এই interface-এ ঢোকা (in) ট্রাফিকে প্রযোজ্য। ক্রমিক নম্বর (১০, ২০ …) ফাঁক রেখে দেওয়া হয়, যাতে পরে মাঝে নতুন নিয়ম (যেমন ২৫) বসানো যায়।

Stateless-এর বড় দুর্বলতা: ফিরতি ট্রাফিক

ভেতরের একটি ল্যাপটপ বাইরে HTTPS অনুরোধ পাঠাল। উত্তর আসবে উৎস port 443 থেকে, ল্যাপটপের কোনো ephemeral port-এ (যেমন 51000). Stateless ACL জানে না এটি কোনো অনুরোধের উত্তর, তাই লিখতে হয় “উৎস port 443, গন্তব্য port 1024–65535 — permit” — আর তখন যে কেউ উৎস port 443 বসিয়ে ভেতরের যেকোনো উঁচু port-এ packet পাঠাতে পারে। পুরোনো router-এর “established” শব্দ TCP-র ACK bit দেখে কিছুটা সামলাত, কিন্তু ACK bit-ও জাল করা যায়, আর UDP-তে তেমন কিছুই নেই। সমাধান পরের অংশে।

৩ · Stateful firewall — conntrack-এর চারটি অবস্থা

Stateful firewall প্রতিটি কথোপকথনের একটি সারি মনে রাখে — পর্ব ১৯-এ (NAT) দেখা Linux-এর conntrack table-এর মতোই। নতুন packet এলে আগে খোঁজে: “এটি কি কোনো চেনা কথোপকথনের অংশ?” Linux-এর conntrack প্রতিটি packet-কে এই অবস্থাগুলোর একটিতে ফেলে:

অবস্থামানেসাধারণ নীতি
NEWনতুন কথোপকথনের প্রথম packet (বা উত্তর আসার আগে একই দিকের packet)শুধু নির্দিষ্ট সেবায় অনুমতি
ESTABLISHEDদুই দিকেই packet দেখা গেছে — চালু কথোপকথনঅনুমতি
RELATEDনতুন, কিন্তু চেনা কথোপকথনের সাথে সম্পর্কিত — যেমন একটি চালু সংযোগ নিয়ে ICMP-র “Fragmentation Needed”, বা helper-এর চেনা FTP ডেটা-সংযোগঅনুমতি
INVALIDকোনো কথোপকথনে মেলে না, বা TCP-র নিয়মে অসম্ভব — যেমন অচেনা সংযোগ নিয়ে ICMP errorবাতিল

এ থেকেই আধুনিক firewall-এর মানক নকশা: “ESTABLISHED আর RELATED-কে অনুমতি, INVALID বাতিল, তারপর নির্দিষ্ট কয়েকটি সেবার জন্য NEW-কে অনুমতি, বাকি সব বাতিল।” ফিরতি ট্রাফিকের জন্য কোনো ফুটো রাখতে হয় না — উত্তর ঢোকে শুধু অনুরোধ আগে বেরিয়ে থাকলে। আর একটি সংযোগে হাজার packet হলেও NEW মাত্র একটি, তাই প্রথম নিয়মেই বেশিরভাগ packet মিলে যায় — দ্রুত, আর তালিকা ছোট।

UDP আর ICMP-র “সংযোগ”

UDP-র কোনো handshake নেই, তবু conntrack একটি “ছদ্ম-সংযোগ” বানায়: একটি datagram বেরোলে 5-tuple মনে রাখে, উল্টো দিকের datagram এলে ESTABLISHED. শেষ কখন, তা বোঝার উপায় নেই, তাই কিছুক্ষণ নীরব থাকলে সারি মুছে যায় (timeout) — এজন্যই UDP অ্যাপের keepalive লাগে (পর্ব ২৮). ICMP Echo-তে identifier দিয়ে request আর reply জোড়া হয়। আর ICMP error বার্তার ভেতরে মূল packet-এর header উদ্ধৃত থাকে (পর্ব ২০), তাই conntrack সেটি পড়ে বলতে পারে এটি কোন সংযোগের সাথে RELATED.

নিচের simulator একটি host (10.0.0.5) — বাইরে যাওয়া সব নতুন সংযোগ চলবে, ভেতরে নতুন সংযোগ শুধু TCP 443-এ। Timeout শেখার সুবিধার জন্য ছোট: UDP ৩০ সেকেন্ড।

// Stateful firewall for host 10.0.0.5: a small conntrack table decides each packet.
const TIMEOUT = { tcp: 3600, udp: 30 };             // idle seconds (teaching values)
const ct = new Map();                                // key = flow as the initiator sent it
const key = (p, s, sp, d, dp) => `${p} ${s}:${sp} > ${d}:${dp}`;
const allowNewIn = (p, dp) => p === "tcp" && dp === 443;   // the only inbound service
function pkt(t, dir, p, s, sp, d, dp, about) {
  for (const [k, e] of ct) if (t - e.last > TIMEOUT[e.p]) {
    ct.delete(k); console.log(`t=${t}  (entry "${k}" expired)`); }
  let state, ok;
  if (p === "icmp-error") {                          // error about an existing flow?
    state = ct.has(about) ? "RELATED" : "INVALID"; ok = state === "RELATED";
  } else {
    const fwd = ct.get(key(p, s, sp, d, dp)), rev = ct.get(key(p, d, dp, s, sp));
    const e = fwd || rev;
    if (e) { if (rev) e.seen = true; e.last = t; state = e.seen ? "ESTABLISHED" : "NEW"; ok = true; }
    else {
      state = "NEW"; ok = dir === "out" || allowNewIn(p, dp);
      if (ok) ct.set(key(p, s, sp, d, dp), { p, last: t, seen: false });
    }
  }
  const what = p === "icmp-error" ? `icmp error re: ${about}` : `${p} ${s}:${sp} -> ${d}:${dp}`;
  console.log(`t=${t}  ${dir.padEnd(3)} ${what.padEnd(44)} ${state.padEnd(11)} ${ok ? "ACCEPT" : "DROP"}`);
}
pkt(0, "out", "tcp", "10.0.0.5", 51000, "198.51.100.20", 443);
pkt(1, "in",  "tcp", "198.51.100.20", 443, "10.0.0.5", 51000);
pkt(2, "in",  "tcp", "203.0.113.9", 40000, "10.0.0.5", 22);
pkt(3, "in",  "tcp", "203.0.113.9", 40001, "10.0.0.5", 443);
pkt(4, "out", "udp", "10.0.0.5", 53000, "198.51.100.53", 53);
pkt(5, "in",  "udp", "198.51.100.53", 53, "10.0.0.5", 53000);
pkt(6, "in",  "icmp-error", "192.0.2.1", 0, "10.0.0.5", 0, "tcp 10.0.0.5:51000 > 198.51.100.20:443");
pkt(7, "in",  "icmp-error", "192.0.2.1", 0, "10.0.0.5", 0, "tcp 10.0.0.5:52000 > 198.51.100.99:443");
pkt(70, "in", "udp", "198.51.100.53", 53, "10.0.0.5", 53000);
console.log(`entries left: ${ct.size}`);

আউটপুট:

t=0  out tcp 10.0.0.5:51000 -> 198.51.100.20:443      NEW         ACCEPT
t=1  in  tcp 198.51.100.20:443 -> 10.0.0.5:51000      ESTABLISHED ACCEPT
t=2  in  tcp 203.0.113.9:40000 -> 10.0.0.5:22         NEW         DROP
t=3  in  tcp 203.0.113.9:40001 -> 10.0.0.5:443        NEW         ACCEPT
t=4  out udp 10.0.0.5:53000 -> 198.51.100.53:53       NEW         ACCEPT
t=5  in  udp 198.51.100.53:53 -> 10.0.0.5:53000       ESTABLISHED ACCEPT
t=6  in  icmp error re: tcp 10.0.0.5:51000 > 198.51.100.20:443 RELATED     ACCEPT
t=7  in  icmp error re: tcp 10.0.0.5:52000 > 198.51.100.99:443 INVALID     DROP
t=70  (entry "udp 10.0.0.5:53000 > 198.51.100.53:53" expired)
t=70  in  udp 198.51.100.53:53 -> 10.0.0.5:53000       NEW         DROP
entries left: 2

t=0–1: ভেতর থেকে HTTPS সংযোগ বেরোল (NEW, বাইরে যাওয়া অনুমোদিত), সারি তৈরি হলো; উত্তর এল উল্টো 5-tuple-এ — সারি মিলল, ESTABLISHED, ACCEPT. Stateless ACL-এর মতো কোনো “উঁচু port খোলা” নিয়ম লাগেনি। t=2–3: বাইরে থেকে দুটি নতুন সংযোগ — port 22-এরটি কোনো নিয়মে নেই, DROP; port 443-এরটি সেবা হিসেবে অনুমোদিত, ACCEPT. t=4–5: DNS-এর UDP প্রশ্ন আর উত্তর — handshake ছাড়াই ESTABLISHED. t=6: পথের একটি router (192.0.2.1) চালু HTTPS সংযোগ নিয়ে ICMP error পাঠাল — RELATED, ACCEPT. এটা না ঢুকলে Path MTU Discovery ভেঙে যেত (পর্ব ২০). t=7: অচেনা সংযোগ নিয়ে ICMP error — INVALID, DROP. t=70: DNS-এর সারি ৩০ সেকেন্ডের বেশি নীরব, তাই মুছে গেছে; দেরিতে আসা “উত্তর” এখন নতুন inbound UDP, DROP. শেষে দুটি TCP সারি বাকি।

সতর্কতা: conntrack table-এর আকার সীমিত (Linux-এ nf_conntrack_max). প্রচুর নতুন সংযোগের বন্যায় (যেমন SYN flood, পর্ব ৫০) table ভরে গেলে নতুন বৈধ সংযোগও আটকে যায় — stateful firewall নিজেই তখন দুর্বল জায়গা। খুব ব্যস্ত সার্ভারে তাই কিছু ট্রাফিক conntrack থেকে বাদ রাখা (notrack) বা SYN cookie-র মতো কৌশল ব্যবহার করা হয়।

৪ · Proxy, NGFW আর firewall কোথায় বসে — DMZ, ভেতরের ভাগ আর বাইরে যাওয়ার নিয়ম

Layer 4-এর ওপরে: proxy, NGFW আর WAF

Packet filter শুধু header দেখে। কিন্তু port 443-এ যা যাচ্ছে তা ব্যাংকের ওয়েবসাইট, নাকি ম্যালওয়্যারের নিয়ন্ত্রণ-সার্ভার? এর উত্তর পেতে firewall-কে আরও ওপরের স্তরে উঠতে হয়:

  • Application-layer gateway বা proxy firewall: client সরাসরি সার্ভারে যায় না, proxy-র সাথে কথা বলে; proxy নিজে আলাদা সংযোগ খুলে protocol বুঝে যাচাই করে (যেমন শুধু অনুমোদিত HTTP পদ্ধতি)। দুই সংযোগের মাঝে থাকায় নিয়ন্ত্রণ বেশি, কিন্তু ধীর আর প্রতিটি protocol-এর জন্য আলাদা কোড লাগে।
  • Next-generation firewall (NGFW): বাজারের একটি নাম, সংজ্ঞা vendor-ভেদে আলাদা — সাধারণত stateful filtering-এর সাথে অ্যাপ চেনা, ব্যবহারকারী-ভিত্তিক নিয়ম আর আক্রমণ-চিহ্ন খোঁজা (IPS, পর্ব ৫০). কেউ কেউ এনক্রিপ্টেড ট্রাফিক দেখতে TLS ভেঙে আবার এনক্রিপ্ট করে (TLS inspection), যা গোপনীয়তা আর বিশ্বাসের গুরুতর প্রশ্ন তোলে (পর্ব ৪৮).
  • WAF (web application firewall): ওয়েব অ্যাপের সামনে বসে SQL injection-এর মতো ক্ষতিকর HTTP অনুরোধ খোঁজে — নিরাপদ কোডের বিকল্প নয়, বাড়তি একটি স্তর।

Host firewall আর network firewall

Host firewall চলে প্রতিটি যন্ত্রের নিজের OS-এ (Linux-এ nftables, Windows-এ Defender Firewall) — শুধু সেই যন্ত্রকে রক্ষা করে। Network firewall বসে নেটওয়ার্কের সীমানায় — অনেক যন্ত্রকে একসাথে রক্ষা করে, কিন্তু একই নেটওয়ার্কের দুই যন্ত্রের মাঝের ট্রাফিক দেখে না। ভালো নকশায় দুটিই থাকে (defense in depth, পর্ব ৪৬).

DMZ — দুই firewall-এর মাঝের উঠান

অফিসের ওয়েব আর মেইল সার্ভারে ইন্টারনেট থেকে পৌঁছাতে হবে; হিসাব বিভাগের কম্পিউটারে নয়। সবাই একই LAN-এ থাকলে ওয়েব সার্ভার দখল হওয়া মানে হিসাব বিভাগও হাতের নাগালে। সমাধান DMZ (demilitarized zone) বা screened subnet: বাইরে-মুখী সার্ভারগুলোর আলাদা নেটওয়ার্ক, দুই দিকে firewall দিয়ে ঘেরা।

  Internet
     │
 [ বাইরের firewall ]   ইন্টারনেট → DMZ: শুধু TCP 80/443 (ওয়েব), 25 (মেইল)
     │
 ────┴──── DMZ (203.0.113.0/28)  ওয়েব সার্ভার, মেইল সার্ভার, reverse proxy
     │
 [ ভেতরের firewall ]   DMZ → LAN: প্রায় কিছুই না (শুধু ওয়েব → DB 5432)
     │                LAN → DMZ: admin-দের SSH, ব্যবস্থাপনা
 ────┴──── ভেতরের LAN (10.20.0.0/16)  কর্মী, হিসাব, ডেটাবেস

নিয়মের মূল কথা: DMZ থেকে ভেতরে প্রায় কিছুই যাবে না, কারণ DMZ-কেই সবচেয়ে বেশি আক্রমণের মুখে ধরা হয়। ছোট প্রতিষ্ঠানে একটি firewall-এর তিনটি interface (WAN, DMZ, LAN) দিয়েও একই zone তৈরি হয় (“three-legged” নকশা).

ভেতরের ভাগ আর বাইরে যাওয়ার নিয়ম

সীমানার firewall পেরিয়ে কেউ ভেতরে ঢুকে পড়লে? পুরো অফিস এক সমতল নেটওয়ার্ক হলে সে পাশের সব যন্ত্রে ঘুরে বেড়ায় (lateral movement). তাই ভেতরেও ভাগ করা হয় — অতিথি Wi-Fi, কর্মী, সার্ভার, CCTV আলাদা VLAN-এ (পর্ব ১৩), মাঝে firewall-এর নিয়ম: একে বলে network segmentation; আরও সূক্ষ্ম, প্রতিটি workload-এর চারপাশে নিয়ম হলে microsegmentation.

অনেকে শুধু ঢোকার নিয়ম লেখেন, বাইরে যাওয়া সব খোলা রাখেন। কিন্তু egress filtering (বাইরে যাওয়া ট্রাফিকের নিয়ম) কয়েকটি কারণে জরুরি:

  • ম্যালওয়্যারের ফোন-ব্যাক: আক্রান্ত যন্ত্র সাধারণত নিজেই বাইরের নিয়ন্ত্রণ-সার্ভারে সংযোগ খোলে — inbound নিয়ম তা থামায় না। সার্ভারগুলো যদি শুধু হালনাগাদের সার্ভার আর DNS resolver-এ যেতে পারে, ফোন-ব্যাক অনেক কঠিন হয়।
  • ডেটা পাচার কমানো: ডেটাবেস সার্ভারের ইন্টারনেটে সরাসরি যাওয়ার কোনো কারণ নেই।
  • অন্যের ক্ষতি না করা: নিজের নেটওয়ার্ক থেকে জাল উৎস-ঠিকানার packet যেন না বেরোয় — ISP পর্যায়ে এটাই BCP 38-এর ingress filtering (পর্ব ৫০, প্রচলিত আক্রমণ আর প্রতিরক্ষা). ভেতরের যন্ত্র থেকে বাইরে TCP 25 সাধারণত বন্ধ রাখা হয়, যাতে আক্রান্ত যন্ত্র spam ছড়াতে না পারে।

৫ · Linux-এ firewall — netfilter-এর hook আর nftables

Linux kernel-এর netfilter অংশ packet-এর যাত্রাপথে পাঁচটি জায়গায় “আংটা” রেখেছে — প্রতিটিকে বলে hook. নিয়মের তালিকা (chain) এই hook-গুলোতে ঝোলানো হয়, আর packet সেখানে পৌঁছালে নিয়মগুলো চলে।

 ঢোকা packet                                              বেরোনো packet
 ──► PREROUTING ──► [routing সিদ্ধান্ত] ──► FORWARD ──► POSTROUTING ──►
                          │                                ▲
                          ▼                                │
                        INPUT                            OUTPUT
                          │                                ▲
                          ▼                                │
                    local process (sshd, nginx) ───────────┘
  • PREROUTING: ঢোকামাত্র, routing-এর আগে — conntrack-এর খোঁজ আর DNAT এখানে।
  • INPUT: এই যন্ত্রেরই প্রোসেসের জন্য — সার্ভারের firewall.
  • FORWARD: অন্য কোথাও যাবে, যন্ত্রটি শুধু router — নেটওয়ার্ক firewall.
  • OUTPUT: এই যন্ত্রের প্রোসেস নিজে যা পাঠায় — egress filtering.
  • POSTROUTING: বেরোনোর ঠিক আগে — SNAT আর masquerade (পর্ব ১৯).

একটি Linux router (LAN eth1: 192.168.1.0/24, WAN eth0: 203.0.113.5) ধরি। তার forward chain-এর নীতি drop, নিয়ম দুটি: (১) ct state established,related accept, (২) iifname "eth1" oifname "eth0" accept — LAN থেকে বাইরে নতুন সংযোগ চলবে। সাথে postrouting-এ masquerade. একটি ল্যাপটপের প্রথম packet আর তার উত্তর ধরে hook-গুলো দেখি।

  1. PREROUTINGconntrack: NEWeth1 দিয়ে ঢুকল
  2. Routingগন্তব্য বাইরে→ eth0
  3. FORWARDনিয়ম ২ মিললaccept
  4. POSTROUTINGmasqueradeসারি পাকা
  5. উত্তর ফেরেESTABLISHEDনিয়ম ১, eth1
Packet আর conntrack
কোথায়
উৎস → গন্তব্য
ct state
যে নিয়ম মিলল
  1. Packet eth1 দিয়ে ঢুকল, PREROUTING hook. ল্যাপটপ 192.168.1.11:50000 থেকে 198.51.100.20:443-এ একটি TCP SYN পাঠাল। Conntrack সারি খুঁজে পেল না, তাই একটি অস্থায়ী সারি বানিয়ে অবস্থা দিল NEW. এখানে কোনো DNAT নিয়ম নেই।
  2. Routing সিদ্ধান্ত। গন্তব্য এই router-এর নিজের কোনো ঠিকানা নয়, তাই packet INPUT-এ যাবে না, যাবে FORWARD-এ। Routing table বলে বেরোবে eth0 দিয়ে (default route).
  3. FORWARD hook — stateful নিয়ম মেলানো। নিয়ম ১ (established,related) মেলে না, কারণ অবস্থা NEW. নিয়ম ২: ঢোকা interface eth1, বেরোনো eth0 — মিলল, accept. না মিললে chain-এর নীতি drop কাজ করত।
  4. POSTROUTING — masquerade আর সারি পাকা। উৎস বদলে 203.0.113.5:50000 (port খালি থাকায় একই রাখা গেল)। Packet hook-গুলো পেরিয়ে টিকে যাওয়ায় conntrack এবার সারিটি পাকা (confirmed) করল — তাতে প্রত্যাশিত উত্তরের চেহারাও লেখা আছে।
  5. উত্তর ফেরে — ESTABLISHED. সার্ভারের SYN-ACK এল eth0-তে, গন্তব্য 203.0.113.5:50000. PREROUTING-এ conntrack সারি পেয়ে অবস্থা ESTABLISHED করল আর NAT-এর উল্টো বদল করে গন্তব্য বানাল 192.168.1.11:50000. FORWARD-এ প্রথম নিয়মেই accept; বাইরে থেকে আসা packet-এর জন্য আলাদা কোনো নিয়ম লাগেনি।

nftables-এর গঠন: table, chain, rule, set

nftables-এ সবকিছু চারটি স্তরে সাজানো। Table একটি ধারক, সাথে একটি family: ip (IPv4), ip6, বা inet (দুটোই একসাথে — সার্ভারে প্রায় সবসময় এটাই সুবিধাজনক)। Chain-এর ভেতরে নিয়ম; base chain একটি hook-এ বসে, যেমন type filter hook input priority filter; policy drop; — অর্থাৎ ছাঁকার কাজ, INPUT hook-এ, অগ্রাধিকার filter (সংখ্যায় 0), আর কোনো নিয়ম না মিললে drop. Rule-এ শর্ত আর সিদ্ধান্ত। আর set ও map দিয়ে অনেক ঠিকানা বা port একটি নিয়মেই — হাজারটি ঠিকানা থাকলেও খোঁজা দ্রুত। counter প্রতিটি নিয়মে কতগুলো packet মিলল গোনে, log kernel log-এ লেখে।

নিচে একটি ছোট ওয়েব সার্ভারের পূর্ণ ruleset: loopback, চালু সংযোগ, শুধু ব্যবস্থাপনা নেটওয়ার্ক থেকে SSH, সবার জন্য HTTP/HTTPS, জরুরি ICMP, বাকি সব বাতিল। ডান পাশের নম্বর ধরে ব্যাখ্যা নিচে।

#!/usr/sbin/nft -f
# /etc/nftables.conf - a small web server (IPv4 + IPv6)
flush ruleset                                         # 1

table inet host_fw {                                  # 2
    set mgmt_v4 {                                     # 3
        type ipv4_addr
        flags interval
        elements = { 10.20.0.0/24 }
    }

    chain input {
        type filter hook input priority filter; policy drop;          # 4

        iif "lo" accept                                               # 5
        ct state vmap { established : accept, related : accept, invalid : drop }   # 6

        ip saddr @mgmt_v4 tcp dport 22 ct state new accept            # 7
        tcp dport { 80, 443 } ct state new counter accept             # 8

        icmp type echo-request limit rate 5/second accept             # 9
        icmp type { destination-unreachable, time-exceeded, parameter-problem } accept
        icmpv6 type { destination-unreachable, packet-too-big, time-exceeded,
                      parameter-problem, echo-request, nd-router-advert,
                      nd-neighbor-solicit, nd-neighbor-advert } accept  # 10

        limit rate 10/minute log prefix "nft-in-drop: "               # 11
        counter comment "reached policy drop"
    }

    chain forward {
        type filter hook forward priority filter; policy drop;        # 12
    }

    chain output {
        type filter hook output priority filter; policy accept;       # 13
    }
}
  1. flush ruleset — আগের সব নিয়ম মুছে নতুন শুরু। পুরো ফাইল nft -f দিয়ে একবারে (atomic) বসে — হয় সব নিয়ম, নয় কিছুই না।
  2. table inet host_fw — IPv4 আর IPv6 দুটোর জন্য একটি table. শুধু IPv4-এর নিয়ম লিখে IPv6 খোলা রেখে দেওয়া একটি প্রচলিত ভুল।
  3. set mgmt_v4 — ব্যবস্থাপনা নেটওয়ার্কের একটি নামযুক্ত set (flags interval থাকায় পুরো prefix রাখা যায়); পরে নিয়ম না বদলে শুধু set-এ ঠিকানা যোগ করা যায়।
  4. input chain, policy drop — যা স্পষ্টভাবে অনুমোদিত নয়, তা বাতিল (default deny).
  5. iif "lo" accept — যন্ত্রের নিজের সাথে নিজের কথা (loopback); এটা বন্ধ করলে অনেক অ্যাপ অদ্ভুতভাবে ভাঙে।
  6. ct state vmap { … } — একটি verdict map: অবস্থা দেখে একবারে সিদ্ধান্ত — ESTABLISHED আর RELATED accept, INVALID drop. অংশ ৩-এর মানক নকশার প্রথম লাইন।
  7. SSH শুধু @mgmt_v4 থেকে — ইন্টারনেটের সবার সামনে SSH খোলা না রাখা সবচেয়ে কার্যকর অভ্যাসগুলোর একটি।
  8. TCP 80 আর 443 — সবার জন্য; { 80, 443 } একটি anonymous set, counter দিয়ে কত নতুন সংযোগ এল গোনা যায়।
  9. ICMPv4: ping সেকেন্ডে ৫টি পর্যন্ত, আর জরুরি error বার্তা। Destination-unreachable-এর ভেতরেই “Fragmentation Needed” — এটি বন্ধ করলে Path MTU Discovery ভাঙে (কোন ICMP রাখবেন, পর্ব ২০-এ)। চালু সংযোগের error এমনিতেই RELATED হয়ে ঢোকে; এই লাইন বাড়তি নিশ্চয়তা।
  10. ICMPv6: IPv6-এ router fragment করে না, তাই packet-too-big ছাড়া PMTUD চলে না; আর neighbor solicitation/advertisement (NDP, ARP-এর বদলে) ছাড়া পাশের যন্ত্রের MAC-ই জানা যায় না। এগুলো বন্ধ করলে IPv6 কার্যত অচল।
  11. log, সীমা দিয়ে — বাতিলের আগে মিনিটে সর্বোচ্চ ১০টি packet log-এ; সীমা না দিলে আক্রমণের সময় log-ই ডিস্ক ভরাতে পারে। শেষ counter গোনে কতগুলো packet নীতির drop-এ পৌঁছাল।
  12. forward chain, drop — এটি সার্ভার, router নয়; কিছু পার করবে না।
  13. output chain, accept — সরলতার জন্য বাইরে যাওয়া খোলা। কড়া নকশায় এখানেও drop দিয়ে শুধু DNS, হালনাগাদ আর দরকারি গন্তব্য খোলা হয় (অংশ ৪-এর egress filtering).

নিজেকে তালাবন্ধ করবেন না: দূরের সার্ভারে SSH দিয়ে ঢুকে policy drop বসালেন, আর SSH-এর নিয়মে ভুল — সংযোগ সঙ্গে সঙ্গে কেটে যাবে, আর ফেরার পথ নেই। নিরাপদ অভ্যাস: (১) আগে sudo nft -c -f /etc/nftables.conf দিয়ে শুধু যাচাই করুন — -c কিছু বসায় না, শুধু ভুল ধরে; (২) বসানোর আগে একটি “ফেরত যাওয়ার টাইমার” রাখুন, যেমন একটি আলাদা session-এ কয়েক মিনিট পর পুরোনো ruleset ফিরিয়ে আনার কমান্ড, আর সব ঠিক থাকলে টাইমার বাতিল করুন; (৩) সম্ভব হলে cloud-এর console বা সরাসরি কিবোর্ডের পথ খোলা রাখুন। পদ্ধতির খুঁটিনাটি distribution আর পরিবেশভেদে আলাদা — নিজের সিস্টেমের ডকুমেন্টেশন দেখে নিন।

iptables, ufw আর firewalld

অনেক পুরোনো নির্দেশিকা আর স্ক্রিপ্ট এখনো iptables-এ লেখা। একই নীতি iptables-এ (IPv6-এর জন্য আলাদা ip6tables লাগে):

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A INPUT -p tcp -s 10.20.0.0/24 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/second -j ACCEPT
iptables -P INPUT DROP          # policy LAST - after the SSH rule exists

খেয়াল করুন নীতি (-P INPUT DROP) একদম শেষে — আগে বসালে চালু SSH সংযোগই কেটে যেত। আধুনিক অনেক distribution-এ iptables কমান্ডটি আসলে iptables-nft: পুরোনো ভাষা, কিন্তু নিয়ম বসে kernel-এর nftables কাঠামোয়; iptables -V সাধারণত “(nf_tables)” বা “(legacy)” দেখায়। দুই ধরনের নিয়ম মেশালে বিভ্রান্তি হয়, তাই একটি পথ বেছে নিন (নিজের distribution কোনটি ব্যবহার করে, যাচাই করে নিন); অনুবাদে iptables-translate সাহায্য করে।

প্রতিদিনের কাজে অনেকে সরাসরি nftables না লিখে একটি সহজ “সামনের মুখ” (front-end) ব্যবহার করেন, যা ভেতরে nftables বা iptables-এর নিয়ম বানায়: Ubuntu-তে ufw (sudo ufw default deny incoming, sudo ufw allow proto tcp from 10.20.0.0/24 to any port 22), আর Fedora/RHEL পরিবারে firewalld, যা zone ধারণায় চলে (sudo firewall-cmd --permanent --add-service=https, তারপর --reload). একটি যন্ত্রে একটির বেশি firewall ব্যবস্থাপক চালালে একে অপরের নিয়ম মুছে দিতে পারে।

Windows আর cloud

Windows-এ Defender Firewall প্রতিটি নেটওয়ার্ককে একটি profile-এ ফেলে (Domain, Private, Public) — কফিশপের Wi-Fi “Public” হলে নিয়ম সবচেয়ে কড়া।

PS> Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction
PS> New-NetFirewallRule -DisplayName "Web HTTPS in" -Direction Inbound `
      -Protocol TCP -LocalPort 443 -Action Allow -Profile Domain,Private

Cloud-এ firewall আসে দুই রূপে (নিচের নাম AWS-এর; Azure, Google Cloud-এর ধারণা কাছাকাছি, নাম আর খুঁটিনাটি আলাদা)। Security group প্রতিটি VM বা network interface-এর সাথে যুক্ত, stateful — অনুমতি পাওয়া অনুরোধের উত্তর আপনাআপনি ফেরে, আর এতে শুধু allow নিয়ম লেখা যায়। Network ACL পুরো subnet-এ বসে, stateless — নম্বরযুক্ত নিয়ম ক্রমানুসারে, allow আর deny দুটোই, আর ফিরতি ট্রাফিকের জন্য ephemeral port-এর পরিসর আলাদা করে খুলতে হয় — অংশ ২-এর সমস্যাটি হুবহু। Cloud নেটওয়ার্কের বিস্তারিত পর্ব ৫৪-এ।

নিজের firewall নিরাপদে পরীক্ষা

নিয়ম বসানোর পর যাচাই করুন — শুধু নিজের যন্ত্র থেকে, নিজের যন্ত্রে। sudo nft list ruleset দেখায় এখন কী বসানো আছে, আর counter-এর সংখ্যা বলে কোন নিয়মে packet মিলছে। তারপর নিজের দ্বিতীয় একটি যন্ত্র (বা VM) থেকে অনুমোদিত সেবায় সংযোগ করে দেখুন, আর অননুমোদিত port-এ চেষ্টা করে দেখুন সত্যিই আটকায় কি না; log-এ nft-in-drop খুঁজুন। অন্যের নেটওয়ার্ক বা যন্ত্রে অনুমতি ছাড়া “পরীক্ষা” অনৈতিক, আর অনেক দেশে আইনত অপরাধ।

এই কোর্সের কোড যে container-এ চলে, সেখানে আমরা root নই। নিচের স্ক্রিপ্ট শুধু দেখে — কোন টুল আছে, আমরা কে, আর নিয়ম পড়ার চেষ্টা করলে kernel কী বলে। কিছু বদলানোর চেষ্টা করে না।

echo "== 1. who am I? =="
echo "  uid=$(id -u) user=$(id -un)"
[ "$(id -u)" -eq 0 ] && echo "  -> root" || echo "  -> not root"
cap=$(awk '/^CapEff/ {print $2}' /proc/self/status)
if (( (16#$cap >> 12) & 1 )); then echo "  CAP_NET_ADMIN: yes"; else echo "  CAP_NET_ADMIN: no (CapEff=$cap)"; fi
echo "== 2. firewall / VPN tools =="
for t in nft iptables ip6tables ufw firewall-cmd wg wg-quick; do
  command -v "$t" >/dev/null && echo "  $t: found" || echo "  $t: not found"
done
echo "== 3. read-only listing attempts (nothing is changed) =="
if command -v nft >/dev/null; then
  nft list ruleset >/dev/null 2>/tmp/nft.err && echo "  nft list ruleset: OK" \
    || echo "  nft list ruleset failed: $(head -c 120 /tmp/nft.err)"
else echo "  nft not installed - skipped"; fi
if command -v iptables >/dev/null; then
  iptables -S >/dev/null 2>/tmp/ipt.err && echo "  iptables -S: OK" \
    || echo "  iptables -S failed: $(head -c 120 /tmp/ipt.err)"
else echo "  iptables not installed - skipped"; fi
echo "== 4. what the kernel shows an ordinary user =="
for f in /proc/net/ip_tables_names /proc/net/nf_conntrack /proc/sys/net/netfilter/nf_conntrack_max; do
  if [ -r "$f" ]; then echo "  $f: readable, first line: $(head -n 1 "$f")"
  elif [ -e "$f" ]; then echo "  $f: $(cat "$f" 2>&1 >/dev/null | sed 's/^cat: [^:]*: //')"
  else echo "  $f: absent"; fi
done
[ -d /sys/module/wireguard ] && echo "  wireguard module: loaded" || echo "  wireguard module: not visible"

আসল রানের আউটপুট:

== 1. who am I? ==
  uid=999 user=wandbox
  -> not root
  CAP_NET_ADMIN: no (CapEff=0000000000000000)
== 2. firewall / VPN tools ==
  nft: not found
  iptables: not found
  ip6tables: not found
  ufw: not found
  firewall-cmd: not found
  wg: not found
  wg-quick: not found
== 3. read-only listing attempts (nothing is changed) ==
  nft not installed - skipped
  iptables not installed - skipped
== 4. what the kernel shows an ordinary user ==
  /proc/net/ip_tables_names: Permission denied
  /proc/net/nf_conntrack: absent
  /proc/sys/net/netfilter/nf_conntrack_max: readable, first line: 65536
  wireguard module: not visible

আমরা wandbox নামের সাধারণ ব্যবহারকারী (uid 999), root নই। /proc/self/status-এর CapEff পুরোটাই শূন্য — অর্থাৎ CAP_NET_ADMIN নামের capability-ও নেই, যেটি ছাড়া kernel firewall-এর নিয়ম পড়তে বা বদলাতে দেয় না। এই container-এ nft, iptables, wg — কোনো টুলই নেই, তাই তৃতীয় ধাপ সৎভাবে “skipped” বলেছে। তবু চতুর্থ ধাপে kernel-এর সিদ্ধান্ত সরাসরি দেখা যায়: /proc/net/ip_tables_names ফাইলটি আছে, কিন্তু পড়তে গেলে Permission denied — কোন table বসানো আছে সেটুকুও শুধু privileged ব্যবহারকারী জানতে পারেন। Conntrack-এর সর্বোচ্চ সারির সংখ্যা (nf_conntrack_max = 65536) সবাই পড়তে পারে, কিন্তু সারিগুলো এখানে দেখা যায় না। সাধারণ Linux যন্ত্রে root ছাড়া nft list ruleset বা iptables -S চালালেও একই ধরনের “Operation not permitted” বা “Permission denied (you must be root)” বার্তা আসে (সংস্করণভেদে ভাষা আলাদা)। শিক্ষা: firewall দেখা আর বদলানো দুটোই privileged কাজ — আর যে প্রোগ্রাম root হিসেবে চলে, দখল হলে সে firewall-ও বদলে দিতে পারে; সেবাগুলো root ছাড়া চালানোর এটি আরেকটি কারণ।

৬ · VPN-এর ভিত্তি — tunnel, overhead আর MTU-র হিসাব

রাজশাহী শাখার একটি কম্পিউটারকে ঢাকা অফিসের হিসাবের সার্ভারে যেতে হবে। মাঝে খোলা ইন্টারনেট। দুটি সমস্যা: ঢাকার সার্ভারের ঠিকানা private (10.20.0.15), ইন্টারনেটে route হয় না; আর পথে কেউ ডেটা পড়তে বা বদলাতে পারে। VPN (virtual private network) দুটোরই সমাধান — তিনটি কাজ একসাথে করে:

  1. Tunnel: ভেতরের packet (উৎস 10.x, গন্তব্য 10.x) পুরোটাই একটি নতুন packet-এর payload হয়ে যায়, যার উৎস আর গন্তব্য দুই অফিসের public ঠিকানা।
  2. এনক্রিপশন আর integrity: ভেতরের packet এনক্রিপ্ট হয়, আর প্রতিটি packet-এ একটি যাচাই-চিহ্ন থাকে — পথে বদলালে ধরা পড়ে। (AEAD-এর মতো ধারণা পর্ব ৪৭-এ, Cryptography-র ভিত্তি)
  3. পরিচয় যাচাই: দুই প্রান্ত নিশ্চিত হয় অপর পাশে সত্যিই বৈধ peer — pre-shared key, certificate বা public key দিয়ে।

কুরিয়ার সার্ভিসে একটি গোপন চিঠি পাঠাচ্ছেন। ভেতরের খামে আসল ঠিকানা লেখা — “হিসাব বিভাগ, কক্ষ ১৫”, যা কুরিয়ার চেনে না। তাই সেই খাম একটি তালাবন্ধ বাক্সে ভরে বাইরে লিখলেন “ঢাকা অফিস, মতিঝিল”। কুরিয়ার শুধু বাইরের ঠিকানা দেখে, বাক্স খুলতে পারে না। ঢাকা অফিসের রিসেপশন বাক্স খুলে (চাবি শুধু তাঁর কাছে), সিল ঠিক আছে কি না দেখে, ভেতরের খাম কক্ষ ১৫-এ পাঠান। বাক্স = tunnel, তালা = এনক্রিপশন, সিল = integrity, চাবি মেলানো = পরিচয় যাচাই.

VPN মূলত দুই ধরনের: site-to-site — দুই অফিসের gateway-এর মাঝে স্থায়ী tunnel, ভেতরের কম্পিউটারগুলো কিছুই টের পায় না; আর remote access — কর্মীর ল্যাপটপ বাইরে থেকে অফিসের gateway-এ যুক্ত হয়। Tunnel-এর ভেতরের নেটওয়ার্ক overlay (10.x-এর জগৎ), আর যে আসল নেটওয়ার্কের ওপর দিয়ে বাক্সগুলো যায় তা underlay (ইন্টারনেট).

বাক্সের ওজন — overhead আর MTU

প্রতিটি tunnel নতুন header যোগ করে, অথচ underlay-এর লিংকের MTU সাধারণত 1500 বাইটই থাকে। তাই ভেতরের packet ছোট হতে হবে। WireGuard-এর হিসাব (IPv4 underlay):

20 (বাইরের IPv4) + 8 (UDP) + 16 (WireGuard header) + 16 (Poly1305 tag) = 60 বাইট
ভেতরের MTU = 1500 − 60 = 1440; IPv6 underlay-এ 40 + 8 + 32 = 80 → 1420

WireGuard-এর data header-এ আছে type (১ বাইট), ৩ বাইট সংরক্ষিত, receiver index (৪ বাইট) আর একটি counter (৮ বাইট) — মোট ১৬; শেষে এনক্রিপশনের যাচাই-চিহ্ন (tag) ১৬ বাইট। বাইরের packet IPv6 হলে overhead ৮০ বাইট। এজন্যই wg-quick-এর মতো টুল সাধারণত ডিফল্ট MTU 1420 ধরে — দুই রকম underlay-এই নিরাপদ (আপনার টুলের ডিফল্ট আর PPPoE-র মতো ছোট underlay MTU থাকলে হিসাব আলাদা — যাচাই করে নিন)। ভেতরে TCP চললে MSS = 1420 − 20 (IPv4) − 20 (TCP) = 1380.

MTU ভুল হলে কী হয়? বড় packet tunnel-এ ঢুকতে পারে না; ICMP “Fragmentation Needed” ফেরত যাওয়ার কথা, কিন্তু পথে কোনো firewall ICMP আটকালে প্রেরক কিছুই জানে না — ছোট ওয়েবপেজ খোলে, বড় ফাইল আটকে যায়। এই PMTUD black hole-এর প্রচলিত ওষুধ MSS clamping: tunnel-এর gateway TCP-র SYN-এ MSS-এর মান কমিয়ে লিখে দেয়, যাতে দুই প্রান্ত শুরু থেকেই ছোট segment পাঠায়। nftables-এ এর একটি রূপ: tcp flags syn tcp option maxseg size set rt mtu (forward chain-এ) — route-এর MTU থেকে MSS বসায়।

৭ · IPsec — AH, ESP, SA আর IKEv2

IPsec IETF-এর মানসম্মত VPN কাঠামো, IP স্তরেই কাজ করে — তাই এর ওপরের যেকোনো protocol সুরক্ষা পায়। Router, firewall আর OS-এ প্রায় সর্বত্র সমর্থিত, তাই প্রতিষ্ঠানের site-to-site VPN-এ এখনো সবচেয়ে প্রচলিত। মূল নথি RFC 4301 (স্থাপত্য), RFC 4303 (ESP) আর RFC 7296 (IKEv2).

অংশকী করেমনে রাখার কথা
AH (IP protocol 51)শুধু integrity আর উৎস যাচাই, এনক্রিপশন নেইবাইরের IP header-এর অপরিবর্তনীয় ঘরও যাচাই করে — তাই NAT ঠিকানা বদলালেই যাচাই ব্যর্থ; আজ খুব কম ব্যবহৃত
ESP (IP protocol 50)এনক্রিপশন + integrity (আধুনিক রূপে AES-GCM-এর মতো AEAD)বাস্তবে প্রায় সব IPsec মানে ESP
Transport modeমূল IP header রেখে শুধু payload সুরক্ষাদুই host-এর মাঝে সরাসরি
Tunnel modeপুরো মূল packet ভেতরে, নতুন বাইরের IP headergateway-gateway (site-to-site) আর remote access
SA আর SPISA = এক দিকের চুক্তি: কোন অ্যালগরিদম, কোন key, কত দিন; SPI = ৩২ bit-এর নম্বর, যা দেখে প্রাপক SA খুঁজে পায়প্রতিটি tunnel-এ অন্তত দুটি SA (দুই দিকের জন্য একটি করে)
IKEv2 (UDP 500)দুই প্রান্তের পরিচয় যাচাই, key বিনিময় (Diffie-Hellman), SA তৈরি আর নিয়মিত নবায়নControl plane; ESP হলো data plane

ESP tunnel mode-এর একটি packet (AES-GCM ধরে):

┌──────────┬────────────┬──────┬──────────────────────────┬─────────────┬──────┐
│ নতুন IP  │ ESP header │  IV  │  মূল IP header + ডেটা    │ ESP trailer │ ICV  │
│ 20 বাইট  │ SPI 4+seq 4│  8   │  (এনক্রিপ্টেড)            │ pad + 2     │  16  │
└──────────┴────────────┴──────┴──────────────────────────┴─────────────┴──────┘
             └──────────── integrity যাচাই ──────────────────────────────┘

NAT আর IPsec: ESP সরাসরি IP-র ওপর বসে, কোনো port নেই — তাই PAT জানে না কোন ভেতরের যন্ত্রকে উত্তর দেবে (পর্ব ১৯). সমাধান NAT-T (RFC 3948): IKEv2 দুই প্রান্তের মাঝে NAT আছে কি না টের পেলে ESP packet-কে UDP port 4500-এর datagram-এ মুড়ে পাঠায়, আর নিয়মিত keepalive দিয়ে NAT-এর সারি বাঁচিয়ে রাখে। দাম: আরও ৮ বাইট overhead. firewall-এ তাই IPsec gateway-এর জন্য খোলা থাকে UDP 500, UDP 4500, আর NAT না থাকলে IP protocol 50.

IPsec কেন জটিল: অনেক অ্যালগরিদমের মধ্যে আলোচনা, দুই প্রান্তে মিলতে হয় এমন অনেক বিকল্প (proposal, lifetime, কোন ট্রাফিক tunnel-এ যাবে তার “traffic selector”), আর vendor-ভেদে আলাদা ব্যাখ্যা — দুই vendor-এর gateway-এর মাঝে tunnel তুলতে প্রায়ই দীর্ঘ খোঁজাখুঁজি লাগে। যত বিকল্প, তত ভুল কনফিগারেশন আর পুরোনো দুর্বল অ্যালগরিদম চালু থেকে যাওয়ার সুযোগ। এই অভিজ্ঞতা থেকেই WireGuard-এর নকশা।

৮ · WireGuard — public key দিয়ে peer, AllowedIPs দিয়ে routing

WireGuard তৈরি করেন Jason A. Donenfeld; Linux kernel-এ এটি যুক্ত হয় ৫.৬ সংস্করণে (২০২০ সালের শুরুর দিকে). এখন Windows, macOS, Android, iOS আর BSD-তেও আছে। এর নকশা ইচ্ছা করেই সংকীর্ণ:

  • বিকল্প নেই: একটি নির্দিষ্ট অ্যালগরিদম-গুচ্ছ (Curve25519, ChaCha20-Poly1305, BLAKE2s). দুর্বলতা পাওয়া গেলে পুরো protocol-এর নতুন সংস্করণ — আলোচনার জটিলতাই নেই।
  • Peer মানে একটি public key: SSH-এর key-র মতো — কোনো ব্যবহারকারী-নাম বা certificate কর্তৃপক্ষ নেই। বৈধ key ছাড়া packet এলে WireGuard কোনো উত্তরই দেয় না।
  • Handshake: Noise protocol framework-এর ওপর ভিত্তি করে ১-RTT-র একটি handshake; প্রতি কয়েক মিনিটে নতুন session key, তাই পুরোনো key চুরি হলেও আগের ট্রাফিক পড়া যায় না (forward secrecy, পর্ব ৪৭).
  • শুধু UDP: TCP-র ওপর TCP চালানোর সমস্যা এড়াতে (নিচে OpenVPN দেখুন); প্রচলিত port 51820.
  • ছোট কোড: kernel-এর অংশটি কয়েক হাজার লাইনের — বহু লক্ষ লাইনের প্রচলিত VPN-এর তুলনায় পর্যালোচনা করা অনেক সহজ।

Cryptokey routing — AllowedIPs-এর দুই কাজ

WireGuard-এর কেন্দ্রীয় ধারণা cryptokey routing: প্রতিটি peer-এর সাথে একটি AllowedIPs তালিকা। এই একটি তালিকা দুটি কাজ করে:

  • বাইরে পাঠানোর সময় — routing table: গন্তব্য ঠিকানা কোন peer-এর AllowedIPs-এ পড়ে, তা longest prefix match-এ (পর্ব ২২) খুঁজে সেই peer-এর key দিয়ে এনক্রিপ্ট আর তার endpoint-এ পাঠানো। কোনো peer না মিললে packet বাতিল।
  • ভেতরে নেওয়ার সময় — ACL: একটি packet decrypt আর যাচাই হওয়ার পর দেখা হয়, ভেতরের উৎস ঠিকানা কি সেই peer-এরই AllowedIPs-এ? না হলে বাতিল। ফলে ল্যাপটপের key দিয়ে কেউ শাখা অফিসের ঠিকানা সেজে packet পাঠাতে পারে না।

একটি অফিস gateway-এর তিনটি peer: ল্যাপটপ (10.8.0.2/32), শাখা অফিস (10.8.0.3/32 আর পুরো 192.168.50.0/24), আর একটি ল্যাব (192.168.50.128/25 — শাখার ব্লকের ওপরের অর্ধেক)। নিচের simulator দুই দিকের সিদ্ধান্ত দেখায়, সাথে একটি MTU ক্যালকুলেটর — অংশ ৬-এর হিসাব আর IPsec ESP tunnel mode (AES-GCM ধরে) পাশাপাশি।

// WireGuard cryptokey routing on the office gateway + tunnel MTU calculator.
const ip = s => s.split(".").reduce((a, o) => a * 256 + Number(o), 0);
const peers = { laptop: ["10.8.0.2/32"], branch: ["10.8.0.3/32", "192.168.50.0/24"],
                lab: ["192.168.50.128/25"] };
function lookup(addr) {                              // longest-prefix match over AllowedIPs
  let best = null, bestLen = -1;
  for (const [name, list] of Object.entries(peers)) for (const pfx of list) {
    const [net, len] = pfx.split("/"), size = 2 ** (32 - len);
    if (Math.floor(ip(addr) / size) === Math.floor(ip(net) / size) && +len > bestLen)
      { best = name; bestLen = +len; }
  }
  return best;
}
console.log("-- outgoing: which peer gets the packet? --");
for (const dst of ["10.8.0.2", "192.168.50.20", "192.168.50.200", "10.8.0.9"])
  console.log(`dst ${dst.padEnd(15)} -> ${lookup(dst) ?? "no peer: dropped (no key for this address)"}`);
console.log("-- incoming: decrypted OK, is the inner source allowed for that peer? --");
for (const [from, src] of [["laptop", "10.8.0.2"], ["laptop", "192.168.50.20"],
                           ["branch", "192.168.50.20"], ["branch", "192.168.50.200"]])
  console.log(`from ${from.padEnd(6)} inner src ${src.padEnd(15)} ` +
    (lookup(src) === from ? "ACCEPT" : `DROP (belongs to ${lookup(src) ?? "nobody"})`));
console.log("-- largest inner packet that fits a 1500-byte link --");
const wg = outer => 1500 - outer - 8 - 32;           // UDP 8 + WG header 16 + tag 16
const esp = (outer, natt) => {                       // ESP tunnel, AES-GCM: SPI+seq 8, IV 8, ICV 16
  let p = 1500 - outer - (natt ? 8 : 0) - 8 - 8 - 2 - 16;  // 2 = pad length + next header
  while ((p + 2) % 4) p--;                           // ESP payload+trailer: multiple of 4
  return p;
};
console.log(`WireGuard over IPv4: ${wg(20)}   over IPv6: ${wg(40)}`);
console.log(`ESP tunnel over IPv4: ${esp(20, false)}   +NAT-T (UDP 4500): ${esp(20, true)}   over IPv6: ${esp(40, false)}`);
console.log(`TCP MSS inside WireGuard MTU 1420 (IPv4 inner): ${1420 - 20 - 20}`);

আউটপুট:

-- outgoing: which peer gets the packet? --
dst 10.8.0.2        -> laptop
dst 192.168.50.20   -> branch
dst 192.168.50.200  -> lab
dst 10.8.0.9        -> no peer: dropped (no key for this address)
-- incoming: decrypted OK, is the inner source allowed for that peer? --
from laptop inner src 10.8.0.2        ACCEPT
from laptop inner src 192.168.50.20   DROP (belongs to branch)
from branch inner src 192.168.50.20   ACCEPT
from branch inner src 192.168.50.200  DROP (belongs to lab)
-- largest inner packet that fits a 1500-byte link --
WireGuard over IPv4: 1440   over IPv6: 1420
ESP tunnel over IPv4: 1446   +NAT-T (UDP 4500): 1438   over IPv6: 1426
TCP MSS inside WireGuard MTU 1420 (IPv4 inner): 1380

বাইরে যাওয়া: 192.168.50.200 শাখার /24 আর ল্যাবের /25 দুটোতেই পড়ে — দীর্ঘতম prefix /25 জেতে, তাই ল্যাব। 10.8.0.9 কারও AllowedIPs-এ নেই — বাতিল (Linux-এ প্রোগ্রাম সাধারণত “Required key not available” ধরনের ত্রুটি পায়)। ভেতরে নেওয়া: ল্যাপটপের key দিয়ে আসা packet-এর উৎস 192.168.50.20 শাখার ঠিকানা, তাই DROP. সূক্ষ্ম শেষ লাইন: শাখার key দিয়ে উৎস 192.168.50.200 — শাখার /24-এর মধ্যে হলেও longest prefix অনুযায়ী ঠিকানাটি ল্যাবের, তাই DROP. MTU: WireGuard 1440 আর 1420, অংশ ৬-এর হিসাবের সাথে মেলে। ESP-তে IPv4-এর ওপর 1446: 20 + 8 + 8 + (1446 + 2) + 16 = 1500; NAT-T-এর UDP header যোগ হলে 1438, IPv6-এ 1426. অ্যালগরিদম বদলালে (যেমন AES-CBC আর HMAC) IV, padding আর ICV বদলায়, তাই ESP-র সংখ্যা নির্দিষ্ট কনফিগারেশন ধরে হিসাব করতে হয়।

দুই peer-এর একটি পূর্ণ কনফিগারেশন

রহিমার ল্যাপটপ বাসা থেকে অফিসের LAN (10.20.0.0/16)-এ যাবে। Tunnel-এর ভেতরের ঠিকানা 10.8.0.0/24. Key-গুলো এখানে স্পষ্ট নকল নাম — আসল key কখনো কোথাও প্রকাশ করবেন না।

# ===== office gateway: /etc/wireguard/wg0.conf =====
[Interface]
Address    = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <office-private-key>

# Rahima's laptop
[Peer]
PublicKey  = <laptop-public-key>
AllowedIPs = 10.8.0.2/32

# ===== laptop: /etc/wireguard/wg0.conf =====
[Interface]
Address    = 10.8.0.2/32
PrivateKey = <laptop-private-key>
DNS        = 10.20.0.53

# the office; split tunnel: only office networks go into the tunnel
[Peer]
PublicKey  = <office-public-key>
Endpoint   = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 10.20.0.0/16
PersistentKeepalive = 25
  • Key বানানো: প্রতিটি যন্ত্রে umask 077; wg genkey | tee private.key | wg pubkey > public.key. Private key যন্ত্র ছাড়ে না; অপর প্রান্ত পায় শুধু public key.
  • Gateway-এর AllowedIPs = 10.8.0.2/32 — এই peer থেকে শুধু এই একটি উৎস-ঠিকানা গ্রহণযোগ্য, আর এই ঠিকানার packet শুধু তার কাছেই যায়।
  • ল্যাপটপের AllowedIPs = 10.8.0.0/24, 10.20.0.0/16 — শুধু অফিসের নেটওয়ার্ক tunnel-এ, বাকি ইন্টারনেট বাসার পথে। Endpoint জানা থাকায় ল্যাপটপই যোগাযোগ শুরু করে; gateway ল্যাপটপের বর্তমান ঠিকানা শেখে প্রথম বৈধ packet থেকে, তাই Wi-Fi থেকে মোবাইল ডেটায় গেলেও tunnel টেকে (roaming).
  • PersistentKeepalive = 25 — ল্যাপটপ NAT-এর পেছনে, তাই প্রতি ২৫ সেকেন্ডে একটি ছোট packet, যাতে NAT-এর সারি না মোছে (কারণটি পর্ব ২৮-এ দেখেছেন)।
  • চালু আর যাচাই: sudo wg-quick up wg0, তারপর sudo wg show — প্রতিটি peer-এর শেষ handshake কখন আর কত বাইট আদান-প্রদান হলো দেখায়। Gateway-কে router হতে হবে: net.ipv4.ip_forward=1, আর forward chain-এ iifname "wg0" oifname "eth1" ip daddr 10.20.0.0/16 accept ধরনের নিয়ম; firewall-এ UDP 51820 খোলা।

এবার একটি packet ধরে পুরো যাত্রা। ল্যাপটপের বাসার ঠিকানা 192.168.0.105, বাসার router-এর public ঠিকানা 203.0.113.77; অফিস gateway 198.51.100.10:51820; গন্তব্য অফিসের সার্ভার 10.20.0.15:443.

  1. ল্যাপটপ10.8.0.2route: wg0
  2. wg0peer: officeএনক্রিপ্ট
  3. বাসার NAT203.0.113.77UDP পার
  4. অফিস gatewaydecrypt + যাচাইAllowedIPs ✓
  5. সার্ভার10.20.0.15উত্তর ফেরে
ভেতরের আর বাইরের packet
ভেতরের packet
বাইরের packet
সিদ্ধান্ত
  1. অ্যাপ একটি সাধারণ packet পাঠাল। ব্রাউজার 10.20.0.15:443-এ সংযোগ খুলছে। Kernel-এর routing table-এ wg-quick আগেই লিখে রেখেছে: 10.20.0.0/16 dev wg0. তাই packet গেল wg0 নামের virtual interface-এ। আকার 1420 বাইট — wg0-এর MTU-র সমান।
  2. Cryptokey routing: কোন peer? wg0 গন্তব্য 10.20.0.15 নিয়ে peer-গুলোর AllowedIPs খুঁজল — মিলল “office” peer-এর 10.20.0.0/16. সেই peer-এর session key দিয়ে পুরো ভেতরের packet ChaCha20-Poly1305-এ এনক্রিপ্ট হলো; সামনে বসল ১৬ বাইটের header (type 4, receiver index, counter), পেছনে ১৬ বাইটের tag.
  3. UDP-তে মোড়া। এনক্রিপ্টেড অংশ একটি UDP datagram-এ, উৎস ল্যাপটপের 192.168.0.105:47000, গন্তব্য peer-এর endpoint 198.51.100.10:51820. মোট 1420 + 32 + 8 + 20 = 1480 বাইট — 1500-এর মধ্যে, তাই fragmentation নেই।
  4. বাসার NAT পার। বাসার router উৎস বদলে 203.0.113.77:47000 করল — একটি সাধারণ বহির্গামী UDP প্রবাহ। পথের কেউ দেখে শুধু দুই public ঠিকানার মাঝে UDP; ভেতরের ঠিকানা, port বা ডেটা কিছুই নয়।
  5. Gateway: decrypt, যাচাই, AllowedIPs পরীক্ষা। Receiver index দেখে gateway session খুঁজল, tag মিলিয়ে নিশ্চিত হলো packet বদলায়নি, counter দেখে নিশ্চিত হলো এটি পুরোনো packet-এর পুনরাবৃত্তি নয়। Decrypt-এর পর ভেতরের উৎস 10.8.0.2 — laptop peer-এর AllowedIPs-এ আছে, তাই গ্রহণ। Endpoint হিসেবে শিখে রাখল 203.0.113.77:47000. তারপর packet wg0 থেকে বেরিয়ে gateway-এর forward chain পেরিয়ে LAN-এ।
  6. উত্তর ফেরে উল্টো পথে। সার্ভার 10.8.0.2-কে উত্তর দিল; gateway-এর route বলে ঠিকানাটি wg0-এর। Cryptokey routing-এ longest prefix match: 10.8.0.2 → laptop peer. এনক্রিপ্ট করে পাঠানো হলো শেখা endpoint 203.0.113.77:47000-এ — বাসার NAT-এর সারি চালু থাকায় উত্তর ল্যাপটপে পৌঁছায়।

OpenVPN আর TLS-ভিত্তিক VPN

OpenVPN (২০০১ সাল থেকে) TLS দিয়ে key বিনিময় আর certificate দিয়ে পরিচয় যাচাই করে; প্রচলিত port UDP 1194. বহু বছর এটিই ছিল খোলা উৎসের প্রধান remote-access VPN. এটি TCP-র ওপরেও চলে (যেমন TCP 443), যা কড়া firewall পেরোতে সুবিধাজনক — কিন্তু তখন ভেতরের আর বাইরের দুই TCP-ই হারানো packet আবার পাঠায়, আর ক্ষতিপূর্ণ লিংকে দুই স্তরের timer একে অপরকে বাড়িয়ে গতি ভেঙে দেয় — “TCP-over-TCP” সমস্যা। তাই সম্ভব হলে VPN চলে UDP-তে।

৯ · কোন পথে কোন ট্রাফিক — split tunnel, DNS leak, zero trust আর আইন

Split tunnel বনাম full tunnel

উপরের ল্যাপটপ শুধু অফিসের নেটওয়ার্ক tunnel-এ পাঠায় — split tunnel; সাধারণ ব্রাউজিং বাসার ইন্টারনেটেই যায়, অফিসের ব্যান্ডউইথ বাঁচে। Full tunnel (WireGuard-এ AllowedIPs = 0.0.0.0/0, ::/0) সব ট্রাফিক অফিস দিয়ে পাঠায় — সব ট্রাফিকে প্রতিষ্ঠানের নীতি চলে, অচেনা Wi-Fi-তেও সুরক্ষা থাকে, কিন্তু gateway-এর ওপর চাপ বাড়ে আর সেখানে masquerade-ও লাগে।

একটি সূক্ষ্ম ফাঁদ DNS leak: সব ট্রাফিক tunnel-এ গেলেও যন্ত্র যদি DNS প্রশ্ন ISP-র resolver-এ পাঠাতে থাকে, তবে কোন সাইটে যাওয়া হচ্ছে তা বাইরে দেখা যায়, আর অফিসের ভেতরের নামও মেলে না। প্রতিকার: tunnel-এর DNS সার্ভার বসানো (WireGuard-এ DNS =) আর OS সেটিই ব্যবহার করছে কি না যাচাই। Tunnel শুধু IPv4 নিলে IPv6 ট্রাফিকও পাশ দিয়ে বেরোতে পারে।

“VPN” শব্দের দুই অর্থ

বিজ্ঞাপনের “VPN অ্যাপ” আর অফিসের VPN প্রযুক্তিতে কাছাকাছি, উদ্দেশ্যে আলাদা। অফিসের VPN আপনাকে একটি নির্দিষ্ট নেটওয়ার্কে ঢোকায়; consumer VPN আপনার সব ট্রাফিক একটি বাণিজ্যিক প্রতিষ্ঠানের সার্ভার দিয়ে ইন্টারনেটে বের করে. তখন স্থানীয় নেটওয়ার্ক বা ISP গন্তব্য দেখে না, কিন্তু VPN প্রতিষ্ঠান সবই দেখতে পারে — বিশ্বাস সরে যায়, মুছে যায় না। এটি ম্যালওয়্যার, phishing বা দুর্বল পাসওয়ার্ড থেকেও রক্ষা করে না।

Zero trust — “ভেতরে ঢুকলেই বিশ্বাস” নীতির অবসান

প্রচলিত VPN দিয়ে ঢুকলে আপনি “ভেতরের” মানুষ, আর ভেতরের নেটওয়ার্কের অনেক কিছুতে পৌঁছাতে পারেন — আক্রান্ত ল্যাপটপ হলে আক্রমণকারীও তাই পায়। Zero trust network access (ZTNA, ধারণাটি পর্ব ৪৬-এ) এর বিকল্প: প্রতিটি অনুরোধে ব্যবহারকারী, যন্ত্রের অবস্থা আর নির্দিষ্ট অ্যাপ যাচাই করে শুধু সেই অ্যাপে প্রবেশাধিকার, পুরো নেটওয়ার্কে নয়। Google-এর BeyondCorp এর একটি পরিচিত উদাহরণ। বাস্তবে অনেক প্রতিষ্ঠান দুটি একসাথে চালায়।

আইনি দিক: VPN ব্যবহারের নিয়ম দেশভেদে আলাদা — কোথাও সম্পূর্ণ বৈধ, কোথাও লাইসেন্স বা অনুমোদিত সেবাই শুধু চলে, কোথাও সীমাবদ্ধ। বাংলাদেশসহ যেকোনো দেশে প্রতিষ্ঠানের জন্য VPN বসানো বা সেবা দেওয়ার আগে সেই সময়ের প্রযোজ্য আইন আর নিয়ন্ত্রক সংস্থার নির্দেশনা নিজে যাচাই করে নিন; এই পর্ব আইনি পরামর্শ নয়। আর অফিসের VPN-এ প্রতিষ্ঠানের ব্যবহার-নীতি মেনে চলুন।

আরও গভীরে: nftables-এর নিয়ম kernel-এ একটি ছোট virtual machine-এর bytecode হিসেবে চলে — nft নিয়মকে সেই নির্দেশে অনুবাদ করে netlink দিয়ে পাঠায়, তাই নতুন ধরনের match-এর জন্য প্রায়ই kernel বদলাতে হয় না। আরও আগে, network card-এর driver-এর স্তরেই XDP (eBPF) packet ফেলে দিতে পারে — বড় DDoS-এ conntrack পর্যন্ত পৌঁছানোর আগেই। WireGuard-এর handshake-এর নাম Noise_IKpsk2; চাপের সময় এর “cookie” ব্যবস্থা handshake-এর আগে প্রেরকের ঠিকানা যাচাই করায়, আর ESP-এর sequence number ও WireGuard-এর counter দুটোই একই packet দুবার গ্রহণ (replay) ঠেকায়।

পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:

  • Stateless আর stateful firewall-এর পার্থক্য? — প্রথমটি প্রতিটি packet আলাদা দেখে; দ্বিতীয়টি সংযোগের অবস্থা মনে রেখে উত্তর আপনাআপনি ঢুকতে দেয়।
  • ACL-এ কোনো নিয়ম না মিললে কী হয়? — শেষের implicit deny-তে packet বাতিল; আর প্রথম মেলা নিয়মেই সিদ্ধান্ত।
  • DMZ কী আর কেন? — বাইরে-মুখী সার্ভারের আলাদা নেটওয়ার্ক, যাতে সেগুলো দখল হলেও ভেতরের LAN-এ সরাসরি পৌঁছানো না যায়।
  • IPsec-এ AH আর ESP-র পার্থক্য, আর NAT-T কেন? — AH শুধু integrity, ESP এনক্রিপশনও; ESP-তে port নেই বলে NAT পেরোতে UDP 4500-এ মোড়া হয়।
  • WireGuard-এ AllowedIPs কী করে? — বাইরে পাঠাতে কোন peer (routing), আর ভেতরে নিতে উৎস ঠিকানা সেই peer-এর কি না (ACL).

১০ · AI-এর যুগে firewall আর VPN — নিয়ম চালানোর আগে যাচাই

“আমার সার্ভারের জন্য একটি firewall বানিয়ে দাও” — AI কয়েক সেকেন্ডে নিয়ম লিখে দেবে। কিন্তু firewall-এর ভুলের দাম দুই রকম: বেশি খোলা হলে আক্রমণের দরজা, বেশি বন্ধ হলে নিজেই তালাবন্ধ। চেনা ভুলগুলো:

AI-এর ভুলকেন ভুলকীভাবে ধরবেন
“কাজ না করলে সব port খুলে দিন” বা policy accept দিয়ে শুরুসমস্যা খোঁজার শর্টকাট স্থায়ী ফুটো হয়ে যায়Default deny রেখে counter আর log দেখে কোন নিয়মে packet আটকাচ্ছে খুঁজুন
ICMP পুরো বন্ধ করার পরামর্শPMTUD ভাঙে; IPv6-এ NDP বন্ধ হলে নেটওয়ার্কই অচলপর্ব ২০ আর RFC 4890-এর তালিকার সাথে মেলান
নিয়মের ক্রম উল্টো, বা policy drop SSH-এর নিয়মের আগেপ্রথম মিলেই সিদ্ধান্ত; ভুল ক্রমে নিজেই বাইরেঅংশ ২-এর মতো কয়েকটি packet হাতে মেলান; nft -c; ফেরত-টাইমার রাখুন
শুধু IPv4-এর নিয়ম (table ip বা শুধু iptables)IPv6 পুরো খোলা থেকে যায়inet family ব্যবহার করুন, IPv6 ঠিকানা থেকেও পরীক্ষা করুন
iptables আর nftables মিশিয়ে, বা পুরোনো ifconfig/netstatদুই কাঠামোর নিয়ম একসাথে বিভ্রান্তি তৈরি করে; পুরোনো টুল অনেক distribution-এ নেইiptables -V, nft list ruleset, ip, ss দিয়ে নিজের সিস্টেম যাচাই করুন
ভুল VPN হিসাব: “WireGuard-এর MTU 1500”, AllowedIPs-এ সবাইকে 0.0.0.0/0Overhead ভুলে যাওয়া; একাধিক peer-এ একই prefix হলে শেষেরটিই পায়, routing গোলমালঅংশ ৬-এর হিসাব নিজে করুন; প্রতিটি peer-এর AllowedIPs আলাদা আর ন্যূনতম রাখুন
বানানো RFC নম্বর বা vendor-এর কমান্ডকে সর্বজনীন বলাভাষার মডেল বিশ্বাসযোগ্য শোনানো নম্বর আর কমান্ড বানাতে পারেrfc-editor.org-এ শিরোনাম মেলান (ESP 4303, IKEv2 7296, NAT-T 3948); man nft, vendor-এর ডকুমেন্টেশন

AI-কে firewall-এর কাজ দিলে পরিবেশ, সীমা আর যাচাইয়ের পথ স্পষ্ট করে দিন:

আমার একটি Linux সার্ভার আছে: [distribution আর সংস্করণ এখানে লেখো]। এতে চলে nginx (TCP 80, 443) আর SSH (TCP 22). আমি SSH করি শুধু 10.20.0.0/24 থেকে। IPv4 আর IPv6 দুটোই চালু। ১. nftables-এ একটি inet table দিয়ে ruleset লেখো: policy drop, loopback, established/related, invalid drop, SSH শুধু ওই subnet থেকে, 80/443 সবার জন্য, আর PMTUD ও IPv6 NDP-র জন্য দরকারি ICMP/ICMPv6. ২. প্রতিটি লাইনের মানে বাংলায় ব্যাখ্যা করো, আর কোনো লাইন বাদ দিলে কী ভাঙবে তা বলো। ৩. দূর থেকে বসানোর সময় নিজেকে তালাবন্ধ না করার নিরাপদ ধাপ দাও (nft -c দিয়ে যাচাই, ফেরত যাওয়ার টাইমার)। ৪. আমার নিজের দ্বিতীয় যন্ত্র থেকে নিয়মগুলো কীভাবে পরীক্ষা করব তা বলো; অন্য কারও নেটওয়ার্কে কিছু করতে বলবে না। ৫. কোনো RFC বা ডকুমেন্টেশনের উল্লেখ করলে নাম আর নম্বর দাও; নিশ্চিত না হলে স্পষ্ট বলো।

AI-এর firewall বা VPN পরামর্শ প্রয়োগের আগে — চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।

প্র ০১“শক্ত বাইরের খোলস, নরম ভেতর” — সীমানার একটি বড় firewall-এর ওপর ভরসা করা নিরাপত্তা-নকশা কেন ধীরে ধীরে দুর্বল প্রমাণিত হলো?

নব্বইয়ের দশকে একটি প্রতিষ্ঠানের নেটওয়ার্ককে দুর্গের মতো ভাবা হতো: ইন্টারনেটের সাথে একটিমাত্র সংযোগ, সেখানে একটি firewall, আর ভেতরে সবাই বিশ্বস্ত। Bellovin আর Cheswick নিজেরাই এই ধারণার সীমা নিয়ে সতর্ক করেছিলেন — ভেতরের নেটওয়ার্ককে তাঁরা “শক্ত খোলসের ভেতরে নরম, চিবানো যায় এমন কেন্দ্র” বলে বর্ণনা করেছিলেন। তখনকার বাস্তবতায় নকশাটি যুক্তিসংগত ছিল: কর্মীরা অফিসে বসতেন, সার্ভার অফিসের ঘরে, আর বাইরে যাওয়ার পথ একটাই।

তারপর একের পর এক দেয়াল ফুটো হলো। ল্যাপটপ বাসা আর কফিশপ ঘুরে ভেতরে ফেরে। ইমেইল আর ওয়েবসাইট দিয়ে ম্যালওয়্যার সরাসরি কর্মীর যন্ত্রে পৌঁছায় — firewall তা “বৈধ outbound ট্রাফিকের উত্তর” হিসেবেই ঢুকতে দেয়। VPN দিয়ে বাইরের যন্ত্র ভেতরের মানুষ হয়ে যায়, আর cloud আসার পর সার্ভারই আর অফিসের ঘরে থাকে না।

বড় বড় ঘটনায় একটি নকশা বারবার দেখা গেছে: আক্রমণকারী একটি দুর্বল জায়গা দিয়ে ঢোকে — একটি phishing ইমেইল, একটি সরবরাহকারীর অ্যাকাউন্ট — তারপর সমতল ভেতরের নেটওয়ার্কে নির্বিঘ্নে ঘুরে মূল্যবান সার্ভারে পৌঁছায়। এজন্যই নকশা বদলেছে তিন দিকে: ভেতরের ভাগ (segmentation, microsegmentation), প্রতিটি host-এ নিজের firewall, আর zero trust — যেখানে প্রতিটি অনুরোধে পরিচয় আর যন্ত্রের অবস্থা যাচাই হয়, নেটওয়ার্কে অবস্থান নয়। Google-এর BeyondCorp প্রকল্পটি এই চিন্তার পরিচিত উদাহরণ, যেখানে কর্মীদের অভ্যন্তরীণ অ্যাপে প্রবেশাধিকার VPN-এর বদলে পরিচয় আর যন্ত্রের অবস্থার ওপর নির্ভর করে।

তবে সীমানার firewall অর্থহীন হয়ে যায়নি। ইন্টারনেট থেকে আসা স্বয়ংক্রিয় স্ক্যান আর সাধারণ আক্রমণের বড় অংশ সেটিই থামায়, আর egress filtering-এর জায়গাও সেটি। পরিবর্তনটা হলো ভূমিকায়: একমাত্র দেয়াল থেকে অনেক স্তরের একটি স্তর।

মূল উপলব্ধি: নিরাপত্তার সীমানা এখন আর একটি ভৌগোলিক রেখা নয়; তা প্রতিটি যন্ত্র, প্রতিটি অ্যাপ আর প্রতিটি অনুরোধে ভাগ হয়ে গেছে। সীমানার firewall দরকার, কিন্তু যথেষ্ট নয়।

প্র ০২Stateful firewall stateless-এর চেয়ে নিরাপদ, তবু data center-এর কিছু অংশে, ISP-র router-এ আর cloud-এর network ACL-এ stateless নিয়মই রাখা হয়। কেন?

State মনে রাখার দাম আছে। প্রতিটি সংযোগের জন্য একটি সারি — 5-tuple, অবস্থা, timeout, NAT-এর তথ্য — memory নেয়, আর প্রতিটি নতুন সংযোগে সারি বানানো, খোঁজা আর মোছার কাজ CPU নেয়। একটি ছোট অফিসের জন্য এটা নগণ্য। কিন্তু একটি ISP-র core router প্রতি সেকেন্ডে কোটি কোটি packet পার করে, লাখো আলাদা প্রবাহ; সেখানে প্রতিটি প্রবাহের অবস্থা রাখা ব্যয়বহুল, আর hardware-এর দ্রুততম পথ (ASIC) সাধারণত সরল, অবস্থাহীন মেলানোর জন্যই তৈরি।

দ্বিতীয় সমস্যা আক্রমণ। State table নিজেই একটি সীমিত সম্পদ; জাল উৎস-ঠিকানার অগণিত SYN packet পাঠিয়ে table ভরিয়ে দিলে stateful firewall নতুন বৈধ সংযোগও নিতে পারে না — তখন firewall-ই DDoS-এর লক্ষ্য। তাই বড় সেবার সামনে প্রায়ই প্রথমে stateless ছাঁকনি (বা XDP-এর মতো খুব আগের স্তরের ছাঁকনি) বসে, যা স্পষ্ট আবর্জনা ফেলে দেয়, আর তার পেছনে stateful স্তর।

তৃতীয় কারণ পথের অসমতা। বড় নেটওয়ার্কে একটি সংযোগের যাওয়া আর ফেরা ভিন্ন router দিয়ে হতে পারে (asymmetric routing). Stateful firewall যদি শুধু এক দিকের packet দেখে, ফিরতি packet-কে সে চেনে না — INVALID ভেবে ফেলে দেয়। Stateless নিয়ম এতে ভাঙে না।

Cloud-এ দুটি একসাথে রাখার পেছনেও স্তরভিত্তিক চিন্তা: subnet-এর সীমানায় মোটা দাগের stateless ACL, আর প্রতিটি যন্ত্রের পাশে সূক্ষ্ম, stateful security group. দাম: stateless ACL-এ ফিরতি ট্রাফিকের ephemeral port-এর পরিসর ভুলে গেলে সব সংযোগ রহস্যজনকভাবে আটকে যায়।

মূল উপলব্ধি: “কোনটি ভালো” প্রশ্নের উত্তর নির্ভর করে কোথায় বসছে তার ওপর। State নিরাপত্তা আর সরলতা দেয়, কিন্তু memory, গতি আর আক্রমণ-সহনশীলতার দামে; বাস্তব নেটওয়ার্ক দুটিকে স্তরে স্তরে মেলায়।

প্র ০৩Linux-এ firewall-এর টুল চারবার বদলেছে — ipfwadm, ipchains, iptables, nftables. প্রতিবার কী সমস্যার সমাধান হলো, আর এত বছর পরেও iptables কেন রয়ে গেছে?

Linux 2.0-এর ipfwadm ছিল BSD-র ipfw-এর ধাঁচে একটি সরল packet filter. Linux 2.2-এর ipchains নিয়মগুলোকে “chain”-এ সাজায়, যাতে নিজের chain বানিয়ে নিয়ম পুনর্ব্যবহার করা যায়। কিন্তু দুটিই মূলত stateless ছিল, আর NAT ছিল আলাদা জোড়াতালি।

১৯৯৮ সালে Rusty Russell netfilter প্রকল্প শুরু করেন, আর Linux 2.4-এর সাথে এল netfilter-এর hook, connection tracking আর iptables. বড় পরিবর্তন তিনটি: stateful filtering (conntrack), NAT-কে একই কাঠামোয় আনা, আর module দিয়ে নতুন match আর target যোগ করার সুবিধা। প্রায় দুই দশক ধরে Linux-এর firewall মানেই iptables ছিল — অসংখ্য স্ক্রিপ্ট, বই, router-এর firmware আর Docker-এর মতো টুল এর ওপর দাঁড়িয়ে।

কিন্তু iptables-এর নকশার সমস্যা জমছিল। IPv4, IPv6, ARP আর bridge-এর জন্য আলাদা আলাদা টুল আর kernel কোড (iptables, ip6tables, arptables, ebtables). প্রতিটি নতুন match-এর জন্য kernel module. আর ruleset বদলানো মানে পুরো table userspace-এ এনে বদলে আবার kernel-এ পাঠানো — হাজার নিয়মের সিস্টেমে ধীর। nftables (Linux 3.13, ২০১৪) সমাধান দেয় একটি ছোট virtual machine দিয়ে: kernel-এ সাধারণ কিছু নির্দেশ, আর নতুন ধরনের মেলানো userspace-এর nft অনুবাদ করে দেয়। একটি টুল সব family-র জন্য, set আর map দিয়ে দ্রুত খোঁজা, আর পরিবর্তন একবারে (atomic).

iptables টিকে আছে অভ্যাস আর বিপুল বিদ্যমান স্ক্রিপ্টের কারণে। এজন্যই সমাধান এসেছে iptables-nft আকারে — পুরোনো ভাষা, নতুন kernel কাঠামো। অনেক বড় distribution ডিফল্টে nftables-এর পেছনের দিকে চলে গেছে, তবু নির্দেশিকা আর AI-এর উত্তরে iptables এখনো প্রচুর দেখা যায়।

মূল উপলব্ধি: অবকাঠামোর টুল বদলায় ধীরে, কারণ পুরোনো ভাষায় লেখা জ্ঞান আর স্বয়ংক্রিয় কাজ বিশাল। ভালো রূপান্তর পুরোনো ভাষাকে নতুন ভিত্তির ওপর চালু রাখে — আর প্রকৌশলীকে জানতে হয় নিজের যন্ত্রে আসলে কোনটি চলছে।

প্র ০৪WireGuard ইচ্ছা করেই “cryptographic agility” (অ্যালগরিদম বেছে নেওয়ার স্বাধীনতা) বাদ দিয়েছে, যা IPsec আর TLS-এর মূল বৈশিষ্ট্য। এটি দূরদর্শী সিদ্ধান্ত, নাকি ঝুঁকি?

Cryptographic agility-র যুক্তি সহজ: কোনো অ্যালগরিদম ভাঙলে protocol না বদলে অন্য অ্যালগরিদমে চলে যাওয়া যায়। IPsec আর TLS তাই দুই প্রান্তের মাঝে আলোচনা করে কোন অ্যালগরিদম চলবে। কিন্তু বাস্তবে এই স্বাধীনতার দাম চড়া হয়েছে। আলোচনার কোডই আক্রমণের লক্ষ্য হয়েছে: TLS-এর ইতিহাসে বেশ কয়েকটি বড় আক্রমণ (যেমন FREAK আর Logjam, ২০১৫) দুই প্রান্তকে পুরোনো, দুর্বল “export” মানের অ্যালগরিদমে নামিয়ে আনার কৌশল ব্যবহার করেছে — যা কেবল এজন্যই সম্ভব ছিল যে বিকল্পগুলো তখনো সমর্থিত ছিল। পুরোনো অ্যালগরিদম “সামঞ্জস্যের জন্য” বছরের পর বছর চালু থাকে।

WireGuard-এর নকশাকারীরা উল্টো পথে গেলেন: একটি নির্দিষ্ট, আধুনিক অ্যালগরিদম-গুচ্ছ, কোনো আলোচনা নেই। কোনোটি দুর্বল প্রমাণিত হলে protocol-এর নতুন সংস্করণ আসবে, আর সব প্রান্ত সেটিতে হালনাগাদ হবে। এতে কোড ছোট থাকে, ভুল কনফিগারেশনের সুযোগ প্রায় নেই, আর আনুষ্ঠানিক যাচাই (formal verification) সহজ হয় — WireGuard-এর handshake নিয়ে গবেষকেরা কম্পিউটার-সহায়িত প্রমাণও করেছেন।

ঝুঁকিটাও বাস্তব। কোনো অ্যালগরিদমে হঠাৎ গুরুতর দুর্বলতা পাওয়া গেলে সারা পৃথিবীর যন্ত্র একসাথে হালনাগাদ করা কঠিন; পুরোনো router বা embedded যন্ত্র বছরের পর বছর হালনাগাদ পায় না। কিছু নিয়ন্ত্রিত পরিবেশে নির্দিষ্ট মানের অ্যালগরিদম বাধ্যতামূলক (যেমন সরকারি মানদণ্ড), আর সেগুলো WireGuard-এর গুচ্ছে না থাকলে সেখানে IPsec-ই বেছে নিতে হয়। আর quantum কম্পিউটারের সম্ভাব্য হুমকি নিয়ে প্রস্তুতিতেও প্রশ্ন ওঠে — WireGuard একটি ঐচ্ছিক pre-shared key রেখেছে, যা বাড়তি একটি স্তর হিসেবে ব্যবহার করা যায়।

মূল উপলব্ধি: নিরাপত্তায় বিকল্প মানে আক্রমণের পৃষ্ঠও। “কম কিন্তু সঠিক” নকশা পর্যালোচনা আর প্রয়োগ সহজ করে; তার দাম হালনাগাদের শৃঙ্খলা আর কিছু পরিবেশে নমনীয়তার অভাব।

প্র ০৫অনেক firewall এখন TLS ভেঙে ভেতরের ট্রাফিক দেখে (TLS inspection), আবার QUIC আর encrypted DNS এমন দেখা প্রায় অসম্ভব করছে। নিরাপত্তা দল আর গোপনীয়তার এই টানাপোড়েন কীভাবে দেখবেন?

Firewall-এর ইতিহাস এক অর্থে দৃশ্যমানতার ইতিহাস। প্রথমে port দেখেই অ্যাপ চেনা যেত — 80 মানে ওয়েব, 25 মানে মেইল। তারপর সব কিছু port 443-এ HTTPS-এর ভেতরে চলে গেল, আর port অর্থহীন হলো। NGFW তখন TLS handshake-এর খোলা অংশ (যেমন সার্ভারের নাম, SNI) দেখে অ্যাপ চিনতে শুরু করে, আর আরও গভীরে দেখতে কিছু প্রতিষ্ঠান TLS inspection চালু করে: প্রতিষ্ঠানের যন্ত্রে নিজস্ব একটি root certificate বসিয়ে firewall প্রতিটি সংযোগ মাঝপথে খুলে দেখে, তারপর আবার এনক্রিপ্ট করে পাঠায়।

এর পক্ষে যুক্তি আছে: ম্যালওয়্যার আর ডেটা পাচার এখন প্রায় সবই এনক্রিপ্টেড, না দেখলে ধরা যায় না। কিন্তু খরচও বড়। গবেষণায় দেখা গেছে, অনেক inspection পণ্য নিজে যে সংযোগ খোলে তা মূলের চেয়ে দুর্বল — পুরোনো protocol, দুর্বল যাচাই। ব্যাংক বা স্বাস্থ্যের মতো সংবেদনশীল সাইটও খোলা হয়ে যায়, আর certificate pinning-এর মতো সুরক্ষা ভাঙে। একটি বড় “মাঝের মানুষ” নিজেই আক্রমণের মূল্যবান লক্ষ্য।

অন্যদিকে protocol-নকশাকারীরা ক্রমেই বেশি তথ্য এনক্রিপ্ট করছেন: TLS 1.3 certificate লুকায়, QUIC প্রায় পুরো transport header এনক্রিপ্ট করে (পর্ব ৩৩), DNS over HTTPS প্রশ্নগুলো ওয়েব ট্রাফিকের মতো করে দেয়, আর Encrypted Client Hello সার্ভারের নামও লুকানোর দিকে এগোচ্ছে। ফলে নেটওয়ার্কের মাঝখান থেকে দেখার সুযোগ কমছে, আর নিরাপত্তা দল দৃশ্যমানতা খুঁজছে প্রান্তে — যন্ত্রের endpoint সুরক্ষা, ব্রাউজারের নীতি আর পরিচয়-ভিত্তিক প্রবেশাধিকারে।

নৈতিক দিকটিও স্পষ্ট রাখা দরকার: প্রতিষ্ঠানের যন্ত্রে, স্বচ্ছ নীতি আর আইনের সীমার মধ্যে inspection একটি সিদ্ধান্ত; ব্যক্তির অজান্তে তার ট্রাফিক খোলা আরেক জিনিস।

মূল উপলব্ধি: এনক্রিপশন নেটওয়ার্কের মাঝখানকে অন্ধ করছে, আর সেটা ইচ্ছাকৃত। নিরাপত্তার দৃষ্টি তাই সরে যাচ্ছে মাঝের বাক্স থেকে প্রান্তে আর পরিচয়ে — firewall থাকছে, কিন্তু সে আর সব দেখে না।

অনুশীলন

খাতা-কলম নিন — নিয়ম, অবস্থা আর বাইট ধরে ধরে হিসাব করুন।

  1. হাতে মেলান (ACL): একটি ACL: (১) permit tcp 10.0.0.0/8 → any port 80; (২) deny tcp 10.5.0.0/16 → any; (৩) permit udp any → 10.9.9.9/32 port 53; (৪) permit tcp any → any port 443. শেষে implicit deny. এই packet-গুলোর ফল কী, আর কোন নিয়মে? (ক) tcp 10.5.1.1 → 192.0.2.10:80; (খ) tcp 10.5.1.1 → 192.0.2.10:443; (গ) udp 172.16.0.4 → 10.9.9.9:53; (ঘ) tcp 172.16.0.4 → 10.9.9.9:53. লেখকের ইচ্ছা ছিল 10.5.0.0/16-এর সব TCP বন্ধ — কীভাবে ঠিক করবেন?

    (ক) নিয়ম ১, PERMIT — 10.5.1.1 /8-এর মধ্যে, port 80; নিয়ম ২ পর্যন্ত যাওয়াই হয় না। (খ) নিয়ম ১ মেলে না (port 443), নিয়ম ২, DENY. (গ) নিয়ম ১, ২ TCP-র, মেলে না; নিয়ম ৩, PERMIT. (ঘ) TCP, port 53: নিয়ম ১ (port 80 নয়), ২ (উৎস 172.16, /16-এর বাইরে), ৩ (UDP-র), ৪ (port 443 নয়) — কোনোটিই মেলে না, implicit deny. (বাস্তবে বড় DNS উত্তরের জন্য TCP 53-ও লাগে — পর্ব ৩৫.)

    ঠিক করা: নির্দিষ্ট নিয়ম ওপরে — deny tcp 10.5.0.0/16 → any নিয়মটিকে নিয়ম ১-এর আগে নিন। তখন (ক) DENY হবে, আর বাকি 10.0.0.0/8 আগের মতো port 80 পাবে। এটাই অংশ ২-এর “ছায়া পড়া নিয়ম”-এর সমস্যা।

  2. হিসাব (tunnel MTU): একটি বাসার সংযোগ PPPoE, তাই underlay MTU 1492. (ক) এর ওপর IPv4-এ WireGuard চালালে ভেতরের সর্বোচ্চ MTU কত? (খ) ভেতরে IPv4 TCP-র MSS কত? (গ) কেউ ডিফল্ট 1420 রেখে দিলে বড় packet-এর কী হবে? (ঘ) একই লিংকে IPsec ESP tunnel mode (AES-GCM, IV 8, ICV 16) আর NAT-T থাকলে ভেতরের সর্বোচ্চ packet কত (ESP payload + ২ বাইট trailer ৪-এর গুণিতক)?

    (ক) 1492 − 60 = 1432. (খ) 1432 − 20 − 20 = 1392. (গ) 1420 + 60 = 1480 ≤ 1492, তাই কোনো সমস্যা নেই — 1420 ছোট বলে নিরাপদ; শুধু ১২ বাইট করে অপচয়। উল্টো ক্ষেত্রে, যদি কেউ MTU 1440 রাখেন: 1440 + 60 = 1500 > 1492 — বাইরের packet বড় হয়ে যায়, fragment হয় বা PMTUD-র ওপর নির্ভর করে; ICMP আটকানো থাকলে black hole.

    (ঘ) স্থির অংশ: বাইরের IPv4 20 + UDP 8 (NAT-T) + ESP header 8 + IV 8 + ICV 16 = 60, আর trailer 2. তাই P + 2 ≤ 1492 − 60 = 1432, অর্থাৎ P ≤ 1430; আর P + 2 = 1432 ৪-এর গুণিতক (1432 ÷ 4 = 358) — তাই P = 1430. যাচাই: 20 + 8 + 8 + 8 + 1432 + 16 = 1492.

  3. আউটপুট অনুমান করুন: অংশ ৩-এর stateful simulator-এ শুধু allowNewIn বদলে p === "tcp" && (dp === 443 || dp === 22) করা হলো, আর TIMEOUT-এ udp: 30 বদলে udp: 120. কোন কোন লাইন বদলাবে, আর শেষে কতটি সারি থাকবে?
    t=2  in  tcp 203.0.113.9:40000 -> 10.0.0.5:22         NEW         ACCEPT
    ...
    t=70  in  udp 198.51.100.53:53 -> 10.0.0.5:53000       ESTABLISHED ACCEPT
    entries left: 4

    t=2-এর SSH সংযোগ এখন অনুমোদিত, তাই ACCEPT আর একটি নতুন সারি। t=70-এ DNS সারির নীরবতা 70 − 5 = 65 সেকেন্ড, যা 120-এর কম — তাই “expired” লাইন আর আসে না, উত্তর ESTABLISHED হিসেবে ACCEPT. শেষে সারি চারটি: HTTPS বহির্গামী, SSH, HTTPS অন্তর্গামী আর DNS. বাকি লাইন অপরিবর্তিত। শিক্ষা: বড় timeout দেরিতে আসা উত্তর বাঁচায়, কিন্তু table-এ বেশি সারি জমে।

  4. কমান্ড লিখুন (nftables): একটি Linux gateway-এর LAN eth1 (192.168.1.0/24), WAN eth0, আর WireGuard wg0 (10.8.0.0/24). inet family-তে একটি forward chain লিখুন: নীতি drop; চালু সংযোগ অনুমোদিত, invalid বাতিল; LAN থেকে ইন্টারনেটে নতুন সংযোগ; wg0 থেকে শুধু LAN-এর TCP 443 আর 22; আর বাকি বাতিল হওয়ার আগে সীমিত log.
    # উদাহরণ — root লাগে, শুধু নিজের ল্যাব বা VM-এ; nft -c -f দিয়ে আগে যাচাই
    table inet gw {
        chain forward {
            type filter hook forward priority filter; policy drop;
            ct state vmap { established : accept, related : accept, invalid : drop }
            iifname "eth1" oifname "eth0" accept
            iifname "wg0" oifname "eth1" ip daddr 192.168.1.0/24 tcp dport { 22, 443 } accept
            limit rate 10/minute log prefix "gw-fwd-drop: "
        }
    }

    প্রথম নিয়মেই ফিরতি ট্রাফিক চলে যায়, তাই LAN-এর ইন্টারনেট বা VPN ব্যবহারকারীর উত্তরের জন্য আলাদা নিয়ম লাগে না। wg0-এর নিয়মে interface, গন্তব্য ব্লক আর port তিনটিই আছে — VPN ব্যবহারকারী পুরো LAN-এ সব সেবা পান না, শুধু যা দরকার (least privilege). সাথে লাগবে net.ipv4.ip_forward=1, আর LAN থেকে ইন্টারনেটের জন্য postrouting-এ masquerade (পর্ব ১৯). LAN-এর যন্ত্রগুলো যাতে 10.8.0.0/24-এ উত্তর পাঠাতে পারে, gateway-ই তাদের default gateway হওয়া দরকার, নইলে আলাদা route.

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি Linux router-এর ভেতর দিয়ে LAN থেকে ইন্টারনেটে যাওয়া নতুন সংযোগের প্রথম packet-এর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. LAN interface দিয়ে packet ঢোকে; PREROUTING-এ conntrack সারি না পেয়ে অবস্থা NEW দেয়
  2. Routing সিদ্ধান্ত: গন্তব্য এই যন্ত্রের নয়, বেরোবে WAN interface দিয়ে
  3. FORWARD hook-এ filter chain-এর নিয়ম মেলানো হয় আর accept হয়
  4. POSTROUTING-এ masquerade উৎস ঠিকানা বদলায়
  5. Conntrack সারিটি পাকা করে, আর packet WAN interface দিয়ে বেরিয়ে যায়

একটি ACL-এ নিয়ম তিনটি, এই ক্রমে: (১) permit tcp 192.168.0.0/16 → any port 443; (২) deny ip 192.168.5.0/24 → any; (৩) permit ip any → any. TCP packet: উৎস 192.168.5.9, গন্তব্য 198.51.100.7, port 443. কী হবে?

  • নিয়ম ২-এ DENY
  • Implicit deny-তে বাতিল
  • নিয়ম ১-এ PERMIT
  • নিয়ম ৩-এ PERMIT

Linux conntrack-এ একটি চালু TCP সংযোগ নিয়ে পথের একটি router থেকে ICMP “Fragmentation Needed” বার্তা এল। এর অবস্থা কী, আর একটি সাধারণ stateful ruleset এর সাথে কী করে?

  • NEW — নির্দিষ্ট নিয়ম না থাকলে বাতিল
  • RELATED — “established, related accept” নিয়মে গ্রহণ
  • INVALID — বাতিল
  • ESTABLISHED — সংযোগের অংশ হিসেবে গ্রহণ

একটি IPsec VPN-এর দুই gateway-এর একটি বাসার PAT router-এর পেছনে। ESP-কে NAT পেরোতে সাধারণত কী করা হয়?

  • ESP-এর বদলে AH ব্যবহার করা হয়
  • Tunnel mode বদলে transport mode করা হয়
  • শুধু UDP 500 খোলা হয়
  • NAT-T — ESP-কে UDP port 4500-এ মুড়ে পাঠানো হয়

একটি WireGuard gateway-এর peer A-র AllowedIPs = 10.8.0.2/32, peer B-র AllowedIPs = 10.8.0.3/32, 192.168.50.0/24. Peer A-র key দিয়ে আসা একটি packet সফলভাবে decrypt হলো; তার ভেতরের উৎস 192.168.50.7. Gateway কী করে?

  • Packet বাতিল করে, কারণ উৎস ঠিকানাটি A-র AllowedIPs-এ নেই
  • Decrypt সফল, তাই গ্রহণ করে
  • Packet-টি peer B-র কাছে পাঠিয়ে দেয়
  • A-র AllowedIPs-এ 192.168.50.7 যোগ করে নেয়

IPv4 underlay-এর MTU 1500. এর ওপর WireGuard (বাইরের IPv4 20, UDP 8, WireGuard header 16, tag 16 বাইট) চললে ভেতরের সর্বোচ্চ MTU কত?

  • 1420
  • 1440
  • 1460
  • 1500

AWS-ধরনের cloud-এ একটি subnet-এর network ACL-এ inbound TCP 443 অনুমোদিত, outbound-এ শুধু TCP 443 অনুমোদিত। ভেতরের ওয়েব সার্ভারে বাইরের ব্যবহারকারীরা সংযোগ করতে পারছেন না। সবচেয়ে সম্ভাব্য কারণ কী?

  • Security group stateless বলে উত্তর আটকাচ্ছে
  • Inbound নিয়মে port 443 ভুল
  • Network ACL stateless, তাই outbound-এ ফিরতি ট্রাফিকের জন্য ephemeral port-এর পরিসর খোলা নেই
  • ICMP বন্ধ থাকায় TCP handshake হয় না

একটি প্রতিষ্ঠানের ওয়েব আর মেইল সার্ভার DMZ-এ রাখা হয়েছে। DMZ আর ভেতরের LAN-এর মাঝের firewall-এ কোন নীতি সবচেয়ে যুক্তিসংগত?

  • DMZ থেকে LAN-এ সব ট্রাফিক অনুমোদিত, কারণ দুটোই প্রতিষ্ঠানের
  • ইন্টারনেট থেকে LAN-এ সরাসরি সংযোগ অনুমোদিত, DMZ শুধু বাড়তি
  • দুই দিকেই সব ট্রাফিক বন্ধ
  • DMZ থেকে LAN-এ শুধু নির্দিষ্ট প্রয়োজনীয় সংযোগ, LAN থেকে DMZ-এ নিয়ন্ত্রিত ব্যবস্থাপনা

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. ACL: উপর থেকে নিচে, প্রথম মেলা নিয়মেই সিদ্ধান্ত, শেষে implicit deny. নির্দিষ্ট নিয়ম ওপরে; নইলে “ছায়া পড়া” নিয়ম।
  2. Stateful = conntrack: NEW, ESTABLISHED, RELATED, INVALID. মানক নকশা — established/related accept, invalid drop, নির্দিষ্ট NEW accept, বাকি drop. UDP-র “সংযোগ” timeout-নির্ভর; ICMP error RELATED.
  3. নকশা: host + network firewall, DMZ (DMZ → LAN প্রায় বন্ধ), ভেতরের ভাগ, আর egress filtering. Cloud-এ security group stateful, network ACL stateless.
  4. Linux: hook — PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING. nftables-এ inet table, policy drop, set, vmap, counter, সীমিত log; বসানোর আগে nft -c আর ফেরত-টাইমার; ICMP আর ICMPv6-এর জরুরি বার্তা খোলা।
  5. VPN: tunnel + এনক্রিপশন + পরিচয়। WireGuard overhead IPv4-এ ৬০ (→ 1440), IPv6-এ ৮০ (→ 1420); IPsec ESP + IKEv2 + NAT-T (UDP 4500); WireGuard-এর AllowedIPs = routing + ACL. Split tunnel-এ DNS leak সামলাতে হয়; zero trust প্রতিটি অনুরোধ যাচাই করে।

পরের পর্বে: firewall আর VPN কাদের ঠেকাতে চায় — DDoS, IP spoofing, ARP আর DNS-এর জালিয়াতি, man-in-the-middle; সেগুলো ধারণাগতভাবে কীভাবে কাজ করে, আর IDS/IPS, BCP 38 ও rate limiting দিয়ে প্রতিরক্ষা কীভাবে সাজানো হয়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান