EP11 - 为你的 portal 添加 Load Balance 和挂载 Web ACLs

Elastic Load Balancing

什麽是 Elastic Load Balancing

Elastic Load Balancing 可在多个目标 (例如 Amazon EC2 执行个体、容器、IP 地址、Lambda 函数和虚拟设备) 之间自动分配传入的应用程序流量。
它可以在单一可用区域或跨多个可用区域处理您应用程序流量的各种负载。
Elastic Load Balancing 提供四种负载平衡器,
它们都具有下列特性:高可用性、自动扩展,以及让您的应用程序具备容错功能的强大安全防护。

与传统的 Load Balance 不同的是
以往在做 Load Balance 的时候都是需要建立一台主机
但使用 AWS 的 Elastic Load Balancing
我们就不用另外建一台 EC2
然後再另外安装 Nginx 了

Elastic Load Balancing 有哪些

AWS 提供的 Elastic Load Balancing 有四种
「Application Load Balancer」、「Network Load Balancer」、「Gateway Load Balancer」、「Classic Load Balancer」共四种

Application Load Balancer(ALB)只对外开 80 和 443 port
属於 OSI 七层中的第七层应用层的部分
支援 AWS 的 IP、EC2 和 Lambda

Network Load Balancer(NLB)则是属於第四层
支援 IP、EC2 两种服务
如果要处理 80、443 以外的 port
就只能够使用 NLB 来做附载平衡
除了 IP 和 port 以外
也支援 TCP 和 UDP
这在设定上时需要特别注意
传统我们在使用的 Nginx 比较是 NLB

Gateway Load Balancer(GLB)
则是属於 Layer 3 + Layer 4 的负载平衡
只能套用在 IP 上
实际上我没有用过它
也没办法多做解释

Classic Load Balancer(CLB)就是传统的 Load Balance
有多传统?其实不重要
2022 年 August 15 之後就不能用了
也不要花太多时间了解
了解完了明年还是要翻掉

看可以应用在 AWS 范围的多少
很明显可以看得出来
AWS 比较希望我们用 ALB 就好了
其他的非必要就别用了
再加上 ALB 可以挂载 AWS WAF 的 Web ACLs
让你连线时还可以检查是否有恶意攻击
这当然也是我们要应用的部分

Terraform 建置 load balance

用 IaC 的方式来建置 load balance
最基础的需要设定四个
load balance 本身、目标群组以及把两者绑定
然後是设定 80 和 443 port

上面我们有提到
我们是使用 alb
因此只能够设定 80 和 443
最多也只会有五个区块

安全群组我们先沿用 portal 的 security group

main.tf

resource "aws_lb" "portal" {
    name               = "ithome-ironman-portal"
    internal           = false
    load_balancer_type = "application"
    security_groups    = [ aws_security_group.ithome_ironman_portal.id ]
    subnets            = data.aws_subnet_ids.subnet_ids.ids
    
    enable_deletion_protection = false
    
    tags = {
        Creator = "Terraform"
    }
}

resource "aws_lb_target_group" "portal" {
    name        = "ithome-ironman-portal"
    port        = 80
    protocol    = "HTTP"
    target_type = "ip"
    vpc_id      = data.aws_vpc.default.id

    stickiness {
        type = "lb_cookie"
    }
}

resource "aws_lb_target_group_attachment" "portal01" {
    target_group_arn = aws_lb_target_group.portal.arn
    target_id        = aws_instance.ithome_ironman_portla.private_ip
}

resource "aws_lb_listener" "portal_port80" {
    load_balancer_arn = aws_lb.portal.arn
    port              = "80"
    protocol          = "HTTP"
    
    default_action {
        type             = "forward"
        target_group_arn = aws_lb_target_group.portal.arn
    }
}
terraform apply

建置好後
可以登入 aws cloud console 看到建置好的 load balance
https://ithelp.ithome.com.tw/upload/images/20210923/20141518l7nGshzLZV.png

