2010-06-06 59 views
3

我希望能夠通過IP來禁止用戶。我的想法是將IP列表保留在BannedIPs表中(IP列將作爲索引)。通過IP使用php/mysql禁止

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

這裏的事情,我想知道:

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

注意...

  • 我估計會有1000-10000之間禁止IP的存儲在數據庫中。
  • $ _SERVER ['REMOTE_ADDR']是發送當前請求的IP。
+0

不知道這一點,但在我的大學裏,每個人都有相同的知識產權,所以如果你的網站與學校有關,這可能是一個問題。 – ggfan 2010-06-06 22:30:06

+0

@ggfan:我的網站與學校無關 - 但這是一個很好的觀點。不過,如果我想禁止某個建築物/學校的人,我確實寧願整個地方都被禁止,所以這很好。 – Cam 2010-06-06 22:34:01

+3

不僅僅是學校,還有許多具有代理服務器的組織。公司,圖書館等 – Jeff 2010-06-06 22:34:04

回答

6

首先,我會建議不要使用MySQL和PHP來做到這一點。 Apache有一個禁止IP地址的指令,最終會比本土解決方案更好。

你可以很容易地創建一個後端來查看&編輯一個.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 

此功能由mod_authz_host在Apache 2.2的提供了一個例子。關於每個指令的更多信息可以在Apache's mod_authz_host Documentation Page中找到。


話雖這麼說:

  1. 爲什麼$_SESSION['IP']在所有當用戶的IP是始終可用的$_SERVER['REMOTE_ADDR']?我能看到的唯一原因是爲了省去一趟數據庫......但是,如果您將IP添加到禁止列表中,他仍然可以訪問,直到他的會話過期。

  2. 如果您確實想要使用數據庫,請將IP地址存儲爲INT(或者如果您要支持IPv6,則需要存儲2個BIGINT列)。他們比字符串佔用更少的空間,並且比較快。

至於它的安全性......他們可以通過代理繞過禁令。如果您希望接收響應,欺騙分組中的IP地址是完全沒有用的。

+0

使用.htaccess解決方案,我是否可以將用戶重定向到自定義的「禁止」頁面?這是必要的,因爲我禁止學校/企業。 +1注意到用戶仍然可以訪問,直到會話過期 - 我沒有想到這一點。 – Cam 2010-06-06 22:47:05

+1

@incrediman:是的,你可以......我已經更新了我的答案,以說明你如何實現這一目標。 – 2010-06-06 23:23:10

+0

真棒,謝謝! – Cam 2010-06-06 23:24:34

1

重新您的問題3:

你可能需要的IPv4讓你的數據結構需要允許128位的地址值照顧IPv6的爲好。

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

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

+0

禁止通過電子郵件是不是一個問題,因爲我也禁止與唯一的電子郵件相關的帳戶。另外,+1 - 我喜歡查詢。 – Cam 2010-06-06 22:41:34

1

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
  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是十六進制的。字符串以很小的處理成本覆蓋所有基地。

你也應該知道,服務器變量可以說謊。閱讀:Getting The Real IP Of Your Users

+0

+1。你可以擴展「你應該知道,服務器變量可以說謊」? – Cam 2010-06-06 22:49:19

+0

另外 - 你真的認爲這將是如此巨大的打擊我的分貝,如果IP列索引,並有最大10k的IP? – Cam 2010-06-06 22:55:06

+0

對於一些ISP,REMOTE_ADDR會爲大量用戶顯示相同的結果,因爲他們會使用代理。有時'HTTP_X_FORWARDED_FOR'可以作爲替代方案(請參閱鏈接),但有些情況下,您顯然無法獲取用戶的真實IP地址。我只需重新啓動路由器就可以獲得新的IP(需要30秒)。因此,通過知識產權取締有時候不會有效,在某些情況下禁止你不打算取締的人。仔細玩。 – Oli 2010-06-06 22:55:57