【协议】LLDP、ARP、STP、ICMP协议

目录

LLDP--链路层发现协议,网络设备交互各自的信息

ARP协议

STP 协议(生成树协议)

ICMP协议--传输出错报告控制信息

ARP 详情

2.ARP工作原理

3.ARP协议解析

4.ARP攻击

5.ARP编程示例

6.Linux ARP调试


注意:tcpdump 过滤它们时使用小写,如!arp、lldp、!stp

协议数据样例:ARP-STP-ICMP-LLDP.acp-网络安全文档类资源-CSDN下载

LLDP--链路层发现协议,网络设备交互各自的信息

简略:

LLDP(Link Layer Discovery Protocol,链路层发现协议)

  • 二层协议
  • 网络中相互发现并交互各自的系统及配置信息

大白话,就是各个设备之间用来发送自己 或者接收对方的设备参数和配置信息的协议,例如:你的mac地址是多少,你使能了PFC没有,你的设备名叫什么……

工具lldptool就是使用LLDP协议来查询对方的设备信息和配置信息的:https://blog.csdn.net/bandaoyu/article/details/127999976?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127999976%22%2C%22source%22%3A%22bandaoyu%22%7D

详细说明:
     随着网络技术的发展,接入网络的设备的种类越来越多,配置越来越复杂,来自不同设备厂商的设备也往往会增加自己特有的功能,这就导致在一个网络中往往会有很多具有不同特性的、来自不同厂商的设备,为了方便对这样的网络进行管理,就需要使得不同厂商的设备能够在网络中相互发现并交互各自的系统及配置信息。 
LLDP(Link Layer Discovery Protocol,链路层发现协议)就是用于这个目的的协议。LLDP定义在802.1ab中,它是一个二层协议,它提供了一种标准的链路层发现方式。LLDP协议使得接入网络的一台设备可以将其主要的能力,管理地址,设备标识,接口标识等信息发送给接入同一个局域网络的其它设备。当一个设备从网络中接收到其它设备的这些信息时,它就将这些信息以MIB的形式存储起来。
这些MIB信息可用于发现设备的物理拓扑结构以及管理配置信息。需要注意的是LLDP仅仅被设计用于进行信息通告,它被用于通告一个设备的信息并可以获得其它设备的信息,进而得到相关的MIB信息。它不是一个配置、控制协议,无法通过该协议对远端设备进行配置,它只是提供了关于网络拓扑以及管理配置的信息,这些信息可以被用于管理、配置的目的,如何用取决于信息的使用者。

更多详细内容:原文链接:https://blog.csdn.net/goodluckwhh/article/details/10948065

ARP协议

查看arp

ip neigh

arp -n

简略:

大白话,就是就是广播一个ARP请求包发送IP地址到网络,请求是这个IP地址的主机把这个IP的mac地址返回来。

详细说明:

地址解析协议,即ARP(Address Resolution Protocol),

是根据IP地址获取物理地址的一个TCP/IP协议主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。地址解析协议是建立在网络中各个主机互相信任的基础上的,局域网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存;由此攻击者就可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗ARP命令可用于查询本机ARP缓存中IP地址和MAC地址的对应关系、添加或删除静态对应关系等。相关协议有RARP代理ARPNDP用于在IPv6中代替地址解析协议。

更多的见文章末尾的详情。

STP 协议(生成树协议)

简略:

     用于在局域网中消除数据链路层物理环路的协议。设备通过彼此交互信息发现网络中的环路,然后对某些端口进行阻塞,将环路网络结构修剪成无环路的树型网络结构。

详细说明:

STP(Spanning Tree Protocol,生成树协议)

用于在局域网中消除数据链路层物理环路的协议。运行该协议的设备通过彼此交互信息发现网络中的环路,并有选择的对某些端口进行阻塞,最终将环路网络结构修剪成无环路的树型网络结构,从而防止报文在环路网络中不断增生和无限循环,避免设备由于重复接收相同的报文所造成的报文处理能力下降的问题发生。

STP采用的协议报文是BPDU(Bridge Protocol Data Unit,桥协议数据单元),也称为配置消息,BPDU中包含了足够的信息来保证设备完成生成树的计算过程。STP即是通过在设备之间传递BPDU来确定网络的拓扑结构。

