簡體   English   中英

使用php / mysql禁止IP

[英]Banning by IP with php/mysql

我希望能夠通過IP禁止用戶。 我的想法是將一個IP列表保存為BannedIPs表中的行(IP列將是一個索引)。

為了檢查用戶對表的IP,我將為每個會話保留一個名為$ _SESSION ['IP']的會話變量。 如果在任何請求中,$ _SESSION ['IP']與$ _SERVER ['REMOTE_ADDR']不匹配,我將更新$ _SESSION ['IP']並檢查BannedIPs表以查看IP是否被禁止。 (標志也將保存為會話變量,指定是否禁止用戶)

以下是我想知道的事情:

  1. 這聽起來像是一個關於速度和安全性的好策略(有人能夠以某種方式解決IP禁令,除了更改IP, 編輯:或使用代理 )?
  2. 構造mysql查詢以檢查行是否存在的最佳方法是什么? 也就是說,查詢數據庫以查看是否存在具有某個IP的行(檢查是否被禁止)的最佳方法是什么?
  3. 我應該將IP保存為整數還是字符串?

注意...

  • 我估計數據庫中存儲的1,000-10,000個禁用IP。
  • $ _SERVER ['REMOTE_ADDR']是發送當前請求的IP。

首先,我建議不要使用MySQL和PHP來執行此操作。 Apache有一個Deny IP地址的Deny指令,最終將比本土解決方案更好。

您可以輕松創建后端以查看和編輯包含所有這些條目的.htaccess文件。

這是一個禁止2個IP地址的例子(那些想知道的人的谷歌DNS服務器)並顯示一個自定義頁面,如果被禁止...

Order Allow,Deny
Deny from 8.8.8.8
Deny from 8.8.4.4
Allow from all

ErrorDocument 403 /access_is_denied.htm

此功能由Apache 2.2中的mod_authz_host提供。 有關每個指令的更多信息可以在Apache的mod_authz_host文檔頁面中找到


話雖如此:

  1. 當用戶的IP在$_SERVER['REMOTE_ADDR']始終可用時,為什么$_SESSION['IP']使用$_SESSION['IP'] $_SERVER['REMOTE_ADDR'] 我能看到的唯一原因是保存到數據庫的行程......但是如果你將這個IP添加到你的禁令列表中,他仍然可以訪問,直到他的會話到期。

  2. 如果您確實仍想使用數據庫,請將IP地址存儲為INT (如果要支持IPv6,則存儲2個BIGINT列)。 它們占用的空間少於字符串,比較快。

至於它的安全性......他們可以通過代理來繞過禁令。 如果您希望收到響應,則在數據包中欺騙IP地址是完全沒用的。

  1. 是的,通過HTTP標頭欺騙。
  2. Select Count(*) from bannedIPs where ip = $input ,如果返回0,則不禁止IP。
  3. 我會用字符串。

一般情況下,我建議您記住,您的站點可能被一台路由器后面的許多計算機訪問,這意味着所有用戶都將顯示相同的IP。 你禁止一個,你禁止他們。 我決心通過電子郵件和其他方式禁止。 此外,我想說,那些傷害你網頁的人不會被ip禁令或其他手段阻止。 考慮到這一點,始終保護自己免受XSS,sql注入等常見的待遇。

回答你的第3個問題:

您可能需要處理IPv6以及IPv4,因此您的數據結構需要允許128位地址值。

10.000條目是MySQL的簡單游戲。 只需將索引設置為正確,此金額就沒有問題。

也許您應該考慮使用白名單而不是黑名單,這可能會減少您的IP地址列表?

只要用戶不在旋轉代理后面,您的策略就會起作用。 即通過AOL客戶端訪問網站的AOL用戶將擁有不同的IP地址,因為他們的請求來自不同的代理服務器。 通常這不是問題。

用戶的IP地址保存在您的會話中($ _SESSION ['IP']),該會話通常存儲在您的服務器上,因此足夠安全。

以下是檢查表中條目的示例代碼:

$raw = mysql_query ("SELECT ip FROM ip_blacklist WHERE ip = '" . mysql_escape_string(getenv('REMOTE_ADDR')) . "' LIMIT 0,1");
if ( mysql_num_rows ($raw) ) {
 // match found
}
else {
 // no match found
}

您可以將其修改為僅搜索IP的一部分。 即,而不是192.168.0.1,你可以搜索192.168.0。%:

… WHERE ip LIKE '192.168.0.%' …

這允許您過濾小型網絡,而不是定義所有IP地址。

使用整數通常是最好的方法,特別是如果您使用數據庫和范圍。 如果您想更好地理解/讀取數據,字符串會更好。

  1. http://www.rubyrobot.org/article/protect-your-web-server-from-spambots

    我們的想法是將禁令存儲在PHP(或其他)的數據庫中,但不要使用PHP進行任何過濾。 每個請求額外的數據庫命中可能是從快速到低速的轉折點。

    執行阻塞的位是內核級防火牆iptables。 這由另一個只從數據庫中讀取的腳本更新。 如果你願意的話,你可以用簡單的CSV做一些類似的東西,並完全跳過數據庫聯系。

    總之,iptables的不是一個完整的數據庫查詢的效率高得多

  2. 如果使用SQL,請確保轉義IP輸入。 我可能是偏執狂,但我已經通過$_SERVER['REMOTE_ADDR']看到了各種各樣的廢話。

  3. 字符串。 它們不是數字,而是四個數字的排列。 IPv6是十六進制的。 字符串覆蓋所有基礎,處理成本很低。

您還應該知道服務器變量可能存在。 閱讀: 獲取用戶的真實IP

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM