ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

เข้าเซิร์ฟเวอร์หลังบ้านผ่าน Bastion Host ด้วย SSH ProxyJump
Home เข้าเซิร์ฟเวอร์หลังบ้านผ่าน Bastion Host ด้วย SSH ProxyJump

เข้าเซิร์ฟเวอร์หลังบ้านผ่าน Bastion Host ด้วย SSH ProxyJump

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

คู่มือนี้ตั้งค่าตั้งแต่ฝั่งเซิร์ฟเวอร์จนถึงไฟล์ config ฝั่งเครื่องคุณ ให้พิมพ์ ssh db1 แล้วเข้าได้เลยโดยไม่ต้อง SSH ซ้อนสองครั้ง

สิ่งที่ต้องเตรียม

  • เซิร์ฟเวอร์อย่างน้อยสองเครื่อง เครื่องหนึ่งมี IP สาธารณะ (Bastion) และเครื่องภายในที่คุยกันได้ผ่านเครือข่ายภายใน
  • SSH Key ที่ใช้อยู่แล้ว หากยังไม่มีให้สร้างด้วย ssh-keygen -t ed25519
  • OpenSSH เวอร์ชัน 7.3 ขึ้นไปบนเครื่องคุณ ซึ่งรองรับ ProxyJump ตรวจด้วย ssh -V

ขั้นตอนที่ 1: เตรียมเครื่อง Bastion

เครื่องนี้ควรทำหน้าที่เดียวคือเป็นทางผ่าน ไม่ควรรันเว็บหรือฐานข้อมูล ตั้งค่าให้แน่นที่สุด

sudo nano /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowTcpForwarding yes
X11Forwarding no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers jump

AllowTcpForwarding yes จำเป็นสำหรับการทำ Jump Host ส่วน AllowUsers จำกัดให้ล็อกอินได้เฉพาะบัญชีที่ตั้งไว้สำหรับงานนี้

sudo sshd -t && sudo systemctl reload ssh

สร้างบัญชีสำหรับใช้ผ่านเครื่องกลาง และวาง Public Key ของคุณไว้

sudo adduser --disabled-password --gecos "" jump
sudo mkdir -p /home/jump/.ssh
sudo nano /home/jump/.ssh/authorized_keys
sudo chown -R jump:jump /home/jump/.ssh
sudo chmod 700 /home/jump/.ssh
sudo chmod 600 /home/jump/.ssh/authorized_keys

ขั้นตอนที่ 2: ปิด SSH ของเครื่องภายในจากอินเทอร์เน็ต

บนเครื่องภายในแต่ละเครื่อง จำกัดให้รับ SSH เฉพาะจาก IP ภายในของ Bastion

# ตัวอย่างด้วย UFW โดย 10.0.0.5 คือ IP ภายในของ Bastion
sudo ufw allow from 10.0.0.5 to any port 22 proto tcp
sudo ufw delete allow 22/tcp
sudo ufw status numbered

หรือให้ sshd ฟังเฉพาะการ์ดเครือข่ายภายใน ซึ่งปลอดภัยกว่าเพราะไม่ต้องพึ่ง Firewall อย่างเดียว

sudo nano /etc/ssh/sshd_config
ListenAddress 10.0.0.11
sudo sshd -t && sudo systemctl restart ssh
sudo ss -tlnp | grep :22

อย่าเพิ่งปิดช่องทางเดิมจนกว่าจะทดสอบเข้าผ่าน Bastion ได้สำเร็จ และให้แน่ใจว่ามี Console สำรองจากผู้ให้บริการไว้ใช้กรณีพลาด

ขั้นตอนที่ 3: วาง Public Key บนเครื่องภายใน

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

ssh-copy-id -o [email protected] [email protected]

จากนั้นเปิด Agent Forwarding เฉพาะเท่าที่จำเป็น หรือหลีกเลี่ยงไปเลยโดยใช้ ProxyJump ซึ่งไม่ต้องใช้ Agent Forwarding อยู่แล้ว

ขั้นตอนที่ 4: ตั้งค่าไฟล์ ~/.ssh/config บนเครื่องคุณ

nano ~/.ssh/config
Host bastion
    HostName 203.0.113.10
    User jump
    Port 22
    IdentityFile ~/.ssh/id_ed25519
    ServerAliveInterval 60

Host web1
    HostName 10.0.0.11
    User deploy
    ProxyJump bastion

