如何在 AWS ALB 上重定向到 https://example.com/ 而不是 https://example.com:443/?

How to redirect to https://example.com/ instead of https://example.com:443/ on AWS ALB?

我已将以下重定向规则配置到我的 AWS Application Load Balancer 以将所有 HTTP 流量重定向到 HTTPS:

问题是,当我现在 curl(或在浏览器中访问域)时,我会得到这个丑陋和冗余的 Location 响应(域更改为 example.com) :

~ $ curl -I http://www.example.com
HTTP/1.1 301 Moved Permanently
Server: awselb/2.0
Date: Mon, 14 Sep 2020 18:28:48 GMT
Content-Type: text/html
Content-Length: 150
Connection: keep-alive
Location: https://www.example.com:443/

我知道 https://www.example.com:443/ 在实践中很好,我知道它不会显示在最终用户浏览器的 URL 字段中。但是,它仍然会显示在浏览器的网络选项卡的 'Response headers' 中,对我来说,与没有端口的重定向相比,它看起来不专业,例如:

~ $ curl -I http://www.apple.com
HTTP/1.1 301 Moved Permanently
Server: AkamaiGHost
Content-Length: 0
Location: https://www.apple.com/
Cache-Control: max-age=0
Expires: Mon, 14 Sep 2020 18:33:23 GMT
Date: Mon, 14 Sep 2020 18:33:23 GMT
Connection: keep-alive
strict-transport-security: max-age=31536000
Set-Cookie: geo=FI; path=/; domain=.apple.com
Set-Cookie: ccl=izHQtSPVGso4jrdTGqyAkA==; path=/; domain=.apple.com

从 URL 中删除端口似乎是合乎逻辑的事情,但不幸的是它是必填字段:

此外,'Switch to full URL' 选项似乎并没有真正帮助,即使可以在那里清除端口:

保存后仍然出现:

有什么方法可以实现吗?

编辑:
我的域通过 AWS Route 53 进行管理。

如果这是您担心的问题,这仍会显示在浏览器的 URL 字段中,但没有端口。

默认解释器假设如果协议是 HTTPS 那么端口是 443 所以你不需要指定任何东西,当重定向发生时它不会在末尾添加端口号,除非你指定 non-standard端口如4430.

您必须指定协议 (HTTPS) 和端口 (443),因为配置需要这些项目,这不会显示给用户。这与其他 AWS 配置相同,例如在 ELB 配置期间。

您可以将 CloudFront 放在您的服务器前面并让它执行 https 重定向。如果您仅将 ELB 用于 SSL 终止,则可以将其完全删除并让 CloudFront 终止您的 SSL。这将为您节省一些钱,因为如果您只将 ELB 用于一个源服务器,它会非常昂贵。 https://aws.amazon.com/cloudfront/

您可以使用 CloudFront 并将源设置为负载均衡器。然后在 cloud-front 上强制 HTTPS 重定向,并将 Viewer Protocol Policy 设置为 Redirect HTTP to HTTPS

在这种方法中,所有 ELB 规则仍将适用。

更新:也许值得一提的是,这非常适合作为练习和展示能力。但是,在 Lambda 重定向和纯负载均衡器重定向之间,我仍然建议您使用 ALB-native。它的性能更高(没有 cold-start,没有额外的跃点),更少 error-prone(不需要编码),其代价只是网络跟踪或开发人员工具上的美观。最终用户永远不会注意到这一点(您可能每天都浏览很多这些站点,但您甚至都不知道)。所以如果你问我,我建议不要用这样的东西投入生产。

如果您想要一些非常简单的重定向,您可以创建一个目标组,指向一个 returns 重定向的 Lambda 函数。它不需要管理 CloudFront 分配或试图使其在负载均衡器后面工作的开销,因为这也需要更改您的 DNS,因为您不能只将 CloudFront 放在负载均衡器后面(据我所知不是,至少)。

对于您的情况,我使用以下代码创建了一个 Lambda 函数 (Python 3.8):

def lambda_handler(event, context):
    response = {}
    
    if event.get('headers', {}).get('x-forwarded-proto', '') == 'http':
        print(event)
        response["statusCode"]=302
        response["headers"] = {"Location": f"https://{event['headers']['host']}{event['path']}"}
        response["body"]=""
        
    return response

然后我用那个 Lambda 函数作为后端创建了一个新的目标组:

最后,我将端口 80 上的侦听器配置为重定向目标组:

通过此实施,您的 302 重定向将按您的预期显示: