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

ความแตกต่างระหว่าง SSH Connection Refused และ Timed Out

เรียนรู้วิธีแยกแยะข้อผิดพลาด SSH ระหว่าง Connection refused ที่เซิร์ฟเวอร์ปฏิเสธการเชื่อมต่อ กับ Connection timed out ที่แพ็กเก็ตไปไม่ถึงปลายทาง พร้อมวิธีตรวจสอบปัญหาเบื้องต้น

ความหมายของ "Connection refused" และ "Connection timed out" ใน SSH

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

โปรดอ่านบรรทัดที่ไคลเอนต์ของคุณแสดงผลอย่างละเอียด เพราะถ้อยคำเหล่านั้นคือการวินิจฉัยปัญหาทั้งหมด

ssh: connect to host 203.0.113.10 port 22: Connection refused
ssh: connect to host 203.0.113.10 port 22: Connection timed out

ระยะเวลาที่ใช้เป็นเบาะแสที่สอง ข้อผิดพลาด Refused จะแสดงผลทันที โดยใช้เวลาเพียงเท่ากับระยะเวลาการรับส่งข้อมูลไป-กลับหนึ่งรอบ ส่วนข้อความ Timed out จะค้างอยู่หลายวินาทีก่อนจะแสดงผล เนื่องจากไคลเอนต์พยายามส่งข้อมูลซ้ำหลายครั้งก่อนที่จะยอมแพ้ ระบบ macOS จะแสดงข้อความ Operation timed out สำหรับเงื่อนไขเดียวกัน หากคุณยังไม่คุ้นเคยกับโปรโตคอลนี้ การทำงานของ SSH และหน้าที่ของ sshd คือพื้นฐานที่คู่มือนี้ใช้เป็นจุดเริ่มต้น

เหตุใด "Connection refused" จึงเป็นข่าวดี

สถานะ Refused คือการส่ง TCP (transmission control protocol) reset กลับมา ไคลเอนต์ของคุณส่งแพ็กเก็ต SYN ไปยังพอร์ต 22 แพ็กเก็ตเดินทางผ่านอินเทอร์เน็ตไปถึง network stack ของเซิร์ฟเวอร์ แต่เคอร์เนลไม่พบซ็อกเก็ตใดที่รอรับการเชื่อมต่อ (listening) อยู่บนพอร์ตนั้น จึงตอบกลับด้วยแพ็กเก็ต RST (reset) ไคลเอนต์ SSH ของคุณจึงแปลงค่า RST นั้นเป็นข้อความ Connection refused

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

  • sshd ไม่ได้ทำงานอยู่ เนื่องจากเริ่มการทำงานล้มเหลวหรือไม่ได้เปิดใช้งานไว้
  • sshd กำลังรอรับการเชื่อมต่อบนพอร์ตอื่น ซึ่งมักเกิดขึ้นหลังจากการปรับปรุงความปลอดภัย (hardening)
  • sshd ถูกผูกไว้กับที่อยู่เดียว เช่น ListenAddress 127.0.0.1 ทำให้เฉพาะตัวเซิร์ฟเวอร์เองเท่านั้นที่เข้าถึงได้
  • ไฟร์วอลล์ถูกตั้งค่าให้ปฏิเสธ (reject) แทนการทิ้งแพ็กเก็ต (drop) ไฟร์วอลล์จึงส่ง RST แทนโฮสต์ การกระทำ reject ใน ufw และกฎของ nftables ที่ลงท้ายด้วย reject with tcp reset ต่างก็ส่งผลเช่นนี้ทั้งสิ้น

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

วิธีแก้ไขปัญหา Connection refused

คุณไม่สามารถแก้ไขปัญหานี้ผ่าน SSH ได้ เนื่องจาก SSH คือส่วนที่ทำงานผิดปกติ ให้เปิดเว็บคอนโซลหรือซีเรียลคอนโซลของผู้ให้บริการของคุณ ล็อกอินเข้าสู่ระบบ แล้วดำเนินการตามคำสั่งต่อไปนี้

systemctl status ssh
sudo ss -tlnp
sudo sshd -T | grep -Ei '^(port|listenaddress|addressfamily)'