Host db1
    HostName 10.0.0.12
    User deploy
    ProxyJump bastion

# ใช้รูปแบบเดียวกับทุกเครื่องในวงเดียว
Host 10.0.0.*
    User deploy
    ProxyJump bastion
    StrictHostKeyChecking accept-new
chmod 600 ~/.ssh/config

ทดสอบ

ssh web1
ssh db1

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

ขั้นตอนที่ 5: คัดลอกไฟล์ผ่าน Bastion

เมื่อมี ~/.ssh/config แล้ว คำสั่งคัดลอกไฟล์ใช้ชื่อย่อได้เลย

scp report.csv web1:/home/deploy/
rsync -avz ./dist/ web1:/var/www/example.com/
sftp db1

หากไม่อยากใช้ไฟล์ config ระบุ ProxyJump ในบรรทัดคำสั่งได้

scp -o [email protected] report.csv [email protected]:/tmp/

ขั้นตอนที่ 6: เปิดพอร์ตฐานข้อมูลมาที่เครื่องคุณชั่วคราว

ใช้ร่วมกับโปรแกรมจัดการฐานข้อมูลบนเครื่องคุณได้ โดยไม่ต้องเปิดพอร์ต 3306 สู่อินเทอร์เน็ตเลย

ssh -L 13306:127.0.0.1:3306 db1 -N

จากนั้นตั้งค่าโปรแกรมให้เชื่อมต่อไปที่ 127.0.0.1 พอร์ต 13306 ปิดอุโมงค์ด้วย Ctrl+C เมื่อเลิกใช้

ขั้นตอนที่ 7: ใช้การเชื่อมต่อซ้ำเพื่อให้เร็วขึ้น

การเปิดการเชื่อมต่อผ่านสองชั้นทุกครั้งจะช้ากว่าปกติเล็กน้อย เปิดใช้ ControlMaster เพื่อใช้ช่องเดิมซ้ำ

nano ~/.ssh/config
Host *
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 10m
mkdir -p ~/.ssh && chmod 700 ~/.ssh

ครั้งแรกจะช้าเท่าเดิม ครั้งถัดไปภายใน 10 นาทีจะเชื่อมต่อได้ทันที มีประโยชน์มากกับ rsync และสคริปต์ที่เรียก ssh ซ้ำหลายรอบ

ขั้นตอนที่ 8: บันทึกว่าใครเข้าเครื่องเมื่อไร

เพราะทุกคนต้องผ่าน Bastion จึงมีจุดเดียวที่ต้องเก็บ Log

sudo journalctl -u ssh --since today | grep 'Accepted'
sudo last -a | head -20

ส่ง Log ของ Bastion ไปเก็บที่เครื่องรวม Log เพื่อให้ลบทิ้งไม่ได้แม้เครื่องถูกยึด ดูวิธีได้ในคู่มือเรื่องการรวม Log ด้วย rsyslog

ปัญหาที่พบบ่อย

ssh web1 แล้วขึ้น Permission denied (publickey)

ตรวจว่า Public Key ของคุณอยู่ใน ~/.ssh/authorized_keys ของผู้ใช้บนเครื่อง ปลายทาง ไม่ใช่แค่บน Bastion ดูรายละเอียดด้วย ssh -v web1 ซึ่งจะแสดงว่าลองกุญแจตัวไหนไปแล้วบ้าง

ProxyJump ใช้ไม่ได้ ขึ้น bad configuration option

OpenSSH เก่ากว่า 7.3 ให้ใช้รูปแบบเดิมแทน ProxyCommand ssh -W %h:%p bastion

เชื่อมต่อค้างแล้วหลุดบ่อย

เพิ่ม ServerAliveInterval 60 และ ServerAliveCountMax 3 ในบล็อก Host * เพื่อให้ส่งสัญญาณรักษาการเชื่อมต่อเป็นระยะ

ลืมว่า Bastion IP อะไรตอนเครื่องเปลี่ยน

แก้ที่ ~/.ssh/config จุดเดียว ทุกเครื่องปลายทางที่อ้าง ProxyJump bastion จะตามไปเอง นี่คือเหตุผลหลักที่ควรตั้งชื่อย่อแทนการพิมพ์ IP ทุกครั้ง

ต้องการให้ทีมงานช่วยวางโครงสร้างการเข้าถึงเซิร์ฟเวอร์ให้ปลอดภัย ติดต่อ THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security