SSD Nodes Learn 🎉 VPS เริ่ม $5.50/เดือน
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-08-21

วิธีตรวจสอบพอร์ตที่เปิดใช้งานบน Linux ด้วยคำสั่ง ss และ nc

เรียนรู้วิธีตรวจสอบพอร์ตบน Linux อย่างถูกต้องด้วยคำสั่ง ss เพื่อดูสถานะการฟัง และใช้ nc หรือ nmap ทดสอบจากภายนอก พร้อมอธิบายความแตกต่างระหว่างพอร์ตที่ถูกบล็อกและพอร์ตที่ปิดสนิท

การตรวจสอบว่าพอร์ตเปิดอยู่หรือไม่บน Linux: เลือกคำถามที่ถูกต้องก่อน

ในการตรวจสอบว่าพอร์ตเปิดอยู่หรือไม่บน Linux ให้ตัดสินใจก่อนว่าคุณกำลังถามคำถามอะไร เพราะคำว่า "เปิด" มีความหมายต่างกันในแต่ละจุดที่คุณตรวจสอบ บนตัวเซิร์ฟเวอร์เอง คำว่าเปิดหมายถึงมี process ผูกอยู่กับพอร์ตนั้นและกำลังรอการเชื่อมต่อ จากเครื่องอื่น คำว่าเปิดหมายถึงแพ็กเก็ตเดินทางไปถึง process นั้นและได้รับคำตอบกลับมา เมื่อไม่มีคำตอบกลับมา คำถามที่แท้จริงคืออุปกรณ์ใดเป็นตัวทิ้งแพ็กเก็ตนั้น sudo ss -ltnp ใช้ตอบคำถามแรก nc -z หรือ nmap ใช้ตอบคำถามที่สอง ส่วนตัวนับของ Firewall และ tcpdump ใช้ตอบคำถามที่สาม

การตรวจสอบด้วยวิธีที่ผิดคือสาเหตุที่ทำให้เสียเวลาไปทั้งบ่าย การทดสอบบนเซิร์ฟเวอร์จะไม่ผ่าน Firewall ของผู้ให้บริการเครือข่าย เพราะตัวกรองนั้นอยู่นอกตัวเครื่อง หากคุณยังใหม่กับเรื่องหมายเลขพอร์ต วิธีการทำงานของพอร์ตและซ็อกเก็ตบน Linux จะครอบคลุมถึงรูปแบบที่คู่มือนี้ใช้เป็นพื้นฐาน

อะไรกำลังฟังพอร์ตอยู่บนเครื่องนี้? อ่านผลลัพธ์จาก ss

ss มาพร้อมกับ iproute2 จึงมีอยู่ในทุก distribution ปัจจุบัน ส่วน netstat มาจาก net-tools ซึ่ง Ubuntu ไม่ได้ติดตั้งเป็นค่าเริ่มต้นมาหลายปีแล้ว ดังนั้น netstat -tulpn จึงมักจะตอบกลับด้วย netstat: command not found ให้เรียนรู้การใช้ ss เพื่อหลีกเลี่ยงความผิดหวัง

sudo ss -ltnp

-l แสดงเฉพาะ socket ที่กำลังฟังอยู่เท่านั้น -t จำกัดรายการให้เหลือเพียง TCP -n แสดงผลเป็นตัวเลขแทนการแปลงชื่อ ทำให้คำสั่งทำงานได้ทันที -p ระบุชื่อ process ที่เป็นเจ้าของ ซึ่งจำเป็นต้องใช้สิทธิ์ root หากไม่มี sudo คอลัมน์ Process จะว่างเปล่าสำหรับทุก process ที่คุณไม่ได้เป็นเจ้าของ ให้สลับ -t เป็น -u เพื่อดู UDP

State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
LISTEN 0      4096   127.0.0.53%lo:53    0.0.0.0:*   users:(("systemd-resolve",pid=612,fd=14))
LISTEN 0      128    0.0.0.0:22          0.0.0.0:*   users:(("sshd",pid=921,fd=3))
LISTEN 0      511    127.0.0.1:8080      0.0.0.0:*   users:(("node",pid=1442,fd=19))
LISTEN 0      128    [::]:22             [::]:*      users:(("sshd",pid=921,fd=4))