systemctl status ssh ใช้ชื่อยูนิตนี้บน Ubuntu และ Debian ส่วนบน RHEL และระบบที่สร้างจากฐานเดียวกัน เช่น AlmaLinux ยูนิตจะมีชื่อว่า sshd คำสั่ง ss -tlnp จะแสดงรายการ TCP socket ทั้งหมดที่อยู่ในสถานะ listening พร้อมกับระบุ process ที่เป็นเจ้าของ ซึ่งถือเป็นข้อมูลที่เชื่อถือได้มากที่สุด หากไม่มีบรรทัดใดระบุถึง sshd แสดงว่าไม่มีการเปิดพอร์ตรับการเชื่อมต่อ ไม่ว่าไฟล์คอนฟิกจะระบุไว้อย่างไรก็ตาม คำสั่ง sshd -T จะแสดงคอนฟิกที่ใช้งานจริงหลังจากรวมไฟล์ Include ทั้งหมดเข้าด้วยกันแล้ว ซึ่งเป็นจุดที่พอร์ตที่ถูกลืมใน /etc/ssh/sshd_config.d/ จะปรากฏให้เห็น

โปรดอ่านคอลัมน์ address อย่างละเอียด 0.0.0.0:22 หมายถึงทุก IPv4 address บนเครื่อง [::]:22 หมายถึงทุก IPv6 address ส่วน 127.0.0.1:22 หมายถึงเฉพาะ loopback เท่านั้น ดังนั้นการเชื่อมต่อจากระยะไกลทั้งหมดจะถูกปฏิเสธ ในขณะที่การเชื่อมต่อภายในด้วย ssh localhost จะทำงานได้ตามปกติ

หากไม่มีการเปิดพอร์ตรับการเชื่อมต่อ ให้เริ่มการทำงานของ service และอ่านข้อความแจ้งเตือนเมื่อ service ไม่สามารถเริ่มทำงานได้

sudo sshd -t
sudo systemctl enable --now ssh
sudo journalctl -u ssh -n 50 --no-pager

sshd -t จะตรวจสอบไวยากรณ์ของคอนฟิกและแสดงชื่อไฟล์พร้อมหมายเลขบรรทัดที่มีคำสั่งผิดพลาดโดยไม่กระทบต่อ service ที่กำลังทำงานอยู่ ควรเรียกใช้คำสั่งนี้ก่อนการรีสตาร์ททุกครั้ง เพราะหากคอนฟิกไม่ถูกต้อง sshd จะหยุดทำงานทันทีที่เริ่ม และการเชื่อมต่อครั้งถัดไปของคุณจะถูกปฏิเสธ

กับดักของ socket activation บน Ubuntu

Ubuntu 24.04 มาพร้อมกับ systemd socket unit สำหรับ OpenSSH ในกรณีที่ unit นี้ถูกเปิดใช้งานอยู่ systemd จะเป็นผู้ถือพอร์ตที่รอรับการเชื่อมต่อและเริ่มการทำงานของ sshd ต่อการเชื่อมต่อหนึ่งครั้ง ดังนั้นการแก้ไข Port 2222 ใน sshd_config จึงไม่มีผลใดๆ และเซิร์ฟเวอร์จะยังคงตอบรับการเชื่อมต่อที่พอร์ตเดิม ตรวจสอบโหมดการทำงานของระบบคุณก่อนที่จะทำการแก้ไขใดๆ

systemctl is-enabled ssh.socket
systemctl status ssh.socket

หาก socket ถูกเปิดใช้งานอยู่ ให้ตั้งค่าพอร์ตใน socket unit แทนการตั้งค่าใน sshd_config

sudo systemctl edit ssh.socket
[Socket]
ListenStream=
ListenStream=2222

บรรทัด ListenStream= ที่ว่างเปล่ามีความจำเป็น เนื่องจาก systemd จะนำการตั้งค่าใหม่ไปเพิ่มต่อจากค่าที่กำหนดไว้เดิม หากละเว้นบรรทัดนี้ เซิร์ฟเวอร์จะรอรับการเชื่อมต่อจากทั้งสองพอร์ตพร้อมกัน นำการเปลี่ยนแปลงไปใช้ด้วย sudo systemctl daemon-reload และ sudo systemctl restart ssh.socket จากนั้นตรวจสอบด้วย sudo ss -tlnp เพื่อยืนยันว่าพอร์ตใหม่เป็นพอร์ตที่ระบบกำลังถืออยู่ การเปลี่ยนพอร์ตเป็นขั้นตอนปกติในการ เพิ่มความปลอดภัยให้กับ SSH บน VPS และเป็นขั้นตอนที่ทำให้ผู้ใช้งานถูกล็อกออกจากระบบบ่อยที่สุด