更多详情:交换机知识--生成树协议 - https://smb.tp-link.com.cn/service/detail_article_154.html

ICMP协议--传输出错报告控制信息

  • 简介

ICMP(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议簇的一个子协议,用于在IP主机路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。 [1] 

  • 工作原理

ICMP提供一致易懂的出错报告信息。发送的出错报文返回到发送原数据的设备,因为只有发送设备才是出错报文的逻辑接受者。

发送设备随后可根据ICMP报文确定发生错误的类型,并确定如何才能更好地重发失败的数据包。但是ICMP唯一的功能是报告问题而不是纠正错误,纠正错误的任务由发送方完成。

我们在网络中经常会使用到ICMP协议,比如我们经常使用的用于检查网络通不通的Ping命令(Linux和Windows中均有),这个“Ping”的过程实际上就是ICMP协议工作的过程。还有其他的网络命令跟踪路由的Tracert命令也是基于ICMP协议的。

  • 报文格式

ICMP报文包含在IP数据报中,属于IP的一个用户,IP头部就在ICMP报文的前面,所以一个ICMP报文包括IP头部、ICMP头部和ICMP报文,IP头部的Protocol值为1就说明这是一个ICMP报文,ICMP头部中的类型(Type)域用于说明ICMP报文的作用及格式,此外还有一个代码(Code)域用于详细说明某种ICMP报文的类型,所有数据都在ICMP头部后面。 [3] 

图2ICMP报文格式

图2ICMP报文格式

ARP 详情

(本段内容复制自:ARP协议图文详解,包含完整测试代码 ,仅做备份,最新内容请看原文)

2.ARP工作原理


图 1 ARP工作原理

2.1 局域网通信
局域网主机A和主机B通信,如果双方原来没有通信过,主机A只知道主机B的IP地址,不知道主机B的MAC地址,此时主机A和主机B无法正常通信。

局域网通信的基础通信双方都得知道对方的MAC地址,MAC地址通常是存储在主机的ARP表中。

此时主机A会尝试去获取主机B的MAC地址,获取的MAC地址的方式是发送ARP请求(以广播形式发送),主机B如果收到ARP请求会回复ARP响应给主机A。

主机A收到响应后会把主机B的IP和MAC地址记录在ARP表中,此时主机A能够发送数据给主机B,主机B因为收到主机A的ARP请求,通过ARP请求知道主机A的MAC地址,把主机A的IP和MAC地址记录在ARP表中,主机B也能给主机A发送数据,正阳主机A和主机B就能正常通信。

2.2 跨网段通信


主机A要访问一个公网主机,由于主机A和公网主机IP地址不再同一网段,此时需要用到路由功能,路由功能后续章节会详细介绍。

我们只要记住一个核心点,路由功能核心作用就是找到去往目的IP的网关IP地址。

网关IP地址必须和主机A处于同一局域网。找到网关IP地址的目的是为了获取网关MAC地址,获取到网关MAC地址,可以通过网关MAC地址把数据包发送给网关,让网关转发数据包至公网。

如果通过网关IP获取到网关MAC地址可以参考局域网通信。

跨网段通信流程:

步骤1:通过路由查找到网关IP地址

步骤2:如果不知道网关MAC地址,需要通过ARP协议获取到网关MAC地址。

步骤3:把网关MAC地址填入以太网报文头部,将数据包发给网关。

步骤4:网关转发数据包至公网。

3.ARP协议解析


3.1 ARP报文结构


图 2 ARP报文结构 

硬件类型:2字节,表示使用的网络类型,例如以太网、令牌环等。
协议类型:2字节,表示使用的协议类型,例如IPv4、IPX等。
硬件地址长度:1字节,表示硬件地址的长度,例如以太网地址长度为6字节。
协议地址长度:1字节,表示协议地址的长度,例如IPv4地址长度为4字节。
操作码:2字节,表示ARP请求(数值为1)或ARP响应(数值为2)。
发送方硬件地址:6字节,表示发送方的硬件地址。
发送方协议地址:4字节,表示发送方的协议地址。
目标硬件地址:6字节,表示目标的硬件地址。
目标协议地址:4字节,表示目标的协议地址。

3.2 ARP请求


图 3 ARP请求报文

 ARP请求各个字段如何填充如上图:

硬件类型:1,ARPHRD_ETHER类型

协议类型:0x8000,IPv4协议

硬件地址长度:6字节,MAC地址长度

协议地址长度:4字节,IP地址长度

操作码:1,ARP请求码

发送方MAC地址:14:23:0a:39:e3:75

发送方IP地址:192.168.1.1

目的MAC地址:00:00:00:00:00:00

目的IP地址:192.168.1.19

3.3 ARP响应


 图 4 ARP响应报文

 ARP响应各个字段如何填充如上图:

硬件类型:1,ARPHRD_ETHER类型

协议类型:0x8000,IPv4协议

硬件地址长度:6字节,MAC地址长度

协议地址长度:4字节,IP地址长度

操作码:2,ARP响应

发送方MAC地址:00:93:37:5b:d9:2f

发送方IP地址:192.168.1.19

目的MAC地址:14:23:0a:39:e3:75

目的IP地址:192.168.1.1

4.ARP攻击


 图 5 ARP攻击

ARP攻击(Address Resolution Protocol attack)是一种网络攻击方式,它利用ARP协议进行攻击,通过伪造或欺骗网络中的ARP响应包,将合法网络设备的IP地址映射到攻击者所控制的设备上,从而使攻击者可以窃取或篡改网络中的数据流量。

ARP攻击可以分为两种类型,一种是ARP欺骗(ARP Spoofing),另一种是ARP投毒(ARP Poisoning)。

4.1 ARP欺骗


攻击者会向网络中的设备发送伪造的ARP响应包,使其将攻击者所控制的设备的MAC地址当作目标设备的MAC地址,从而使攻击者可以拦截、篡改或窃取网络中的数据流量。

4.2 ARP投毒


攻击者会向网络中的设备发送大量的伪造ARP响应包,从而使网络设备的ARP缓存被攻击者所控制的设备所替换,这样一来,攻击者就可以直接访问目标设备,而无需再进行ARP欺骗攻击。

4.3 如何预防ARP攻击?


a.使用静态ARP表:将网络设备的IP地址和MAC地址的映射关系手动输入到静态ARP表中,可以防止攻击者篡改ARP响应包。

b.使用端口安全(Port Security):在交换机上配置端口安全,限制每个端口能够连接的MAC地址数量,可以有效地防止ARP攻击。

c.使用ARP防火墙(ARP Firewall):ARP防火墙可以监控网络流量中的ARP请求和响应包,并根据预设的规则进行过滤和阻断,从而有效地防止ARP攻击。

d.加密网络流量:使用加密技术(如SSL、TLS等)对网络流量进行加密,可以防止数据被窃听和篡改,从而有效地保护网络安全。

5.ARP编程示例


5.1 ARP请求示例代码

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/udp.h>
#include <netinet/ip.h>
#include <linux/in.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
 
uint8_t src_mac[ETH_ALEN] = {0x08,0x00,0x27,0x06,0x38,0xba};
uint8_t nexthop_mac[ETH_ALEN] = {0x08,0x00,0x27,0xc1,0xdf,0xea};
 
#define LOCAL_IP "192.168.1.18"
#define PEER_IP "192.168.1.19"
 
#define MAX_BUF_SIZE (2048)
#define IP_ADDR_LEN (4)
 
struct _arphdr {
        __be16          ar_hrd;
        __be16          ar_pro;
        unsigned char   ar_hln;
        unsigned char   ar_pln;
        __be16          ar_op;
 
        unsigned char           ar_sha[ETH_ALEN];
        unsigned char           ar_sip[4];
        unsigned char           ar_tha[ETH_ALEN];
        unsigned char           ar_tip[4];
};
 
uint32_t create_pack(char *buf) {
    struct ethhdr *eh = (struct ethhdr *)buf;
    memcpy(eh->h_dest, nexthop_mac, ETH_ALEN);
    memcpy(eh->h_source, src_mac, ETH_ALEN);
    eh->h_proto = htons(ETH_P_ARP);
 
    struct _arphdr *ah = (struct _arphdr *)(buf + ETH_HLEN);
        ah->ar_hrd = htons(ARPHRD_ETHER);
    ah->ar_pro = htons(ETH_P_IP);
        ah->ar_hln = ETH_ALEN;
    ah->ar_pln = IP_ADDR_LEN;
        ah->ar_op = htons(ARPOP_REQUEST);
 
    memcpy(ah->ar_sha, src_mac, ETH_ALEN);
    uint32_t src_ip = inet_addr(LOCAL_IP);
    memcpy(ah->ar_sip, &src_ip, IP_ADDR_LEN);
 
    memcpy(ah->ar_tha, nexthop_mac, ETH_ALEN);
    uint32_t peer_ip = inet_addr(PEER_IP);
    memcpy(ah->ar_tip, &peer_ip, IP_ADDR_LEN);
 
    return ETH_HLEN + sizeof(struct _arphdr);
}
 
int main(int argc , char *argv[]) {
    int ret;
    int sockfd;
    char send_buf[MAX_BUF_SIZE] = {0};
    struct sockaddr_ll local;
    struct sockaddr_ll peer;
 
    sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
    if (sockfd == -1) {
        perror("socket error");
        return -1;
    }
 
    bzero(&peer, sizeof(struct sockaddr_ll));
    peer.sll_family = PF_PACKET;
    peer.sll_protocol = htons(ETH_P_ARP);
    peer.sll_ifindex = 2;
    peer.sll_hatype = ARPHRD_ETHER;
    peer.sll_pkttype = PACKET_OTHERHOST;
    peer.sll_halen = ETH_ALEN;
    memcpy(peer.sll_addr, nexthop_mac, ETH_ALEN);
 
    uint32_t slen = create_pack(send_buf);
 
    while(1) {
        ret = sendto(sockfd, send_buf, slen, 0, (struct sockaddr *)&peer, sizeof(peer));
        if (ret <= 0) {
            printf("sendto ret:%d, errno:%d(%s)\n", ret, errno, strerror(errno));
            break;
        }
 
        sleep(1);
    }
 
    close(sockfd);
 
    return 0;
}



5.2 ARP响应示例代码

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/in.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
 
uint8_t src_mac[ETH_ALEN] = {0x08,0x00,0x27,0xc1,0xdf,0xea};
uint8_t nexthop_mac[ETH_ALEN] = {0x08,0x00,0x27,0x06,0x38,0xba};
#define LOCAL_IP "192.168.1.19"
#define PEER_IP "192.168.1.18"
 
#define IP_ADDR_LEN (4)
#define MAX_BUF_SIZE (2048)
 
struct _arphdr {
    __be16              ar_hrd;
    __be16              ar_pro;
    unsigned char       ar_hln;
    unsigned char       ar_pln;
    __be16              ar_op;
 
    unsigned char               ar_sha[ETH_ALEN];
    unsigned char               ar_sip[4];
    unsigned char               ar_tha[ETH_ALEN];
    unsigned char               ar_tip[4];
};
 
void print_arp(char *msg, const char *buf) {
    struct _arphdr *ah = (struct _arphdr *)(buf + ETH_HLEN);
    printf("%s\n"
            "硬件类型:%u\n"
            "协议类型:%u\n"
            "硬件地址长度:%u\n"
            "协议地址长度:%u\n"
            "操作码:%u\n"
            "发送方硬件地址:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n"
            "发送方协议地址:%02hx.%02hx.%02hx.%02hx\n"
            "接收方硬件地址:%02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n"
            "接收方协议地址:%02hx.%02hx.%02hx.%02hx\n",
            msg,
            ntohs(ah->ar_hrd),
            ntohs(ah->ar_pro),
            ah->ar_hln,
            ah->ar_pln,
            ntohs(ah->ar_op),
            ah->ar_sha[0], ah->ar_sha[1], ah->ar_sha[2], ah->ar_sha[3], ah->ar_sha[4], ah->ar_sha[5],
            ah->ar_sip[0], ah->ar_sip[1], ah->ar_sip[2], ah->ar_sip[3],
            ah->ar_tha[0], ah->ar_tha[1], ah->ar_tha[2], ah->ar_tha[3], ah->ar_tha[4], ah->ar_tha[5],
            ah->ar_tip[0], ah->ar_tip[1], ah->ar_tip[2], ah->ar_tip[3]);
}
 
int parse_pack(char *msg, char *buf) {
    print_arp(msg, buf);
    return 0;
}
 
uint32_t create_pack(char *sbuf, char *rbuf) {
    struct ethhdr *eh = (struct ethhdr *)sbuf;
    memcpy(eh->h_dest, nexthop_mac, ETH_ALEN);
    memcpy(eh->h_source, src_mac, ETH_ALEN);
    eh->h_proto = htons(ETH_P_ARP);
 
    struct _arphdr *rah = (struct _arphdr *)(rbuf + ETH_HLEN);
    struct _arphdr *ah = (struct _arphdr *)(sbuf + ETH_HLEN);
        ah->ar_hrd = htons(ARPHRD_ETHER);
    ah->ar_pro = htons(ETH_P_IP);
        ah->ar_hln = ETH_ALEN;
    ah->ar_pln = IP_ADDR_LEN;
        ah->ar_op = htons(ARPOP_REPLY);
 
    memcpy(ah->ar_sha, src_mac, ETH_ALEN);
    uint32_t src_ip = inet_addr(LOCAL_IP);
    memcpy(ah->ar_sip, &src_ip, IP_ADDR_LEN);
    memcpy(ah->ar_tha, rah->ar_sha, ETH_ALEN);
    memcpy(ah->ar_tip, rah->ar_sip, IP_ADDR_LEN);
 
    return ETH_HLEN + sizeof(struct _arphdr);
}
 
bool isvalid(const char *buf) {
    struct ethhdr *eh = (struct ethhdr *)buf;
    if (ntohs(eh->h_proto) == ETH_P_ARP) return true;
    return false;
}
 
int main(int argc , char *argv[]) {
    int ret;
    int sockfd;
    char send_buf[MAX_BUF_SIZE] = {0};
    char recv_buf[MAX_BUF_SIZE] = {0};
    struct sockaddr_ll peer;
    socklen_t peerlen = 0;
 
    sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
    if (sockfd == -1) {
        perror("socket error");
        return -1;
    }
 
    bzero(&peer, sizeof(struct sockaddr_ll));
    peer.sll_family = PF_PACKET;
    peer.sll_protocol = htons(ETH_P_ARP);
    peer.sll_ifindex = 2;
    peer.sll_hatype = ARPHRD_ETHER;
    peer.sll_pkttype = PACKET_OTHERHOST;
    peer.sll_halen = ETH_ALEN;
    memcpy(peer.sll_addr, nexthop_mac, ETH_ALEN);
 
    while(1) {
        memset(recv_buf, 0, MAX_BUF_SIZE);
        ret = recvfrom(sockfd, recv_buf, MAX_BUF_SIZE, 0, NULL, NULL);
        if (ret <= 0) {
            printf("recvfrom ret:%d error\n", ret);
            break;
        } else {
            bool bret = isvalid(recv_buf);
            printf("ret:%d, bret:%d\n", ret, bret);
            if (bret == false) {
                continue;
            }
            parse_pack("recv buf", recv_buf);
 
            memset(send_buf, 0, MAX_BUF_SIZE);
            int slen = create_pack(send_buf, recv_buf);
            slen += 18;
            printf("sendbuf len:%d\n", slen);
            ret = sendto(sockfd, send_buf, slen, 0, (struct sockaddr *)&peer, sizeof(peer));
            if (ret <= 0) {
                printf("sendto ret:%d error:%d(%s)\n", ret, errno, strerror(errno));
                break;
            }
        }
    }
 
    close(sockfd);
 
    return 0;
}


6.Linux ARP调试


6.1 查看ARP表
ip neigh
6.2 手动添加ARP表项
ip neigh add 192.168.1.19 dev enp0s3 lladdr 08:00:27:c1:df:ea
6.3 删除ARP表项
ip neigh del 192.168.1.19 dev enp0s3 lladdr 08:00:27:c1:df:ea

原文链接:https://blog.csdn.net/weixin_28673511/article/details/130795407

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值