SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-09-04

วิธีเปลี่ยนพอร์ต SSH บน Rocky Linux และ AlmaLinux

คู่มือการเปลี่ยนพอร์ต SSH บน Rocky Linux และ AlmaLinux ให้ปลอดภัยโดยไม่ถูกตัดการเชื่อมต่อ ครอบคลุมการตั้งค่า firewalld การเพิ่มพอร์ตใน SELinux ด้วย semanage และการแก้ไข sshd_config

เหตุผลที่การเปลี่ยนพอร์ต SSH ในที่นี้ต้องทำถึง 3 ขั้นตอน

การเปลี่ยนพอร์ต SSH บน Rocky Linux, AlmaLinux, CentOS Stream หรือ Fedora การแก้ไขเพียงจุดเดียวไม่เพียงพอ ระบบแยกส่วนกัน 3 ระบบต่างมีผลต่อการทำงานของการเชื่อมต่อบนพอร์ตใหม่ firewalld เป็นตัวตัดสินว่าแพ็กเก็ตจะมาถึงเครื่องหรือไม่ SELinux เป็นตัวตัดสินว่า sshd จะได้รับอนุญาตให้ bind พอร์ตหมายเลขนั้นได้หรือไม่ และ sshd_config เป็นตัวกำหนดว่า daemon จะเรียกใช้พอร์ตใด หากข้ามขั้นตอน SELinux ไป daemon จะปฏิเสธการเริ่มทำงาน หากข้ามขั้นตอน firewalld ไป daemon จะเริ่มทำงานและรอรับการเชื่อมต่อ แต่จะไม่มีใครสามารถเข้าถึงได้

บน Ubuntu งานเดียวกันนี้ทำได้ด้วยการแก้ไขเพียงจุดเดียวแล้วรีสตาร์ท เพราะ Ubuntu ใช้ AppArmor แทน SELinux และไม่มีโปรไฟล์ที่จำกัดว่า sshd สามารถ bind พอร์ตใดได้บ้าง หาก ufw เปิดใช้งานอยู่ คุณเพียงแค่เพิ่มกฎเข้าไปหนึ่งข้อ นี่คือความแตกต่างทั้งหมด ตระกูล RHEL จะเปิดใช้งาน firewalld และบังคับใช้ SELinux มาตั้งแต่การติดตั้งใหม่ ซึ่งทั้งสองระบบนี้ให้ความสำคัญกับหมายเลขพอร์ต

ให้ดำเนินการตามลำดับนี้เพื่อให้เซสชันปัจจุบันของคุณยังคงใช้งานได้ตลอดทุกขั้นตอน:

  1. เปิดพอร์ตใหม่ใน firewalld โดยให้พอร์ต 22 เปิดไว้ก่อนในขณะนี้
  2. เพิ่ม label ของ SELinux สำหรับพอร์ตใหม่ด้วย semanage
  3. ตั้งค่าพอร์ตในไฟล์คอนฟิกูเรชันของ sshd
  4. รีสตาร์ท sshd จากนั้นล็อกอินผ่านพอร์ตใหม่จากเทอร์มินัลที่สองก่อนที่จะปิดเทอร์มินัลแรก
ค้นหาเว็บคอนโซล (VNC หรือ serial) ของผู้ให้บริการของคุณก่อนเริ่มดำเนินการ และตรวจสอบว่าคุณสามารถล็อกอินผ่านช่องทางนั้นได้ คอนโซลดังกล่าวคือทางรอดของคุณหากการเปลี่ยนแปลงเกิดข้อผิดพลาด การเปลี่ยนพอร์ตเป็นสาเหตุที่พบบ่อยที่สุดที่ทำให้ผู้เช่าล็อกตัวเองออกจากเซิร์ฟเวอร์ที่เพิ่งชำระเงินไป

ขั้นแรก ติดตั้ง semanage

semanage เป็นเครื่องมือสำหรับแก้ไขการตั้งค่า policy ของ SELinux ซึ่งการติดตั้ง Rocky Linux หรือ AlmaLinux แบบขั้นต่ำจะไม่มีเครื่องมือนี้มาให้ โดยเครื่องมือดังกล่าวอยู่ในแพ็กเกจ policycoreutils-python-utils

sudo dnf install -y policycoreutils-python-utils