เหตุใด "Connection timed out" จึงหมายถึงไม่มีการตอบกลับ

การหมดเวลา (timeout) คือความเงียบ ไคลเอนต์ของคุณส่งแพ็กเก็ต SYN ออกไป และส่งซ้ำหลายครั้งในช่วงเวลาหนึ่งหรือสองนาที แต่ไม่ได้รับแพ็กเก็ตใดๆ ตอบกลับมาเลย กรณีนี้ไม่สามารถสรุปสิ่งใดเกี่ยวกับเซิร์ฟเวอร์ได้ เพราะไม่มีสัญญาณใดๆ จากเซิร์ฟเวอร์ส่งกลับมา

ความเงียบคือผลลัพธ์ที่เกิดจากกฎ DROP และการทิ้งแพ็กเก็ต (dropping) เป็นสิ่งที่ตั้งใจให้เกิดขึ้น การปฏิเสธการเชื่อมต่อ (rejection) จะบอกผู้ที่กำลังสแกนเครือข่ายว่าโฮสต์นี้มีตัวตนอยู่จริง ดังนั้น ufw และไฟร์วอลล์เครือข่ายของผู้ให้บริการคลาวด์ทุกรายจึงเลือกที่จะทิ้งแพ็กเก็ตที่ไม่ต้องการโดยไม่ส่งอะไรกลับไป การหมดเวลาที่คุณพบมักเกิดจากไฟร์วอลล์ที่กำลังทำหน้าที่ของมันบนพอร์ตที่คุณต้องการเปิดใช้งาน

  • ที่อยู่ไม่ถูกต้อง: เรคคอร์ด DNS ยังคงชี้ไปยังเซิร์ฟเวอร์ที่คุณสร้างใหม่ หรือพิมพ์ผิดจนไปลงที่ที่อยู่ซึ่งไม่มีใครใช้งาน
  • โฮสต์ไม่ได้เปิดทำงาน: อาจปิดเครื่องอยู่ หรืออยู่ในระหว่างการรีบูต การที่ผู้ให้บริการระงับการใช้งานเนื่องจากปัญหาการชำระเงินก็แสดงผลลัพธ์จากภายนอกเหมือนกันทุกประการ
  • ไฟร์วอลล์ของโฮสต์ทิ้งแพ็กเก็ตพอร์ต 22 ซึ่งมักเกิดจากการที่ ufw enable ทำงานก่อนที่จะมีกฎอนุญาตใดๆ ถูกกำหนดไว้
  • ไฟร์วอลล์ของผู้ให้บริการที่อยู่หน้าอินสแตนซ์ทิ้งแพ็กเก็ตดังกล่าว ทำให้ระบบปฏิบัติการไม่เห็นแพ็กเก็ตนั้นเลย
  • เครือข่ายของคุณเองบล็อกการเชื่อมต่อขาออกที่พอร์ต 22 ซึ่งเป็นเรื่องปกติที่พบได้ในเครือข่ายสำนักงานและโรงแรม

เรียกใช้การทดสอบจากฝั่งปลายทางของการเชื่อมต่อ

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

getent hosts vps.example.com
ssh -G vps.example.com | grep -Ei '^(hostname|port|user)'
ssh -vvv -o ConnectTimeout=10 user@vps.example.com
nc -vz -w 5 203.0.113.10 22

getent hosts จะแสดงที่อยู่ซึ่งเครื่องของคุณจะใช้จริง ซึ่งช่วยตรวจพบระเบียน DNS ที่เก่าเกินไปได้ในเวลาไม่กี่วินาที ssh -G จะพิมพ์การตั้งค่าที่ไคลเอนต์ของคุณนำไปใช้หลังจากอ่าน ~/.ssh/config จึงช่วยตรวจพบบล็อก Host เก่าที่เขียนทับชื่อโฮสต์ พอร์ต หรือผู้ใช้งานอย่างเงียบๆ ssh -vvv จะแสดงให้เห็นว่าความพยายามไปได้ไกลแค่ไหน: บรรทัดสุดท้ายที่ระบุถึงการเชื่อมต่อไปยังที่อยู่ตามด้วยการหยุดชะงักนานๆ คืออาการ timeout ในขณะที่บรรทัดที่รายงานเวอร์ชัน OpenSSH ของฝั่งรีโมทหมายความว่า TCP เชื่อมต่อสำเร็จแล้ว และปัญหาที่แท้จริงของคุณคือการยืนยันตัวตน สำหรับบน Windows ให้ใช้ Test-NetConnection 203.0.113.10 -Port 22 ใน PowerShell แทน nc

