ARP工作原理
首先先講ARP(Address Resolution Protocol )的工作機制,假設今天A要傳封包給B
1.當A要傳送封包B的時候,A會先檢查自己的 arp cache中有沒有B 的ip 與mac對應。
2.如果有﹐就直接使用此位址來傳送封包 如果沒有﹐則向網路發出一個 ARP Request broadcast
封包查詢B的實體位址,
3.這時網路上所有的主機都會收到這個廣播封包並檢查封包的 IP 欄位是否和自己的 IP 位址
一致
4.如果不是則忽略,如果是則會先將A的mac和 ip 資料更新到自己的 arp cache﹐如果已經有該
IP 的對應則更新覆蓋過去
5.然後B再回應一個 ARP Reply 封包給A﹐告知A自己的實體位址是多少,當A收到 ARP Reply
之後﹐也會更新自己的 ARP cache
ARP病毒
另外常聽到受到arp 病毒的攻擊,這是一種叫做ARP spoofing的病毒,主要是藉由
發送一個假的ARP封包竄改ARP Cache使得資料無法正確傳輸到目的地,造成網路無法連結,便稱作ARP攻擊。由於一般的ARP Cache是根據經過的ARP封包不斷的變更本身的ARP列表,假設接收到的ARP封包所提供的資料是偽造的,就會讓資料無法傳輸到實際的目的地。甚至可能因為資料導向某特定電腦,駭客可利用病毒竊取封包資料或修改封包內容。
Static ARP
這種arp病毒,可以藉由設定static arp 來讓主機不要發出arp request
進而不會收到假的arp 封包,static arp也可以讓主機不用浪費時間
去找相關的ip,mac對應,加快效率
SIOCSARP/SIOCDARP/SIOCGARP
下面使用ioctl方式配合SIOCSARP SIOCDARP
SIOCGARP來設定arp cache
其中
SIOCSARP = 負責add與modify arp entry
SIOCDARP=負責delete arp entry
SIOCGARP=負責get arp entry
可以參考下面的code來對arp 做set/del/get
1.StaticArpSet ==> 須給定ip與mac位址
1.StaticArpDel ==> 須給定ip位址
1.StaticArpGet==> 須給定ip位址與interface
這邊有一個地方要注意,就是arp_ha.sa_family如果沒填
就必需要指定interface name,否則會fail
//strcpy(arpreq.arp_dev, "eth0");也就是說這行不能省
我是設成arpreq.arp_ha.sa_family = AF_UNIX
如此kernel就會根據你所填的subnet ip給定所在的interface
然後如果是get則一定要給interface,不然也會fail
我也不太清楚為什麼!
ARP Flag
設定static arp時,一般給定flag為ATF_PERM(永久的)
與complete ATF_COM,下面flag值與意義供參考
標誌(flag) 值 含義(meaning)
ATF_COM 0x02 查找完成(Lookup complete)
ATF_PERM 0x04 永久記錄(Permanent entry)
ATF_PUBL 0x08 張貼記錄(Publish entry)
ATF_USETRAILERS 0x10 n求使用延伸檔名(Trailers requested)
ATF_NETMASK 0x20 使用網路掩碼(Use a netmask)
ATF_DONTPUB 0x40 不回復(Don't answer)
Check ARP Cache
要確認是否寫入arp cache,可以下commmand
cat /proc/net/arp
然後你就會看到如下格式的表格
IP address HW type Flags HW address Mask Device
192.168.10.1 0x1 0x2 00:50:56:C0:00:08 * eth0
192.168.10.2 0x1 0x2 00:50:56:EB:52:02 * eth0
192.168.10.11 0x1 0x6 00:23:FB:11:22:33 * eth0
reference code
//===============reference code========================//
#define SIN_ADDR(x) (((struct sockaddr_in *) (&(x)))->sin_addr.s_addr)
int StaticArpSet(char *ip, char *mac)
{
struct arpreq arpreq;
int flags;
int rtv;
int sock_fd;
printf("set arp entry IP=%s\tMac=%s\n", ip, mac);
memset(&arpreq, 0, sizeof(struct arpreq));
arpreq.arp_pa.sa_family = AF_INET;
arpreq.arp_ha.sa_family = AF_UNIX;
SIN_ADDR(arpreq.arp_pa) = inet_addr(ip);
sscanf(mac,"%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX",
&arpreq.arp_ha.sa_data[0], &arpreq.arp_ha.sa_data[1],
&arpreq.arp_ha.sa_data[2], &arpreq.arp_ha.sa_data[3],
&arpreq.arp_ha.sa_data[4], &arpreq.arp_ha.sa_data[5]);
//strcpy(arpreq.arp_dev, "eth0");
arpreq.arp_flags = ATF_PERM | ATF_COM;
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
rtv = ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq);
close(sock_fd);
if (rtv < 0)
{
printf("%s\n", "set arp fail...");
return -1;
}
else
printf("%s\n", "success");
return 0;
}
int StaticArpDel(char *ip)
{
struct arpreq arpreq;
int rtv, sock_fd;
printf("del arp entry Ip : %s\n", ip);
memset(&arpreq, 0, sizeof(struct arpreq));
arpreq.arp_pa.sa_family = AF_INET;
arpreq.arp_ha.sa_family = AF_UNIX;
SIN_ADDR(arpreq.arp_pa) = inet_addr(ip);
//strcpy(arpreq.arp_dev, "eth0");
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
rtv = ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq);
close(sock_fd);
if (rtv < 0)
{
printf("%s\n", "del arp fail...");
return -1;
}
else
printf("%s\n", "success...");
return 0;
}
int StaticArpGet(char *ip, char *devname)
{
struct arpreq arpreq;
int rtv, sock_fd;
char macaddr[18]={0};
unsigned char *hw_addr;
printf("check arp table Ip : %s\n", ip);
memset(&arpreq, 0, sizeof(struct arpreq));
arpreq.arp_pa.sa_family = AF_INET;
arpreq.arp_ha.sa_family = AF_UNIX;
SIN_ADDR(arpreq.arp_pa) = inet_addr(ip);
strcpy(arpreq.arp_dev, devname);
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
rtv = ioctl(sock_fd, SIOCGARP, (caddr_t)&arpreq);
close(sock_fd);
if (rtv < 0)
{
printf("%s\n", "Not found in cache");
return -1;
}
else
{
printf("%s\n", "success");
hw_addr = (unsigned char *) arpreq.arp_ha.sa_data;
snprintf(macaddr,sizeof(macaddr),"%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX",
hw_addr[0], hw_addr[1], hw_addr[2], hw_addr[3], hw_addr[4],
hw_addr[5]);
printf("macaddr [ %s ]\n",macaddr);
}
return 0;
}
沒有留言:
張貼留言