การรันคำสั่งก่อนติดตั้งแพ็กเกจดังกล่าวจะทำให้เกิดข้อผิดพลาด sudo: semanage: command not found ซึ่งเป็นจุดที่ผู้อ่านหลายคนตัดสินใจว่า SELinux ไม่ได้ถูกติดตั้งไว้และข้ามขั้นตอนนี้ไป ความจริงคือ SELinux ถูกติดตั้งอยู่แล้ว เพียงแต่ขาดเครื่องมือจัดการเท่านั้น หากไวยากรณ์ dnf เป็นเรื่องใหม่สำหรับคุณ คำสั่งที่เทียบเท่ากันของ dnf และ apt จะช่วยให้คุณเข้าใจได้โดยอ้างอิงจากสิ่งที่คุณรู้อยู่แล้ว

เลือกพอร์ตและตรวจสอบว่าไม่มีกระบวนการใดใช้งานอยู่

คุณสามารถเลือกพอร์ต TCP ใดก็ได้ที่ว่างอยู่ระหว่าง 1024 ถึง 65535 โดยให้ตรวจสอบ 2 ขั้นตอนก่อนตัดสินใจเลือก:

sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222

คำสั่งแรกจะแสดงว่ามีกระบวนการใดกำลังฟัง (listen) อยู่ที่พอร์ตนั้นหรือไม่ ส่วนคำสั่งที่สองจะตรวจสอบว่านโยบาย SELinux ได้กำหนดพอร์ตนั้นให้กับบริการประเภทอื่นไปแล้วหรือไม่ หากพอร์ตว่างอยู่ ทั้งสองคำสั่งจะไม่แสดงผลลัพธ์ใดๆ หากนโยบายได้กำหนดพอร์ตนั้นไว้แล้ว คำสั่ง semanage port -a ในขั้นตอนที่ 2 จะล้มเหลวด้วยข้อผิดพลาด ValueError: Port tcp/2222 already defined ซึ่งวิธีแก้ไขคือการเลือกหมายเลขพอร์ตใหม่

ในคู่มือนี้จะใช้พอร์ต 2222 เป็นตัวอย่าง อย่างไรก็ตาม พอร์ตนี้เป็นพอร์ตแรกๆ ที่เครื่องมือสแกนจะตรวจสอบต่อจากพอร์ต 22 ดังนั้นบนเซิร์ฟเวอร์จริงควรเลือกพอร์ตที่คาดเดาได้ยากกว่านี้

ขั้นตอนที่ 1: เปิดพอร์ตใน firewalld

sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

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

ให้คงรายการบริการ ssh ไว้ตามเดิมก่อน รายการนี้คือสิ่งที่ทำให้พอร์ต 22 เปิดอยู่ และเป็นช่องทางสำรองของคุณในระหว่างการทดสอบ

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

ขั้นตอนที่ 2: กำหนดป้ายกำกับพอร์ตสำหรับ SELinux

sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t

-a เป็นคำสั่งสำหรับเพิ่มการกำหนดพอร์ตใหม่ ส่วน -t ssh_port_t คือประเภทที่พอร์ต SSH ต้องใช้ คำสั่งที่สองจะแสดงรายการทั้งหมดที่ ssh_port_t ครอบคลุมอยู่ในปัจจุบัน เพื่อให้คุณตรวจสอบได้ว่าหมายเลขพอร์ตของคุณถูกเพิ่มเข้าไปแล้วก่อนที่จะดำเนินการกับ daemon

เหตุใด SELinux จึงบล็อกพอร์ตดังกล่าว

SELinux (Security-Enhanced Linux) จะกำหนดป้ายกำกับ (label) ให้กับทุกวัตถุในระบบ ซึ่งหมายเลขพอร์ต TCP ก็ถือเป็นวัตถุชนิดหนึ่งเช่นกัน SSH daemon จะทำงานภายใต้ขอบเขตที่เรียกว่า sshd_t โดยนโยบายจะอนุญาตให้ sshd_t ผูกกับพอร์ต TCP ที่มีป้ายกำกับ ssh_port_t เท่านั้น ซึ่งโดยค่าเริ่มต้นจะมีเพียงพอร์ต 22 เท่านั้นที่มีป้ายกำกับนี้ เมื่อคุณสั่งให้ daemon ผูกกับพอร์ต 2222 เคอร์เนลจะตรวจสอบป้ายกำกับดังกล่าว แล้วพบว่านโยบายได้กำหนดประเภททั่วไปไว้สำหรับหมายเลขพอร์ตนั้น จึงปฏิเสธสิทธิ์ name_bind บนซ็อกเก็ต

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

