รายการพอร์ตที่เปิดคือรายการเส้นทางเข้าถึงเซิร์ฟเวอร์ของคุณ ทุกอย่างที่เหลือ — ไฟร์วอลล์ WAF การตรวจจับการบุกรุก — สร้างอยู่บนสิ่งนั้น จึงเป็นเหตุผลว่าทำไม «อะไรกำลังรับฟังอยู่ที่นี่» จึงมาก่อนในการตรวจสอบใด ๆ และทำไมมันจึงเป็นการตรวจที่ให้คำตอบไม่น่าพอใจบ่อยที่สุดด้วย: ครึ่งหนึ่งของสิ่งที่พบไม่ได้ถูกเปิดโดยคุณ แต่โดยตัวติดตั้งของแพ็กเกจบางตัว
การอ่านผลลัพธ์
sudo ss -tulpn
ธง: t คือ TCP, u คือ UDP, l คือเฉพาะที่รับฟัง, p คือกระบวนการ, n คือให้ตัวเลขเป็นตัวเลข ถ้าไม่มี sudo คอลัมน์กระบวนการจะว่างเปล่าและการทำแบบฝึกหัดนี้ก็ไร้ความหมาย
สิ่งที่สำคัญคือคอลัมน์ Local Address:Port และความต่างตรงนั้นเป็นเรื่องพื้นฐาน:
127.0.0.1:3306— บริการเข้าถึงได้จากตัวเครื่องเองเท่านั้น นั่นดี;0.0.0.0:3306— จากทุกที่อยู่ IPv4 นั่นคือจากอินเทอร์เน็ต นี่คือสิ่งที่ต้องตรวจ;[::]:3306— เรื่องเดียวกันสำหรับ IPv6 บรรทัดแยกต่างหาก และถูกมองข้ามเป็นประจำ;203.0.113.25:443— บนที่อยู่เฉพาะ โดยปกติเป็นความตั้งใจ
จากนั้นสำหรับทุกบรรทัดที่มี 0.0.0.0 หรือ [::] ให้ถามคำถามเดียว: คนแปลกหน้าควรเข้าถึงสิ่งนี้ได้หรือไม่ สำหรับ 80 และ 443 คำตอบคือใช่ สำหรับเกือบทุกอย่างที่เหลือคือไม่
สิ่งที่มักพบ
Redis พอร์ต 6379 บรรทัดที่อันตรายที่สุดที่นั่น โดยค่าเริ่มต้น Redis ไม่ต้องการรหัสผ่าน และคำสั่งของมันอนุญาตให้เขียนไฟล์ลงดิสก์ — นั่นคือคีย์ของคนอื่นใน authorized_keys ระหว่างที่ Redis ปรากฏบนที่อยู่สาธารณะกับการถูกใช้งานนั้นห่างกันเป็นชั่วโมง บางครั้งน้อยกว่านั้น ตรวจ bind 127.0.0.1 และ protected-mode yes ในไฟล์ตั้งค่า
Memcached, 11211/UDP แม้ข้างในจะไม่มีอะไรมีค่า เซิร์ฟเวอร์ของคุณก็กลายเป็นตัวขยายการโจมตีของคนอื่น — และคำร้องเรียนจะมาจากผู้ให้บริการของคุณ
MySQL และ PostgreSQL, 3306 และ 5432 มีรหัสผ่านก็จริง แต่การเดารหัสผ่านเกิดขึ้นตลอดเวลา และเวอร์ชันของฐานข้อมูลก็อัปเดตน้อยกว่าที่ควร พวกมันแทบไม่จำเป็นต้องหันออกข้างนอกเลย: แอปพลิเคชันอยู่บนเครื่องเดียวกัน และสำหรับงานของคุณเอง อุโมงค์ SSH ก็เพียงพอ
Elasticsearch 9200, MongoDB 27017 ในอดีตไม่มีการยืนยันตัวตนโดยค่าเริ่มต้น อินสแตนซ์สาธารณะของพวกนี้เป็นแหล่งข่าวข้อมูลรั่วไหลอย่างสม่ำเสมอ
Docker API, 2375 พอร์ตควบคุม Docker ที่เปิดอยู่คือ root บนโฮสต์โดยไม่มีรหัสผ่านใด ๆ ทั้งสิ้น มันมักปรากฏหลังการทดลองเข้าถึง Docker จากระยะไกล
แผงควบคุมและ phpMyAdmin บนพอร์ตของตัวเอง: 8080, 8083, 10000 ไม่ใช่ว่าห้ามเปิดเด็ดขาด แต่พวกมันคือสิ่งที่เก็บสะสมความพยายามส่วนใหญ่ไว้
แก้ที่บริการ ไม่ใช่ที่ไฟร์วอลล์
ความอยากปิดทุกสิ่งที่พบด้วยกฎ UFW นั้นเข้าใจได้ แต่นั่นเป็นแนวที่สอง ไม่ใช่แนวแรก กฎอาจถูกลบโดยพลาด ไฟร์วอลล์อาจถูกปิดชั่วคราวขณะแก้จุดบกพร่อง และ Docker ก็เผยแพร่พอร์ตอ้อม UFW ไปเลย การตั้งค่าการผูกในไฟล์ตั้งค่าของบริการเองรอดพ้นทั้งหมดนั้น:
- MySQL/MariaDB —
bind-address = 127.0.0.1; - PostgreSQL —
listen_addresses = 'localhost'; - Redis —
bind 127.0.0.1 ::1; - Docker Compose — เผยแพร่เป็น
"127.0.0.1:5432:5432"
ไฟร์วอลล์วางทับไว้เป็นประกัน ไม่ใช่แทนที่สิ่งนี้
หากระบวนการเมื่อไม่ชัดเจน
ss ให้ชื่อและ pid จากนั้น:
sudo systemctl status <pid>
sudo lsof -i :8080
คำสั่งแรกบอกว่ากระบวนการอยู่ในยูนิต systemd ใด — ปกติเพียงพอที่จะเข้าใจว่ามันคืออะไรและจำเป็นหรือไม่ กระบวนการแปลกหน้าที่รับฟังบนพอร์ตสูงและเริ่มจากนอกไดเรกทอรีระบบ — สมมติว่าจาก /tmp หรือ /dev/shm — ไม่ใช่คำถามเรื่องการตั้งค่าอีกต่อไป แต่เป็นเหตุให้ต้องสอบสวนแยกต่างหาก
การตรวจจากภายนอกเป็นสิ่งบังคับ
ss ตอบคำถาม «อะไรกำลังรับฟัง» ไม่ใช่ «เข้าถึงอะไรได้บ้าง» ระหว่างสองสิ่งนั้นมีไฟร์วอลล์ NAT และกฎของผู้ให้บริการเองคั่นอยู่ คำตอบที่ซื่อสัตย์มาจากการสแกนจากเครื่องอื่นเท่านั้น:
nmap -Pn -p- 203.0.113.25
nmap -Pn -p- -6 2001:db8::1
อย่าข้ามคำสั่งที่สอง: VPS เกือบทุกเครื่องมีที่อยู่ IPv6 กฎของมันเขียนแยกกัน และบริการก็รับฟังบนโปรโตคอลทั้งสองเวอร์ชันพร้อมกัน
นี่ไม่ใช่การตรวจครั้งเดียวจบ
รายการพอร์ตที่เปิดเปลี่ยนไปเอง คุณติดตั้งแพ็กเกจแล้วมันพาบริการมาและเปิดพอร์ต คุณอัปเดตแผงแล้วมันคืนค่าเริ่มต้นกลับมา คุณรันคอนเทนเนอร์แล้วมันเผยแพร่พอร์ตอ้อมไฟร์วอลล์ การตรวจครั้งเดียวตอบสำหรับวันนี้เท่านั้น ไม่มากไปกว่านั้น
คุณค่าไม่ได้อยู่ที่ตัวรายการแต่อยู่ที่การเปลี่ยนแปลงของมัน: พอร์ตใหม่ที่เมื่อวานยังไม่มีคือสัญญาณสั้น ๆ ที่ให้ข้อมูลมาก นี่แหละคือวิธีที่ควรเฝ้าดูมัน — เป็นสแนปช็อตพร้อมประวัติ ไม่ใช่ผลลัพธ์ ss ที่ระลึกได้จากความจำ หน้าเดโมด้านล่างแสดงสิ่งนั้นพอดี