ให้ทดสอบที่พอร์ต ไม่ใช่ที่โฮสต์ การที่ ping ล้มเหลวไม่ได้พิสูจน์อะไรเลย เพราะผู้ให้บริการจำนวนมากกรอง ICMP (internet control message protocol) ไว้ที่ขอบเครือข่าย และการ ping สำเร็จก็ไม่ได้พิสูจน์อะไรเช่นกัน เพราะมันไม่ได้บอกข้อมูลเกี่ยวกับพอร์ต 22 เลย

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

ไฟร์วอลล์ของผู้ให้บริการที่คุณมองไม่เห็นจากเซิร์ฟเวอร์

แผงควบคุม VPS ส่วนใหญ่นำเสนอไฟร์วอลล์เครือข่าย ซึ่งบางครั้งเรียกว่า security group หรือ cloud firewall โดยจะทำงานอยู่ต้นทางก่อนถึงอินสแตนซ์ของคุณและมีรายการกฎเป็นของตัวเอง ufw status บนเซิร์ฟเวอร์จะไม่สามารถมองเห็นกฎเหล่านี้ได้ จึงเป็นเหตุผลว่าทำไมประโยคที่ว่า "แต่ฉันอนุญาตพอร์ต 22 ไว้แล้วนะ" ถึงเป็นเรื่องที่พบได้บ่อย ให้เปิดแผงควบคุมและอ่านรายการกฎเหล่านั้นก่อนที่คุณจะแก้ไขกฎใดๆ บนตัวเซิร์ฟเวอร์

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

sudo tcpdump -ni any tcp port 22

หากไม่มีข้อมูลใดปรากฏขึ้นในขณะที่ไคลเอนต์ของคุณพยายามเชื่อมต่อ แสดงว่าแพ็กเก็ตถูกทิ้งไปก่อนที่จะถึงระบบปฏิบัติการ ดังนั้นข้อผิดพลาดจึงเกิดจากไฟร์วอลล์ของผู้ให้บริการหรือเส้นทางไปยังโฮสต์ หากแพ็กเก็ต SYN มาถึงแต่ไม่มีการตอบกลับออกไป แสดงว่าการทิ้งแพ็กเก็ตเกิดขึ้นในระดับโลคัลและเป็นหน้าที่ของ ufw หรือ nftables การทดสอบเพียงครั้งเดียวนี้จะช่วยแยกสาเหตุของปัญหา timeout ออกเป็นสองส่วน ซึ่งเป็นเหตุผลว่าทำไมการเข้าถึงผ่านคอนโซลจึงคุ้มค่าที่จะทำ

ลำดับการตั้งค่า ufw, IPv6 และการแบนตัวเอง

ความผิดพลาดเรื่องลำดับการตั้งค่า ufw ทำให้ผู้ใช้งานถูกตัดการเชื่อมต่อบ่อยที่สุด sudo ufw enable จะใช้โยบายปฏิเสธการเชื่อมต่อขาเข้า (deny incoming) เป็นค่าเริ่มต้นทันที ดังนั้นหากคุณยังไม่ได้ตั้งกฎอนุญาต SSH เซสชันปัจจุบันของคุณจะยังคงอยู่ได้ด้วยสถานะการเชื่อมต่อเดิม แต่การเชื่อมต่อใหม่ทั้งหมดจะหมดเวลา (timeout) ไป ให้ตั้งกฎอนุญาตก่อนแล้วจึงเปิดใช้งาน

sudo ufw allow OpenSSH
sudo ufw status verbose

