နားလည်ထားရမယ့် အချက်
Port number ဆိုတာ ရုပ်ပိုင်းဆိုင်ရာ အရာတစ်ခု မဟုတ်ပါဘူး။ သင့်စက်ရဲ့ နောက်ကျောမှာ 443 လို့ နံပါတ်တပ်ထားတဲ့ ပေါက်တစ်ခု မရှိပါဘူး။ Port ဆိုတာ transport header ထဲက 16-bit ကိန်းတစ်ခုဖြစ်ပြီး၊ သူ့တာဝန်တစ်ခုတည်းက demultiplexing ပါ — IP address တစ်ခုက စက်တစ်လုံးဆီ ရောက်လာပေမယ့်၊ အဲဒီစက်မှာ program အများကြီး run နေပြီး၊ ဒီ bytes တွေကို ဘယ် program ဆီ ပေးရမလဲ ဆုံးဖြတ်ဖို့ kernel က key တစ်ခု လိုအပ်ပါတယ်။ Port က အဲဒီ key ဖြစ်ပါတယ်။ IP က data ကို မှန်ကန်တဲ့ host ဆီ ပို့ပေးပြီး၊ port က အဲဒီ host ပေါ်က မှန်ကန်တဲ့ process ဆီ ပို့ပေးပါတယ်။
IANA က တန်ဖိုး 65,536 ခုကို range သုံးခု ခွဲထားပါတယ်။ Well-known port တွေ (0–1023) က စံ service တွေအတွက် ဖြစ်ပြီး Unix မှာ bind လုပ်ဖို့ အခွင့်အရေး လိုအပ်ပါတယ် — ဒါကြောင့်ပဲ web server တွေက port 80 ကို ရယူဖို့အတွက်သာ root အဖြစ် စတင်ခဲ့ကြတာ ဖြစ်ပါတယ်။ Registered port တွေ (1024–49151) ကို တောင်းဆိုမှုအရ သီးခြား application တွေအတွက် သတ်မှတ်ပေးထားပါတယ်။ Ephemeral port တွေ (49152–65535) ကတော့ connection တစ်ခုရဲ့ သင့်ဘက်က ယာယီ source port လိုအပ်တဲ့အခါ kernel က ဆွဲယူတဲ့ ရေကန် ဖြစ်ပါတယ် — ဒါတွေကို သင် ဘယ်တော့မှ ရွေးလိုက်တာ မဟုတ်ဘဲ၊ တကယ့် range ကလည်း operating system အလိုက် ကွဲပြားပါတယ်။
လူတွေ လွဲမှားတတ်တဲ့ အချက်ကတော့ port တစ်ခုတည်းက connection တစ်ခုကို မသတ်မှတ်ပေးဘူး ဆိုတာပါ။ 4-tuple ကသာ သတ်မှတ်ပေးတာဖြစ်ပြီး — source IP, source port, destination IP, destination port ဖြစ်ပါတယ်။ ဒါက ရောက်လာတဲ့ segment တစ်ခုကို မှန်ကန်တဲ့ socket ဆီ ပို့ဖို့ kernel က hash လုပ်တဲ့ အရာ ဖြစ်ပါတယ်။ ဒါကြောင့်ပဲ web server တစ်လုံးဟာ port 443 တစ်ခုတည်းပေါ်မှာ connection ထောင်ပေါင်းများစွာကို တစ်ပြိုင်နက် ကိုင်တွယ်နိုင်တာ ဖြစ်ပါတယ် — အားလုံးက တူညီတဲ့ destination IP နဲ့ port ကို မျှသုံးပေမယ့်၊ တစ်ခုစီမှာ ကွဲပြားတဲ့ source IP နဲ့ source port ရှိလို့ tuple နှစ်ခု ဘယ်တော့မှ မထပ်ပါဘူး။ "connection တစ်ခုက port တစ်ခု ကုန်တယ်" ဆိုတဲ့ ရိုးရာ အယူအဆ မှားက ဒီနေရာက လာပြီး၊ တကယ့် ကန့်သတ်ချက်က ကွဲပြားတဲ့ tuple အရေအတွက် ဖြစ်ကာ အဲဒါက အများကြီး ပိုများပါတယ်။
THE 4-TUPLE: WHAT ACTUALLY IDENTIFIES A CONNECTION
--------------------------------------------------
( src IP , src port , dst IP , dst port )
| | | |
| | | +-- which service (443 = https)
| | +------------ which machine (the server)
| +---------------------- kernel-picked, per connection
+-------------------------------- which machine (the client)
Three clients, ONE listening port on the server:
203.0.113.7 :52001 ---+
|
203.0.113.7 :52002 ---+----> 198.51.100.10 : 443
| (one listening socket)
203.0.113.9 :52001 ---+
Server-side connection table:
src ip src port dst ip dst port conn
----------- -------- -------------- -------- ----
203.0.113.7 52001 198.51.100.10 443 #1
203.0.113.7 52002 198.51.100.10 443 #2
203.0.113.9 52001 198.51.100.10 443 #3
The right-hand columns are IDENTICAL on every row. The tuples
still differ, so the kernel never confuses one conn for another.
Port ranges (IANA):
0 - 1023 well-known privileged to bind on Unix
1024 - 49151 registered assigned on request
49152 - 65535 ephemeral kernel picks your source portလက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
HTTPS connection ၂၀,၀၀၀ ကို terminate လုပ်နေတဲ့ load balancer တစ်ခုကို စဉ်းစားကြည့်ပါ။ တစ်ခုစီတိုင်းမှာ destination port က 443 ဖြစ်ပြီး destination IP ကလည်း အတူတူပါပဲ၊ ဒါပေမယ့် ဘယ်တစ်ခုမှ အချင်းချင်း အနှောင့်အယှက် မဖြစ်ပါဘူး။ ရောက်လာတဲ့ segment တစ်ခုစီမှာ source IP နဲ့ source port ပါလာပြီး၊ kernel က 4-tuple အပြည့်ကို ကြည့်ပြီး မှန်ကန်တဲ့ socket ကို ရှာပါတယ်။ Port 443 ပေါ်က listening socket ကတော့ ပဉ္စမ အရာတစ်ခုဖြစ်ပြီး — သူက connection အသစ်တွေကို လက်ခံရုံသာ လုပ်ကာ၊ ဆက်သွယ်ပြီးသား connection တွေက သူတို့ကိုယ်ပိုင် entry တွေထဲမှာ သီးခြား ရှိနေပါတယ်။
Tuple က တကယ် ကိုက်ခဲစေတဲ့ နေရာက client ဘက်မှာ ဖြစ်ပါတယ်။ တူညီတဲ့ destination ဆီ အထွက် connection အများကြီး ဖွင့်နေတဲ့ စက်တစ်လုံးဟာ သူ့ရဲ့ ephemeral port range ကြောင့် ကန့်သတ်ခံရပါတယ် — source IP, destination IP, destination port သုံးခုစလုံး သတ်မှတ်ပြီးသား ဖြစ်နေတဲ့အခါ ကျန်တဲ့ ပြောင်းလဲနိုင်တဲ့ field က source port တစ်ခုတည်းသာ ကျန်လို့ပါ — Linux default range နဲ့ဆိုရင် တစ်ပြိုင်နက် connection ၂၈,၀၀၀ ဝန်းကျင်သာ ရပါတယ်။ ဒါက load testing လုပ်နေစဉ် တွေ့ရတဲ့ "cannot assign requested address" error အတိအကျ ဖြစ်ပြီး၊ ဖြေရှင်းနည်းတွေက tuple ကနေ တိုက်ရိုက် ဆင်းသက်လာပါတယ် — ephemeral range ကို ကျယ်ပေးပါ၊ source IP ထပ်ဖြည့်ပါ၊ ဒါမှမဟုတ် TIME_WAIT socket တွေကို လျှော့ပါ။
အောက်က code က destination တစ်ခုတည်းကို မျှသုံးတဲ့ 4-tuple အများအပြားကို တည်ဆောက်ပြပြီး၊ သူတို့ ကွဲပြားနေဆဲ ဖြစ်ကြောင်း ပြသကာ၊ port number အနည်းငယ်ကို IANA range တွေအဖြစ် ခွဲခြားပေးပါတယ်။
အတူတူ စမ်းရေးကြည့်မယ်
# IANA port ranges. No sockets are opened here -- this is pure arithmetic
# over numbers that the kernel would use as demultiplexing keys.
RANGES = (
(0, 1023, "well-known"),
(1024, 49151, "registered"),
(49152, 65535, "ephemeral"),
)
def classify(port):
if not 0 <= port <= 65535:
raise ValueError("a port is a 16-bit number: %d" % port)
for low, high, name in RANGES:
if low <= port <= high:
return name
def fmt(conn):
return "%s:%-5d -> %s:%d" % conn
# Four connections all arriving at the SAME server port.
connections = [
("203.0.113.7", 52001, "198.51.100.10", 443),
("203.0.113.7", 52002, "198.51.100.10", 443),
("203.0.113.9", 52001, "198.51.100.10", 443),
("203.0.113.9", 61000, "198.51.100.10", 443),
]
print("4-tuples seen by the server:")
for conn in connections:
print(" ", fmt(conn))
print()
print("distinct 4-tuples :", len(set(connections)))
print("distinct dst ip:port :", len({(c[2], c[3]) for c in connections}))
print("=> one listening port, four independent connections")
print()
print("%-8s %s" % ("port", "range"))
print("-" * 24)
for port in (22, 80, 443, 3000, 8080, 52001, 65535):
print("%-8d %s" % (port, classify(port)))
4-tuples seen by the server:
203.0.113.7:52001 -> 198.51.100.10:443
203.0.113.7:52002 -> 198.51.100.10:443
203.0.113.9:52001 -> 198.51.100.10:443
203.0.113.9:61000 -> 198.51.100.10:443
distinct 4-tuples : 4
distinct dst ip:port : 1
=> one listening port, four independent connections
port range
------------------------
22 well-known
80 well-known
443 well-known
3000 registered
8080 registered
52001 ephemeral
65535 ephemeral၅ မိနစ် စမ်းကြည့်
connections list ထဲကို ဒုတိယ server တစ်ခု (ဥပမာ destination port 80 ကို ပြောင်း) ထည့်ပြီး distinct dst ip:port အရေအတွက် ဘယ်လို ပြောင်းလဲသွားလဲ ကြည့်ပါ။ ပြီးရင် source IP နဲ့ destination ကို ပုံသေထားပြီး ephemeral range (49152-65535) ကနေ ဘယ်နှစ်ခု တစ်ပြိုင်နက် connection ဖွင့်လို့ရလဲ တွက်ပြပါ။
သတိလေးတစ်ချက်
"Connection တစ်ခုက server ပေါ်မှာ port တစ်ခု ကုန်တယ်" လို့ ထင်ခြင်း — server က port 443 တစ်ခုတည်းပေါ်မှာ connection ထောင်ပေါင်းများစွာ ကိုင်နိုင်ပြီး၊ ကန့်သတ်ချက်က ကွဲပြားတဲ့ 4-tuple အရေအတွက်နဲ့ file descriptor limit ဖြစ်ပါတယ်
Ephemeral range ကို 49152-65535 လို့ hard-code လုပ်ခြင်း — တကယ့် range က OS အလိုက် ကွဲပြားပြီး Linux default က 32768-60999 ဖြစ်လို့၊ port classification logic က မမှန်တဲ့ အဖြေ ပေးနိုင်ပါတယ်
IANA — Service Name and Transport Protocol Port Number Registry — Computer Networking