getenforce จะบอกให้คุณทราบว่าระบบอยู่ในโหมดใด บนโหมด Permissive การปฏิเสธการเข้าถึงจะถูกบันทึกไว้แต่ไม่มีการบังคับใช้จริง ทำให้การเปลี่ยนพอร์ตดูเหมือนจะใช้งานได้ แต่จะเกิดปัญหาในวันที่ใครบางคนรันคำสั่ง setenforce 1 หรือเมื่อรีบูตเครื่องเข้าสู่โหมด enforcing คุณจึงควรติดป้ายกำกับพอร์ตไว้ไม่ว่าจะอยู่ในโหมดใดก็ตาม คู่มือพื้นฐาน SELinux สำหรับเซิร์ฟเวอร์ ได้อธิบายรายละเอียดเกี่ยวกับโหมด, บริบท (context) และบูลีน (boolean) ไว้อย่างครบถ้วน พอร์ตไม่ใช่เพียงวัตถุเดียวที่ทำให้เกิดปัญหานี้ นโยบายเดียวกันนี้ยังป้องกันไม่ให้คอนเทนเนอร์อ่านไดเรกทอรีของโฮสต์ที่ถูก mount ไว้จนกว่าพาธนั้นจะถูกติดป้ายกำกับใหม่ ซึ่งเป็นเหตุผลว่าทำไม การติดตั้ง Docker บน Rocky Linux หรือ AlmaLinux จึงต้องมีขั้นตอนเกี่ยวกับ SELinux ซึ่งคู่มือของ Ubuntu ไม่เคยกล่าวถึง

ขั้นตอนที่ 3: ตั้งค่าพอร์ตในไฟล์คอนฟิกูเรชันของ sshd

บน Rocky Linux 9 และ 10, AlmaLinux 9 และ 10 รวมถึง Fedora เวอร์ชันปัจจุบัน ไฟล์ /etc/ssh/sshd_config จะเริ่มต้นด้วยบรรทัด include ดังนั้นตำแหน่งที่เหมาะสมที่สุดสำหรับการแก้ไขของคุณคือการสร้างไฟล์ drop-in วิธีนี้จะช่วยให้การอัปเดตแพ็กเกจไม่ทับซ้อนกับการตั้งค่าของคุณ

grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -t

หาก grep ไม่พบคำสั่ง Include ซึ่งเป็นกรณีที่พบได้ใน Rocky Linux 8 และอิมเมจรุ่นเก่าอื่นๆ ให้ใส่ Port 2222 ลงใน /etc/ssh/sshd_config โดยตรงแทน ทั้งนี้ sshd -t จะทำการตรวจสอบไวยากรณ์ของคอนฟิกูเรชันทั้งหมดรวมถึงไฟล์ drop-in ด้วย หากพบข้อผิดพลาดให้แก้ไขให้เรียบร้อยก่อนทำการรีสตาร์ท เพราะหากคอนฟิกูเรชันมีไวยากรณ์ผิดพลาด จะส่งผลให้ daemon ไม่สามารถกลับมาทำงานได้

Port สามารถปรากฏได้มากกว่าหนึ่งครั้ง และ sshd จะรอรับการเชื่อมต่อในทุกพอร์ตที่ระบุไว้ การคงค่า Port 22 ไว้ควบคู่กับ Port 2222 ในช่วงวันแรกถือเป็นมาตรการป้องกันที่ทำได้ง่ายและมีประสิทธิภาพ ตราบใดที่คุณไม่ลืมที่จะลบค่าเดิมออกในภายหลัง

sshd ของคุณถูกเริ่มทำงานโดย socket unit หรือไม่

อิมเมจบางตัวเริ่มการทำงานของ SSH ผ่านระบบ socket activation ของ systemd แทนที่จะเป็น service ที่ทำงานค้างไว้ตลอดเวลา ในกรณีที่มีการตั้งค่าเช่นนี้ systemd จะเป็นผู้ถือครอง socket ที่รอรับการเชื่อมต่อและส่งต่อการเชื่อมต่อเหล่านั้นไปยัง sshd ดังนั้นบรรทัด Port ใน sshd_config จึงถูกละเว้นโดยสิ้นเชิง โปรดตรวจสอบก่อนที่คุณจะรีสตาร์ทสิ่งใดก็ตาม:

