我将Cloudflare放在ALB的前面,并尝试了Azure AD身份验证


我将Cloudflare放在ALB(AWS)的前面,并尝试通过Cloudflare Access进行Azure AD身份验证。
应该可以在任何云中实现它,因此当您需要进行一点身份验证时,它非常方便。

宪法

cloudflare.png

  • ALB的安全组阻止了除Cloudflare之外的访问。
  • 通过使用Lambda验证jwt来阻止从您自己的Cloudflare之外的Cloudflare进行访问。

必要的事情

  • Cloudflare帐户
  • AWS账户
  • 2个域名

    • 域A
    • 域B
  • AWS ACM为域B获得的一张通配符证书

环境

  • 创建用于Azure AD身份验证的目标资源
  • 设置Cloudflare DNS
  • 设置Cloudflare访问
  • 将Cloudfrale的IP地址设置为ALB的安全组
  • 测验
  • 1.为Azure AD身份验证创建资源

  • 在AWS端为ALB目标创建Lambda
  • 创建一个ALB

  • 创建一个HTTPS侦听器并关联域B证书
  • 创建目标组和目标Lambda
  • 将ALB别名记录设置为Route53上域B的子域
    • 我参考以下内容来验证jwt。

      • https://developers.cloudflare.com/access/setting-up-access/validate-jwt-tokens/
    • 创建Lambda时的上瘾点

      • 在Amazon Linux上安装Pip并压缩Lambda软件包。
      • 由于Amazon Linux当前yum存储库的Python版本是3.6,因此Lambda端也匹配3.6。
      • 在压缩Lambda软件包时,请不要忘记将其包含在" .libs_cffi_backend"下。
      • 由于ALB的运行状况检查无法通过Cloudflare验证jwt,因此请取消选中运行状况检查。

    设置Cloudflare后检查下面Lambda中指定的值。

    <表格>

    Lambda中指定的常量




    <身体>

    CERTS_URL

    Cloudflare访问登录页面域+" / cdn-cgi / access / certs"

    AUDIENCE_TAG

    Cloudflare访问策略受众标记


    requirements.txt

    1
    2
    3
    pyjwt
    cryptography
    cffi

    Lambda_function.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    import jwt
    import json
    import urllib.request

    CERTS_URL = 'https://*******************/cdn-cgi/access/certs'
    AUDIENCE_TAG = '**************************************'

    def get_public_keys():
        headers = {
            'User-Agent': 'curl/7.61.1'
        }
        req = urllib.request.Request(CERTS_URL, headers=headers)
        with urllib.request.urlopen(req) as response:
            res = response.read()
        public_keys = []
        jwk_set = json.loads(res)

        for key_dict in jwk_set['keys']:
            public_key = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(key_dict))
            public_keys.append(public_key)
        return public_keys


    def validate(header):
        is_valid = False
        token = ''
        if 'cf-access-jwt-assertion' in header:
            token = header['cf-access-jwt-assertion']
        else:
            return is_valid

        keys = get_public_keys()

        for key in keys:
            try:
                decoded_token = jwt.decode(token, key=key, audience=AUDIENCE_TAG)
                # print(decoded_token)
                is_valid = True
                break
            except Exception as e:
                print(e)
                pass
        return is_valid


    def lambda_handler(event, context):
        is_valid = validate(event['headers'])

        if is_valid:
            res = {
                "isBase64Encoded": False,
                "statusCode": 200,
                "statusDescription": "200 OK",
                "headers": {
                    "Set-cookie": "cookies",
                    "Content-Type": "text/html"
                }
            }

            res['body'] = """<html>
            <head>
            hello world
            </head>
            <body>
            <h1>Hello World</h1>
            </body>
            </html>"""
        else:
            res = {
                "isBase64Encoded": False,
                "statusCode": 403,
                "statusDescription": "403"
            }

        return res

    2.设置Cloudflare DNS

    在Cloudflare侧注册域A。

    2_1_add_site.png

    选择一个计划。

    2_2_plan.png

    在域A注册服务商中,设置Cloudfrale名称服务器。
    设置后,返回到Cloudflare屏幕并单击下面。

    2_3.png

    Cloudflare花费了几个小时才能识别该域。

    注册CNAME记录。

    2_4_cname.png

    <表格>

    项目




    <身体>

    类型

    CNAME

    名称

    域A

    内容

    域B的子域(在Route53中设置了ALB CNAME)

    代理状态

    代理


    SSL / TLS屏幕上,选择Full。

    2_5.png

    到此为止的设置,访问域A时,它将被代理到域B的子域,并且将调用ALB的目标Lambda。

    3.设置Cloudflare Access

    启用Cloudflare访问。

    3_1.png

    设置除以下内容以外的默认设置。

    • 选择Access Premium,因为该计划使用Azure AD

    3_2.png

    选择Azure AD作为登录方法

    3_4_loginmethod.png

    向Azure AD注册应用程序。

    4_1.png

    创建客户端机密。

    4_2.png

    设置权限。

    4_3.png

    检查应用程序ID和目录ID。

    4_5.png

    设置在Cloud Flare端在Azure AD中设置的值。

    4_4.png

    4.将Cloudfrale IP地址设置为ALB安全组

    在ALB安全组中设置以下IP地址。
    https://www.cloudflare.com/ips/

    5.测试

    访问域A时,将显示Cloudflare身份验证屏幕。

    5_1.png

    使用Azure AD进行身份验证...

    5_2.png

    如果显示由Lambda生成的页面,则成功!

    5_3.png