直接输入 DNS 却会出现 504 的错误
这是因为我们的 inbound 只开电脑的 ip
但是现在连到 ec2 的是 load balance 的 ip
所以还需要跳整 inbound/outbound 的设定
https://ithelp.ithome.com.tw/upload/images/20210923/20141518nTG3JBm0S3.png

修改 portal 的 inbound 和 outbound

load balance 的 ip 是浮动的
portal 如果是抓当下的 ip
过几个月 ip 改变後就要再次修改
所以我这次的修改我们还需要修改一下 inbound

之前我们是设定 var.personal_cidr
现在要改成 0.0.0.0/0

resource "aws_security_group_rule" "ithome_ironman_igress_80" {
    type              = "ingress"
    from_port         = 80
    to_port           = 80
    cidr_blocks       = ["0.0.0.0/0",]
    protocol          = "tcp"
    security_group_id = aws_security_group.ithome_ironman_portal.id
}

resource "aws_security_group_rule" "ithome_ironman_igress_443" {
    type              = "ingress"
    from_port         = 443
    to_port           = 443
    cidr_blocks       = ["0.0.0.0/0",]
    protocol          = "tcp"
    security_group_id = aws_security_group.ithome_ironman_portal.id
}
terraform apply

执行配置後
打开网页就可以看到 ALLOWED_HOSTS 的错误讯息
这时候我们只要把 Load Balance 的 Host 加上去即可
push code 还可以顺便测试昨天建好的 CI/CD
https://ithelp.ithome.com.tw/upload/images/20210923/201415181bhzL2oShG.png

汇入凭证後的修改

目前我手边没有可用的 DNS 和 凭证可供参考
因此下列的程序码不保证可以用

在 UI 介面中填写凭证相关资讯後
Terraform 就可以透过 data 将汇入的凭证找出来
添加一个 listener,绑定凭证监听 443 port
原本 80 port 的则强制转导到 443 port

data "aws_acm_certificate" "dns_host" {
    domain = "*.你的网域"
    status = ["ISSUED"]
}

resource "aws_lb_listener" "portal_portal443" {
    load_balancer_arn = aws_lb.portal.arn
    port              = "443"
    protocol          = "HTTPS"
    ssl_policy        = "ELBSecurityPolicy-2016-08"
    certificate_arn   = data.aws_acm_certificate.dns_host.arn
  
    default_action {
        type             = "forward"
        target_group_arn = aws_lb_target_group.portal.arn
    }
}

resource "aws_lb_listener" "portal_port80" {
    load_balancer_arn = aws_lb.portal.arn
    port              = "80"
    protocol          = "HTTP"
    
    default_action {
        type             = "redirect"
        target_group_arn = aws_lb_target_group.portal.arn
      
        redirect {
            port        = "443"
            protocol    = "HTTPS"
            status_code = "HTTP_301"
        }
    }
}

AWS WAF

什麽是 AWS WAF

AWS WAF是一种 Web 应用程序防火墙
可让您监控转送至 Amazon CloudFront 分发、Amazon API Gateway REST API、Application Load Balancer 或的 HTTP(S) 请求

Web ACLs

Web 存取控制清单(Web ACL)可让您详细控制受保护资源回应的所有 HTTP(S) Web 请求。

您可以保护 Amazon CloudFront、Amazon API Gateway、Application Load Balancer 和AWS AppSync的费用。

每个区域最多可产生 100 个 Web ACL
而每个 Web ACL 最多可订到 最大 1500 Web ACL 容量单位 (WCU)
至於 WCU 就有点谜了
根据你的规则来订
像是 1 个 IP 就是 1 个 WCU
通常用 IP 都是锁白名单或是黑名单
至於其他规则,像是 SQL Inject、Cross Site Scripting 各自的 WCU 都不同
总计上限就是 1500

使用上是非常够用了
一条 Web ACLs 可以绑定多个 ALB
如果超过 1500 就多制定一条
能够制定到 150000 单位其实公司也是有一定规模

AWS Shield

AWS 针对 DDoS 攻击提供 AWS Shield Standard 和 AWS Shield Advanced 保护。