systemctl is-enabled sshd.socket

หากได้รับคำตอบเป็น enabled หมายความว่าพอร์ตถูกกำหนดไว้ที่ socket unit ไม่ใช่ใน sshd_config:

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

จำเป็นต้องใช้ ListenStream= แบบว่างเปล่า ค่าต่างๆ จะถูกสะสมรวมกันจากไฟล์ drop-in ดังนั้นหากไม่มีการกำหนดค่าว่างเพื่อล้างรายการก่อน socket จะยังคงรอรับการเชื่อมต่อที่พอร์ต 22 ควบคู่ไปกับพอร์ต 2222 ให้ใช้การตั้งค่าด้วย sudo systemctl daemon-reload แล้วตามด้วย sudo systemctl restart sshd.socket หาก unit ดังกล่าวถูกปิดใช้งานหรือไม่มีอยู่บนเซิร์ฟเวอร์ของคุณ หัวข้อนี้จะไม่มีผลกับคุณ

ขั้นตอนที่ 4: รีสตาร์ทและทดสอบจากเทอร์มินัลที่สอง

sudo systemctl restart sshd
systemctl status sshd
sudo ss -tlnp | grep sshd

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

ssh -p 2222 youruser@203.0.113.10

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

Firewall drop หรือ SELinux denial? วิธีแยกแยะความแตกต่าง

จากแล็ปท็อปของคุณ ความล้มเหลวทั้งสองรูปแบบดูแทบไม่ต่างกัน แต่บนเซิร์ฟเวอร์นั้นทั้งสองกรณีมีความแตกต่างกันอย่างสิ้นเชิง

  • หาก systemctl status sshd แสดงว่า unit ล้มเหลว แสดงว่า daemon ไม่ได้รับ socket ของตน ซึ่งเป็นข้อผิดพลาดจากการตั้งค่าหรือเกิดจาก SELinux denial
  • หาก unit ยังทำงานอยู่และ ss -tlnp แสดงว่า sshd ผูกกับพอร์ตใหม่เรียบร้อยแล้ว แสดงว่า daemon ทำงานปกติและปัญหาอยู่ที่เส้นทางเครือข่าย ไม่ว่าจะเป็น firewalld, ไฟร์วอลล์ของผู้ให้บริการ หรือที่อยู่และพอร์ตที่คุณระบุ

สำหรับกรณีของ SELinux ให้ตรวจสอบบันทึก audit แทนการคาดเดา:

sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pager

การปฏิเสธ (denial) ใน name_bind บนคลาส tcp_socket จะระบุชื่อกระบวนการใน comm="sshd", หมายเลขพอร์ตใน src= และ label ที่พอร์ตนั้นถืออยู่จริงใน tcontext= ฟิลด์สุดท้ายนั้นคือคำตอบ หากเป็นค่าอื่นที่ไม่ใช่ ssh_port_t แสดงว่าขั้นตอนที่ 2 ไม่ได้ถูกนำไปใช้กับพอร์ตที่คุณกำลังใช้งาน ซึ่งมักเกิดจากการพิมพ์หมายเลขผิดหรือใช้โปรโตคอลไม่ถูกต้อง ให้ติดตั้ง setroubleshoot-server หากคุณต้องการให้ sealert แปลงบันทึกดังกล่าวให้เป็นประโยคที่อ่านเข้าใจง่าย

ข้อความที่ sshd เขียนขึ้นเมื่อ kernel ปฏิเสธการ bind จะมีลักษณะดังนี้:

error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.

Permission denied บนพอร์ตที่สูงกว่า 1024 ซึ่งไม่จำเป็นต้องใช้สิทธิ์ root ในการ bind คือสัญญาณบ่งชี้ของ SELinux ส่วน Address already in use ในบรรทัดเดียวกันคือข้อผิดพลาดที่ต่างออกไป ซึ่งหมายถึงมีกระบวนการอื่นกำลังใช้งานพอร์ตนั้นอยู่ จากฝั่งไคลเอนต์ ความแตกต่างระหว่าง connection refused และ connection timed out จะช่วยแยกแยะกรณีเครือข่ายทั้งสองออกจากกัน เพราะการปฏิเสธ (refused) หมายความว่าแพ็กเก็ตของคุณไปถึงโฮสต์แล้วแต่ไม่มีบริการใดรอรับอยู่ ในขณะที่การหมดเวลา (timeout) หมายความว่าไม่มีการตอบกลับใดๆ เลย

