နားလည်ထားရမယ့် အချက်
Bug အများစုက ကိုယ့်ဘာသာကိုယ် အော်ပြောတတ်တယ် — crash ဖြစ်တယ်၊ stack trace ထွက်တယ်၊ test နီသွားတယ်။ Subnet bug ကတော့ ဘာမှ မပြောဘူး။ Networking ထဲမှာ လူ့အာရုံနဲ့ စက်ရဲ့ arithmetic က တစ်ထပ်တည်း တူနေတဲ့ နေရာဆိုတာ ဒီတစ်ခုပဲ ရှိတယ် — ကွဲထွက်တဲ့ အချိန်ရောက်မှ ကွာသွားတာ။ 192.168.10.20 နဲ့ 192.168.10.130 ကို မြင်လိုက်ရင် "နှစ်ခုလုံး 192.168.10 နဲ့ စတယ်၊ ဒါဆို network တစ်ခုတည်းပေါ့" လို့ တွေးမိတယ်။ /24 ဖြစ်ခဲ့ရင် အဲဒါ မှန်တယ်။ 192.168.10.0/24 ထဲက host တိုင်းဟာ broadcast domain တစ်ခုတည်းကို တကယ် မျှသုံးတာမို့ ရှေ့ octet သုံးလုံးကို နှိုင်းယှဉ်ပြီး ဆုံးဖြတ်တဲ့ code ဟာ ရေးထားသမျှ test အားလုံးကို အောင်မြင်စွာ ဖြတ်သွားမယ်။ ပြီးတော့ တစ်နေ့မှာ warehouse scanner တွေကို finance machine တွေနဲ့ ခွဲထားဖို့ အဲဒီ /24 ကို /26 လေးခုအဖြစ် ခွဲလိုက်တယ်။ Code ကတော့ ယုံကြည်မှုအပြည့်နဲ့ အဖြေအဟောင်းကိုပဲ ဆက်ပြနေဦးမယ် — အောက်က အမှန်တရားကတော့ တိတ်တဆိတ် ပြောင်းသွားပြီးဖြစ်ပေမယ့်ပေါ့။
ဒါက bug class ပါပဲ — subnet membership ကို interface မှာ တကယ် config လုပ်ထားတဲ့ mask နဲ့ မဟုတ်ဘဲ octet အာရုံနဲ့ ဆုံးဖြတ်လိုက်တာ။ Helper တစ်ခုထဲမှာ /24 ကို hardcode လုပ်ထားတာ၊ address prefix ကို string အနေနဲ့ နှိုင်းယှဉ်တာ၊ နောက်ဆုံး octet ကို သုည ပြောင်းပြီး network address တွက်တာ — သုံးမျိုးလုံး အမှားတစ်ခုတည်းကို အဝတ်အစား လဲဝတ်ထားတာပါ။ Mask ကို ဖတ်မယ့်အစား ယူဆလိုက်တာ။
အန္တရာယ်အများဆုံး အကြောင်းရင်းကတော့ crash မဖြစ်လို့ပဲ။ Crash ဖြစ်ရင် ticket ဖွင့်ဖြစ်တယ်။ ယုံကြည်မှုအပြည့်နဲ့ မှားနေတဲ့ reachability report ကတော့ ယုံကြည်ခံရတယ်။ Engineer တစ်ယောက်က DIRECT ဆိုတာ ဖတ်လိုက်၊ switch path ကောင်းနေတယ်လို့ ကောက်ချက်ချလိုက်ပြီး path ထဲမှာ ကတည်းကမပါတဲ့ firewall ကို တစ်ရက်လုံး လိုက်ရှာနေတယ်။ ဒါကို ဖမ်းနိုင်တဲ့ အလေ့အကျင့်က ရိုးရှင်းတယ် — address တစ်ခုကနေ network ကို လက်နဲ့ မတွက်နဲ့။ address နဲ့ သူ့ရဲ့ တကယ့် prefix နှစ်ခုလုံးကို Python ရဲ့ ipaddress module ကို ပေးလိုက်ပြီး AND လုပ်ခိုင်းပါ။ ပြီးရင် mask boundary ကို ဖြတ်ပြီး test လုပ်ပါ — /24 ချည်းပဲ သုံးထားတဲ့ test suite က ဒီ failure ကို လုံးဝ မမြင်နိုင်ဘူး။
ONE /24 OR FOUR /26 BLOCKS?
---------------------------
Real config: 192.168.10.0/24 carved into four /26 blocks of 64
.0 ------ .63 .64 ----- .127 .128 ---- .191 .192 ---- .255
+-------------+ +-------------+ +-------------+ +-------------+
| SUBNET A | | SUBNET B | | SUBNET C | | SUBNET D |
| reception | | warehouse | | server-nas | | (unused) |
| .20 | | .70 | | .130 | | |
| sales .50 | | | | | | |
+------+------+ +------+------+ +------+------+ +-------------+
| | |
+-------+-------+-------+-------+
| |
+--------------------------------+
| GATEWAY 192.168.10.1 |
| routes between the /26 blocks |
+--------------------------------+
The script assumes /24, so it sees ONE flat subnet:
+-----------------------------------------------------------+
| 192.168.10.0/24 everybody DIRECT, gateway never needed |
+-----------------------------------------------------------+
^ this is the lieလက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Debug လုပ်ရမယ့် ရုံးခန်း network ကို အရင်ကြည့်ရအောင်။ ရှေ့ပိုင်း ရုံးခန်းနဲ့ နောက်ဖေး warehouse ကို ခွဲလိုက်တဲ့အခါ 192.168.10.0/24 range တစ်ခုတည်းကို /26 လေးခုအဖြစ် ခွဲလိုက်တယ်။ Reception (.20) နဲ့ sales laptop (.50) က 192.168.10.0/26 ထဲမှာ။ Warehouse scanner (.70) က 192.168.10.64/26 ထဲမှာ။ NAS (.130) က 192.168.10.128/26 ထဲမှာ။ 192.168.10.1 က gateway ဖြစ်ပြီး အဲဒီ /26 တွေကြားမှာ route လုပ်ပေးတယ်။
အောက်က script ကို ရေးထားတဲ့အတိုင်း အတိအကျ run ကြည့်ပါ။ Error မတက်ဘူး၊ warning မပေးဘူး၊ ပြီးတော့ အလွန် professional ဆန်တဲ့ report တစ်ခု ထုတ်ပေးတယ် — host table၊ dash မျဉ်း၊ ပြီးရင် host အတွဲတိုင်းအတွက် အဖြေတစ်ကြောင်းစီ။ Host table ကို အရင်ဖတ်ပါ၊ သက်သေက အဲဒီမှာ ရှိတယ်။ Row တိုင်းကို မတူတဲ့ /26 နဲ့ config လုပ်ထားပေမယ့် row တိုင်းက net= တန်ဖိုး တစ်ခုတည်းကိုပဲ ပြနေတယ်။ အောက်က အဖြေတွေကို ဖတ်ကြည့်ရင် အတွဲ ခြောက်တွဲလုံးက DIRECT လို့ ပြောနေတယ်။
အခု အတွဲတစ်တွဲအတွက် လက်နဲ့ တွက်ကြည့်ပါ။ /26 ဆိုတာ address 64 လုံးမို့ block boundary တွေက .0၊ .64၊ .128 နဲ့ .192 မှာ ကျတယ်။ .70 က ဘယ် block ထဲလဲ။ .130 က ဘယ် block ထဲလဲ။ အဲဒီ ဂဏန်းနှစ်လုံးကို ချရေးပြီးတာနဲ့ report က သူ့ဟာသူ ကိုယ့်ကိုယ်ကို ဆန့်ကျင်နေတာ မျက်စိရှေ့မှာ ပေါ်လာမယ်။ ကျန်တာက မုသားပြောစေတဲ့ code လိုင်းကို ရှာဖွေဖို့ပဲ။
အတူတူ စမ်းရေးကြည့်မယ်
"""Office network reachability checker.
Every host is configured in CIDR notation. Two hosts can talk directly
through the switch when they share a subnet; otherwise the packet has to
be handed to the gateway. This script prints a report -- check it against
the configured masks by hand before you trust it.
"""
import ipaddress
HOSTS = {
"reception-pc": "192.168.10.20/26",
"sales-laptop": "192.168.10.50/26",
"warehouse-scanner": "192.168.10.70/26",
"server-nas": "192.168.10.130/26",
}
GATEWAY = "192.168.10.1"
# The office is "a 192.168.10.x network", so a /24 is close enough. Right?
ASSUMED_PREFIX = 24
def network_of(cidr):
"""Return the network this host address belongs to."""
addr = cidr.split("/")[0]
return ipaddress.ip_network(addr + "/" + str(ASSUMED_PREFIX), strict=False)
def same_subnet(cidr_a, cidr_b):
"""True when both hosts sit in the same subnet."""
return network_of(cidr_a) == network_of(cidr_b)
def main():
print("HOST TABLE")
print("-" * 62)
for name in HOSTS:
cidr = HOSTS[name]
print("{:<20} {:<20} net={}".format(name, cidr, network_of(cidr)))
print()
print("REACHABILITY REPORT")
print("-" * 62)
names = list(HOSTS)
for i in range(len(names)):
for j in range(i + 1, len(names)):
a = names[i]
b = names[j]
if same_subnet(HOSTS[a], HOSTS[b]):
verdict = "DIRECT (switch only)"
else:
verdict = "VIA GATEWAY " + GATEWAY
print("{:<20} -> {:<20} {}".format(a, b, verdict))
main()
HOST TABLE
--------------------------------------------------------------
reception-pc 192.168.10.20/26 net=192.168.10.0/24
sales-laptop 192.168.10.50/26 net=192.168.10.0/24
warehouse-scanner 192.168.10.70/26 net=192.168.10.0/24
server-nas 192.168.10.130/26 net=192.168.10.0/24
REACHABILITY REPORT
--------------------------------------------------------------
reception-pc -> sales-laptop DIRECT (switch only)
reception-pc -> warehouse-scanner DIRECT (switch only)
reception-pc -> server-nas DIRECT (switch only)
sales-laptop -> warehouse-scanner DIRECT (switch only)
sales-laptop -> server-nas DIRECT (switch only)
warehouse-scanner -> server-nas DIRECT (switch only)
၅ မိနစ် စမ်းကြည့်
လက္ခဏာက ဒီလိုပါ — script က error မတက်ဘဲ အဆင်ပြေပြေ run ပြီး host အတွဲ ခြောက်တွဲလုံး switch ကနေ တိုက်ရိုက် ဆက်သွယ်နိုင်တယ်လို့ ပြောတယ်။ Network team ကတော့ warehouse scanner ဟာ router ကို မဖြတ်ဘဲ NAS ကို မရောက်နိုင်ဘူးလို့ တစ်ခွန်းတည်း ပြောနေတယ်။ တစ်ဖက်ဖက်က မှားနေတယ်။
သံသယအရှိဆုံး ဖြစ်သင့်တဲ့ row နှစ်ကြောင်းကနေ စပါ — warehouse-scanner -> server-nas နဲ့ reception-pc -> server-nas။ HOSTS dict ထဲက အဲဒီ host တွေရဲ့ config လုပ်ထားတဲ့ CIDR ကို ယူပြီး၊ report က ပြနေတဲ့ prefix မဟုတ်ဘဲ အဲဒီမှာ တကယ်ရေးထားတဲ့ prefix ကို သုံးပြီး network address ကို လက်နဲ့ တွက်ကြည့်ပါ။ ပြီးရင် ကိုယ်တွက်ထားတဲ့ network address လေးခုကို host table က host တိုင်းအတွက် ပြနေတဲ့ net= တန်ဖိုး တစ်ခုတည်းနဲ့ နှိုင်းယှဉ်ပါ။
တာဝန်ရှိတဲ့ လိုင်းကို တွေ့ပြီဆိုရင် host တစ်ခုချင်းစီရဲ့ ကိုယ်ပိုင် prefix ကို သုံးအောင် ပြင်ပြီး ပြန် run ပါ။ မှန်ကန်တဲ့ report ဆိုရင် အတွဲ တစ်တွဲတည်းကိုသာ DIRECT ပြပြီး ကျန် ငါးတွဲကို VIA GATEWAY ပြရမယ်။ နောက်ဆုံးအဆင့်အနေနဲ့ fix က တကယ် အလုပ်ဖြစ်မဖြစ် သက်သေပြပါ — host အားလုံးကို /24 ပြောင်းပြီး report က DIRECT ချည်းပဲ ပြန်ဖြစ်သွားလား စစ်ပါ။ ဖြစ်သွားရင် မူလ bug ဟာ test တွေကို ဘာကြောင့် ဒီလောက်ကြာအောင် လွတ်သွားနိုင်ခဲ့တာလဲဆိုတာကိုပါ ကိုယ်တိုင် သက်သေပြလိုက်ပြီးဖြစ်တယ်။
သတိလေးတစ်ချက်
Interface မှာ config လုပ်ထားတဲ့ mask ကို ဖတ်မယ့်အစား helper ထဲမှာ prefix length (အများအားဖြင့် /24) ကို hardcode လုပ်ထားတာ။ တစ်ယောက်ယောက်က subnet ခွဲလိုက်တဲ့နေ့အထိ code က မှန်နေမယ်၊ အဲဒီနောက်တော့ ယုံကြည်မှုအပြည့်နဲ့ အမြဲ မှားနေတော့မယ်။
IP address တွေကို string အနေနဲ့ နှိုင်းယှဉ်တာ။ '192.168.1.10' < '192.168.1.9' ဟာ စာသားအနေနဲ့ True၊ address အနေနဲ့ False ဖြစ်တယ်။ ဒါကြောင့် sorting၊ range check နဲ့ ACL matching အားလုံး တိတ်တဆိတ် မှားကုန်တယ်။ နှိုင်းယှဉ်တိုင်း ipaddress.ip_address() နဲ့ အရင် ပြောင်းပါ။
Python documentation - ipaddress: IPv4/IPv6 manipulation library — Computer Networking