ตรวจสอบพอร์ตที่เปิดอยู่บน Linux ด้วย ss และ lsof
เมื่อเว็บไซต์เปิดไม่ขึ้น Service เริ่มทำงานไม่ได้เพราะแจ้งว่า Address already in use หรือคุณอยากรู้ว่าเซิร์ฟเวอร์เปิดช่องทางอะไรให้คนภายนอกเข้ามาได้บ้าง คำถามแรกที่ต้องตอบคือ "ตอนนี้มีโปรแกรมไหนกำลังรอรับการเชื่อมต่อ (Listen) อยู่ที่พอร์ตไหน และรับจาก IP ใด" บน Linux รุ่นปัจจุบันมีเครื่องมือหลักสองตัวที่ตอบคำถามนี้ได้ คือ ss ซึ่งมากับระบบอยู่แล้ว และ lsof ซึ่งแสดงความสัมพันธ์ระหว่างโปรเซสกับไฟล์และ Socket ได้ละเอียดกว่า
บทความนี้อธิบายวิธีอ่านผลลัพธ์ของทั้งสองคำสั่ง วิธีหาว่าโปรแกรมใดจับพอร์ตไว้ วิธีนับการเชื่อมต่อที่เข้ามา และวิธีแยกให้ออกว่าพอร์ตที่ "เปิดอยู่ในเครื่อง" กับพอร์ตที่ "เข้าถึงได้จากภายนอก" เป็นคนละเรื่องกัน
สิ่งที่ต้องเตรียม
- เข้าเซิร์ฟเวอร์ผ่าน SSH ด้วยผู้ใช้ที่ใช้
sudoได้ (หากยังไม่มี ดู สร้างผู้ใช้ใหม่และให้สิทธิ์ sudo บน Linux) - Ubuntu 22.04/24.04 หรือ AlmaLinux/Rocky Linux 8-9
- คำสั่ง
ssอยู่ในแพ็กเกจiproute2(Ubuntu) หรือiproute(AlmaLinux/Rocky) ซึ่งติดตั้งมาแล้วเกือบทุกกรณี ส่วนlsofอาจต้องติดตั้งเพิ่ม
ติดตั้ง lsof หากยังไม่มี:
# Ubuntu
sudo apt update && sudo apt install -y lsof
# AlmaLinux / Rocky Linux
sudo dnf install -y lsof
ขั้นตอนที่ 1: ดูพอร์ตที่กำลัง Listen ทั้งหมดด้วย ss
คำสั่งที่ใช้บ่อยที่สุดคือ:
sudo ss -tulpn
ความหมายของแต่ละตัวเลือก:
| ตัวเลือก | ความหมาย |
|---|---|
-t | แสดง Socket แบบ TCP |
-u | แสดง Socket แบบ UDP |
-l | แสดงเฉพาะ Socket ที่อยู่ในสถานะ Listen (รอรับการเชื่อมต่อ) |
-p | แสดงชื่อโปรเซสและ PID ที่เป็นเจ้าของ Socket (ต้องใช้ sudo จึงจะเห็นโปรเซสของผู้ใช้อื่น) |
-n | แสดงตัวเลขพอร์ตและ IP แทนการแปลงเป็นชื่อ เช่น แสดง 443 แทน https |
ตัวอย่างผลลัพธ์ (ตัดบางคอลัมน์ให้สั้นลง):
Netid State Local Address:Port Peer Address:Port Process
udp UNCONN 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=612,fd=13))
tcp LISTEN 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=901,fd=3))
tcp LISTEN 127.0.0.1:3306 0.0.0.0:* users:(("mariadbd",pid=1204,fd=21))
tcp LISTEN 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1320,fd=6))
tcp LISTEN [::]:80 [::]:* users:(("nginx",pid=1320,fd=7))
tcp LISTEN *:6379 *:* users:(("redis-server",pid=1411,fd=6))
ขั้นตอนที่ 2: อ่านคอลัมน์ Local Address ให้ถูก
คอลัมน์ที่สำคัญที่สุดคือ Local Address:Port เพราะบอกว่าโปรแกรมรับการเชื่อมต่อจากที่ใด:
| ค่าที่เห็น | ความหมาย |
|---|---|
127.0.0.1:3306 หรือ [::1]:3306 | รับเฉพาะจากภายในเครื่องเอง คนภายนอกเชื่อมต่อไม่ได้แม้ Firewall จะเปิด |
0.0.0.0:80 | รับจากทุก IPv4 ของเครื่อง |
[::]:80 | รับจากทุก IPv6 ของเครื่อง (และบางระบบรวม IPv4 ด้วย) |
*:6379 | รับจากทุกที่อยู่ทั้ง IPv4 และ IPv6 |
203.0.113.10:8080 | รับเฉพาะที่ IP นี้ของเครื่อง |
จากตัวอย่างข้างต้น MariaDB ที่ 127.0.0.1:3306 ปลอดภัยตามค่าเริ่มต้น แต่ Redis ที่ *:6379 เป็นสัญญาณอันตราย เพราะ Redis ไม่ควรเปิดรับจากภายนอก ควรแก้ให้ Bind ที่ 127.0.0.1 (ดู ติดตั้งและตั้งค่า Redis บน Linux Server)
หมายเหตุ: UDP ไม่มีสถานะ Listen แบบ TCP คำสั่ง
ssจึงแสดง UDP ที่รอรับข้อมูลเป็นสถานะUNCONNซึ่งถือว่าเปิดรับอยู่เช่นกัน
ขั้นตอนที่ 3: หาว่าโปรแกรมไหนใช้พอร์ตที่ต้องการ
เมื่อ Nginx หรือ Apache เริ่มไม่ได้เพราะพอร์ต 80 ถูกใช้อยู่ ให้กรองดูเฉพาะพอร์ตนั้น:
sudo ss -ltnp 'sport = :80'
หรือใช้ lsof ซึ่งอ่านง่ายกว่าสำหรับคำถามนี้:
sudo lsof -i :80
ผลลัพธ์ตัวอย่าง:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
apache2 1102 root 4u IPv6 23981 0t0 TCP *:http (LISTEN)
apache2 1105 www-data 4u IPv6 23981 0t0 TCP *:http (LISTEN)
แปลว่า Apache จับพอร์ต 80 อยู่ ถ้าคุณตั้งใจใช้ Nginx แทน ให้หยุดและปิดการเริ่มอัตโนมัติของ Apache ด้วย sudo systemctl disable --now apache2 (บน AlmaLinux/Rocky ชื่อ Service คือ httpd) รายละเอียดการจัดการ Service ดูได้ที่ จัดการ Service บน Linux ด้วย systemctl
ตัวเลือกของ lsof ที่ควรรู้:
# แสดงเฉพาะ TCP ที่ Listen ไม่แปลงชื่อพอร์ตและชื่อโฮสต์
sudo lsof -nP -iTCP -sTCP:LISTEN
# ดูว่าโปรเซส PID 1320 เปิด Socket อะไรอยู่บ้าง
sudo lsof -nP -a -p 1320 -i
# ดูทุก Socket ของผู้ใช้ www-data
sudo lsof -nP -a -u www-data -i
ตัวเลือก -a หมายถึงให้เงื่อนไขทั้งหมดเป็นจริงพร้อมกัน (AND) ถ้าไม่ใส่ lsof จะรวมผลแบบ OR ทำให้ได้รายการยาวเกินจำเป็น
ขั้นตอนที่ 4: ดูการเชื่อมต่อที่กำลังเกิดขึ้น
นอกจากพอร์ตที่รอรับ คุณอาจต้องดูว่ามีใครเชื่อมต่อเข้ามาอยู่บ้าง เช่น เมื่อเว็บช้าผิดปกติและสงสัยว่ามีการเชื่อมต่อจำนวนมาก
# การเชื่อมต่อ TCP ที่ Established ทั้งหมด
ss -tn state established
# นับการเชื่อมต่อที่เข้ามายังพอร์ต 443
ss -Htn state established '( sport = :443 )' | wc -l
# สรุปจำนวน Socket แยกตามสถานะ
ss -s
ตัวเลือก -H ตัดบรรทัดหัวตารางออกเพื่อให้ wc -l นับได้ตรง หากต้องการดูว่า IP ใดเชื่อมต่อเข้ามามากที่สุด ใช้:
ss -Htn state established '( sport = :443 )' \
| awk '{print $4}' | sed 's/:[0-9]*$//' | sort | uniq -c | sort -rn | head
เมื่อใช้ตัวกรอง state คำสั่ง ss จะไม่พิมพ์คอลัมน์ State ออกมา คอลัมน์ที่ 4 จึงเป็น Peer Address ผลที่ได้คือจำนวนการเชื่อมต่อต่อ IP เรียงจากมากไปน้อย
ขั้นตอนที่ 5: ตรวจจากภายนอกว่าพอร์ตเข้าถึงได้จริงหรือไม่
พอร์ตที่ ss แสดงว่า Listen ที่ 0.0.0.0 อาจยังเข้าไม่ได้จากภายนอก เพราะมีชั้นกั้นอีกสองชั้น คือ Firewall ในเครื่อง (UFW, firewalld) และ Firewall ภายนอก ในทางกลับกัน ถ้า Firewall เปิดแต่โปรแกรม Listen ที่ 127.0.0.1 ก็ยังเข้าไม่ได้ ให้ทดสอบจากเครื่องอื่นที่ไม่ใช่เซิร์ฟเวอร์เอง:
# จากเครื่อง Linux หรือ macOS อื่น
nc -zv 203.0.113.10 443
# หรือใช้ nmap ตรวจหลายพอร์ต (สแกนเฉพาะเซิร์ฟเวอร์ของคุณเท่านั้น)
nmap -Pn -p 22,80,443,3306 203.0.113.10
ผลที่เป็นไปได้:
succeededหรือopen: เข้าถึงได้Connection refusedหรือclosed: แพ็กเก็ตไปถึงเครื่อง แต่ไม่มีโปรแกรม Listen ที่พอร์ตนั้นบน IP ภายนอกtimed outหรือfiltered: มี Firewall ทิ้งแพ็กเก็ตระหว่างทาง
หากเป็นกรณี filtered ให้ตรวจ Firewall ในเครื่องตาม ตั้งค่า Firewall ด้วย UFW บน Ubuntu หรือ ตั้งค่า Firewall ด้วย firewalld บน AlmaLinux และ Rocky Linux และหากเซิร์ฟเวอร์มี Security Group หรือ Firewall ภายนอกจากฝั่งผู้ให้บริการ ให้เปิดพอร์ตนั้นเพิ่มด้วย
ตรวจสอบผลลัพธ์
หลังจากแก้ไขค่าของโปรแกรมใดก็ตาม (เช่น เปลี่ยน Bind ของ Redis หรือ MySQL) และรีสตาร์ต Service แล้ว ให้รัน sudo ss -tulpn อีกครั้ง แล้วเทียบกับรายการที่ควรเป็น ตัวอย่างเว็บเซิร์ฟเวอร์ทั่วไปควรเห็นเพียง:
- SSH (22 หรือพอร์ตที่คุณเปลี่ยนไว้) ที่
0.0.0.0และ[::] - HTTP 80 และ HTTPS 443 ที่
0.0.0.0และ[::] - ฐานข้อมูล, Redis, PHP-FPM (ถ้าใช้ TCP) ที่
127.0.0.1เท่านั้น
พอร์ตอื่นที่ไม่รู้จักให้ตรวจด้วย lsof ว่าเป็นของโปรแกรมใด แล้วพิจารณาปิด Service ที่ไม่ได้ใช้
ปัญหาที่พบบ่อย
คอลัมน์ Process ว่างเปล่า
เกิดจากรัน ss -p หรือ lsof โดยไม่ใช้ sudo ผู้ใช้ทั่วไปจะเห็นเฉพาะโปรเซสของตัวเอง ให้รันซ้ำด้วย sudo
ปิด Service แล้ว แต่พอร์ตยังถูกใช้อยู่
บน Ubuntu 22.10 ขึ้นไป (รวม 24.04) SSH อาจถูกเปิดผ่าน Socket Activation โดย ssh.socket ของ systemd ซึ่งจะเห็นในคอลัมน์ Process เป็น systemd แทน sshd การหยุด ssh.service อย่างเดียวจึงไม่ปิดพอร์ต ในกรณีทั่วไปให้ใช้ systemctl list-sockets ดูว่ามี Socket Unit ใดจับพอร์ตอยู่
Service เริ่มไม่ได้ แต่ ss ไม่เห็นใครใช้พอร์ตนั้น
ให้อ่านข้อความ Error ให้ละเอียด ถ้าเป็น Cannot assign requested address แปลว่าโปรแกรมพยายาม Bind IP ที่ไม่มีอยู่บนเครื่อง (ตรวจ IP ของเครื่องด้วย ip -br addr) ถ้าเป็น Permission denied กับพอร์ตต่ำกว่า 1024 แปลว่าโปรแกรมไม่ได้รันด้วยสิทธิ์ที่ Bind พอร์ตนั้นได้ ส่วน Nginx อาจแจ้ง a duplicate default server เมื่อมีสองไฟล์ประกาศ listen 80 default_server ซ้ำกัน ให้ตรวจด้วย sudo nginx -t และอ่าน Log ของ Service ด้วย journalctl -u ชื่อservice (ดู อ่าน Log ระบบบน Linux ด้วย journalctl)
ภายในเครื่องเชื่อมต่อได้ แต่ภายนอกไม่ได้
ไล่ตรวจตามลำดับ: โปรแกรม Listen ที่ 0.0.0.0 หรือไม่, Firewall ในเครื่องเปิดพอร์ตหรือยัง, Firewall ภายนอกเปิดหรือยัง และบน AlmaLinux/Rocky ถ้าเป็นพอร์ตที่ไม่ใช่ค่ามาตรฐาน SELinux อาจห้ามโปรแกรม Bind พอร์ตนั้น (ดู ใช้งาน SELinux บน AlmaLinux และ Rocky Linux โดยไม่ต้องปิด)
หากตรวจแล้วยังไม่พบสาเหตุ หรือไม่แน่ใจว่าพอร์ตใดควรเปิด ติดต่อทีมซัพพอร์ต THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/
- Categories:
- Cloud
- Tags:
- Cloud
- Cloud Server
Related Posts
หมวดหมู่ที่น่าสนใจ
- Account Settings
- AD Server
- AI
- Alibaba Cloud
- Anti-Spam Gateway
- AWS Amazon Web Services
- Campaign
- CentOS/AlmaLinux
- Cloud
- Cloud Backup
- Cloud Communication
- Cloud Migration
- Cloud Security
- Cloud Server Management
- Cloud Solution
- Cloud Solution for Government
- Cloud Solutions by Industry
- Cloud Storage
- Cloud VPS App Plus +
- Cloud VPS DirectAdmin
- Cloud VPS Plesk
- CSR
- Cyber Security
- Cybersecurity
- Data Sovereignty
- Database Server
- DDoS
- Digital Tranformation
- Digital Transformation
- Direct Mail
- Directadmin
- Domainname
- Ecommerce
- ERP
- Generative AI
- Getting Started
- Google Cloud
- Google G Suite
- Huawei Cloud
- IT News
- Linux Server
- Managed Cloud Services
- Managed Service Provider
- Manual
- Microsoft
- Microsoft 365
- Microsoft Azure
- News
- On-premise
- Private Mail Server
- Promotion
- Recommend Solution (Enterprise)
- Server
- Sovereign Cloud
- THAI DATA CLOUD Platform
- Ubuntu
- Ubuntu
- Uncategorized
- VMware
- VPS Server
- Web Design
- Web Hosting
- Web Hosting (DirectAdmin)
- Web Hosting (Plesk)
- Web Technologies
- Windows Server
- Wordpress
- Zimbra
- เรื่องราวความประทับใจ
- โซลูชันสำหรับธุรกิจการผลิตและยานยนต์
- โซลูชันสำหรับธุรกิจการศึกษา
- โซลูชันสำหรับธุรกิจการเงิน
- โซลูชันสำหรับธุรกิจขนส่งและกระจายสินค้า
- โซลูชันสำหรับธุรกิจค้าปลีก
- โซลูชันสำหรับธุรกิจท่องเที่ยว
- โซลูชันสำหรับธุรกิจบริการสุขภาพและโรงพยาบาล
- โซลูชันสำหรับธุรกิจประกันภัย
- โซลูชันสำหรับธุรกิจพลังงานและสาธารณูปโภค
- โซลูชันสำหรับธุรกิจสื่อสารมวลชนและเอ็นเตอร์เทนเมนท์
- โซลูชันสำหรับธุรกิจอสังหาริมทรัพย์
- โซลูชันสำหรับธุรกิจเทคโนโลยี


