如何跟踪 IP 以阻止恶意用户?
Posted
技术标签:
【中文标题】如何跟踪 IP 以阻止恶意用户?【英文标题】:How can I track IPs to block malicious users? 【发布时间】:2016-11-11 13:49:51 【问题描述】:这里有一些获取用户IP的理论
Theory1:如果您不使用负载均衡器,请使用REMOTE_ADDR
。如果您使用负载均衡器,请使用它使用的任何东西。在 99% 的情况下,这似乎是 HTTP_X_FORWARDED_FOR
。所以:
function get_ip_address()
$id = '';
if (isset($_SERVER['REMOTE_ADDR']))
$ip = $_SERVER['REMOTE_ADDR'];
else if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
else
$ip = 'UNKNOWN';
return $ip;
Theory2:还有一些其他的 HTTP 标头信息(即$_SERVER['HTTP_...]
) 可能包含 IP。所以:
function get_ip_address()
foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key)
if (array_key_exists($key, $_SERVER) === true)
foreach (explode(',', $_SERVER[$key]) as $ip)
$ip = trim($ip); // just to be safe
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false)
return $ip;
Theory3:同时存储$_SERVER['HTTP_...]
和$_SERVER['REMOTE_ADDR']
之一。所以有两个变量:
function get_ip_address()
foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED') as $key)
if (array_key_exists($key, $_SERVER) === true)
foreach (explode(',', $_SERVER[$key]) as $ip2)
$ip2 = trim($ip2); // just to be safe
if (filter_var($ip2, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false)
$ip1 = $_SERVER['REMOTE_ADDR'];
return array($ip2, ip1);
老实说,我有点困惑。我需要多少列(在数据库中)来存储用户的IP?我的意思是我应该同时存储REMOTE_ADDR
和HTTP_...
吗?还是只是其中之一?
实际上,我有一个查询,它在数据库中加载的每个页面插入用户的 IP。因此,每次加载页面之前都会执行该查询。当然,INSERT
查询(每次针对每个请求和每个用户) 都是有成本的。所以我不希望它没用。我的意思是我想存储一个正确/真实的 IP,或者至少我想做最好的工作来检测用户的 IP *。
* 当用户使用像 HSS 这样的代理时,检测他是不可能的。这就是为什么我说“至少”。
好吧,哪个理论最好?
【问题讨论】:
你只需要一个。您不应该真正依赖 HTTP 标头,因为它们可以在客户端上更改。如果您信任这些信息,即如果连接 IPREMOTE_ADDR
是受信任的负载均衡器或反向代理,则您应该只使用这些 HTTP_X_FORWARDED_...
(和任何其他)变量中的任何一个。
您也可以将网络服务器配置为自动将X-FORWARDED-FOR
放入REMOTE-ADDRESS
,这样您就不必在每个脚本中都这样做了。
您似乎是从数据库负载/性能方面提出这个问题,而不是询问 IP 地址的最准确来源是什么。如果您真的只关心数据库方面,存储一两个之间的差异可以忽略不计。
@devlincarnate 没有数据库不是我的主题。我想知道如何获取真实IP。
@Barmar 我不熟悉网络服务器配置。所以我可以通过 php 做到这一点。我只是想知道我应该存储 both REMOTE-ADDRESS
和 X-FORWARDED-FOR
还是 either REMOTE-ADDRESS
或 X-FORWARDED-FOR
?
【参考方案1】:
您需要决定何时存储 IP,您是否信任发送 X-FORWARDED-FOR
地址的远程地址。如果这样做,则存储转发的地址,否则存储远程地址。所以它可能是这样的:
$load_balancer = '10.20.30.40';
$ip = $_SERVER['REMOTE_ADDR'];
if (isset($_SERVER['X_FORWARDED_FOR'] && $ip = $load_balancer)
$ip = $_SERVER['X_FORWARDED_FOR'];
然后在数据库中记录$ip
。
我认为将负载平衡器 IP 存储在数据库中也没有任何意义。在处理数据库数据时执行信任检查将需要您有另一个表来说明负载平衡器 IP 在不同时间段内的情况。
【讨论】:
首先,您为什么不关心其余的情况?HTTP_CLIENT_IP
、HTTP_X_FORWARDED
等.. 第二,这个 IP 10.20.30.40
是什么?老实说,我不知道什么是 负载均衡器 ..
您在问题的第二行中提到了负载均衡器。
负载平衡器是您在运行服务器集群时使用的反向代理服务器。客户端连接到负载均衡器,并将连接转发到实际服务器之一。如果您不使用负载均衡器,则无需担心这些东西,只需使用 REMOTE_ADDR
。
我看到 +1。所以$ip = $_SERVER['REMOTE_ADDR'];
,就这样?在这种情况下,当用户使用像 HSS 这样的代理时会发生什么?
您不能信任由您不管理的代理服务发送的标头。因此,当他们使用这样的公共代理时,请使用REMOTE_ADDR
。【参考方案2】:
我认为在 *** 上这个问题已经有了很好的答案,所以我不会详细说明要选择哪个值。 见https://***.com/a/15699240/6543678
关于记录用户 IP 地址,我要注意两点。
首先你应该使用一些nosql数据库来完成这个任务。
您可以将其配置为日志后端并简单地调用类似 \Log::info("$ip
login as $email
", \Log::GROUP_IP) 或类似的东西,这些东西很容易使用,然后在数据库中搜索你。
另一方面,从我的角度来看,记录 ip 根本没有帮助。 实施避免机器人(例如谷歌验证码)的良好策略,禁止攻击性用户的帐户。 真正的黑客知道如何隐藏他们的 IP。使用好的代理很容易,您可以使用被黑的个人计算机/服务器,使用 tor 或许多其他方式来隐藏您的身份。
只是不要在日志 IP 上浪费太多时间,以防您的真正目标是保护您的网站。
【讨论】:
以上是关于如何跟踪 IP 以阻止恶意用户?的主要内容,如果未能解决你的问题,请参考以下文章