今天是要来填之前未补之坑,
那就是建立 VPN 连线,
以小公司来说,
其实能够快速加快产品上市比较重要,
因此能够内部 CI/CD 服务能够使用就好,
真的要卡控就卡公司内的 IP,
有需要的话就使用远端遥控工具到公司的电脑做操作。
当组织规模持续过大,
甚至采用不同的开发方法(如:成对开发),
我们会发现的确还是需要一台 VPN,
小公司也许没办法花费太多预算在基础设施上,
这时候使用 AWS 托管的 VPN 服务就是个不错的选择,
我们可以建立一个 VPN 连线,
让我们直接连到 AWS 的 Endpoint,
这样我们就可以直接存取 private subnet 的资源,
不用在 public subnet 另外架设负载平衡器,
还要消耗多个 public ip 和 private ip。
中间穿插一个与 VPN 无关的元件做为暖身
会先回顾负载平衡器
只是为了要在建立 VPN 以後
再次调整 AWS 上的架构
从程序码的角度来看
我们可以看到 internal 是 false
因此外网可以读取得到
在 subents 中填入所有 public 的 subnets
可以理解成我们可能会随机从一个 public 的 subnets 中连进去
并且这个接口可视为 DMZ 网段
因此也可以直接连到我们放在 aws 上 private subnet 的其他资源
resource "aws_lb" "jenkins" {
name = "jenkins"
internal = false
load_balancer_type = "application"
security_groups = [ aws_security_group.elb_internal.id ]
subnets = data.aws_subnet_ids.public_subnet_ids.ids
enable_deletion_protection = false
tags = {
Creator = "Terraform"
}
}
从 AWS Cloud Console 登入後
在 EC2 的画面中左侧选择网路介面
可以看到我们为 Jenkins 建立的负载平衡器
实际上 subnets 会关系到我们建立的负载平衡器
会在每个 subnet 上各配置一个专属的 private ip
并且每个 subnet 也都会配置一个 public ip
这样在其他可用区域挂掉之後
可由其他可用区域接手继续运作
因此 AWS 负载平衡器贵虽贵
但还是贵的有其道理
可以在多个可用区域作用
可以挂 Web ACLs(虽然只有 ALB 可以用)
可以挂 SSL 凭证
负载平衡器老实说是个不小的花费
但是如果都架设在内网
可以想要的话也可以将 Gitlab 和 Jenkins 的负载平衡器拔除
Gitlab 有整合 Let's Encrypt
Jenkins 则可以考虑在上面架设 Nginx
并且自签凭证然後设定於 Nginx 上
最後再将 DNS 设定直接指向 Jenkins 和 Gitlab 的 private ip 上
刚刚说的只是其中一个做法
真心觉得 AWS 可以帮你申请套用凭证真的太方便了
因此我们不考虑把凭证改回设定在 EC2 上
但是负载平衡器会改成内部使用
不可公开存取
以下建立 VPN 连线的做法
是参考自这个 Youtube 影片
觉得字数太多有点烦躁的人
建议可以直接观看影片
照着影片一步一步实作
easy-rsa
专案easy-rsa 是一个可以凭证产生工具
可以使用 cli 的方式去产生及管理这些产生的 CA 和 PKI
cd /vagrant_data/project
git clone https://github.com/OpenVPN/easy-rsa.git
cd easy-rsa/easyrsa3/
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa build-server-full ithome-ironman.com nopass
./easyrsa build-client-full markmewmew.ithome-ironman.com nopass
刚刚根据 CA 产生的 crt 会放在 issued
底下
而 private key 则会放在 private 底下
mkdir acm
cp pki/ca.crt acm
cp pki/issued/ithome-ironman.com.crt acm
cp pki/issued/markmewmew.ithome-ironman.com.crt acm
cp pki/private/ithome-ironman.com.key acm
cp pki/private/markmewmew.ithome-ironman.com.key acm
分别将 Server Side 和 Client Side 的 凭证使用 aws cli 汇入到 aws
汇入後可以会出现凭证的 ARN
Server 凭证
aws acm import-certificate --certificate fileb://ithome-ironman.com.crt --private-key fileb://ithome-ironman.com.key --certificate-chain fileb://ca.crt --region ap-northeast-1
Client 凭证
aws acm import-certificate --certificate fileb://markmewmew.ithome-ironman.com.crt --private-key fileb://markmewmew.ithome-ironman.com.key --certificate-chain fileb://ca.crt --region ap-northeast-1
汇入後我们就可以在 AWS Cloud Console 的 Cert Manager
中
看到我们目前使用的凭证
首先我们用 data 将汇入的凭证查询出来
让我们在建立 clien vpn endpoint 时
可以直接拿来使用
stage/main.tf
data "aws_acm_certificate" "vpn_server_cert" {
domain = "ithome-ironman.com"
statuses = ["ISSUED"]
}
data "aws_acm_certificate" "vpn_client_cert" {
domain = "markmewmew.ithome-ironman.com"
statuses = ["ISSUED"]
}
stage/main.tf
resource "aws_ec2_client_vpn_endpoint" "markmew_ithome_ironman" {
description = "markmew-ithome-ironman"
server_certificate_arn = data.aws_acm_certificate.vpn_server_cert.arn
client_cidr_block = "172.31.0.0/20"
authentication_options {
type = "certificate-authentication"
root_certificate_chain_arn = data.aws_acm_certificate.vpn_client_cert.arn
}
connection_log_options {
enabled = false
}
}
在建立 vpn 网路的关联需要花费不少时间(大概七到十分钟)
建议这里可以先去喝杯咖啡稍待一下
网路的部分要设定 public 或 private 都没差
因为在连上之後
会因为路由的关系
只能连到 AWS 上的资源
但是外网都连不到
main.tf
resource "aws_ec2_client_vpn_network_association" "public_a" {
client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.markmew_ithome_ironman.id
subnet_id = aws_subnet.public_a.id
}
resource "aws_ec2_client_vpn_network_association" "public_c" {
client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.markmew_ithome_ironman.id
subnet_id = aws_subnet.public_c.id
}
resource "aws_ec2_client_vpn_network_association" "public_d" {
client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.markmew_ithome_ironman.id
subnet_id = aws_subnet.public_d.id
}
terraform apply
登入 AWS Cloud Console
在 VPC 页面的侧栏中 VIRTUAL PRIVATE NETWORK (VPN)
的区块
点按 Client VPN Endpoints
进入 VPN 列表页
选择我们刚刚建立的 VPN 後
点按上方的 Download Client Configuration
即可下载设定档
如果有仔细前一个步骤 VPN 的资讯
会发现它给的 DNS 是 Wild Card
因此网址我们可以任意加前缀字
使用文字编辑器打开下载的 ovpn 档
remote 後方的 vpn 网址
在网址的前方加上任意网址
让其变成 sub domain
remote ithome-ironma.ncvpn-endpoint-03a3157c3d2edd90f.prod.clientvpn.ap-northeast-1.amazonaws.com 443
设定档末
加上 client 的 cert 和 key 的位置
cert /Users/mark/vagrant/data/project/easy-rsa/easyrsa3/acm/markmewmew.ithome-ironman.com.crt
key /Users/mark/vagrant/data/project/easy-rsa/easyrsa3/acm/markmewmew.ithome-ironman.com.key
我们到这个网址 https://aws.amazon.com/tw/vpn/client-vpn-download/
下载 AWS 的 VPN Client 工具并安装
打开 VPN Client
选择管理描述档
将刚刚修改完後的描述档加入
连上 VPN 以後
就可以直接从 web 打内网 IP 连到 Jenkins
在 VPC 页面中
确认 DNS hostnames
和 DNS resolutions
都是 enabled
在 AWS 上的 DNS Server
预设是 VPC 的 CIDR 固定保留给 AmazonProvidedDNS
而 AmazonProvidedDNS 可以解析 Route53 上的私有托管区域
说是这样说
但是我建立好 VPN 连线以後
SSH 到 Jenkins Server 上
查看 DHCP 套用的设定 cat /etc/resolv.conf
发现 nameserver 是 127.0.0.53
因此挂载 DNS 的部分可能会因人而异
修改刚刚设定的 aws_ec2_client_vpn_endpoint
stage/main.tf
resource "aws_ec2_client_vpn_endpoint" "markmew_ithome_ironman" {
description = "markmew-ithome-ironman"
server_certificate_arn = data.aws_acm_certificate.vpn_server_cert.arn
client_cidr_block = "172.31.0.0/20"
dns_servers = ["172.31.16.2", "127.0.0.53"]
authentication_options {
type = "certificate-authentication"
root_certificate_chain_arn = data.aws_acm_certificate.vpn_client_cert.arn
}
connection_log_options {
enabled = false
}
}
将 jenkins 的负载平衡器 internal 改为 true
subnets 改为 private
stage/main.tf
resource "aws_lb" "jenkins" {
name = "jenkins"
internal = true
load_balancer_type = "application"
security_groups = [ aws_security_group.elb_internal.id ]
subnets = data.aws_subnet_ids.private_subnet_ids.ids
enable_deletion_protection = false
tags = {
Creator = "Terraform"
}
}
terraform apply
我们建立一个私有托管网域
跟我在 GoDaddy 上的网域名称是相同的
如此就可以营造出外部 DNS 和内部 DNS 的情境
stage/main.tf
resource "aws_route53_zone" "private" {
name = "markmewmew.com"
vpc {
vpc_id = aws_vpc.stage.id
}
}
resource "aws_route53_record" "jenkins" {
zone_id = aws_route53_zone.private.zone_id
name = "jenkins.markmewmew.com"
type = "A"
alias {
name = aws_lb.jenkins.dns_name
zone_id = aws_lb.jenkins.zone_id
evaluate_target_health = true
}
}
连上 VPN 以後
我们打开网页确认网址是可用的
并且试着在 vagrant 的 console 中
确认网址会解析到内部 IP
目前还需要调整 Gitlab 的 load balance 设定
在EP13 - 灾难演练,重建你的 VPC中
有教各位如何重建 EC2
而重建 Octopuse Deploy 的工作也就交给各位了
之前我们在设定 Jenkins Pipeline 时
有些还是使用 private ip
如果拔掉 public 网段中的 alb 改用 NLB
就可以同时支援 22、80、443 port 的转发
既然已经要 VPN 才能连到
其实有没有使用到 Web ACLs 的保护就是其次了
这部分就不太重要了
如果公司规模日益增长
或是目前服务的公司规模很大
那就建议改用其他方式
Customer Gateways + Virtual Private Gateways + Site-to-Site VPN Connections
就适用於大型规模的架构
让我们可以根据 VPN 的终端设备
直接设定连到 AWS 上
并且预设支援的设备也有提供相对应的组态档
设定上就需要与公司的网管合作
并讨论如何规划目前公司内部网路
及安全性的问题
参考资料:
>>: [从0到1] C#小乳牛 练成基础程序逻辑 Day 24 - String操纵术I 遍历综合技 Trim()
Quantum Counting Quantum search + Quantum phase es...
从历史中学习 我们最讨厌事件历史重演QQ 在每次遇到问题後,我们全员都会一起开个检讨会议,当中会提到...
进入到尾声,范例的最後一片拼图,马上开始吧!!! 地图的部分使用了leaflet JS和OpenSt...
前言 这次主要是更新我之前的笔记,那时候刚学习 JavaScript,对於一些结果可能不是很懂,刚好...
Priority queue Priority queue和queue一样也有两种形式 : max ...