我正在使用Flask,需要获取用户的IP地址。这通常通过request.remote_addr完成,但由于此应用程序托管在第三方(并使用cloudflare),它只返回本地主机。
Flask建议获得X-Forwarded-Host,但随后他们立即表示存在安全风险。有没有一种安全的方法来获得客户端真正的IP?
答案 0 :(得分:7)
这里的问题不是ProxyFix本身会导致用户访问您的系统,而是ProxyFix将采用曾经最可靠的信息,并用可能不可靠的信息替换它。
对于初学者,当您不使用ProxyFix时,很可能从TCP数据包中的源IP地址检索REMOTE_ADDR属性。虽然并非不可能,the source IP address in TCP packets are tough to spoof。因此,如果您需要一种可靠的方法来检索用户的IP地址,REMOTE_ADDR是一种很好的方法。在大多数情况下,当您执行request.remote_addr
时,您可以依靠它为您提供准确的内容。
问题是,当然,在反向代理情况下,TCP连接不是来自最终用户;相反,最终用户与反向代理建立TCP连接,然后反向代理与您的Web应用程序建立第二个TCP连接。因此,您应用中的request.remote_addr
将具有反向代理的IP地址,而不是原始用户。
ProxyFix应该解决这个问题,这样你就可以让request.remote_addr
拥有用户的IP地址而不是代理。它通过查看远程代理(如Apache和Nginx)添加到HTTP头(X-Forwarded-For
)并使用它在那里找到的用户IP地址的典型HTTP头来实现此目的。请注意,Cloudflare使用不同的HTTP标头,因此ProxyFix可能无法帮助您;您需要编写自己的中间件实现,以使request.remote_addr
使用原始客户端的IP地址。但是,在本答复的其余部分中,我将继续将该修复称为“ProxyFix”。
所以,总结一下; ProxyFix采用一种已知的最安全的解决方案,从TCP数据包中检索用户的IP地址,并使用解析易受欺骗的HTTP标头的非常安全的解决方案将其切换。
因此,仅在反向代理情况下使用ProxyFix的建议意味着:如果您接受来自非代理的位置的连接,请不要使用此方法。这通常意味着让反向代理(如Nginx或Apache)处理所有传入流量,并使您的应用程序在防火墙后面实际使用ProxyFix。
您还应该阅读this post,其中解释了过去如何破坏ProxyFix(although is now fixed)。这也将解释ProxyFix的工作原理,并为您提供有关如何设置num_proxies argument的建议。
假设您的用户位于A点,他们将请求发送到Cloudflare(B),最终将请求发送到您的最终应用程序(C点)。 Cloudflare will send the IP address of A in the CF-Connecting-IP header
如上所述,如果用户找到指向C的IP地址,他们可以直接向C点发送特制的HTTP请求,其中包括他们想要的任何标题信息。 ProxyFix将使用其逻辑来确定HTTP头中的IP地址,如果您依赖该值,那么这当然是有问题的。大多数情况下都是如此。
因此,您可能希望使用类似mod_cloudflare的东西,它允许您直接在Apache mod中执行这些代理修复,但仅当HTTP连接来自Cloudflare IP地址时(由TCP IP源)。您也可以只接受来自Cloudflare的连接。有关详细信息,请参阅How do I restore original visitor IP to my server logs,并帮助其他服务器(如Nginx)执行此操作。
这应该给你一个开始。但是,请记住,您仍然不是“安全”:您只关闭了一个可能的攻击向量,并且该攻击向量假定攻击者知道您的实际应用程序的IP地址。在这种情况下,恶意用户可能会尝试使用欺骗性Cloudflare IP地址although this would be extremely difficult进行TCP攻击。更有可能的是,如果他们想要造成严重破坏,他们只会DDOS你的源服务器,因为他们绕过了Cloudflare。因此,在保护您的应用程序时还需要考虑更多的事情。希望这有助于您了解如何使一部分更安全。