Day 12 – 使用 CDK 部署 Bastion Host 防禦主機!

2020 12th 鐵人賽

要說明自動部署前我們應該要先說明怎麼好好保護我們的內網機器而說到內網機器就會說到我們的 Bastion Host,畢竟大家都不會想要我們的機器在外面裸奔吧 XD 所以在介紹自動部署之前我們先來介紹 Bastion Host 中文可能稱它為防禦主機或是堡壘主機

https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20200928/201177014SQspjkASO.jpg?w=640&ssl=1

Bastion Host

一般來說比較偷懶的時候會在 Application 的 EC2 上面設定一個 Static IP 白名單 22 Port 來保護我們的機器而這其實不太安全,所以比較好的做法其實是設定一台 Bastion Host 來當我們的跳板機,所有的連線會經由這台跳板機連到內部的 private 網路主機,這其實是相對安全的一個方法,以架構來看我們會希望它是這個架構。

https://i2.wp.com/ithelp.ithome.com.tw/upload/images/20200928/20117701HMzU5AKzFO.png?w=640&ssl=1 (圖片來源:AWS Security Blog

而我們今天就要來教大家如何使用 CDK 架設一台 Bastion Host

使用 SSH 直接連接 Bastion Host

不知道大家有沒有發現前幾天的教學文其實是在教大家如何建立自己的 Bastion Host,而 CDK 其實有一個簡單的 function 可以簡單的建立 Bastion Host

在這邊先把 SSH 開成 any 有需要設定 static ip 可以使用host.allowSshAccessFrom(ec2.Peer.ipv4('192.192.192.192/32'));

這樣就不用寫昨天的一堆程式只要一行就可以達成拉!

const host = new ec2.BastionHostLinux(this, "BastionHost", {
  vpc,
  subnetSelection: { subnetType: ec2.SubnetType.PUBLIC },
});
host.allowSshAccessFrom(ec2.Peer.anyIpv4());

使用 AWS Systems Manager 的 Session Manager 連接 Bastion Host

另外如果使用 Session Manager 連入 Bastion 其實可以更簡單的部署 Bastion,看起來是不是又更短了呢!

const host = new ec2.BastionHostLinux(this, "BastionHost", {
  vpc,
});

Session Manager 使用本機 SSH 連線

相信大家平常習慣連接 EC2 Instance 機器方法是 SSH,而 Session Manager 也支援直接使用 SSH 的方法,在這裡我們可以使用工具 aws-ssm-ec2-proxy-command 來簡單達成此功能

安裝 SSH Proxy Command

  • 先下載 aws-ssm-ec2-proxy-command.sh 把它放入 ~/.ssh/aws-ssm-ec2-proxy-command.sh
  • 加入執行權限 chmod +x ~/.ssh/aws-ssm-ec2-proxy-command.sh

設定 SSH Config

編輯 ~/.ssh/config 加入

host i-* mi-*
  IdentityFile ~/.ssh/id_rsa
  ProxyCommand ~/.ssh/aws-ssm-ec2-proxy-command.sh %h %r %p ~/.ssh/id_rsa.pub
  StrictHostKeyChecking no

如此我們就可以使用 ssh <INSTACEC_USER>@<INSTANCE_ID> 連接主機拉! 假設我們的機器 ID 是 i-0de45ffd579418348 就可以使用

$ ssh -A ec2-user@i-0de45ffd579418348

分析一下 aws-ssm-ec2-proxy-command 這隻腳本

其實它與我們昨天教大家登入 SSM 指令最大的不同在於

aws ec2-instance-connect send-ssh-public-key  \
  --instance-id "$ec2_instance_id" \
  --instance-os-user "$ssh_user" \
  --ssh-public-key "file://$ssh_public_key_path" \
  --availability-zone "$instance_availability_zone"

此指令會把我們設定的 ~/.ssh/id_rsa.pub 上傳上去主機裡面,所以當我們下次使用 SSH 指令的時候就可以直接登入主機啦!

連接到 private network 的 App Host

預設設定 App Host 會放入本機的 SSH Key 並且只有 Bastion Host 可以連入,這樣我們就可以先跳到 Bastion Host 再連到 App Host 拉! https://i1.wp.com/ithelp.ithome.com.tw/upload/images/20200926/20117701t6d1mfFudM.png?w=640&ssl=1

參考資料

  • https://globaldatanet.com/blog/ssh-and-scp-with-aws-ssm
  • https://github.com/qoomon/aws-ssm-ec2-proxy-command
  • https://aws.amazon.com/tw/blogs/aws/new-port-forwarding-using-aws-system-manager-sessions-manager/
  • https://aws.amazon.com/tw/blogs/security/how-to-record-ssh-sessions-established-through-a-bastion-host/