阻擋 IP 登入的做法


Tek 發表



限制單獨 IP 即範圍內的IP

在一個網頁應用程式上,例如留言板、討論板等程式都曾經有人問過該如何使用瀏覽者的 IP 地址來限制或阻擋登入• 在這邊我將使用 ASP.Net 語言提供一個完整的 IP 限制範例,並解釋該程式• 如果您本身完全不瞭解 Networking ,和對 ASP.Net, SQL 網頁程式沒有絲毫經驗的話,這一篇教學文章可能學起來會很吃力• 另外,文章將只會將說明限制單獨IP,和 IP 範圍•

【IP 限制】限制 IP 的做法:

要限制 IP 登入的時候,您可以有這四種常見的做法,分別為:
1. 阻擋一個單一完整的 IP 資料,例如: 172.128.0.0
2. 只允許一個單一的完整 IP 登入
3. 阻擋一個範圍的 IP 資料,例如: 172.128.0.0 ~ 172.191.255.255
4. 只允許一個範圍的 IP 登入

【限制注意事項】不應該隨便限制(禁止)的 IP 範圍:

1. 本機 IP: 127.0.0.1 和上線時的IP
2. 私有IP,包括:
Class A: 10.0.0.0 - 10.255.255.255
Class B: 172.16.0.0 - 172.31.255.255
Class C: 192.168.0.0 - 192.168.255.255

不能隨便限制的原因:
1. 本機 IP 就是您自己的電腦IP
2. 私有 IP 只能用在區域網路裡,資料不能對外傳播•所以這是自己人•

【要求 IP】ServerVariables

用要求瀏覽者 IP 很簡單,使用 httprequest class 的 servervariables member即可! 以下是範例:


<Script Language="VB" Runat="Server">
Sub Page_Load()
Dim ip As String = Request.ServerVariables("REMOTE_HOST")
Response.Write("你的IP: " & ip)
End Sub
</Script>


【限制多個單獨 IP: 一】使用陣列

要限制多個 IP 地址,我們可以使用陣列來儲存• 然後使用 filter 來搜尋•步驟是這樣的:

1. 先放入要被限制的 IP 地址
2. 要求瀏覽者 IP 地址
3. 拿著瀏覽者 IP 在陣列中搜尋是否有符合的IP
4. 如果有符合的IP,則禁止• 沒有,則繼續下一個動作•

這是一個程式範例:

<Script Runat="Server" Language="VB">
Sub Page_Load()
Dim ips() As String
Dim visitorip As String
ips(0) = "210.243.5.7"
ips(1) = "210.243.8.7"
ips(2) = "123.255.255.10"
ips(3) = "192.210.10.10"
ips(4) = "127.0.0.1"
visitorip = Request.ServerVariables("REMOTE_HOST")
If join(filter(ips, visitorip)) = "" Then
Response.Write("您的 IP 被限制")
Else
Response.Write("您的 IP 沒被限制")
End If
End Sub
</Script>


【限制多個單獨 IP: 二】使用資料庫

使用資料庫的限制邏輯跟上面使用陣列一樣,只是這一次我們寫法會有很大不同• 而且這一次我們依賴SQL 語句的 Select 指令加 Where Clause 來搜尋資料庫裡的IP是否和目前使用者的有符合資料... 如果有的話,則限制,沒則不限制• 這是程式範例:


<%@Import NameSpace="System.Data.OLEDB"%>
<Script Runat="Server" Language="VB">
Sub Page_Load()
Dim conn As OLEDBConnection
Dim cmd As OLEDBCommand
Dim dbreader As OLEDBDataReader
Dim ip As String = Request.ServerVariables("REMOTE_HOST")
conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
Server.MapPath("ipdb.mdb")
conn.Open()
cmd.CommandText = "Select * From ip_table Where resip = '"& ip &"'"
cmd.Connection = conn
dbreader = cmd.ExecuteReader()
If dbreader.Read Then
Response.Write("被限制")
Else
Response.Write("沒被限制")
End If
conn.Close()
End Sub
</Script>


程式簡要運作步驟:
1. 先匯入Namespace: System.Data.OLEDB
2. 宣告並建立資料庫連線
3. 宣告資料庫指令 class
4. 宣告資料讀取物件 class
5. 設定資料庫指令物件的指令文字(SQL 語句控制)
6. 指定資料庫指令物件的資料庫連線來源
7. 指令物件執行資料庫讀取物件
8. 讀取物件使用 read member 傳會boolean判斷是否有資料存在•
9. 有資料傳回 True, 代表瀏覽者是被限制的• 沒有則不限制•
10.關閉資料庫連線

【限制範圍IP 】以另一種形態方式看 IP 資料 -- Decimal IP Address

每一個 IP 事實上也可以轉換成十進位方式看待,這樣子我們也可以方便再一次依賴SQL select 的 where clause• 假設我們有一個 IP 是218.187.133.255 ,而這一家ISP (Internet Service Provider) 所分配的 IP 是218.0.0.0 ~ 218.255.255.255 之間• 我們就把所有的 IP 資料轉換成decimal 看待:

轉換 218.187.133.255:

218 x 16777216 = 3657433088
187 x 65536 = 12255232
133 x 256 = 34048
255 x 1 = 255
所有值加起來 = 3669722623 (decimal)