คอลัมน์ Local Address เป็นตัวตัดสินทุกอย่าง และเป็นคอลัมน์ที่คนมักจะมองข้ามไป

  • 0.0.0.0:22 หมายถึงทุก IPv4 address บนเครื่อง ดังนั้นจึงสามารถเข้าถึงได้จากภายนอกหาก firewall อนุญาต
  • [::]:22 คือความหมายเดียวกันสำหรับ IPv6
  • 127.0.0.1:8080 หมายถึง loopback เท่านั้น ไม่มีอะไรจากภายนอกเครื่องนี้ที่สามารถเข้าถึงได้
  • 10.20.0.5:5432 หมายถึง address ของ interface นั้นเพียงอย่างเดียว ซึ่งเป็นเรื่องปกติในการตั้งค่าเครือข่ายส่วนตัว
  • คอลัมน์ Process ที่ว่างเปล่ามักเกิดจากการขาดสิทธิ์ sudo ไม่ใช่เพราะไม่มี process นั้นอยู่จริง

หากต้องการตรวจสอบพอร์ตใดพอร์ตหนึ่ง ให้กรองภายใน ss แทนการใช้ grep กับรายการทั้งหมด:

sudo ss -ltnp 'sport = :8080'
sudo lsof -nP -iTCP:8080 -sTCP:LISTEN
sudo fuser 8080/tcp

ผลลัพธ์ที่ว่างเปล่าจากทั้งสามคำสั่งหมายความว่าไม่มีอะไรถือพอร์ตนั้นอยู่ บริการอาจหยุดทำงาน, เริ่มต้นไม่สำเร็จ หรือกำลังฟังอยู่ที่อื่น ให้ตรวจสอบ systemctl status <unit> และ journalctl -u <unit> -n 50 ก่อนที่คุณจะแตะต้องกฎ firewall แม้แต่ข้อเดียว

เหตุผลที่การใช้ 127.0.0.1 ใน Local Address ทำให้เสียเวลาทั้งบ่าย

Socket ที่ถูก bind ไว้กับ 127.0.0.1 จะไม่สามารถเข้าถึงได้จากโฮสต์อื่น และไม่มีกฎ firewall ใดที่เปลี่ยนเรื่องนี้ได้ Kernel จะส่งต่อ 127.0.0.0/8 ไปยัง loopback interface เท่านั้น และแพ็กเก็ตที่มีที่อยู่ปลายทางดังกล่าวซึ่งเข้ามาทาง network card จริงจะถูกทิ้งเนื่องจากถือว่าเป็น martian packet ดังนั้นกระบวนการทำงานจึงรันอยู่ ss แสดงสถานะว่ากำลังฟังอยู่ ufw allow 8080 รายงานว่าสำเร็จ แต่การเชื่อมต่อจากแล็ปท็อปของคุณยังคงล้มเหลว มันล้มเหลวด้วย Connection refused ทันที เพราะแพ็กเก็ตไปถึง public address ของคุณแล้ว แต่ไม่พบ socket ที่ bind ไว้ที่นั่น Kernel จึงตอบกลับด้วย TCP reset

โปรแกรมจำนวนมากตั้งใจ bind ไว้ที่ loopback ซึ่งเป็นค่าเริ่มต้นที่เหมาะสมสำหรับฐานข้อมูลหรืออินเทอร์เฟซผู้ดูแลระบบ คุณมีทางเลือกที่ถูกต้องสองทาง คือเปลี่ยน bind address ในไฟล์คอนฟิกของโปรแกรมนั้น (listen_addresses ใน postgresql.conf, bind ใน redis.conf หรืออาร์กิวเมนต์ host ที่แอปพลิเคชันของคุณรับค่า) แล้วจึงเปิด firewall หรือปล่อยให้มันอยู่ที่ loopback แล้วเข้าถึงผ่านช่องทางอื่น เช่น nginx reverse proxy หรือ SSH tunnel จากแล็ปท็อปของคุณ:

ssh -L 8080:127.0.0.1:8080 user@203.0.113.10

