วิธีเปลี่ยนพอร์ต SSH บน Rocky Linux และ AlmaLinux
การเปลี่ยนพอร์ต SSH บน RHEL-based Linux ต้องตั้งค่า firewalld, SELinux และ sshd_config ให้ถูกต้อง ทำตามขั้นตอนที่แนะนำเพื่อป้องกันการถูกตัดการเชื่อมต่อจากเซิร์ฟเวอร์
เหตุใดการเปลี่ยนพอร์ต SSH จึงต้องทำสามขั้นตอนในที่นี้
การเปลี่ยนพอร์ต SSH บน Rocky Linux, AlmaLinux, CentOS Stream หรือ Fedora การแก้ไขเพียงจุดเดียวไม่เพียงพอ ระบบแยกส่วนสามระบบต่างมีส่วนตัดสินว่าการเชื่อมต่อบนพอร์ตใหม่จะใช้งานได้หรือไม่ firewalld เป็นตัวตัดสินว่าแพ็กเก็ตจะเข้าถึงเครื่องได้หรือไม่ SELinux เป็นตัวตัดสินว่า sshd จะได้รับอนุญาตให้ bind พอร์ตหมายเลขนั้นหรือไม่ และ sshd_config เป็นตัวกำหนดว่า daemon จะเรียกใช้พอร์ตใด หากข้ามขั้นตอน SELinux ไป daemon จะปฏิเสธการเริ่มทำงาน หากข้ามขั้นตอน firewalld ไป daemon จะเริ่มทำงานและฟังพอร์ตอยู่ แต่จะไม่มีใครเข้าถึงได้
บน Ubuntu งานเดียวกันนี้ทำได้ด้วยการแก้ไขเพียงจุดเดียวแล้วรีสตาร์ท เพราะ Ubuntu ใช้ AppArmor แทน SELinux และไม่ได้ติดตั้งโปรไฟล์ที่จำกัดว่า sshd สามารถ bind พอร์ตใดได้บ้าง หากมีการรัน ufw อยู่ คุณเพียงแค่เพิ่มกฎหนึ่งข้อ นั่นคือความแตกต่างทั้งหมด ตระกูล RHEL ติดตั้ง firewalld มาให้รันอยู่และเปิดใช้งาน SELinux ในโหมด enforcing ตั้งแต่ติดตั้งใหม่ ซึ่งทั้งสองระบบนี้ให้ความสำคัญกับหมายเลขพอร์ต
ให้ดำเนินการตามลำดับนี้เพื่อให้เซสชันปัจจุบันของคุณยังคงใช้งานได้ตลอดทุกขั้นตอน:
- เปิดพอร์ตใหม่ใน firewalld โดยให้พอร์ต 22 เปิดไว้ก่อนในขณะนี้
- เพิ่ม SELinux label สำหรับพอร์ตใหม่ด้วย
semanage - ตั้งค่าพอร์ตในไฟล์คอนฟิกูเรชันของ sshd
- รีสตาร์ท
sshdจากนั้นล็อกอินผ่านพอร์ตใหม่จากเทอร์มินัลที่สองก่อนที่จะปิดเทอร์มินัลแรก
ค้นหาเว็บคอนโซลของผู้ให้บริการของคุณ (VNC หรือ serial) ก่อนเริ่มดำเนินการ และตรวจสอบว่าคุณสามารถล็อกอินผ่านช่องทางนั้นได้ คอนโซลดังกล่าวคือทางรอดของคุณหากการเปลี่ยนแปลงเกิดข้อผิดพลาด การเปลี่ยนพอร์ตเป็นหนึ่งในสาเหตุที่พบบ่อยที่สุดที่ทำให้ผู้เช่าล็อกตัวเองออกจากเซิร์ฟเวอร์ที่เพิ่งชำระเงินไป
ขั้นแรก ติดตั้ง semanage
semanage เป็นเครื่องมือสำหรับแก้ไขการตั้งค่า policy ของ SELinux ซึ่งการติดตั้ง Rocky Linux หรือ AlmaLinux แบบ minimal จะไม่มีเครื่องมือนี้มาให้ โดยเครื่องมือดังกล่าวอยู่ในแพ็กเกจ 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 ได้กำหนดพอร์ตนั้นให้กับ service ประเภทอื่นไปแล้วหรือไม่ หากพอร์ตว่างอยู่ ทั้งสองคำสั่งจะไม่แสดงผลลัพธ์ใดๆ หากนโยบายได้จองพอร์ตนั้นไว้แล้ว คำสั่ง 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) ไว้อย่างครบถ้วน
ขั้นตอนที่ 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 หรือไม่
บาง image เริ่มการทำงานของ 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 ปฏิเสธการเข้าถึง? วิธีแยกแยะความแตกต่าง
จากแล็ปท็อปของคุณ ความล้มเหลวทั้งสองรูปแบบดูแทบไม่ต่างกัน แต่บนเซิร์ฟเวอร์นั้นทั้งสองกรณีมีความแตกต่างกันอย่างสิ้นเชิง
- หาก
systemctl status sshdแสดงว่า unit ล้มเหลว แสดงว่า daemon ไม่ได้รับ socket ของตน ซึ่งเป็นข้อผิดพลาดจากการตั้งค่าหรือการปฏิเสธจาก SELinux - หาก unit ทำงานอยู่และ
ss -tlnpแสดงว่า sshd ผูกกับพอร์ตใหม่แล้ว แสดงว่า daemon ทำงานปกติและปัญหาอยู่ที่เส้นทางเครือข่าย ได้แก่ firewalld, ไฟร์วอลล์แยกต่างหากของผู้ให้บริการ หรือที่อยู่และพอร์ตที่คุณระบุ
สำหรับกรณีของ SELinux ให้ตรวจสอบบันทึก audit แทนการคาดเดา:
sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pagerการปฏิเสธ 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 จะช่วยแยกแยะกรณีของเครือข่ายทั้งสองออกจากกัน เนื่องจาก connection refused หมายความว่าแพ็กเก็ตของคุณไปถึงโฮสต์แล้วแต่ไม่มีบริการใดรอรับอยู่ ในขณะที่ connection timed out หมายความว่าไม่มีการตอบกลับใดๆ เลย
ปิดพอร์ต 22 และอัปเดตไคลเอนต์ของคุณ
เมื่อคุณเข้าสู่ระบบผ่านพอร์ตใหม่ได้สำเร็จหลายครั้งแล้ว ให้ปิดการใช้งานพอร์ต 22:
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-allไม่ต้องแก้ไข SELinux label บนพอร์ต 22 ปล่อยไว้ตามนโยบายพื้นฐานของระบบ เนื่องจากพอร์ตดังกล่าวจะไม่มีผลใดๆ เมื่อ firewall ปฏิเสธการรับแพ็กเก็ตแล้ว
จากนั้นให้แก้ไขการตั้งค่าที่ฝั่งไคลเอนต์ เนื่องจากเครื่องมือทุกตัวที่เคยใช้พอร์ตเริ่มต้นจำเป็นต้องได้รับการระบุพอร์ตใหม่ ให้เพิ่มการตั้งค่าลงใน ~/.ssh/config บนเครื่องของคุณเพียงครั้งเดียว แทนการพิมพ์ -p ซ้ำๆ ตลอดไป:
Host myvps
HostName 203.0.113.10
Port 2222
User youruserscp, sftp, rsync และ Ansible จะอ่านค่าจากไฟล์ดังกล่าวทั้งหมด อย่างไรก็ตาม งานสำรองข้อมูล (backup jobs), การตรวจสอบสถานะ (monitoring checks) และสคริปต์ cron ที่ระบุพอร์ต 22 ไว้โดยตรง (hardcode) จะไม่ได้รับผลจากการตั้งค่านี้ ดังนั้นให้ค้นหาและแก้ไขรายการเหล่านี้ในขณะที่คุณยังจำรายละเอียดการเปลี่ยนแปลงได้แม่นยำ
การเปลี่ยนพอร์ตมีผลอย่างไรและไม่มีผลอย่างไร
การเปลี่ยนพอร์ตช่วยลดสัญญาณรบกวนใน log ได้ เนื่องจากสแกนเนอร์อัตโนมัติจะโจมตีพอร์ต 22 อยู่ตลอดเวลา การย้ายออกจากพอร์ตนี้จะช่วยลดบรรทัดขยะเหล่านั้นออกจาก journal ทำให้มองเห็นเหตุการณ์จริงได้ง่ายขึ้น อย่างไรก็ตาม นี่ไม่ใช่มาตรการรักษาความปลอดภัย สแกนเนอร์ใดก็ตามที่กวาดตรวจพอร์ตทั้งหมดจะพบ daemon ของคุณและอ่าน version banner ได้อยู่ดี ให้ถือว่าการเปลี่ยนพอร์ตเป็นเพียงการจัดระเบียบระบบ และใช้การป้องกันที่แท้จริงด้วยการยืนยันตัวตนผ่าน key เท่านั้นโดยปิดการล็อกอินด้วยรหัสผ่าน ซึ่ง คู่มือการเพิ่มความปลอดภัย SSH สำหรับ VPS ได้อธิบายขั้นตอนไว้อย่างละเอียด
ทุกสิ่งที่กล่าวมาข้างต้นทำงานเหมือนกันบน RHEL rebuilds ทั้งสองค่ายหลัก เนื่องจากสร้างมาจาก source เดียวกัน ดู การเปรียบเทียบ Rocky Linux และ 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-firewalldsubpackage fail2ban-firewalld ช่วยให้ fail2ban เขียนคำสั่งแบนผ่าน firewalld ซึ่งเป็นสิ่งที่คุณต้องการในเครื่องที่ firewalld เป็นผู้ดูแลกฎทั้งหมด
jail แบบมาตรฐานของ sshd ตั้งค่า port = ssh ไว้ ซึ่งชื่อดังกล่าวจะถูก resolve ผ่าน /etc/services ไปยังพอร์ต 22 หลังจากที่คุณเปลี่ยนพอร์ต jail จะเฝ้าดูพอร์ตที่ไม่มีใครโจมตี ทำให้ไม่มีการแบนเกิดขึ้นในขณะที่ความพยายามล็อกอินที่ล้มเหลวสะสมอยู่ที่พอร์ต 2222 ให้กำหนดพอร์ตเป็นตัวเลขใน /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600backend = 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 ครอบคลุมถึงการตั้งค่า timer และตัวเลือกระหว่างการดาวน์โหลดอัปเดตกับการติดตั้งอัปเดตเหล่านั้น
FAQ
ทำไม sshd ถึงไม่ยอมเริ่มทำงานหลังจากเปลี่ยนพอร์ตบน Rocky Linux?
สาเหตุเกือบทั้งหมดเกิดจากการไม่ได้กำหนด label ให้พอร์ตใน SELinux โดย sshd จะทำงานภายใต้ข้อจำกัดของ domain sshd_t และนโยบายความปลอดภัยจะอนุญาตให้ผูกพอร์ตที่ระบุ 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 อนุญาตแล้ว ดังนั้นแพ็กเก็ตจึงถูกทิ้ง (drop) ในระหว่างทาง ให้ตรวจสอบ 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 ครั้งเดียวและไม่จำเป็นต้องพิมพ์มันอีกต่อไป