2011-09-03 175 views
3

我是一名iphone開發人員 - 新開發web dev,請耐心等待!
我目前正在使用MAMP進行本地測試。如何處理IPv4地址旁邊的IPv6地址

我在我的網站上有一個高度安全的部分。隨着需要用戶/通行證 - 它也檢查用戶的IP。如果該帳戶之前沒有從該IP使用過,則會將該IP以及唯一ID添加到保留表中,並向用戶發送一封電子郵件,要求確認從該位置訪問其帳戶。

如果用戶登錄,並且他們的IP與我的「允許」表中的用戶ID相關聯的任何IP都不匹配,它將執行上述任務,並且他們會收到一封電子郵件。

我用它來生成他們點擊鏈接的URL代碼看起來有點像這樣:

if (preg_match('/^127./',$ip)) { 
    // accessed from this machine 
    $val_url = "http://localhost:8888/mywebsite/admin/aproove_ip.php?email=$admin_email&val=$hash"; 
} 
else if (preg_match('/^192\.168./',$ip)) { 
    // accessed form a local networked computer 
    $val_url = "http://super.local:8888/mywebsite/admin/aproove_ip.php?email=$admin_email&val=$hash"; 
    // note super.local is my machine's address, 8888 is MAMP port 
} 
else { 
    // accessed from the WWW 
    $val_url = "http://www.mywebsite.com/admin/aproove_ip.php?email=$admin_email&val=$hash"; 
} 

現在,這已經完全在我的電腦上測試時的工作。我決定(不要問爲什麼)從我的iPod Touch和它發給我的電子郵件(以驗證IP)進行測試,它給了我完整的在線地址,就好像它已經從WWW(即沒有任何正則表達式都滿意)。我查看了包含請求的保留表,並且請求的IP爲:fe80::da30:62ff:fe18:6681

我猜這是ipv6? - 我需要知道的是:

  • 我應該期望ipv6地址在我的網站上線嗎?
  • 我怎樣才能知道,如果它是一個本地請求(像我正則表達式對192.168 ...和127 ...)

我將非常感謝有這方面的意見,我覺得很困惑

+1

+1想使你的代碼的IPv6兼容!即使IPv4地址已經用完,今天編寫的程序仍然不支持IPv6。 – snap

回答

7

如果你想確保沒有發生IPv6連接,可以將Listen 0.0.0.0:80添加到你的apache配置中。但是大多數網絡主機仍然不支持IPv6(我知道,我們在2011年),所以人們甚至不可能通過IPv6連接到您。你看到這個的唯一原因是因爲bonjour(什麼使.local地址工作)在IPv6上運行。

如果您想讓代碼IPv6準備就緒,幾乎不需要進行任何更改,因爲大多數IP PHP功能都適用於IPv4和IPv6。我記得的唯一改變是將MySQL表中的varchar數據類型增加到IPv6地址的最大長度(39)。

我不確定IPv6是否按照IPv4所做的相同規則subnet播放,但我認爲驗證IPv6地址是本地的會比較困難。

編輯:

fe80::/10似乎是本地鏈路地址,這可能是因爲檢查前4位一樣簡單。

+0

謝謝! - 已經讓我的varchar 39字符變長了 - 我想我應該不用擔心bonjour,那只是爲了測試,最後當它在線時它會做我想做的事情,IPv6或不! –

+3

您不應該使用varchar來存儲IP地址 - 無論是v4還是v6。它阻止了你用位掩碼高效地查詢它們,並浪費了很多存儲空間。請使用INET_ATON()和INET_NTOA()在MySQL中分別存儲和檢索IP地址。 –

+2

對於在一般應用程序中存儲IP的大多數用途,只是爲了跟蹤用戶,並且由於MySQL不能證明以可讀方式存儲IP的本地方式,通常我只是爲了方便而使用varchar(尤其是當它可以是IPv6或IPv4 )。 –

2

要查看IPv6地址是否是本地的,您必須知道哪些地址在本地使用。 IPv6不會執行NAT(通常)。有些網絡在內部使用ULA(唯一本地地址),但許多網絡只使用從ISP內部獲得的地址。

你必須考慮的一件事是,一些(大多數?這些天)使用隱私擴展。這意味着他們的IPv6地址會隨着時間而改變。這會導致你的表增長很多,並且會使用戶一遍又一遍地重新認證。我認爲你最好的選擇是隻存儲子網(前64位)並匹配。

以防萬一您不知道IPv6地址語法:地址使用十六進制數字並且具有ssss:ssss:ssss:ssss:nnnn:nnnn:nnnn:nnnn其中s是子網,n是節點/主辦。每個4位數據塊中的前導零被省略,並且多個0的塊被替換爲::一次。所以fe80::da30:62ff:fe18:6681實際上是fe80:0000:0000:0000:da30:62ff:fe18:6681。我自己的網絡服務器地址爲2001:4038:0:16::16,這是2001:4038:0000:0016:0000:0000:0000:0016的簡稱,子網是2001:4038:0:16::/64

示例代碼從地址獲得子網:

<?php 

# Get the original IP address, for example from the command line 
$original_ip_str = $argv[1]; 

# Converto to binary form (suppress errors, we handle them) 
$original_ip_bin = @inet_pton($original_ip_str); 
if ($original_ip_bin === FALSE) { 
    $subnet_str = FALSE; 
    $subnet_bin = FALSE; 
} else { 
    if (strlen($original_ip_bin) == 16) { 
    # IPv6: Replace the last 64 bits with zeroes 
    $subnet_bin = substr_replace($original_ip_bin, str_repeat("\000", 8), -8); 
    } 

    # Convert the result back to readable form (optional) 
    $subnet_str = inet_ntop($subnet_bin); 
} 

# Show the result 
echo "IPv6 address: $original_ip_str\n"; 
echo "IPv6 subnet: $subnet_str\n"; 
+0

你能提供一些代碼來從IPv6地址獲取子網嗎? - 然後我的代碼存儲在我的數據庫中... –

+0

當然!代碼添加在答案中 –