Docker มีความแตกต่างในลักษณะเดียวกันในแฟล็ก publish ของมัน -p 8080:8080 จะ bind กับ 0.0.0.0 และเปิดเผย container สู่สาธารณะ ส่วน -p 127.0.0.1:8080:8080 จะ bind กับ loopback และจำกัดไว้เฉพาะภายในเครื่องเท่านั้น

วิธีตรวจสอบว่าพอร์ตเปิดอยู่หรือไม่บน Linux จากเครื่องอื่น

ให้ทำการทดสอบนี้จากเครือข่ายอื่น การทดสอบจากภายในเซิร์ฟเวอร์เองจะพิสูจน์ได้เพียงว่าเส้นทาง loopback ทำงานได้เท่านั้น แม้แต่การเชื่อมต่อไปยัง Public IP ของคุณเองจากเซิร์ฟเวอร์ก็ยังข้าม firewall ของผู้ให้บริการไปได้ เพราะตัวกรองนั้นทำงานอยู่นอก VPS ของคุณ

nc -zv -w 3 203.0.113.10 443

-z จะทำการเชื่อมต่อและปิดการเชื่อมต่อโดยไม่ส่งข้อมูล -w 3 จะยกเลิกการทำงานหลังจากผ่านไป 3 วินาที ซึ่ง flag นี้มีความสำคัญมาก หากไม่มีการกำหนด timeout แพ็กเก็ตที่ถูกทิ้งจะทำให้ client พยายามส่ง SYN ซ้ำนานกว่า 2 นาที ก่อนที่ kernel จะหยุดทำงาน ผลลัพธ์ที่สำเร็จจะมีลักษณะดังนี้:

Connection to 203.0.113.10 443 port [tcp/https] succeeded!

หากไม่มีเครื่องมือดังกล่าว (nc: command not found) ให้ติดตั้ง netcat-openbsd บน Debian หรือ Ubuntu หรือใช้ฟีเจอร์การเปลี่ยนเส้นทางเครือข่าย (network redirection) ที่มีมาใน bash ซึ่งไม่จำเป็นต้องติดตั้งแพ็กเกจใดๆ เพิ่มเติม:

timeout 3 bash -c '</dev/tcp/203.0.113.10/443' && echo open || echo "no answer"

ไวยากรณ์ดังกล่าวเป็นฟีเจอร์ของ bash ดังนั้นให้รันด้วย bash ส่วน /bin/sh บน Debian และ Ubuntu คือ dash ซึ่งไม่มี /dev/tcp และจะรายงานว่าไม่พบ path ดังกล่าว สำหรับการตรวจสอบพอร์ตหลายพอร์ตพร้อมกัน หรือเมื่อคุณต้องการให้ระบุสถานะอย่างชัดเจน ให้ใช้ nmap กับโฮสต์ที่คุณดูแลอยู่:

sudo nmap -Pn -p 22,80,443 203.0.113.10
sudo nmap -Pn -p 1-1024 203.0.113.10

-Pn จะข้ามขั้นตอนการค้นหาโฮสต์ (host discovery) ผู้ให้บริการ VPS ส่วนใหญ่จะบล็อก ICMP echo ดังนั้นหากไม่มี -Pn ตัว nmap จะตัดสินว่าโฮสต์นั้นออฟไลน์และไม่ทำการสแกน nmap จะแสดงผล open เมื่อมีบางอย่างตอบรับและยอมรับการเชื่อมต่อ แสดงผล closed เมื่อมีการตอบกลับด้วยการ reset และแสดงผล filtered เมื่อไม่มีการตอบกลับใดๆ เลย สำหรับบริการเว็บ curl -sS -o /dev/null -w '%{http_code}\n' https://example.com จะช่วยแยกแยะระหว่างความผิดพลาดของเครือข่ายและความผิดพลาดของแอปพลิเคชันได้ เพราะรหัสสถานะ (status code) เป็นตัวพิสูจน์ว่าเส้นทางทั้งหมดทำงานได้อย่างสมบูรณ์

เหตุใดพอร์ตที่ถูกบล็อกจึงค้าง แต่พอร์ตที่ปิดอยู่จึงปฏิเสธการเชื่อมต่อทันที

การปฏิเสธการเชื่อมต่อทันที แพ็กเก็ตเดินทางถึงเครื่องเป้าหมายและมีบางอย่างตอบกลับมา

