5 วิธีการทำให้ SSH ของคุณ "แข็ง(แกร่ง) อึด ทน"
SSH น่าจะเป็น Protocol ที่หลาย ๆ คนใช้ในการเข้าถึง Shell ของเครื่องปลายทาง สำหรับควบคุมการทำงานของเครื่องคอมพิวเตอร์ต่าง ๆ แต่มันไม่น่าจะดีเท่าไหร่ หาก SSH Server ไม่แข็งแกร่งมากเพียงพอ วันนี้เราจะมาแนะนำ 5 วิธีการที่จะช่วยลด Attack Surface ของ SSH Server ในเครื่องของเรากัน
1. Disable Root Login
Root เรียกว่าเป็น Daddy ของ User ทั้งปวง มาพร้อมกับพลังอำนาจมหาศาล แต่มันก็มาพร้อมกับความรับผิดชอบอันใหญ่ยิ่งด้วยเช่นกัน เราคงไม่อยากให้พลังอำนาจขนาดนี้ไปตกอยู่ในมือของคนที่ไม่ควรจะมีใช่มะ เพื่อป้องกันไม่ให้มันเกิดขึ้น เราจำเป็นที่จะต้องปิด ไม่ให้ใครก็ตาม SSH เข้ามาด้วย Root User ได้
sudo vim /etc/ssh/sshd_config
เราสามารถเข้าไปแก้ไข Config File ที่อยู่ด้านบนนี้ได้เลย
PermitRootLogin no
ให้เรามองหาบรรทัดที่เขียนว่า PermitRootLogin จากเดิมมันจะเป็น yes ให้เราเปลี่ยนเป็น no ซะ เท่านี้ เราก็จะไม่สามารถ Login ผ่าน Root User ได้แล้ว
หากเราต้องการทำงานที่ต้องใช้ Superuser เราก็แค่ใช้ Sudo เท่านั้น หรือถ้าเราต้องการเข้าถึง Root จริง ๆ เราก็แค่ใช้ User พร้อม Sudo เข้าไปแก้ SSH Config อนุญาติให้ Login ผ่าน Root ได้อีกครั้งก็จบ หรือ ถ้าเราสามารถเข้าถึง Physical Machine ได้ก็เข้าได้อยู่แล้ว
2. Limit Maximum Number of Authentication Attempts
Brute Force เป็นอีกหนึ่งการโจมตีที่สามารถใช้เล่นได้ ดังนั้น เพื่อป้องกันไม่ให้ Brute Force Flood เข้ามารัว ๆ และสามารถเข้าถึงเครื่องของเราได้ เราสามารถกำหนด จำนวนครั้งที่สามารถยืนยันตัวตนได้ เช่น เซ็ตไว้ 3 ครั้งคือ ผู้ใช้นั้นสามารถใส่ Credential ผิดได้ 3 ครั้งก่อนมันจะล๊อคผู้ใช้นั้นไปเลย
MaxAuthTries 6
เราสามารถเข้าไปที่ Config File ก่อนหน้านี้ และใส่ MaxAuthTries เข้าไปตามด้วยจำนวนครั้งที่อนุญาติให้ยืนยันตัวตนได้ โดยพื้นฐานจะใช้ประมาณ 6 ครั้ง แต่เราสามารถปรับขึ้นลงตามความเสี่ยงที่เราประเมินได้ หากเราประเมินว่ามันมีการยิงเข้ามาเยอะมาก เราอาจจะปรับจำนวนครั้งลงไปหน่อย เหลือสัก 3 เพื่อให้มันเริ่ม Block เร็วขึ้นได้
PermitEmptyPasswords no
อันนี้เราขอเติมมาหน่อย เผื่อเครื่องใครใช้งานหลายคนแล้วมีไอ้งั่งไปสร้าง User ที่ไม่มี Password เราจะต้องปิดไม่อนุญาติให้ Authenticate โดยไม่มี Password ซะเลย ไม่งั้นหาก Brute Force เจอ ก็คือเกมส์เลยนะ
3. Reduce Login Grace Period
นอกจากการที่เราจะป้องกันไม่ให้ Brute Force ยิงเข้ามา มันจะมีช่วงเวลาที่เราเริ่ม Login แต่เราอาจจะยังไม่ใส่ Password หรือให้ Credential ผิดอะไรก็ตาม ตัว SSH Server มันควรที่จะมีเวลา Timeout ว่า หากเรายังไม่สามารถใส่ Credential ที่ถูกต้องในเวลาที่กำหนด
เพราะว่า ถ้าเราไม่เซ็ตเวลาตรงนี้ไว้ แล้วเราปล่อยให้คนที่ยังแม้แต่จะให้ Credential ที่ไม่ถูกต้องเชื่อมต่อกับ Server ของเราคาไว้นาน ๆ ย่อมเพิ่มโอกาสที่เขาอาจจะใช้วิธีการเช่น Script-Upload เพื่อเข้าถึง Server ของเราได้ ดังนั้น การจำกัดเวลานี้ให้น้อยที่สุดก็จะช่วยลดโอกาสที่จะทำได้ทัน
LoginGraceTime 2m
การตั้งค่านี้จะอยู่ในตัวเลือกที่ชื่อว่า LoginGraceTime โดยค่าพื้นฐานมันจะเซ็ตไว้ให้เรา 2 นาทีด้วยกัน โดยเราสามารถใส่ให้มันเร็วกว่านี้ได้ เช่น เราเองเราจะใส่ 30 เฉย ๆ หมายถึง 30 วินาที เผลอ ๆ หากเราใช้ Key-Based Authentication เราสามารถใส่ให้มันสั้นกว่านี้ได้อีกเยอะเลยละ ลดโอกาสที่จะโดน Side Script ยิงเข้ามามหาศาล
4. Use Key-Based Authentication
อีกวิธีการที่ทำได้คือ แทนที่เราจะใช้ Password Authentication ที่สามารถโดนยิง Brute Force ได้ง่าย เราทำให้ชีวิตพวกมันยากขึ้นด้วยการเปลี่ยนมาใช้ Key-Based Authentication ดีกว่า เราแค่จัดการ Generate Key ไว้ในเครื่องเราและโยน Key ลงไปใน SSH Server เรา เวลาเราจะ Authenticate เข้าใช้งาน เราแค่ Authenticate ด้วย Key ที่เรามีในเครื่อง ทำให้การที่จะโดนยิง Brute Force เพื่อหวังเจอ Password สำหรับเข้าเครื่องมันก็จะยากกว่าเดิมมาก ๆ
PasswordAuthentication no
และเพื่อป้องกันไม่ให้เราโดนยิง Brute Force สำหรับการเดา Password ได้ ไหน ๆ เราไม่ได้ใช้งาน Password Authentication แล้ว ก็ปิดมันไปซะสิ ไม่ใช้ก็ปิด ลด Attack Surface ได้มหาศาล
5. Restricting non-shell User
สำหรับบางเครื่อง อาจจะมีการสร้าง User สำหรับให้ App บางตัวใช้ สำหรับการกำหนดสิทธิ์การเข้าถึงบางอย่าง ซึ่งแน่นอนว่า User พวกนี้ เราไม่ได้สร้างมาเพื่อให้มัน SSH เข้ามาแน่นอน ดังนั้น เหมือนเดิมคือ ไม่ใช้ เราก็ปิดมันซะเลย
sudo usermod --shell /usr/sbin/nologin docker
เราสามารถใช้ Usermod โยน User นั้น ๆ เข้าไปใน Group nologin เท่านี้ก็เรียบร้อยแล้ว ถึงจะรู้ Username แต่ยังไง ก็เข้าไม่ได้ เพราะเราปิดไม่ให้ Login นั่นเอง ถึงจะอยู่หน้าเครื่องก็ไม่ได้เช่นกัน
ทำไมเราไม่เปลี่ยน Port SSH ละ ?
หลาย ๆ คนที่เคยผ่านประสบการณ์มา อ่านถึงตอนนี้แล้วอาจจะเอ๊ะว่า ทำไมใน 5 วิธีการที่เราเล่ามานั้นมันไม่มีวิธีการที่ง่ายที่สุดอย่างการเปลี่ยน Port สำหรับ SSH Service ละ เพราะมันน่าจะทำให้ปลอดภัยขึ้นได้
เราเรียกการซ่อน Port ลักษณะนี้ว่า Security through obscurity (STO) หรือก็คือการที่เราซ่อนข้อมูลบางอย่างเพื่อเพิ่มความปลอดภัย หรือถ้าพูดเป็นสำนวนภาษาอังกฤษคือ Hiding in the plain sight ด้วยวิธีการนี้ มันทำให้คนที่เขาต้องการเข้ามาหาอะไรบางอย่างจากเรา หาเจ้าสิ่งนั้นได้ยาก เช่นถ้าเราจะซ่อนเงิน(เมีย) หากเราเอาไปซ่อนในตู้เซฟ โจรเข้า มันก็เดาได้ว่า เงินหรือทรัพย์สินมันต้องอยู่ในเซฟแน่ ๆ มันก็จะเอาเซฟไป แต่ถ้าเราใช้หลักการนี้คือ เราก็เอาเงินไปแบ่งซ่อนตามหนังสือหน้าต่าง ๆ โอกาสที่โจรจะคิดไปหาในหนังสือมันย่อมน้อยกว่าการหาในเซฟแน่นอน (แกดูน้าค่อมเป็นตัวอย่างดิ ไอดอลเลยคนนี้) นี่แหละคือหลักการที่เราใช้สำหรับการซ่อนพวก Service Port ต่าง ๆ โดยการเปลี่ยนจาก Default Port เป็น Port อะไรสักอย่าง เพื่อซ่อนตัวจากผู้ที่ต้องการเข้าหา Service นั้น ๆ
แต่เชื่อมั้ยว่า สุดท้าย Port ที่เราเปลี่ยนเพื่อซ่อนนี้ มันสามารถหาเจอได้ง่าย ๆ เลยแหละ มันทำได้โดยการ Scan Port ของ Address ของเราอย่างละเอียด ก็ใช้เวลาต่อ Host ไม่นานเท่าไหร่หรอก ทำให้ส่วนตัวเรา ไม่แนะนำวิธีการนี้สักเท่าไหร่ เราคิดว่า มันช่วยได้เมื่อเครื่องของเราอยู่ในพวก Cloud ทั้งหลายแล้ว Expose ออกผ่าน Public IP ของ Cloud Provider ซึ่งมันจะมีคนที่เอา IP Range มาแล้วยิง Port Scan รัว ๆ หากเจอมันก็จะเริ่ม Brute Force ทันที อย่างน้อยที่สุด แมร่งกิน CPU Time และ Network Traffic ของเครื่องเราแน่นอน เสียเงินกันชิบหาย
นอกจากนั้น หากเรามีเครื่องหลายเครื่อง เราจะเปลี่ยนแยกกันคนละ Port หมดเลยมั้ยอะ ถ้าเราทำหมดนั่น มันเพิ่มความซับซ้อนในการใช้งานอีกมหาศาล เราต้องมานั่งจำอีกเหรอว่า เครื่องนี้ เราทำ SSH ไว้ที่ Port ไหนกันนะ มันดูจะเป็นเรื่องตลกเกินไปหน่อย
ดังนั้นสุดท้ายแล้ว ถึงเราจะซ่อนไปเท่าไหร่ มันก็หาเจอได้ไม่ยากขนาดนั้น และสร้างความยุ่งยากในการทำงานเข้าไปอีก เราเลยไม่ค่อยอย่างแนะนำวิธีการนี้เท่าไหร่
ทั้งหมดนี้เป็นเพียงเบื้องต้นเท่านั้น ยังมีอีกหลายวิธีที่ทำได้
ทั้งหมดที่เราเล่ามา เป็นเพียงแค่การตั้งค่าภายใน SSH Service ของเราเท่านั้น แต่จริง ๆ แล้วการ Harden Security ของ SSH Service เราสามารถทำได้มากกว่านี้อีก ตั้งแต่การใช้ Firewall เข้ามาดัก Connection ที่ไม่สมควรจะเข้าถึง SSH ได้แต่แรก หรือกระทั่งการการใช้ 2-Factor Authentication แต่สุดท้าย ไม่ว่าจะเป็นวิธีการใด ๆ ก็ตาม หลักการมันเหมือนเดิมคือ เราพยายามลด Attack Surface ของมันให้ได้มากที่สุด โดยการไม่ใช้อะไรก็ปิด เปิดแค่ที่ต้องใช้พอแล้วแค่นี้เลย
ไว้วันหลังจะมาเล่าวิธีการใช้ fail2ban ในการงัดกับพวก Brute Force Attack อีกทีเด้อ ใส่ไว้นี้เลย มันยาวเกิ้น (จริง ๆ ไม่มี Content จะเขียนแหละ แยกแมร่ง!)