ปิดพอร์ต 22 และอัปเดตไคลเอนต์ของคุณ

เมื่อคุณเข้าสู่ระบบผ่านพอร์ตใหม่ได้สำเร็จหลายครั้งแล้ว ให้ปิดพอร์ต 22 ทิ้ง:

sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

ไม่ต้องแก้ไข SELinux label บนพอร์ต 22 ปล่อยไว้ตามนโยบายพื้นฐานของระบบ เนื่องจากพอร์ตดังกล่าวจะไม่ได้รับแพ็กเก็ตใดๆ อีกเมื่อไฟร์วอลล์บล็อกการเชื่อมต่อแล้ว

จากนั้นให้แก้ไขการตั้งค่าที่ฝั่งไคลเอนต์ เพราะเครื่องมือทุกตัวที่เคยใช้พอร์ตเริ่มต้นจำเป็นต้องได้รับแจ้งการเปลี่ยนแปลง ให้ระบุค่านี้ไว้ใน ~/.ssh/config บนเครื่องของคุณเพียงครั้งเดียว แทนที่จะต้องพิมพ์ -p ตลอดไป:

Host myvps
  HostName 203.0.113.10
  Port 2222
  User youruser

scp, sftp, rsync และ Ansible จะอ่านค่าจากไฟล์ดังกล่าวโดยอัตโนมัติ อย่างไรก็ตาม งานสำรองข้อมูล (backup jobs), การตรวจสอบสถานะ (monitoring checks) และสคริปต์ cron ที่ระบุพอร์ต 22 ไว้โดยตรงจะไม่ได้รับผลจากการตั้งค่านี้ คุณจึงควรตามไปแก้ไขรายการเหล่านั้นในขณะที่ยังจำรายละเอียดการเปลี่ยนแปลงได้แม่นยำ

การเปลี่ยนพอร์ตมีผลอย่างไรและไม่มีผลอย่างไร

การเปลี่ยนพอร์ตช่วยลดสัญญาณรบกวนใน log ได้ เนื่องจากสแกนเนอร์อัตโนมัติจะสุ่มโจมตีพอร์ต 22 อยู่ตลอดเวลา การย้ายออกจากพอร์ตนี้จะช่วยลดบรรทัดขยะเหล่านั้นออกจาก journal ทำให้มองเห็นเหตุการณ์จริงได้ง่ายขึ้น อย่างไรก็ตาม นี่ไม่ใช่มาตรการรักษาความปลอดภัย เพราะสแกนเนอร์ที่กวาดตรวจพอร์ตทั้งหมดจะพบ daemon ของคุณและอ่าน version banner ได้อยู่ดี ให้ถือว่าการเปลี่ยนพอร์ตเป็นเพียงการจัดระเบียบระบบเท่านั้น และใช้การป้องกันที่แท้จริงด้วยการยืนยันตัวตนผ่าน key เท่านั้น (key-only authentication) พร้อมปิดการล็อกอินด้วยรหัสผ่าน ซึ่ง คู่มือการปรับแต่ง SSH ให้ปลอดภัยสำหรับ VPS ได้อธิบายขั้นตอนไว้อย่างละเอียดแล้ว

ทุกสิ่งที่กล่าวมาข้างต้นทำงานเหมือนกันบน RHEL rebuild หลักทั้งสองตัว เนื่องจากสร้างมาจากซอร์สเดียวกัน ดู การเปรียบเทียบระหว่าง Rocky Linux และ AlmaLinux หากคุณยังตัดสินใจเลือกไม่ได้ เหตุผลที่มี rebuild สองตัวที่เกือบจะเหมือนกันให้เลือกนั้น เป็นเพราะ CentOS เลิกเป็น rebuild ตั้งแต่ปี 2020 ซึ่งเป็นเหตุการณ์ที่เล่าไว้โดยละเอียดใน เรื่องราวจาก Red Hat สู่ CentOS ไปจนถึง Rocky และ AlmaLinux โปรดตรวจสอบว่าคุณได้รับ release ใดก่อนที่จะทำตามคู่มือเก่าๆ โดยใช้ cat /etc/os-release คู่มือที่เขียนสำหรับ Rocky Linux 8 ยังคงติดอันดับการค้นหาที่ดีและขั้นตอน semanage กับ firewall-cmd ยังคงถูกต้อง แต่ Rocky 8 ไม่มีบรรทัด include sshd_config.d และไม่มี socket unit ให้ต้องพิจารณา ดังนั้นส่วนของ sshd ในคู่มือเหล่านั้นจึงไม่ตรงกับระบบในปัจจุบัน