nc: connect to 203.0.113.10 port 443 (tcp) failed: Connection refused

สาเหตุที่แตกต่างกันสองประการทำให้เกิดผลลัพธ์นี้ ประการแรกคือไม่มีกระบวนการ (process) ใดผูกอยู่กับที่อยู่และพอร์ตนั้น เคอร์เนลจึงตอบกลับด้วย TCP reset หรือประการที่สองคือกฎของไฟร์วอลล์ปฏิเสธแพ็กเก็ตด้วยการส่ง reset หรือข้อความ ICMP port unreachable กลับมา การปฏิเสธคือคำตอบที่ชัดเจนและเกิดขึ้นภายในหนึ่งรอบการรับส่งข้อมูล (round trip)

การหยุดชะงักตามด้วย timeout มีบางอย่างทิ้งแพ็กเก็ตไปโดยไม่มีการตอบกลับใดๆ

nc: connect to 203.0.113.10 port 443 (tcp) timed out: Operation now in progress

นี่คือสิ่งที่กฎ DROP ทำ และเป็นสิ่งที่ไฟร์วอลล์ของผู้ให้บริการหรือ cloud security group ทำ ความเงียบคือสัญลักษณ์ของการทิ้งแพ็กเก็ต เพราะผู้ส่งไม่สามารถแยกแยะได้ว่าการที่ไม่มีการตอบกลับนั้นเกิดจากการทิ้งแพ็กเก็ตหรือโฮสต์ปลายทางตาย

อาการที่เกิดขึ้นจะบอกคุณว่าควรตรวจสอบที่ใดต่อไป หากได้รับคำตอบว่า refused หมายความว่าแพ็กเก็ตเดินทางผ่านเครือข่ายได้ตามปกติ ให้กลับไปที่ ss -ltnp เพื่อตรวจสอบ bind address และหมายเลขพอร์ต หากได้รับคำตอบว่า timed out หมายความว่าแพ็กเก็ตกำลังถูกทิ้ง ให้ตรวจสอบไฟร์วอลล์จากภายนอกเข้ามาภายใน ความแตกต่างระหว่าง refused กับ timed out บน SSH อธิบายการแยกแยะอาการนี้สำหรับพอร์ต 22 ซึ่งเป็นจุดที่ผู้ใช้ส่วนใหญ่พบปัญหานี้

ufw มีพฤติกรรมทั้งสองแบบให้เลือกใช้โดยเจตนา: ufw deny 8080 คือการ drop และ ufw reject 8080 คือการส่งการปฏิเสธ (reject) ใน nftables เป้าหมายทั้งสองคือ drop และ reject ส่วนใน iptables คือ -j DROP และ -j REJECT โดยปกติแล้วนโยบายเริ่มต้น (default policy) มักจะเป็นการ drop ซึ่งเป็นเหตุผลว่าทำไมการ ไม่มี กฎที่กำหนดไว้จึงทำให้เกิดอาการค้างแทนที่จะได้รับข้อความแสดงข้อผิดพลาด

ใครเป็นผู้บล็อกพอร์ต? เริ่มตรวจสอบจากภายนอกเข้าสู่ภายใน

sudo ufw status verbose
sudo iptables -L INPUT -n -v --line-numbers
sudo nft list ruleset

ตัวนับใน -v คือส่วนที่มีประโยชน์ ให้รันการทดสอบ nc ของคุณจากภายนอก จากนั้นรันคำสั่ง iptables อีกครั้ง แล้วสังเกตว่าตัวนับใดมีการเปลี่ยนแปลง กฎที่จำนวนแพ็กเก็ตเพิ่มขึ้นคือกฎที่จัดการทราฟฟิกของคุณ วิธีนี้ช่วยให้คุณมีหลักฐานยืนยันแทนการคาดเดา

การทดสอบที่ชี้ชัดให้รันบนเซิร์ฟเวอร์เพื่อเฝ้าดูการรับส่งข้อมูลในขณะที่คุณเชื่อมต่อจากภายนอก:

sudo tcpdump -ni any tcp port 8080