同樣的做法也去算這一個範圍的開始跟尾,算出來的結果分別是: 3657433088 ~ 3674210303

這樣子,我們最後只要讓使用SQL的where clause,使用>= 和 <= operators 就可以了• 另外您可以發現,不管你的 IP 給什麼,只要是在範圍218.0.0.0 ~ 218.255.255.255 之間,在十進位的情況下也是在這兩個數字之間•

* 注意使用這種方法必須每一次都要把瀏覽者的 IP 也以十進位看待這樣才能做搜尋•

要查一個IP的範圍是多少到多少,您可以到這一個網站: http://www.checkdomain.com/ 來看

【限制範圍IP 】資料庫的欄位分配

資料庫要分配時,至少要三個欄位或四個欄位• 如果你打算用三個欄位的話,您可以這樣做:

其中兩個欄位要存的是你算出來的十進位 IP,最後一欄是原本的 IP 範圍 memo,例如:

欄位一: 一個範圍的Decimal IP頭,例如: 3657433088
欄位二: 一個範圍的Decimal IP尾,例如: 3674210303
欄位三: 一個範圍的IP,例如: 218.0.0.0 ~ 218.255.255.255

註: 如果您想要把欄位三分別以分開顯示出來,可以使用 split() 來拆散為兩組IP資料,以VBScript寫法做個例子:


<Script Language="VBS">
dim ip_range
dim split_ip
ip_range = "218.0.0.0 ~ 218.255.255.255"
split_ip = split(ip_range, "~")
document.write "IP 頭: " & trim(split_ip(0)) & "<BR>"
document.write "IP 尾: " & Trim(split_ip(1))
</Script>


分開出來後,那麼你要再更新這一比資料的話也就很容易• 兩個步驟,只要把頭和尾再算成decimal一次儲存分別到第一跟第二欄,然後再合併回去原IP資料到第三欄•

如果您是要用四個欄位,那麼你就可以必免使用到 split() 拆散IP做更新或分開顯示的動作•以下是四個欄位的資料庫範例:

欄位一: 一個範圍的Decimal IP頭,例如: 3657433088
欄位二: 一個範圍的Decimal IP尾,例如: 3674210303
欄位三: 一個範圍的IP頭,例如: 218.0.0.0
欄位四: 一個範圍的IP尾,例如: 218.255.255.255

【限制範圍IP 】使用 SQL 語句的 >= 跟 <= 來判斷decimal IP是否在被限制的範圍裡

由於轉換成10進位後,我們就可以很方便的用大於或等於,小於或等於的邏輯判斷去找瀏覽者的decimal IP是否在資料庫被限制的IP 內• 這是用SQL用 >= , <= 的語句範例:

"Select * From ipblacklist Where "& visitor_ip & " >= lower_bound And "& visitor_ip &" <= upper_bound"

visitor_ip = 瀏覽者decimal IP
lower_bound = 被限制的decimal頭
upper_bound = 被限的decimal IP尾

接著,你可以用讀取物件的 reader member傳回布林值看是否有找到• 如果有找到,代表這一個瀏覽者的IP是在你的限制範圍下,沒有則不在限制範圍•

【限制範圍IP 】一個程式例子


<%@Import NameSpace="System.Data.OLEDB"%>
<%@Page Debug="True"%>
<Script Runat="Server" Language="VB">
Sub Page_Load
Dim connstr As String
Dim sqlstr As String
Dim visitor_ip As String
Dim search_reader As OLEDBDataReader
Dim ip_search_cmd As OLEDBCommand
Dim conn As New OLEDBConnection()
visitor_ip = Request.ServerVariables("REMOTE_HOST")
visitor_ip = Cdecimal(visitor_ip)
sqlstr = "Select * From ipblacklist Where "& visitor_ip & _
" >= lower_bound And "& visitor_ip &" <= upper_bound"
connstr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
Server.MapPath("ipblacklist.mdb")
conn.ConnectionString = connstr
conn.Open()
ip_search_cmd = New OLEDBCommand(sqlstr, conn)
search_reader = ip_search_cmd.ExecuteReader()
Response.Write("<h1>Tek's IP blacklist demonstration</h1>")
If search_reader.Read Then
With Response
.Write("<Font Color=""Red"">")
.Write("Sorry, your IP has been added to the visitor blacklist.")
.Write("</Font>")
End With
Else
Response.Write("Hello, how are you doing :-)")
End If
conn.Close()
search_reader.Close()
End Sub

Function Cdecimal(ipaddr) As Double
Dim decimal_result As Double
ipaddr = Split(ipaddr, ".")
ipaddr(0) = ipaddr(0) * 16777216
ipaddr(1) = ipaddr(1) * 65536
ipaddr(2) = ipaddr(2) * 256
decimal_result = cdbl(ipaddr(0)) + cdbl(ipaddr(1)) + cdbl(ipaddr(2)) + cdbl(ipaddr(3))
Return decimal_result
End Function
</Script>


【資源 】一些可以讓您參考IP說明的資源

IP 協定的 RFC 文件參考﹕RFC-791、RFC-1122、RFC-815、RFC-1700。
Coobila 的阿得目前也將準備寫一個限制 IP 範圍的教學,不過會以另一種寫法展示•敬請期待!!


最後更新日期: 7/23/2003 1:54:24 PM