如何限制单个 IP 地址对 Flask 的访问?

Posted

技术标签:

【中文标题】如何限制单个 IP 地址对 Flask 的访问?【英文标题】:How to limit access to Flask for a single IP address? 【发布时间】:2014-04-10 15:45:02 【问题描述】:

我正在使用 Python Flask framework 开发一个网站,我现在进行一些开发,将我的更改推送到远程开发服务器。我将此远程开发服务器设置为使用app.run(host='0.0.0.0') 公开为网站提供服务。

这很好用,但我只是不希望其他人查看我的网站。出于这个原因,我想以某种方式将我的 ip 列入白名单,以便开发服务器仅将网站提供给我自己的 ip 地址,而不给出响应、404 或其他对其他 ip 地址的无用响应。我当然可以将服务器设置为使用 apache 或 nginx 来实际为网站提供服务,但我喜欢在代码更改时自动重新加载网站以开发我的网站

那么有人知道使用内置 Flask 开发服务器的方法吗?欢迎所有提示!

【问题讨论】:

自动重新加载适用于 nginx 或 apache。您只能将某些源地址代理到开发服务器。或者您可以将整个事情放在 http/digest 身份验证之后。 @msvalkon - 好主意!我没有想到直接将 Flask 运行到 Nginx,因为我之前使用 uwsgi 来路由请求,这不允许自动重新加载。感谢您的提示! 【参考方案1】:

使用只是 Flask 的功能,您可以使用before_request() hook 测试request.remote_addr attribute:

from flask import abort, request

@app.before_request
def limit_remote_addr():
    if request.remote_addr != '10.20.30.40':
        abort(403)  # Forbidden

但在服务器上使用防火墙规则可能是更安全、更可靠的选择。

请注意,如果浏览器和服务器之间存在反向代理,则可以屏蔽 Remote_Addr;小心你如何限制这一点,不要把自己锁在外面。如果代理靠近服务器本身(如负载平衡器或前端缓存),您可以检查 request.access_route list 以访问实际 IP 地址。 仅当remote_addr 本身也是受信任的 IP 地址时才这样做

trusted_proxies = ('42.42.42.42', '82.42.82.42', '127.0.0.1')

def limit_remote_addr():
    remote = request.remote_addr
    route = list(request.access_route)
    while remote in trusted_proxies:
        remote = route.pop()

    if remote != '10.20.30.40':
        abort(403)  # Forbidden

【讨论】:

太棒了!谢谢你的提示!我将在开发时使用它.. :)【参考方案2】:

此 IPTABLES/Netfilter 规则将满足您的需求,丢弃所有传入流量,除了来自 your_ip_address 到端口 80 的流量:

$ /sbin/iptables -A INPUT -s ! your_ip_address --dport 80 -j DROP

这是在许多论坛上展示的内容,它允许 localhost 流量 + 从 your_ip_address 对您的 Flask 应用程序的外部访问,但拒绝来自其他 IP 地址的所有流量:

$ /sbin/iptables -A INPUT -i lo -j ACCEPT
$ /sbin/iptables -A INPUT -s your_ip_address --dport 80 -j DROP
$ /sbin/iptables -A INPUT --dport 80 -j REJECT

虽然您可以通过 Flask 轻松实现预期结果(如所选答案中所指出的),但此类问题应在操作系统的网络层处理。考虑到您使用的是类似 Nix 的操作系统,您可以通过 IPTABLES 使用 Netfilter 拒绝/允许传入连接,规则如下。

传入的流量/数据包,首先,它们通过操作系统内核的分析。要拒绝/允许从任何来源到特定端口的流量,这是操作系统防火墙在其内核的网络层上的一项工作。如果您的服务器上没有运行防火墙,则应该对其进行配置。

这里有一个要点:

必须在操作系统的网络层处理流量。不要让应用程序处理此任务,至少在生产环境中是这样。没有人会在这项任务上做得最好,而不是操作系统的内核(希望您使用的是类似 Nix 的操作系统)。 Linux 内核及其模块 (Netfilter) 更可靠、更胜任且更有效地处理此类任务。

【讨论】:

您的答案可能适用于 vps 上的烧瓶服务器......但是,由于问题描述没有提到这一点......不太确定这是最好的解决方案,但对于这种特定情况.【参考方案3】:

我发现这很有帮助,但如果您有多个 IP 地址,还有一种更简单的方法。

trusted_ips = ['42.42.42.42', '82.42.82.42', '127.0.0.1']

@app.before_request
def limit_remote_addr():
if request.remote_addr not in trusted_ips:
    abort(404)  # Not Found

这将检查您信任的 ip 列表,如果远程 ip 不在列表中,则返回“404 - Not Found”。

您还可以通过更改一些内容来阻止特定 ip

bad_ips = ['42.42.42.42', '82.42.82.42', '127.0.0.1']

@app.before_request
def limit_remote_addr():
if request.remote_addr in bad_ips:
    abort(404)  # Not Found

同样的事情,但会阻止 bad_ips 列表中的 ips

【讨论】:

以上是关于如何限制单个 IP 地址对 Flask 的访问?的主要内容,如果未能解决你的问题,请参考以下文章

天翼云服务器如何限制端口仅限部分ip地址访问

网站nginx配置限制单个IP访问频率,预防DDOS恶意攻击

.htaccess:如何通过 IP 限制对单个文件的访问?

限制对 Elastic Beanstalk 的 HTTP 访问

nginx 限流功能

nginx 限制ip/限制访问路径