ต้องกำหนดค่าพอร์ตใหม่ให้กับ fail2ban

fail2ban ไม่ได้อยู่ใน repository พื้นฐาน แต่มาจาก EPEL (extra packages for enterprise Linux):

sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalld

subpackage fail2ban-firewalld ช่วยให้ fail2ban เขียนคำสั่งแบนผ่าน firewalld ซึ่งเป็นสิ่งที่จำเป็นสำหรับเซิร์ฟเวอร์ที่ใช้ firewalld ในการจัดการ ruleset

jail ค่าเริ่มต้นของ sshd ตั้งค่า port = ssh ไว้ ซึ่งชื่อดังกล่าวจะถูกแปลงผ่าน /etc/services ไปเป็นพอร์ต 22 หลังจากที่คุณเปลี่ยนพอร์ตแล้ว jail จะเฝ้าระวังพอร์ตที่ไม่มีการโจมตี ทำให้ไม่มีการแบนเกิดขึ้นในขณะที่มีความพยายามล็อกอินล้มเหลวสะสมอยู่ที่พอร์ต 2222 ให้กำหนดพอร์ตเป็นตัวเลขใน /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600

backend = systemd จะอ่านความล้มเหลวจาก journal แทนที่จะอ่านจาก /var/log/secure ซึ่งเป็นทางเลือกที่ปลอดภัยกว่าสำหรับการติดตั้งแบบ minimal ที่อาจไม่มี rsyslog ติดตั้งอยู่ เริ่มการทำงานด้วย sudo systemctl enable --now fail2ban และตรวจสอบสถานะของ jail ด้วย sudo fail2ban-client status sshd รูปแบบไวยากรณ์ของ jail เหมือนกับที่ใช้ใน การตั้งค่า fail2ban สำหรับ SSH บน Ubuntu 24.04 โดยจะแตกต่างกันเพียงแหล่งที่มาของแพ็กเกจและ action ที่ใช้ในการแบนเท่านั้น

การแพตช์มีความสำคัญมากกว่าพอร์ต

เซิร์ฟเวอร์ที่ย้ายพอร์ต SSH ไปยังพอร์ตอื่นแต่ไม่ได้อัปเดตความปลอดภัยมาเป็นเวลา 4 เดือนนั้นมีความเสี่ยงสูงกว่าเซิร์ฟเวอร์ที่ใช้พอร์ต 22 แต่มีการแพตช์ตัวเองทุกคืน ให้เปิดใช้งาน unattended updates ในเซสชันเดียวกันขณะที่คุณยังเป็น root อยู่: การอัปเดต dnf อัตโนมัติบน Rocky Linux และ AlmaLinux ครอบคลุมถึงการตั้งค่าตัวจับเวลาและตัวเลือกระหว่างการดาวน์โหลดอัปเดตกับการติดตั้งอัปเดต การติดตั้งอัปเดตไม่ได้เป็นการรีสตาร์ท daemon ที่กำลังรันโค้ดเวอร์ชันเก่าอยู่ ดังนั้น การตรวจสอบสิ่งที่ยังคงต้องรีสตาร์ทหรือรีบูต จึงเป็นสิ่งที่ควรทำทุกครั้งที่มีการอัปเดต openssh-server หรือไลบรารีที่เกี่ยวข้องเข้ามาในชุดอัปเดตนั้น

FAQ

ทำไม sshd ถึงไม่ยอมเริ่มทำงานหลังจากเปลี่ยนพอร์ตบน Rocky Linux?