หากมี SYN เข้ามาแต่ไม่มี SYN-ACK ตอบกลับ แสดงว่าแพ็กเก็ตมาถึง VPS ของคุณแล้วแต่โฮสต์เป็นผู้ทิ้งแพ็กเก็ตนั้น ดังนั้นไฟร์วอลล์ของผู้ให้บริการจึงทำงานปกติ แต่กฎในเครื่องของคุณมีปัญหา หากไม่มีผลลัพธ์ใดๆ แสดงว่าแพ็กเก็ตไม่เคยมาถึง ซึ่งสาเหตุมาจากไฟร์วอลล์ของผู้ให้บริการ, security group หรือที่อยู่ IP ไม่ถูกต้อง การแยกแยะจุดนี้เพียงจุดเดียวจะช่วยลดภาระงานส่วนใหญ่ลงได้

มีสองชั้นที่ทำให้ผลลัพธ์ดูเหมือนเป็นไปไม่ได้ ชั้นแรกคือ IPv6: หากชื่อโฮสต์มีระเบียน AAAA ไคลเอนต์ของคุณอาจเชื่อมต่อผ่าน IPv6 ในขณะที่กฎของคุณครอบคลุมเฉพาะ IPv4 ดังนั้นให้ทดสอบแต่ละตระกูลด้วย nc -4 และ nc -6 ก่อนที่จะเชื่อผลลัพธ์ใดผลลัพธ์หนึ่ง กฎ ufw และพอร์ต IPv6 บน VPS จะอธิบายถึงความไม่สอดคล้องนี้ ชั้นที่สองคือ Docker: พอร์ตของคอนเทนเนอร์ที่ถูกเผยแพร่จะตอบสนองจากอินเทอร์เน็ตแม้ว่า ufw status จะแสดงรายการว่าพอร์ตนั้นถูกปฏิเสธก็ตาม เนื่องจากแพ็กเก็ตเหล่านั้นถูกจัดการก่อนที่จะถึง chain ของ ufw เหตุใด Docker จึงเผยแพร่พอร์ตโดยข้าม ufw มีคำอธิบายกลไกและวิธีแก้ไข และ กฎ ufw ที่ควรตั้งค่าบน VPS ใหม่ คือชุดกฎพื้นฐานที่ควรมีไว้ก่อน

เหตุใดคำตอบของ UDP จึงมีความกำกวมโดยธรรมชาติ

UDP ไม่มีการทำ handshake ดังนั้นการตรวจสอบจึงไม่มีจุดที่ระบุความสำเร็จได้ nc -zu 203.0.113.10 53 จะจบการทำงานด้วยสถานะ 0 ทันทีที่แพ็กเก็ตถูกส่งออกไป ซึ่งเป็นการพิสูจน์เพียงว่าเครื่องของคุณได้ส่งแพ็กเก็ตนั้นออกไปแล้ว แต่ไม่ได้พิสูจน์สิ่งใดเกี่ยวกับปลายทาง เมื่อพอร์ต UDP ปิดอยู่ โดยปกติโฮสต์จะตอบกลับด้วยข้อความ ICMP port unreachable และเคอร์เนลจะรายงานข้อผิดพลาดนั้นไปยังซ็อกเก็ตที่เชื่อมต่ออยู่ในการเขียนครั้งถัดไปเท่านั้น ดังนั้นการส่งแพ็กเก็ตตรวจสอบเพียงครั้งเดียวจึงพลาดข้อมูลนี้ไป ไฟร์วอลล์มักจะดรอปแพ็กเก็ต ICMP ทิ้งเป็นปกติ ซึ่งทำให้เบาะแสส่วนนี้หายไป นี่คือเหตุผลที่ nmap แสดงผลเป็น open|filtered สำหรับพอร์ต UDP ส่วนใหญ่ เพราะการไม่มีการตอบกลับคือผลลัพธ์ที่เกิดขึ้นได้ทั้งจากบริการที่เปิดอยู่แต่เงียบเฉย และพอร์ตที่ถูกกรองไว้

