验证调用API的服务器主机名

5
我有一个连接了多个运行AWS Flask服务器的EC2实例的AWS ELB。我不确定AWS ELB是否会将完整请求传递给EC2。我知道我们可以在ELB层面实现限制,但我只想对一个端点进行限制,并验证调用Flask端点的服务器的主机名。这是否可能?

1
假设应用程序负载均衡器,您可以启用代理协议。但这只提供客户端的IP地址,而不是其DNS。该IP地址也可以从x-forwarded-for头中获取。 - Marcin
有没有办法验证 SSL 证书? - Sanjay Sharma
也许这并不适用于你的用例,但是你可以考虑使用 ALB / WAF 在负载均衡器级别强制执行限制。 - Marcello Romani
@TeimatiniMarínMeza 是的,那已经存在了。我想增加额外的安全性,因为只有一个特定的客户端(另一个服务器)将访问一个特定的端点,我想限制其他客户端的访问。 - Sanjay Sharma
1
如果你的“另一个服务器”是EC2实例,那么这将非常容易。只需将该实例部署到特定IP范围即可。 如果不在EC2上,则可以在APIGateway实例上启用AWS安全性。然后创建一个角色/用户,并且仅在使用该特定角色/用户调用时才允许ALLOW execute-api:Invoke您的资源。 有道理吗?此外,您可以尝试 https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-resource-policy-whitelist/。 - Teimatini Marin
显示剩余2条评论
3个回答

3

您可以尝试以下方法:

import socket
from flask import request


@app.route("/your_route", methods=["GET"])
def your_route():
    hostname, aliaslist, ipaddrlist = socket.gethostbyaddr(request.remote_addr)

请注意,仅依赖remote_addr是不可靠的,但由于这与主题无关,因此我将参考此答案,该答案使用ProxyFix
有关socket.gethostbyaddr()的更多信息,请查看:socket.gethostbyaddr()

你确定主机名不会被 ELB 掩盖吗? - Sanjay Sharma
1
@SanjaySharma 根据此文档,您应该能够获取/设置别名,如何检索别名在答案中提供。https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html#resource-record-sets-elb-dns-name-procedure - alexisdevarennes

2

我建议您在这种情况下使用装饰器模式,即添加一个名为IP_LIST的新配置选项,其中包含用逗号分隔的地址集。

IP_LIST = "127.0.0.1,127.0.0.2,..."

接下来添加一个新的装饰器函数,并使用该装饰器装饰任何端点。

def ip_verified(fn):
    """
    A custom decorator that checks if a client IP is in the list, otherwise block access.
    """

    @wraps(fn)
    def decorated_view(*args, **kwargs):
        ip_list_str = current_app.config['IP_LIST']
        ip_list = ip_list_str.split(",") if ip_list_str else []

        if request.headers.getlist("X-Forwarded-For"):
            remote_ip = request.headers.getlist("X-Forwarded-For")[0]
        else:
            remote_ip = request.remote_addr

        if remote_ip not in ip_list:
            return "Not sufficient privileges", 403

        return fn(*args, **kwargs)

    return decorated_view

@app.route("/your_route", methods=["GET"])
@ip_verified
def your_route():
    ...

0

一种选择是使用网络负载均衡器,它保留了发出请求的客户端的IP地址。您甚至可以让NLB像ELB一样执行TLS终止。除非您选择使用TLS终止,否则NLB不会更改网络请求中的数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接