โปรไฟล์แอปพลิเคชัน OpenSSH ครอบคลุมเฉพาะพอร์ต 22 เท่านั้น หากคุณวางแผนจะย้าย SSH ไปที่พอร์ต 2222 กฎที่คุณต้องใช้คือ sudo ufw allow 2222/tcp ซึ่งต้องเพิ่มก่อนที่จะเปลี่ยนพอร์ต ไม่ใช่หลังจากนั้น ชุดกฎที่ครอบคลุมกว่านี้อยู่ใน พื้นฐานไฟร์วอลล์ ufw สำหรับ VPS และลำดับการตั้งค่าที่ปลอดภัยเป็นส่วนหนึ่งของ สิ่งที่ควรทำในสิบนาทีแรกบน VPS ใหม่

IPv6 ทำให้เกิดอาการหมดเวลาที่ดูเหมือนผิดปกติ หาก hostname มีระเบียน AAAA อยู่ ไคลเอนต์ของคุณจะพยายามเชื่อมต่อผ่าน IPv6 ก่อน ดังนั้นเซิร์ฟเวอร์ที่ไม่มีกฎสำหรับ IPv6 จะค้าง ในขณะที่การเชื่อมต่อผ่าน IPv4 ปกติจะใช้งานได้ ให้แยกการตั้งค่าทั้งสองส่วนออกจากกันด้วยตนเอง

ssh -4 user@vps.example.com
ssh -6 user@vps.example.com

หาก -4 เชื่อมต่อได้แต่ -6 เชื่อมต่อไม่ได้ วิธีแก้ไขอยู่ที่กฎ IPv6 ของเซิร์ฟเวอร์ และ การเปิดพอร์ตเดียวกันสำหรับ IPv6 ใน ufw จะอธิบายขั้นตอนไว้

คุณอาจแบนตัวเองโดยไม่ตั้งใจ fail2ban จะคอยเฝ้าดู log การยืนยันตัวตนและแทรกกฎไฟร์วอลล์เพื่อบล็อกที่อยู่ IP ที่พยายามเข้าใช้งานล้มเหลวซ้ำๆ ดังนั้นการใช้กุญแจผิดหรือสคริปต์ที่พยายามเชื่อมต่อเบื้องหลังอาจทำให้ที่อยู่ IP ของทั้งสำนักงานถูกบล็อกได้ การแบนแบบทิ้งแพ็กเก็ต (drop) จะมีอาการเหมือนการหมดเวลา ส่วนการแบนแบบปฏิเสธ (reject) จะส่งค่า No route to host กลับมา จากคอนโซล:

sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 198.51.100.24

การเพิ่มที่อยู่ IP ของคุณเองลงใน ignoreip เป็นส่วนหนึ่งของ การตั้งค่า fail2ban ที่ใช้งานได้จริงบน Ubuntu 24.04

ข้อผิดพลาดที่ไม่ได้เกิดจากการปฏิเสธการเชื่อมต่อหรือการหมดเวลา

No route to host หมายความว่าได้รับข้อความ ICMP unreachable กลับมา อาจเป็นเพราะเครื่องของคุณไม่มีเส้นทางไปยังเครือข่ายนั้น หรือมีอุปกรณ์ระหว่างทางตอบกลับด้วยการปฏิเสธทางเทคนิค ซึ่งเป็นผลลัพธ์จากการตั้งค่ากฎ REJECT ใน iptables

Network is unreachable เป็นการตอบกลับจากเครื่องของคุณเอง โดยระบุว่าไม่มีเส้นทางสำหรับ address family นั้นเลย ซึ่งมักเกิดขึ้นเมื่อ hostname ถูก resolve ไปเป็นที่อยู่ IPv6 เท่านั้น ในขณะที่การเชื่อมต่อของคุณรองรับเฉพาะ IPv4

kex_exchange_identification: Connection closed by remote host หมายความว่า TCP เชื่อมต่อสำเร็จแล้ว แต่เซิร์ฟเวอร์ตัดการเชื่อมต่อก่อนที่การแลกเปลี่ยนกุญแจจะเสร็จสิ้น พอร์ตเปิดอยู่และ sshd ทำงานปกติ ดังนั้นให้ตรวจสอบภาระงานของเซิร์ฟเวอร์, ตรวจสอบ MaxStartups หรือตรวจสอบว่ามีการแบนเกิดขึ้นในขณะที่คุณกำลังเชื่อมต่อหรือไม่

Permission denied (publickey) หมายความว่าคุณเข้าสู่ขั้นตอนการยืนยันตัวตนแล้วแต่ไม่ผ่าน เครือข่ายและไฟร์วอลล์ทำงานปกติ ดังนั้นเนื้อหาในคู่มือนี้จึงไม่เกี่ยวข้องกับปัญหาของคุณ ให้ไปที่ การแก้ไขปัญหา Permission denied (publickey) บน SSH แทน