เกือบทุกกรณีเกิดจากการที่ SELinux ไม่มี label กำกับพอร์ตที่ถูกต้อง sshd ทำงานภายใต้ข้อจำกัดของ domain sshd_t และนโยบายอนุญาตให้ผูก (bind) ได้เฉพาะพอร์ตที่ระบุ label เป็น ssh_port_t เท่านั้น ซึ่งโดยปกติจะมีแค่พอร์ต 22 พอร์ตเดียว เคอร์เนลจะปฏิเสธการผูกพอร์ต ทำให้ daemon หยุดทำงานแทนที่จะรอรับการเชื่อมต่อ และ journalctl -u sshd จะแสดงข้อความในรูปแบบ error: Bind to port 2222 on 0.0.0.0 failed: Permission denied. ให้รันคำสั่ง sudo semanage port -a -t ssh_port_t -p tcp 2222 โดยระบุหมายเลขพอร์ตของคุณ จากนั้นจึงเริ่ม service ใหม่ หากไม่พบคำสั่ง semanage ให้ติดตั้งแพ็กเกจ policycoreutils-python-utils ก่อน

ยังจำเป็นต้องใช้ semanage หรือไม่หาก SELinux อยู่ในโหมด permissive?

จำเป็น เพราะในโหมด permissive ระบบจะบันทึกการปฏิเสธไว้แต่ยังคงอนุญาตให้ผูกพอร์ตได้ ทำให้ดูเหมือนว่าการตั้งค่าใช้งานได้ปกติ แต่ตัว label นั้นยังคงขาดหายไป ทันทีที่มีการรันคำสั่ง setenforce 1 หรือมีการรีบูตเครื่องโดยตั้งค่า SELINUX=enforcing ไว้ใน /etc/selinux/config บริการ sshd จะไม่สามารถเริ่มทำงานบนพอร์ตนั้นได้อีก การเพิ่ม label ใช้เพียงคำสั่งเดียวและช่วยป้องกันความล้มเหลวที่อาจเกิดขึ้นในอีกหลายสัปดาห์ข้างหน้าโดยหาสาเหตุไม่พบ

พอร์ตมี label แล้วและ sshd ก็ทำงานอยู่ ทำไมการเชื่อมต่อถึงหมดเวลา (time out)?

การที่ daemon ทำงานได้แสดงว่า SELinux ไม่ได้ขัดขวาง ดังนั้นแพ็กเกจจึงถูกทิ้งระหว่างทาง ให้ตรวจสอบ sudo firewall-cmd --list-ports สำหรับพอร์ตของคุณ และยืนยันว่าคุณได้รันคำสั่ง firewall-cmd --reload หลังจากเพิ่มกฎ --permanent แล้ว เพราะกฎแบบถาวรเพียงอย่างเดียวจะไม่ถูกนำไปใช้กับ firewall ที่กำลังทำงานอยู่ จากนั้นให้ตรวจสอบแผงควบคุมโฮสต์ของคุณว่ามี network firewall แยกต่างหากอยู่หน้า VPS หรือไม่ นั่นเป็นจุดที่สองที่ผู้ใช้งานมักถูกบล็อก ซึ่งไม่มีเครื่องมือใดภายในระบบปฏิบัติการที่จะแสดงให้เห็นได้

ควรใช้พอร์ตใดแทนพอร์ต 22?

พอร์ต TCP ใดก็ได้ที่ว่างอยู่ตั้งแต่ 1024 ถึง 65535 หลีกเลี่ยงการใช้ 2222 และ 22222 บนเซิร์ฟเวอร์จริง เนื่องจากเครื่องมือสแกนจะพยายามตรวจสอบพอร์ตเหล่านี้ทันทีหลังจากพอร์ต 22 ตรวจสอบว่าหมายเลขพอร์ตว่างอยู่ด้วยคำสั่ง sudo ss -tlnp ตรวจสอบว่านโยบาย SELinux ไม่ได้จองพอร์ตนั้นไว้ด้วย sudo semanage port -l และหลีกเลี่ยงพอร์ตที่ถูกกำหนดไว้สำหรับบริการที่คุณอาจติดตั้งในอนาคต การใช้หมายเลขพอร์ตสูงๆ ที่จำยากนั้นไม่มีปัญหา เพราะคุณเพียงแค่บันทึกไว้ใน ~/.ssh/config ครั้งเดียวและไม่ต้องพิมพ์มันอีกเลย