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

Verify hostname of the server who invoked the API

我有一个 AWS ELB 与多个 EC2 相连,这些 EC2 是 运行 AWS Flask 服务器。我不确定 AWS ELB 是否将完整请求传递给 EC2。我知道我们可以在 ELB 级别进行限制,但我只想对一个端点施加限制,并验证在 Flask 中调用端点的服务器的主机名。可能吗?

您可以尝试以下方法:

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 是不可靠的,但是由于这与主题无关,我将参考此 answer which makes use of ProxyFix:

有关 socket.gethostbyaddr() 的更多信息,请查看:socket.gethostbyaddr()

一种选择是像使用 ELB 一样使用 Network Load Balancer which preserves the IP address of the client making the request. You can even have the NLB do the TLS termination。 NLB 不会更改网络请求中的数据,除非您选择使用 TLS 终止。

我建议您在这种情况下使用装饰器模式,即您添加一个新的配置选项 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():
    ...