วิธีเข้าถึงระบบอีกครั้งและวิธีป้องกันการถูกล็อกเอาต์ซ้ำสอง

ผู้ให้บริการ VPS ที่มีมาตรฐานทุกรายจะมีคอนโซลที่ทำงานแยกจากเครือข่ายของ Guest ให้ใช้งานเสมอ ไม่ว่าจะเป็น serial console หรือหน้าจอ VNC ผ่านเบราว์เซอร์ คอนโซลนี้คือช่องทางกู้คืนระบบสำหรับทั้งสองกรณีในคู่มือนี้ เพราะมันยังคงทำงานได้แม้ในขณะที่ sshd ถูกหยุดการทำงาน หรือเมื่อกฎ firewall ปฏิเสธการเชื่อมต่อทั้งหมด ให้ค้นหาคอนโซลนี้ในแผงควบคุม (panel) ของคุณ ล็อกอินด้วย root หรือผู้ใช้ปกติของคุณ จากนั้นจึงดำเนินการตรวจสอบตามขั้นตอนข้างต้น หากคุณไม่เคยตั้งรหัสผ่าน root ไว้ แผงควบคุมส่วนใหญ่จะมีฟังก์ชันสำหรับรีเซ็ตรหัสผ่านให้

ในกรณีที่ไม่มีคอนโซลให้ใช้งาน ทางเลือกสำรองคือโหมดกู้คืน (rescue mode) ของผู้ให้บริการ ระบบจะทำการบูตเข้าสู่ระบบกู้คืนขนาดเล็กและ mount ดิสก์ของคุณ เพื่อให้คุณสามารถแก้ไขไฟล์ /etc/ssh/sshd_config หรือลบกฎ firewall ที่ผิดพลาดในขณะที่ระบบออฟไลน์อยู่ จากนั้นจึงค่อยรีบูตเครื่องใหม่

นิสัยสองประการที่จะช่วยป้องกันการถูกล็อกเอาต์ในอนาคตคือ การเปิด SSH session ทิ้งไว้อีกหนึ่งหน้าต่างเสมอในขณะที่คุณแก้ไข sshd หรือ firewall เพราะ session นั้นจะยังคงสถานะการเชื่อมต่อเดิมไว้ในขณะที่คุณทดสอบการเชื่อมต่อใหม่ และการตั้งค่าคำสั่งย้อนกลับอัตโนมัติก่อนการเปลี่ยนแปลงกฎ firewall ที่มีความเสี่ยง

sudo systemd-run --unit=ufw-rollback --on-active=10min /usr/sbin/ufw disable
sudo systemctl stop ufw-rollback.timer

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

ลำดับขั้นตอนการทำงาน

  1. อ่านข้อความแสดงข้อผิดพลาดและสังเกตระยะเวลาที่ใช้ในการปรากฏข้อความดังกล่าว
  2. หากขึ้นว่า Refused: ให้ไปที่คอนโซลและตรวจสอบ sudo ss -tlnp เพื่อดู socket ที่กำลังรอรับการเชื่อมต่อ (listening socket), พอร์ตที่ใช้ และที่อยู่ (address) ที่ผูกไว้
  3. หากขึ้นว่า Timed out: ให้ยืนยันที่อยู่จากเครื่องของคุณ จากนั้นตรวจสอบ firewall ของผู้ให้บริการในแผงควบคุม และตรวจสอบ host firewall บนเซิร์ฟเวอร์
  4. หากไม่พบข้อความทั้งสองรูปแบบข้างต้น: แสดงว่าคุณมีการเชื่อมต่อ TCP อยู่แล้ว ให้พิจารณาว่าเป็นปัญหาด้านการยืนยันตัวตนหรือภาระงานของเซิร์ฟเวอร์ (server load) แทนที่จะเป็นปัญหาด้านเครือข่าย

FAQ

ทำไม SSH ถึงแจ้งว่า "Connection refused" ทั้งที่ sshd กำลังทำงานอยู่?

