從 Information Elements 解析無線網路的加密細節
無線網路的訊號是公開發送的,雖然無法攔截,但只要你有無線裝置,基本上都能『監聽』空氣中的無線網路封包。也因為無線通訊的本身是不安全的,就如同傳統網路可能被 ISP 或連線路徑中的 Route Node 所監聽一樣,所以無論是哪一種通訊,目前的解決方式都是採用封包或資料加密,以達成安全連線的目的。在一般網路通訊中,常聽到的方法有 Secure Sockets Layer(SSL) 這一類,而對於無線網路通訊來說,就有所謂的 WEP、WPA、WPA2 等等眾多規格。嚴格來說,SSL 和無線網路的加密並不算同一層面的實作,但是他們有相同的目的和類似的原理。
最早的無線加密非常單純,可以用 WEP 一種加密方式走遍天下,只要判斷出遠端無線基地台或存取點需要加密金鑰,我們就可以假設該加密是 WEP 。不過由於 WEP 並不安全,有心人經過封包收集後,還是能很快破出金鑰,所以,日後就出現了 WPA、WPA2 種種加密方法的進階補強版。
想要知道該無線訊號是哪一種加密方法,可以從無線裝置所提供的『Information Elements』去得知,從事件 IWEVGENIE 中,就可取得加密的細節 ,這部份可參考 iwlist 或 LXPanel netstat plugin 內部的實作。
Informations Elements(IEs) 的結構定義,分為兩種:
* 所有數值皆採用 Little Endian
因為 WPA 和 WPA2 是後來擴充上去的定義,並不在原始的 IEs 標準裡,所以許多欄位可能依遵循的標準而有所增減,不過,除非是發射端過於老舊,理論上都應該會遵循後來 WPA/WPA2 擴充的標準。在程式實作解析WPA/WPA2 時,原則上只要是無法辨別的 Type,一律視為 TKIP 就可以向下相容了,可以從 『Wireless Tools』的 Source Code 中找到這樣的處理原則。
關於 Cipher Type 和 Authentication Suite(key_mgmt) 的定義可參考:
LXPanel netstat plugin 在這部份的實作摘錄:
在之前,LXPanel netstat plugin 對 WPA/WPA2 IEs 支援一直有問題,在最近改寫後的 SVN 最新版已經可以很好的處理 IEs,當然這部份是參考 iwlib 的 iwlist.c 寫出來的,其目的是判斷加密的方式,以通知 LXNM 做相對應的處理。如果想要使用這功能,請使用最新 SVN 版本的 LXPanel 以及LXNM,因為改寫過後的 netstat plugin 和舊版 LXNM 完全不相容。
後記
本文的示意圖表是大略畫出來的,其中可能會用到些縮寫或簡化的名詞表示。
最早的無線加密非常單純,可以用 WEP 一種加密方式走遍天下,只要判斷出遠端無線基地台或存取點需要加密金鑰,我們就可以假設該加密是 WEP 。不過由於 WEP 並不安全,有心人經過封包收集後,還是能很快破出金鑰,所以,日後就出現了 WPA、WPA2 種種加密方法的進階補強版。
想要知道該無線訊號是哪一種加密方法,可以從無線裝置所提供的『Information Elements』去得知,從事件 IWEVGENIE 中,就可取得加密的細節 ,這部份可參考 iwlist 或 LXPanel netstat plugin 內部的實作。
Informations Elements(IEs) 的結構定義,分為兩種:
- Type 欄位:
- 0xdd: WPA or Others
- 0x30: WPA2
- OUI 定義(3 Bytes):
- WPA: 0x00, 0x50, 0xf2
- WPA2: 0x00, 0x0f, 0xac
- Data 欄位:
* 所有數值皆採用 Little Endian
因為 WPA 和 WPA2 是後來擴充上去的定義,並不在原始的 IEs 標準裡,所以許多欄位可能依遵循的標準而有所增減,不過,除非是發射端過於老舊,理論上都應該會遵循後來 WPA/WPA2 擴充的標準。在程式實作解析WPA/WPA2 時,原則上只要是無法辨別的 Type,一律視為 TKIP 就可以向下相容了,可以從 『Wireless Tools』的 Source Code 中找到這樣的處理原則。
關於 Cipher Type 和 Authentication Suite(key_mgmt) 的定義可參考:
static const char * iw_ie_cypher_name[] = {
"none",
"WEP-40",
"TKIP",
"WRAP",
"CCMP",
"WEP-104",
};
static const char * iw_ie_key_mgmt_name[] = {
"none",
"802.1x",
"PSK",
};
LXPanel netstat plugin 在這部份的實作摘錄:
void
wireless_gen_ie(ap_info *info, unsigned char *buffer, int ielen)
{
int offset = 2;
int count;
int i;
unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
unsigned char *wpa_oui;
/* check IE type */
switch(buffer[0]) {
case 0xdd: /* WPA or else */
wpa_oui = wpa1_oui;
if((ielen < 8)
|| (memcmp(&buffer[offset], wpa_oui, 3) != 0)
|| (buffer[offset + 3] != 0x01)) {
if (info->haskey)
info->en_method = NS_WIRELESS_AUTH_WEP;
else
info->en_method = NS_WIRELESS_AUTH_OFF;
info->key_mgmt = NS_IW_IE_KEY_MGMT_NONE;
info->group = NS_IW_IE_CIPHER_NONE;
info->pairwise = NS_IW_IE_CIPHER_NONE;
return;
}
/* OUI and 0x01 */
offset += 4;
break;
case 0x30: /* IEEE 802.11i/WPA2 */
wpa_oui = wpa2_oui;
break;
default: /* Unknown */
if (info->haskey)
info->en_method = NS_WIRELESS_AUTH_WEP;
else
info->en_method = NS_WIRELESS_AUTH_OFF;
info->key_mgmt = NS_IW_IE_KEY_MGMT_NONE;
info->group = NS_IW_IE_CIPHER_NONE;
info->pairwise = NS_IW_IE_CIPHER_NONE;
return;
}
/* assume TKIP */
info->en_method = NS_WIRELESS_AUTH_WPA;
info->key_mgmt = NS_IW_IE_KEY_MGMT_NONE;
info->group = NS_IW_IE_CIPHER_TKIP;
info->pairwise = NS_IW_IE_CIPHER_TKIP;
/* 2 bytes for version number (little endian) */
offset += 2;
/* check group cipher for short IE */
if ((offset+4) > ielen) {
/* this is a short IE, we can assume TKIP/TKIP. */
info->group = NS_IW_IE_CIPHER_TKIP;
info->pairwise = NS_IW_IE_CIPHER_TKIP;
return;
}
/* 4 Bytes for group cipher information [3 bytes][1 Byte] */
if(memcmp(&buffer[offset], wpa_oui, 3)!=0) {
/* the group cipher is proprietary */
info->group = NS_IW_IE_CIPHER_NONE;
} else {
/* pick a byte for type of group cipher */
info->group = buffer[offset+3];
}
offset += 4;
/* check pairwise cipher for short IE */
if ((offset+2) > ielen) {
/* this is a short IE, we can assume TKIP. */
info->pairwise = NS_IW_IE_CIPHER_TKIP;
return;
}
/* 2 bytes for number of pairwise ciphers (little endian) */
count = buffer[offset] | (buffer[offset + 1] << 8);
offset += 2;
/* if we are done */
if ((offset+4*count) > ielen) {
return;
}
/* choose first cipher of pairwise ciphers to use,
* FIXME: Let user decide the cipher is the best way. */
for(i=0;i<count;i++) {
if(memcmp(&buffer[offset], wpa_oui, 3)==0) {
/* pick a byte for type of group cipher */
info->pairwise = buffer[offset+3];
}
offset += 4;
}
/* check authentication suites */
if ((offset+2) > ielen) {
/* this is a short IE, we can assume TKIP. */
info->key_mgmt = NS_IW_IE_KEY_MGMT_NONE;
return;
}
/* 2 bytes for number of authentication suites (little endian) */
count = buffer[offset] | (buffer[offset + 1] << 8);
offset += 2;
/* if we are done */
if ((offset+4*count) > ielen) {
return;
/* choose first key_mgmt of authentication suites to use,
* FIXME: Let user decide the key_mgmt is the best way. */
for(i=0;i<count;i++) {
if(memcmp(&buffer[offset], wpa_oui, 3)==0) {
/* pick a byte for type of key_mgmt */
info->key_mgmt = buffer[offset+3];
}
offset += 4;
}
}
在之前,LXPanel netstat plugin 對 WPA/WPA2 IEs 支援一直有問題,在最近改寫後的 SVN 最新版已經可以很好的處理 IEs,當然這部份是參考 iwlib 的 iwlist.c 寫出來的,其目的是判斷加密的方式,以通知 LXNM 做相對應的處理。如果想要使用這功能,請使用最新 SVN 版本的 LXPanel 以及LXNM,因為改寫過後的 netstat plugin 和舊版 LXNM 完全不相容。
後記
本文的示意圖表是大略畫出來的,其中可能會用到些縮寫或簡化的名詞表示。
留言
張貼留言