ให้ทดสอบ UDP ด้วยการสื่อสารผ่านโปรโตคอลที่คุณต้องการใช้งานจริง เซิร์ฟเวอร์ DNS จะตอบกลับ dig +short @203.0.113.10 example.com ด้วยที่อยู่ IP หรือไม่ตอบกลับเลย ส่วนเพียร์ของ WireGuard จะแสดงบรรทัด latest handshake ล่าสุดใน sudo wg show จากนั้นให้พิสูจน์การมาถึงของแพ็กเก็ตที่ฝั่งเซิร์ฟเวอร์:

sudo tcpdump -ni any udp port 51820

หากมีแพ็กเก็ตปรากฏขึ้นในขณะที่ไคลเอนต์ส่งข้อมูล แสดงว่าแพ็กเก็ตมาถึงแล้ว ปัญหาจึงอยู่ที่ตัวบริการหรือ input chain หากไม่มีแพ็กเก็ตปรากฏเลย แสดงว่าแพ็กเก็ตเหล่านั้นไม่เคยไปถึงปลายทาง

รายการตรวจสอบตามลำดับเพื่อค้นหาข้อผิดพลาดให้เร็วที่สุด

  1. บนเซิร์ฟเวอร์ ให้รันคำสั่ง sudo ss -ltnp 'sport = :8080' หากไม่มีผลลัพธ์แสดงออกมา หมายความว่าไม่มีบริการใดกำลังรอรับการเชื่อมต่ออยู่ ให้แก้ไขที่ตัวบริการก่อน
  2. หากมีผลลัพธ์ ให้ตรวจสอบคอลัมน์ Local Address หากเป็น 127.0.0.1 หมายความว่าไม่สามารถเข้าถึงจากภายนอกได้จนกว่าคุณจะทำการ rebind หรือติดตั้ง proxy ไว้ด้านหน้า
  3. จากเครือข่ายอื่น ให้รันคำสั่ง nc -zv -w 3 <public ip> 8080
  4. หากถูกปฏิเสธการเชื่อมต่อ (refusal) ให้กลับไปทำขั้นตอนที่ 1 เนื่องจากที่อยู่ พอร์ต หรือเครื่องที่ระบุอาจไม่ถูกต้อง
  5. หากเกิดการหมดเวลา (timeout) หมายความว่าแพ็กเก็ตถูกทิ้ง ให้เริ่มรัน sudo tcpdump -ni any tcp port 8080 บนเซิร์ฟเวอร์แล้วทดสอบซ้ำ
  6. หาก SYN มาถึงแต่ไม่มีการตอบกลับ แสดงว่าเป็นปัญหาที่ firewall ของโฮสต์ ให้ค้นหากฎที่ตัวนับมีการเปลี่ยนแปลงใน sudo iptables -L INPUT -n -v
  7. หากไม่มี SYN มาถึง แสดงว่าเป็นปัญหาที่ firewall ของผู้ให้บริการ, security group หรือระบุ IP address ผิดพลาด

FAQ

ฉันจะตรวจสอบได้อย่างไรว่าพอร์ตใดเปิดอยู่บนเซิร์ฟเวอร์ Linux ของฉัน?

ให้รัน sudo ss -ltnp สำหรับ TCP และ sudo ss -lunp สำหรับ UDP แต่ละบรรทัดคือ listening socket หนึ่งรายการ และคอลัมน์ Local Address จะระบุว่าใครสามารถเข้าถึงได้บ้าง: 0.0.0.0 และ [::] ยอมรับการเชื่อมต่อจากทุกที่ที่ firewall อนุญาต ในขณะที่ 127.0.0.1 ยอมรับเฉพาะการเชื่อมต่อจากตัวเครื่องเองเท่านั้น คอลัมน์ Process จำเป็นต้องใช้สิทธิ์ root ดังนั้นให้รันด้วย sudo มิฉะนั้นข้อมูลจะว่างเปล่า ss เป็นส่วนหนึ่งของ iproute2 ซึ่งติดตั้งมาให้เสมอ ส่วน netstat เป็นส่วนหนึ่งของ net-tools ซึ่งโดยปกติจะไม่ได้ติดตั้งมาให้

ทำไม ss ถึงแสดงว่าบริการของฉันกำลังฟังอยู่ แต่ฉันยังเชื่อมต่อไม่ได้?