AWS Shield Standard 已自动包含在内
对於您已支付 AWS WAF 和其他 AWS 服务的费用
此无需额外费用

如果觉得基础不够使用
对於额外的 DDoS 攻击保护
有提供 AWSRouteAWS Shield Advanced
可为 AWS 的资源提供扩充的 DDoS 攻击防护。

既然基础已经有了
我们就只会使用 Web ACLs 就好了

Terraform 建置 WebACLs

WebACLs 的建置就真的比较无脑
是使用 AWS 做好的 AWSManagedRulesCommonRuleSet
至於里面包含什麽呢?
有兴趣的可以自己参考官方文件
从 URI 到档案名称的读写
大致上就是该挡的都帮你做了
不确定要加哪些 ACL 的话
建议预设就用这个

去 terraform 查找写法时
记得要找 aws_wafv2
不然会找到旧版 waf 的写法

resource "aws_wafv2_web_acl" "fundamental_acl" {
    name  = "fundamental-acl"
    scope = "REGIONAL"
    
    default_action {
        allow {}
    }

    rule {
        name     = "aws-managed-common-rule"
        priority = 1
        
        override_action {
            count {}
        }
        
        statement {
            # aws support suggests to use this to protect the common attach
            managed_rule_group_statement {
                name        = "AWSManagedRulesCommonRuleSet"
                vendor_name = "AWS"
            }
        }

        visibility_config {
            cloudwatch_metrics_enabled = false
            metric_name                = "aws-managed-common-rule"
            sampled_requests_enabled   = false
        }
    }
    
    tags = {
        Creator = "Terraform"
    }
    
    visibility_config {
        cloudwatch_metrics_enabled = false
        metric_name                = "fundamental-acl"
        sampled_requests_enabled   = false
    }
}
terraform apply

建立完成後登入 aws cloud console
就可以看到我们建立的成果
https://ithelp.ithome.com.tw/upload/images/20210923/201415186tQEpAlWgo.png

https://ithelp.ithome.com.tw/upload/images/20210923/20141518r688vzLo6y.png

上面我们有提到每个 Web ACL 最多可订到 最大 1500 Web ACL 容量单位 (WCU)
我们用了一条 AWS 的规则就占了 700
其实使用起来还是绰绰有余

https://ithelp.ithome.com.tw/upload/images/20210923/201415183WVeStprTy.png

WebACLs 关联 ALB

再多建立一个关联
把 web acls 和 load balance 接起来
这样就算是配置完成罗

resource "aws_wafv2_web_acl_association" "portal" {
    resource_arn = aws_lb.portal.arn
    web_acl_arn  = aws_wafv2_web_acl.fundamental_acl.arn
}

完成後可以在 aws cloud console 的 Associated AWS resources 中
看到我们的 alb 已经套用上去了

https://ithelp.ithome.com.tw/upload/images/20210923/201415180QeINqqzSm.png

参考资料:

  1. Elastic Load Balancing
  2. Elastic Load Balancing 功能
  3. AWS WAF 配额
  4. AWS受管理规则规则群组清单
  5. aws_wafv2_web_acl
  6. aws_wafv2_web_acl_association

<<:  day9 稽核 (雷)除了技术,也要学管理

>>:  <Day8> Contract — 取得股票(Stock)资讯

[Day18] THM AgentSudo

URL : https://tryhackme.com/room/agentsudoctf IP ...

CSS微动画 - Loading又来了!文字版再出击~

Q: 倒数 8 篇了!逐渐进入养老阶段,会一直Loading吗? A: Loading只是代表,主...

day15_Linux ARM 的网站开发之旅

Linux ARM 可以当日常的网站开发吗? 我们这里的能够开发,定义为可以独立执行, 除错, 并发...

【C++】Binary Search

Binary Search 是一个搜寻演算法~ 它的时间复杂度只有O log(n)~ 但使用它之前要...

DAY25 深度学习-卷积神经网路-Yolo v3

今天介绍一下Yolo v3, 首先在v3中使用了darknet-53的架构,架构如下图: 相比v2的...