場景:
內網環境需要開啟多個DHCP服務器,分別給不同的設備進行PXE安裝。
存在的問題:
多個DHCP的情況下,設備在啟動時隨機從一個DHCP服務器獲取IP(哪個DHCP服務器先響應就從哪個獲取)並從那個服務器讀取配置進行引導安裝。
如果提供IP的DHCP服務器不是期望的那個,就無法得到正確的配置文件,也就無法進行正常引導安裝。
初步解決方法:
DHCP服務提供配置可以對響應進行限制,僅給某些設備(設備的MAC)分配IP,對其它設備的請求則不予響應。
/etc/dhcpd.conf配置大致如下:
subnet 128.128.0.0 netmask 255.255.0.0 {
......
filename "pxelinux.0";
}
deny unknown-clients;
host <hostname1> { hardware ethernet <XX:XX:XX:XX:XX:XX>;}
host <hostname2> { hardware ethernet <XX:XX:XX:XX:XX:YY>;}
這樣配置以后,DHCP服務器僅會對<XX:XX:XX:XX:XX:XX> <XX:XX:XX:XX:XX:YY>這些MAC進行響應。
依然存在的問題:
如果每個DHCP服務器都做了限制,僅給指定MAC分配IP,並且沒有兩個DHCP服務器同時配置了同一MAC,那么每個MAC能夠得到響應的DHCP服務器就是唯一確定的。
但不可避免,有些DHCP服務器並沒有或者忘記設置,依然導致DHCP響應泛濫,設備還是可能從不期望的DHCP服務器獲取響應。
進一步的解決方法:
要求每個使用的DHCP服務器在/etc/dhcpd.conf指定具體的MAC。對於那些泛濫響應的DHCP服務器,使用Dhcpstarv將其提供的IP(DHCP 響應)消耗掉。Dhcpstarv的執行方式就是不斷偽造一些MAC地址進行DHCP請求,把DHCP服務器能夠響應的IP地址都消耗掉。
具體操作:
當你想啟動DHCP服務,給某台設備進行PXE安裝,但是發現同一網絡中還存在另一個DHCP服務器也在提供DHCP服務,那么就可以使用Dhcpstarv了。
命令使用(ethX就是連接到要消耗的網絡的網卡,不要指定錯了):
# ./dhcpstarv -v -i ethX
類似下面的輸出就說明dhcpstarv正在消耗DHCP響應
14:54:20 01/10/14: got address 128.128.18.199 for 00:16:36:4c:d7:48 from 128.128.18.5
14:54:20 01/10/14: got address 128.128.18.200 for 00:16:36:06:98:de from 128.128.18.5
等不再有類似的輸出結果,說明DHCP的響應被消耗差不多了。讓dhcpstarv程序繼續運行,啟動你自己的DHCP服務器。
恢復方法:
如果DHCP服務器未進行限制MAC配置,不幸被Dhcpstarv消耗完,可以通過以下方法恢復“被攻擊”DHCP服務器:
1. 修改配置文件/etc/dhcpd.conf,增加限制MAC的配置:
deny unknown-clients;
host <hostname1> { hardware ethernet <XX:XX:XX:XX:XX:XX>;}
host <hostname2> { hardware ethernet <XX:XX:XX:XX:XX:YY>;}
2. 刪除文件 /var/lib/dhcp/db/dhcpd.leases
3. 重啟DHCP服務
如何定位攻擊來源:
Dhcpstarv在發送的DHCP請求包中偽造隨機的源MAC,其偽造方式是:固定前3個字節硬件設備“制造商”為“001636”,后3個字節隨機生成。源代碼位置:
dhcpstarv-0.2.1/src/main.c:130行
unsigned char vendor_mac_prefix[] = { 0x00, 0x16, 0x36 };
但是,以太網幀的源MAC還是發送數據幀的網卡的真實MAC,因此為了定位Dhcpstarv偽造的DHCP請求包的來源,可以通過抓包,根據以太網幀中的源MAC確定Dhcpstarv的位置。
DHCP請求包是封裝在UDP數據報,UDP數據報偏移36字節的位置即是DHCP請求包的源MAC,過濾UDP數據報的前3個字節為“001636”,就可以得到Dhcpstarv偽造的DHCP請求包。命令如下:
# tcpdump -i bond0 -ne src port 68 and udp[36:2]=0x0016 and udp[38]=0x36
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on bond0, link-type EN10MB (Ethernet), capture size 96 bytes
13:51:31.254469 00:18:82:b0:7e:22 > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 286: 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:16:36:81:30:15, length 244
13:51:32.000714 00:18:82:b0:7e:22 > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 304: 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 00:16:36:81:30:15, length 262