ARP防火墙
???? 像偶等長期在外流浪一簇,靠租個小房間的過日子,與人共享一條寬帶上網。本來嘛,兩三兆的帶寬供四五個人上網肯定是沒啥問題。可是這年頭,一說下載就是P2P,像Bit Torrent(這東西叫“變態”,還真是傳神,就因為太變態,有些國家的ISP都封P2P了),迅雷都是比較出了名的耗帶寬的。迅雷雖然可以限速,可是會有多少人會去設呢?而且還帶了bt功能。bt那東西嘛,設了限速基本沒啥用,特別是對于ADSL的網絡,有人下bt,別人基本就別想好好上網了,比起56k的貓也要慢上不少。于是呼,像P2P終結者等軟件就開始大行其道(當然也有不少人也是為了獨占帶寬用的)。最近,這個網絡里面除了個別人,其他就都別想上網了,嚴重時大家都沒法上網了。這個時候,大家可能會想到用ARP防火墻來防止ARP攻擊,這個時候運氣好的話,網速變快了,如果ARP防火墻功能比較弱的話,就變得沒無效或者網速變得比原來還慢,甚至徹底不能上網了。這個時候,我的土ARP防火墻就該出馬了,再加上一些限制別人網速的功能,就能解決別人下P2P時候網速太慢的問題了。為什么說土呢,就一Console的程序,總長度還沒超過100行。
??? 與ARP相關的軟件很多,有像p2p終結者那樣的流量控制的,還有像Cain那樣的嗅探用的,還有像各種ARP病毒等。這些都利用了一個原理就是ARP欺騙,利用ARP欺騙來實現會話劫持。下面介紹一下ARP欺騙的原理。
??? 在以太網內,機器間的交互是通過mac地址來進行的,通常機器間的交互只要知道對方機器的IP地址即可,那么,通訊的雙方是如何把IP地址轉化成mac地址的呢?正常情況下,如果機器A需要與機器B進行通訊,在機器A不知道機器B的mac地址(MACB)的情況下,機器A會向網絡廣播一個ARP請求數據包(會帶上機器A的IP地址IPA與mac地址MACA),詢問誰是IPB。這個時候IPB接收到這個數據包后會向機器A發一個ARP響應數據包告訴機器A,IPB對應的mac地址是MACB。這樣機器A與機器B都知道了對方的MAC地址了,就能互相通訊了。用簡單的語言來描述的話,就是:A喊一聲,IPB的MAC地址是什么,然后B告訴A,B的MAC地址是MACB。
??? 那么ARP欺騙是怎么回事呢?這個時候機器C來了,C一直聲稱IPB對應的MAC地址是MACC,因為A不知道誰說的是正確的,它會以第一個接收到的數據包為準,所以,只要C一直在說,把B的回應淹沒掉就可以了。這樣A一直會認為IPB的MAC地址就是MACC了。這個時候C就可以偽裝成B與A通訊了。這只是做到了ARP欺騙的第一步,并沒有太大的用處。那么接下去繼續利用ARP欺騙來做到會話劫持。正常情況下,A與B之前會直接進行通訊,這個時候,C又來搗亂了,C用上面的方式欺騙了A,讓A認為C就是B,同時C也用上面的方式欺騙了B,讓B認為了C就是A。此時A本來想發給B的數據包以及B本來想發給C的數據包都發給了C,C只要做一下轉發,轉發給本來就應該接收的那方。從A與B的角度來說,兩者都是正常通訊的,只是大家都不知道,中間還有個C。此時會話劫持已經完成,C可以做很多事情了,如:控制流量,禁止某些數據包通過,篡改某些數據包,獲取數據包里的信息等等。
???? 那么如何防范會話劫持呢。根據上述原理,只要有一方不被欺騙,劫持就不成立了。假如我用的機器就是A機器,那么只對A有控制權,自然只能在A上做手腳了。我們知道操作系統都維護有一個ARP Cache,Cache里存的就是IP與MAC的映射。要防止有人仿冒B,只要Cache里關于B的映射是正確的就行了。操作系統給我們提供了一種方法,那就是可以設置靜態的映射,除非手工重新設置,那么在重啟系統之前是不會變的,那么我們只要拿到正確的B的MAC地址就可以。好在B在絕大部分情況下就是網關,所以很容易拿到正確的MAC地址。剩下的就很簡單了。
??? 在Windows下可以用如下的命令,前面是IP地址,后面是MAC地址linux下也用類似的命令,形式稍有不同,具體可以參見linux下arp命令的幫助。
arp -s 192.168.1.1 00-aa-00-62-c6-09??? 這樣再也不可能有機器來來仿冒成B了。很多ARP防火墻其實只實現到了這一層。這個時候,很多同學都會發現:怎么用了ARP防火墻之后,網速反而慢了啊!這個時候其實還沒完,因為C還可以欺騙B啊。但是C對B的欺騙也不完全,有時候B能認對A有時候不能,所以B發出的數據,有時候會發給A,有時候發給C,而通過C再轉發給A的數據,對于類似于TCP這樣的協議,由于C沒有與A建立會話,所以,絕大部分的數據包都會丟棄,TCP的連接也有可能因為丟包而斷掉,于是為了丟包重發,以及重新建立連接等,消耗大量時間與帶寬,直接的感覺就是網速很慢。所以這個時候還需要做一個事情,就是把C對B的欺騙的校正過來。C發給B的是大量錯誤的ARP響應包,把原來正確的給淹沒掉了,那么要糾正過來也很簡單,那就是發送比C更多的正確的ARP響應包,把C的錯誤的包給淹沒掉就行了。現在有不少ARP防火墻開始支持到第二個層次了。
???? 根據以前原理,用java寫了個簡單的ARP防火墻,利用的是jpcap(包裝了winpcap,libpcap),有興趣的同學可以了解一下下面的核心代碼。
public class IpMacMap {private String ip;private byte[] mac;public IpMacMap() {}public IpMacMap(String ip, byte[] mac) {this.ip = ip;this.mac = mac;}public String getIp() {return ip;}public void setIp(String ip) {this.ip = ip;}public byte[] getMac() {return mac;}public void setMac(byte[] mac) {this.mac = mac;} }private static EthernetPacket getEthernetPacket(byte[] senderMac, byte[] targetMac) {EthernetPacket packet = new EthernetPacket(); // 創建一個以太網頭packet.frametype = EthernetPacket.ETHERTYPE_ARP; // 選擇以太包類型packet.dst_mac = targetMac;packet.src_mac = senderMac;return packet;}?
private static ARPPacket getArpPacket(IpMacMap sender, IpMacMap target, short arpType) throws UnknownHostException {ARPPacket packet = new ARPPacket();packet.hardtype = ARPPacket.HARDTYPE_ETHER; // 選擇以太網類型(Ethernet)packet.prototype = ARPPacket.PROTOTYPE_IP; // 選擇IP網絡協議類型packet.operation = arpType;packet.hlen = 6; // MAC地址長度固定6個字節packet.plen = 4; // IP地址長度固定4個字節packet.target_hardaddr = target.getMac();packet.target_protoaddr = InetAddress.getByName(target.getIp()).getAddress();packet.sender_hardaddr = sender.getMac();packet.sender_protoaddr = InetAddress.getByName(sender.getIp()).getAddress();return packet;}?
?
private static ARPPacket createAntiARPPacket() throws UnknownHostException {IpMacMap source = new IpMacMap();source.setIp(device.addresses[0].address.getHostAddress());//本機IP地址source.setMac(device.mac_address);//本機mac地址IpMacMap target = new IpMacMap();target.setIp(getwayIPAddress);//網關的IPtarget.setMac(getewayMacAddress.getMacAddress());//網關的mac地址ARPPacket antiSpoofPacket = getArpPacket(source, target, ARPPacket.ARP_REPLY);antiSpoofPacket.datalink = getEthernetPacket(source.getMac(), target.getMac());return antiSpoofPacket;}轉載于:https://www.cnblogs.com/qhfrose/archive/2010/08/24/1807703.html
總結
- 上一篇: 一文读懂金融行业软件测试
- 下一篇: Jetson TX1开发笔记(二):TX