มีสาเหตุทั่วไปสองประการและคำสั่งหนึ่งที่ช่วยแยกแยะได้ หาก Local Address คือ 127.0.0.1 แสดงว่าบริการนั้นผูกอยู่กับ loopback และไม่สามารถเข้าถึงได้จากโฮสต์อื่น เนื่องจาก kernel จะส่งข้อมูลช่วงนั้นไปยัง loopback interface เท่านั้น หากเป็น 0.0.0.0 แล้วการเชื่อมต่อยังคงล้มเหลว ให้รัน sudo tcpdump -ni any tcp port <port> บนเซิร์ฟเวอร์แล้วลองเชื่อมต่อจากภายนอก หากมี SYN เข้ามาแต่ไม่มีการตอบกลับ แสดงว่ากฎของ firewall ในเครื่องกำลังทิ้งแพ็กเก็ตนั้น หากไม่มีอะไรเข้ามาเลย แสดงว่าแพ็กเก็ตถูกหยุดก่อนถึง VPS ของคุณ ซึ่งมักเกิดจาก firewall ของผู้ให้บริการหรือ security group

การเชื่อมต่อที่ถูกปฏิเสธ (refused) กับการเชื่อมต่อที่หมดเวลา (timed out) ต่างกันอย่างไร?

การถูกปฏิเสธคือการตอบกลับอย่างหนึ่ง แพ็กเก็ตไปถึงโฮสต์และได้รับ TCP reset หรือ ICMP port unreachable กลับมา ซึ่งหมายความว่าไม่มีบริการใดกำลังฟังอยู่ที่ address และพอร์ตนั้น หรือมีกฎปฏิเสธไว้ การหมดเวลาคือความเงียบ: กฎได้ทิ้งแพ็กเก็ตและไม่มีการส่งสิ่งใดกลับมา ทำให้ client พยายามเชื่อมต่อซ้ำจนกว่าจะยอมแพ้ การถูกปฏิเสธชี้ให้คุณตรวจสอบที่ตัวบริการและ bind address ส่วนการหมดเวลาชี้ให้คุณตรวจสอบที่ firewall โดยควรเริ่มจาก firewall ที่อยู่ใกล้ภายนอกมากที่สุดก่อน

ฉันจะตรวจสอบได้อย่างไรว่าพอร์ต UDP เปิดอยู่?

คุณไม่สามารถรับคำตอบที่เชื่อถือได้จากการตรวจสอบทั่วไป เนื่องจาก UDP ไม่มีการทำ handshake และบริการที่เงียบเฉยจะมีลักษณะเหมือนแพ็กเก็ตที่ถูกทิ้ง nc -zu จะรายงานความสำเร็จทันทีที่ส่งข้อมูลออกไป และ nmap ก็รายงาน open|filtered ด้วยเหตุผลเดียวกัน ให้ทดสอบโดยการสื่อสารผ่านโปรโตคอลนั้นโดยตรง เช่น dig +short @<host> example.com สำหรับ DNS หรือ sudo wg show สำหรับ WireGuard peer ที่มีการทำ handshake ล่าสุด หากต้องการพิสูจน์ว่าแพ็กเก็ตมาถึงจริง ให้รัน sudo tcpdump -ni any udp port <port> บนเซิร์ฟเวอร์ในขณะที่ client ส่งข้อมูล

ฉันยังสามารถใช้ telnet host port เพื่อทดสอบพอร์ตได้หรือไม่?

มันใช้ได้กับ TCP และ Escape character is '^]' หมายความว่าการเชื่อมต่อได้รับการยอมรับ ให้ปิดการเชื่อมต่อด้วย Ctrl+] แล้วตามด้วย quit มีสองเหตุผลที่ทำให้ nc -z เป็นเครื่องมือที่ดีกว่า: telnet ไม่ได้ถูกติดตั้งมาใน image ของเซิร์ฟเวอร์ส่วนใหญ่ในปัจจุบัน และ nc สามารถกำหนดเวลาหมดเวลาด้วย -w รวมถึงกำหนด exit status ที่คุณสามารถนำไปตรวจสอบในสคริปต์ได้ หากไม่มีเครื่องมือใดเลย timeout 3 bash -c '</dev/tcp/<host>/<port>' ไม่จำเป็นต้องติดตั้งแพ็กเกจใดๆ เพิ่มเติม