验证调用 API 的服务器的主机名
Posted
技术标签:
【中文标题】验证调用 API 的服务器的主机名【英文标题】:Verify hostname of the server who invoked the API 【发布时间】:2020-11-25 14:12:11 【问题描述】:我有一个与多个运行 AWS Flask 服务器的 EC2 连接的 AWS ELB。我不确定 AWS ELB 是否将完整的请求传递给 EC2。我知道我们可以在 ELB 级别进行限制,但我只想对一个端点施加限制,并验证在 Flask 中调用端点的服务器的主机名。有可能吗?
【问题讨论】:
假设应用程序负载均衡器,您可以启用proxy protocol。但这仅提供客户端的IP,而不是其DNS。 IP 也可从x-forwarded-for 标头获得。 有没有办法验证SSL证书? 也许这不适合您的用例,但您可以考虑使用 ALB / WAF 在负载均衡器级别实施限制。 ELB 级别的限制......在我看来,ELB 不是实施任何类型限制的正确位置。在我看来,限制是权限的同义词。我宁愿设计一个基于 IAM(也许还有 API Gateway)的解决方案。如果想保持简单,您是否考虑在请求中添加参数/正文以及另一端所需的数据/信息的选项? HTTP 不能满足您的需要/期望。 @SanjaySharma aws.amazon.com/premiumsupport/knowledge-center/… 这样的东西怎么样?如果您的“另一台服务器”是 EC2 实例,这将很容易。只需将实例部署到特定的 IP 范围。如果不在 EC2 中,那么您可以在 APIGateway 实例上启用 AWS 安全性。然后创建一个角色/用户,并 ALLOW execute-api:Invoke for you Resource 仅当使用该特定角色/用户调用时。有意义吗? 【参考方案1】:您可以尝试以下方法:
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 的 answer:
有关socket.gethostbyaddr()
的更多信息,请查看:socket.gethostbyaddr()
【讨论】:
您确定主机名不会被 ELB 屏蔽吗? @SanjaySharma 据此,您应该能够获取/设置别名,答案中提供了如何检索别名。 docs.aws.amazon.com/Route53/latest/DeveloperGuide/…【参考方案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():
...
【讨论】:
【参考方案3】:一种选择是使用Network Load Balancer,它保留发出请求的客户端的IP 地址。您甚至可以让 NLB 像 ELB 一样执行the TLS termination。 NLB 不会更改网络请求中的数据,除非您选择使用 TLS 终止。
【讨论】:
以上是关于验证调用 API 的服务器的主机名的主要内容,如果未能解决你的问题,请参考以下文章
根据 Google Play 商店在应用程序中正确的主机名验证器