เพราะการปฏิเสธการเชื่อมต่อมาจาก socket ไม่ใช่จากตัว service เอง และ sshd ที่กำลังทำงานอยู่ก็ยังสามารถปฏิเสธคุณได้ ให้เปิดคอนโซลของผู้ให้บริการแล้วรัน sudo ss -tlnp หาก socket อยู่บน 127.0.0.1:22 มันจะปฏิเสธไคลเอนต์จากระยะไกลทั้งหมดเพราะถูกผูกไว้กับ loopback เท่านั้น หาก socket อยู่บนพอร์ตอื่น มันจะยังคงปฏิเสธทุกคนที่พยายามเชื่อมต่อผ่านพอร์ต 22 หากมีการใช้ systemd socket activation พอร์ตจะถูกกำหนดจาก ssh.socket ไม่ใช่จาก sshd_config ดังนั้นให้ตรวจสอบ systemctl is-enabled ssh.socket ด้วย นอกจากนี้ กฎของ ufw reject ยังทำให้เกิดการปฏิเสธการเชื่อมต่อในนามของโฮสต์ ดังนั้นควรอ่าน sudo ufw status verbose ก่อนที่จะสรุปผลใดๆ

ทำไม SSH ถึงแจ้งว่าหมดเวลา (time out) ทั้งที่ ufw อนุญาตพอร์ต 22 แล้ว?

เพราะการหมดเวลาหมายความว่าไม่มีการตอบกลับ และ ufw ไม่ใช่ไฟร์วอลล์เดียวที่อยู่ในเส้นทาง แผงควบคุม VPS ส่วนใหญ่จะมี network firewall ทำงานอยู่หน้า instance และระบบปฏิบัติการจะไม่เห็นสิ่งที่ไฟร์วอลล์นั้นดรอปทิ้ง จากคอนโซล ให้รัน sudo tcpdump -ni any tcp port 22 แล้วลองเชื่อมต่อจากแล็ปท็อปของคุณในขณะที่คำสั่งกำลังทำงาน หากไม่มีแพ็กเก็ตเข้ามาเลย แสดงว่าการดรอปเกิดขึ้นที่ต้นทางในแผงควบคุม หากมีแพ็กเก็ตเข้ามาแต่ไม่มีการตอบกลับ แสดงว่าการดรอปเกิดขึ้นในเครื่องที่ ufw หรือ nftables

การ ping ไม่ผ่านหมายความว่า VPS ของฉันล่มใช่หรือไม่?

ไม่เสมอไป ผู้ให้บริการหลายรายกรอง ICMP ที่ขอบเครือข่าย ดังนั้นเซิร์ฟเวอร์ที่ให้บริการตามปกติอาจเพิกเฉยต่อทุก ping ที่คุณส่งไป การ ping ผ่านก็ไม่ได้บอกอะไรมากเช่นกัน เพราะมันไม่ได้ยืนยันว่าพอร์ต 22 เปิดอยู่ ให้ทดสอบที่ตัวพอร์ตโดยตรงด้วย nc -vz -w 5 203.0.113.10 22 จากเครื่องของคุณ หรือใช้ Test-NetConnection 203.0.113.10 -Port 22 ใน PowerShell บน Windows

ฉันเปลี่ยนพอร์ต SSH แล้วไม่มีอะไรเชื่อมต่อได้เลย เกิดอะไรขึ้น?

มีสองสาเหตุหลักที่ทำให้เกิดปัญหานี้ หากไฟร์วอลล์ไม่มีกฎสำหรับพอร์ตใหม่ ความพยายามเชื่อมต่อพอร์ตใหม่จะหมดเวลา (time out) ในขณะที่พอร์ต 22 จะปฏิเสธการเชื่อมต่อ ดังนั้น sudo ufw allow 2222/tcp จึงต้องทำก่อนการเปลี่ยนพอร์ตไม่ใช่หลังจากนั้น หากเครื่องใช้ systemd socket activation สำหรับ SSH ค่า Port 2222 ใน sshd_config จะถูกเพิกเฉยและ systemd จะยังคงถือพอร์ตเดิมไว้ ซึ่งคุณสามารถตรวจสอบได้ด้วย systemctl is-enabled ssh.socket ให้กู้คืนระบบผ่านคอนโซลของผู้ให้บริการ แก้ไขตามสาเหตุที่พบ แล้วจึงเชื่อมต่อด้วย ssh -p 2222 user@203.0.113.10 เมื่อ sudo ss -tlnp แสดงผล socket ใหม่แล้ว