OSPF(开放最短路径优先)是一种用于自治系统(AS)内部的路由协议,它是基于链路状态算法的。OSPF的设计目的是为了提供一种可扩展、快速收敛和高效的路由解决方案。
OSPF概念和特点
自治系统(AS):一个AS是由一组通过统一路由策略或协议互相交换路由信息的路由器组成的网络。
链路状态:OSPF通过链路状态数据库(LSDB)来维护网络的拓扑结构。每个路由器会记录它与网络中其他路由器的连接状态,包括接口、成本和其他参数。
路由器ID(Router ID):每个OSPF路由器需要有一个唯一的32位标识符,用于在LSDB中表示自己。路由器ID通常配置为路由器的某个接口的IP地址。
OSPF区域:为了提高可扩展性和减少LSDB的大小,OSPF将网络划分为多个区域。每个区域有一个唯一的区域ID,并且只包含该区域内的链路状态信息。
链路状态通告(LSA):路由器通过发送LSA来通知其他路由器它所知道的链路状态变化。
洪泛(Flooding):OSPF使用洪泛机制来确保LSA能够被传递给网络中的所有路由器。
数据库描述(DBD):路由器之间通过DBD包来交换LSDB的概要信息。
选举:在OSPF网络中,会选举出区域内的主路由器(DR)和备份路由器(BDR),以及每个接口的指定路由器(DR)和备份指定路由器(BDR)。
无环路设计:OSPF通过SPF算法确保没有环路发生,从而避免路由循环。
快速收敛:OSPF在网络拓扑发生变化时能够快速地重新计算路由,收敛速度比距离矢量协议快。
支持CIDR:OSPF支持无类域内路由(CIDR),能够处理大量子网和聚合路由。
支持VLSM:OSPF支持可变长子网掩码(VLSM),允许在同一网络中使用不同长度的子网掩码。
组播通信:OSPF使用组播地址224.0.0.5(所有OSPF路由器)和224.0.0.6(OSPF DR和BDR)来进行路由器之间的通信。
安全性:OSPF提供了一系列安全特性,如接口认证和Hello包的序列号验证,以防止未授权的访问和路由信息的伪造。
灵活的网络结构:OSPF能够适应多种网络结构,包括点到点、广播、非广播和点到多点网络。
扩展性:OSPF通过区域的概念来提高可扩展性,使得大型网络能够更加高效地运行。
OSPF的这些概念和特点使其成为互联网和私有网络中广泛使用的一种内部网关协议。
OSPF工作过程的简要概述
OSPF(开放最短路径优先)协议的工作过程是一个复杂的过程,涉及多个步骤和机制。以下是OSPF工作过程的简要概述:
1.启动和配置:
2.邻居发现和建立:
3.建立邻接关系:
4.交换链路状态信息:
5.维护LSDB:
6.计算最短路径:
7.更新路由表:
8.路由表维护和更新:
9.状态监控和故障处理:
OSPF协议的工作过程确保了网络的路由信息能够及时更新,并快速响应网络拓扑的变化。这种协议的设计使得OSPF能够高效地支持大型和复杂的数据中心网络。
OSPF的网络类型有哪些
OSPF(开放最短路径优先)协议支持多种网络类型,以适应不同的网络环境和需求。以下是OSPF的主要网络类型:
1.点对点(Point-to-Point, P2P):
2.广播(Broadcast):
3.非广播多路访问(Non-Broadcast, NBMA):
NBMA网络是指不支持广播的 多路访问网络,如帧中继、ATM等。
在NBMA网络中,路由器无法通过发送Hello包来发现邻居,因此需要手动配置邻居关系。
NBMA网络中使用单播方式发送协议报文。
4.点到多点(Point-to-Multipoint, P2MP):
点到多点网络是指一个接口通过点到多点的网络与多台路由器相连。
点到多点网络没有专门的DR和BDR选举机制。
这种网络类型通常用于连接多个客户端的路由器,如通过光纤通道或无线连接。
5.多路访问点到多点(Multipoint-to-Multipoint, MP2MP):
多路访问点到多点网络是指多个路由器通过点到多点的连接相互连接。
这种网络类型没有DR和BDR的选举,所有路由器都是平等的。
MP2MP网络通常用于大型网络,如通过卫星连接的多个分支机构。
6.环路back(Loopback):
7.虚拟链路(Virtual Link):
虚拟链路是一种特殊的网络类型,用于在非直接连接的OSPF区域之间建立逻辑连接。
它允许跨区域的路由,使得不同区域之间的路由器仿佛直接相连。
8.点对多点非广播(Point-to-Multipoint Non-Broadcast, P2MP-NBMA):
P2MP-NBMA网络是一种特殊的点到多点网络,它在NBMA网络上实现了点到多点的功能。
这种网络类型需要手动指定邻居,并使用单播方式发送协议报文。
每种网络类型都有其特定的应用场景和配置要求,OSPF通过这些网络类型的支持,能够适应各种不同的网络架构和需求。
OSPF报头格式
OSPF(开放最短路径优先)协议使用IP协议报文来传输其协议数据,这些数据被封装在不同的OSPF报文类型中。OSPF报文直接封装在IP协议数据包中,IP协议号为89。OSPF报文头部格式对所有报文类型都是相同的,但每种报文类型携带的数据内容不同。以下是OSPF报文头部的详细格式:
占1个字节,指出所采用的OSPF协议版本号。目前最高版本为OSPF v4。
占1个字节,标识对应报文的类型。OSPF有5种报文类型:Hello报文、DD(数据库描述)报文、LSR(链路状态请求)报文、LSU(链路状态更新)报文和LSAck(链路状态应答)报文。
占1个字节,用于进一步区分报文类型。例如,在Hello报文中,Code字段用于指示Hello报文是用于邻居发现、确认邻居关系还是用于发送路由器ID。
占2个字节。它是指整个报文(包括OSPF报头和后面各报文内容部分)的字节长度。
占4个字节,指定发送报文的源路由器ID。
占4个字节,指定发送报文的路由器所对应的OSPF区域号。
占2个字节,是对整个报文(包括OSPF报头和各报文具体内容,但不包括认证字段)的校验和。用于确保报文在传输过程中的完整性。
占2个字节,表示OSPF验证类型。0表示不验证,1表示简单认证,2表示MD5认证。
根据验证类型而定。验证类型为0时未定义,验证类型为1时该字段是密码信息,类型为2时该字段包括Key ID、MD5验证数据长度和序列号的信息。MD5验证数据添加在OSPF报文后面,不包含在Authentication字段中。
除了头部信息,不同类型的OSPF报文还包含特定的数据字段。例如,Hello报文包含用于邻居发现和维护邻居关系的信息,如Hello间隔、Dead间隔等;DD报文用于在邻居之间同步数据库摘要信息;LSR报文用于请求特定类型的LSA;LSU报文用于发送完整的LSA信息;LSAck报文用于对收到的LSA进行确认。
OSPF报文的详细格式和内容可以参考OSPF协议的官方文档或相关技术标准。
OSPF协议中常用的一些数据包类型
1.Hello包(Hello Packet):
2.数据库描述包(Database Description Packet,DBD):
用于在邻居之间同步数据库的概要信息。
包含本地OSPF数据库中LSA的类型、ID和序列号。
DBD包是初始同步过程的一部分,用于确定需要交换哪些具体的LSA。
3.链路状态请求包(Link State Request Packet,LSR):
用于请求对端邻居的特定LSA。
当一个路由器需要了解它尚未收到的LSA时,它会发送LSR包。
LSR包包含请求的LSA的ID和广告路由器的信息。
4.链路状态更新包(Link State Update Packet,LSU):
用于携带完整的LSA信息。
当路由器收到新的LSA或者当LSA的内容发生变化时,它会发送LSU包。
LSU包中包含LSA的具体信息,如链路成本、出口接口等。
5.链路状态确认包(Link State Acknowledgment Packet,LSACK):
用于确认收到的LSU包。
LSACK包包含一个或多个LSA的序列号,表示确认这些LSA已经正确接收。
这有助于确保LSA的可靠传输。
除了上述五种主要类型的包,OSPF还定义了其他一些数据包类型,例如:
提供比基本Hello包更多的信息,如路由器的优先级、DR和BDR的选举状态等。
在某些情况下,LSU包可能被LSP替代,LSP包含一个或多个LSA的集合。
用于在路由器重启过程中维护网络的连通性。
OSPF中LSA的一些基本概念
在OSPF(开放最短路径优先)协议中,链路状态通告(Link State Advertisement,LSA)是核心概念之一。LSAs是OSPF路由器用来描述其连接链路状态的数据包,它们包含了路由器接口的详细信息,如接口类型、成本、邻居路由器等。LSAs是OSPF构建链路状态数据库(LSDB)的基础,从而使得OSPF能够计算出网络中的最短路径。
以下是OSPF中LSA的一些基本概念:
1.LSA类型:
2.LSA的传播:
3.LSA的寿命:
4.LSA的同步:
5.LSA的可靠性:
6.LSA的更新:
LSA是OSPF协议能够高效计算路由的关键,因为它们提供了网络拓扑的详细信息,使得OSPF可以采用Dijkstra算法来计算最短路径树。每种类型的LSA都有其特定的用途和格式,确保了OSPF网络的可靠性和灵活性。
OSPF路径选择的基本过程
路径选择是基于路由器之间的链路状态信息来确定的。OSPF使用最短路径优先(SPF)算法,该算法由Dijkstra提出,用于在复杂的网络中选择数据包传输的最短路径。以下是OSPF路径选择的基本过程:
1.收集链路状态信息:
2.构建链路状态通告(LSA):
3.交换链路状态信息:
路由器通过交换LSU包来更新它们之间的链路状态信息。
这确保了所有路由器都有一个最新的网络拓扑视图。
4.运行最短路径优先(SPF)算法:
5.维护和更新路径:
6.路径选择依据:
7.类型1的外部路由和类型2的外部路由:
OSPF的路径选择过程确保了网络数据的传输遵循最短路径,从而优化了网络性能,降低了延迟。此外,OSPF的快速收敛特性使得网络在发生变化时能够迅速适应,保证网络的稳定性和可靠性
OSPF协议解析及相关技术探索(C/C++代码实现)
...
typedef struct ospf2_header{
u_int8_t version;
u_int8_t type;
u_int16_t length;
u_int32_t router_id;
u_int32_t area_id;
u_int16_t checksum;
u_int16_t auth_type;
u_int8_t auth_data[8];
} ospf2_header;
// type 1 - Hello
typedef struct ospf2_hello{
u_int32_t mask;
u_int16_t hello_interval;
u_int8_t opts;
u_int8_t rtr_priority;
u_int32_t rtr_dead_interval;
u_int32_t d_rtr;
u_int32_t bd_rtr;
} ospf2_hello;
// type 2 - Database Description
typedef struct ospf2_db_dscrp_hdr{
u_int16_t iface_mtu;
u_int8_t opts;
u_int8_t bits;
u_int32_t dd_seq_num;
} ospf2_db_dscrp_hdr;
// type 3 - LSA Request
typedef struct ospf2_ls_req_hdr{
u_int32_t type;
u_int32_t ls_id;
u_int32_t adv_rtr;
} ospf2_ls_req_hdr;
// type 4 - LSA Update
typedef struct ospf2_ls_upd_hdr {
u_int32_t num_lsa;
} ospf2_ls_upd_hdr;
// LSA Router
typedef struct ospf2_lsa_rtr {
u_int8_t flags;
u_int8_t dummy;
u_int16_t nlinks;
} ospf2_lsa_rtr;
// LSA Router Link
typedef struct ospf2_lsa_rtr_link {
u_int32_t id;
u_int32_t data;
u_int8_t type;
u_int8_t num_tos;
u_int16_t metric;
} ospf2_lsa_rtr_link;
// LSA Network Header
typedef struct ospf2_lsa_net {
u_int32_t mask;
} ospf2_lsa_net;
// LSA Network Attached
typedef struct ospf2_lsa_net_att {
u_int32_t att_rtr;
} ospf2_lsa_net_att;
// LSA Network Link
typedef struct ospf2_lsa_net_link {
u_int32_t att_rtr;
} ospf2_lsa_net_link;
// LSA Summary
typedef struct ospf2_lsa_sum {
u_int32_t mask;
u_int32_t metric;
} ospf2_lsa_sum;
// LSA AS-External
typedef struct ospf2_lsa_asext {
u_int32_t mask;
u_int32_t metric;
u_int32_t fw_addr;
u_int32_t ext_tag;
} ospf2_lsa_asext;
// LSA Header
typedef struct ospf2_lsa_hdr {
u_int16_t age;
u_int8_t opts;
u_int8_t type;
u_int32_t ls_id;
u_int32_t adv_rtr;
u_int32_t seq_num;
u_int16_t ls_chksum;
u_int16_t len;
} ospf2_lsa_hdr;
// LLS Data Block
typedef struct ospf2_lls_data_block {
u_int16_t checksum;
u_int16_t data_length;
} ospf2_lls_data_block;
typedef struct ospf2_lsa {
struct ospf2_lsa_hdr hdr;
union {
struct ospf2_lsa_rtr rtr;
struct ospf2_lsa_net net;
struct ospf2_lsa_sum sum;
struct ospf2_lsa_asext asext;
} data;
} ospf2_lsa;
//-------------
typedef struct ospf3_header{
u_int8_t version;
u_int8_t type;
u_int16_t length;
u_int32_t router_id;
u_int32_t area_id;
u_int16_t checksum;
u_int8_t instance_id;
u_int8_t dummy;
} ospf3_header;
typedef struct ospf3_hello{
u_int32_t interface_id;
u_int32_t opts;
u_int16_t hello_interval;
u_int16_t rtr_dead_interval;
u_int32_t d_rtr;
u_int32_t bd_rtr;
u_int32_t neighbor_id;
} ospf3_hello;
...
...
typedef struct ospf3_lsa_hdr {
u_int16_t age;
u_int16_t type;
u_int32_t ls_id;
u_int32_t adv_rtr;
u_int32_t seq_num;
u_int16_t ls_chksum;
u_int16_t len;
} ospf3_lsa_hdr;
// Router-LSA header
typedef struct ospf3_lsa_rtr_hdr {
u_int32_t opts;
} ospf3_lsa_rtr_hdr;
// Router-LSA
typedef struct ospf3_lsa_rtr {
u_int8_t type;
u_int8_t dummy;
u_int16_t metric;
u_int32_t if_id;
u_int32_t n_if_id;
u_int32_t n_rtr_id;
} ospf3_lsa_rtr;
// Network-LSA Header
typedef struct ospf3_lsa_net_hdr {
u_int32_t opts;
} ospf3_lsa_net_hdr;
// Network-LSA
typedef struct ospf3_lsa_net {
u_int32_t att_rtr;
} ospf3_lsa_net;
// Inter-Area-Prefix-LSA
typedef struct ospf3_lsa_inter_area_prefix_hdr {
u_int32_t metric;
u_int8_t p_len;
u_int8_t p_opts;
u_int16_t dummy;
} ospf3_inter_area_prefix_hdr;
// Inter-Area-Router-LSA
typedef struct ospf3_lsa_inter_area_rtr {
u_int32_t opts;
u_int32_t metric;
u_int32_t dst_rtr_id;
} ospf3_lsa_inter_area_rtr;
// AS-External-LSA
typedef struct ospf3_lsa_asext_hdr {
u_int32_t metric;
u_int8_t p_len;
u_int8_t p_opts;
u_int16_t ref_ls;
} ospf3_lsa_asext_hdr;
// Link-LSA Header
typedef struct ospf3_lsa_link_hdr {
u_int32_t opts;
struct in6_addr addr;
u_int32_t num_pref;
} ospf3_lsa_link_hdr;
// Link-LSA
typedef struct ospf3_lsa_link {
u_int8_t p_len;
u_int8_t p_opts;
u_int16_t dummy;
} ospf3_lsa_link;
typedef struct ospf3_lsa_intra_area_prefix_hdr{
u_int16_t num_pref;
u_int16_t type;
u_int32_t ref_ls_id;
u_int32_t ref_adv_rtr;
} ospf3_lsa_intra_area_prefix_hdr;
// Intra-Area-Prefix LSA
typedef struct ospf3_lsa_intra_area_prefix {
u_int8_t p_len;
u_int8_t p_opts;
u_int16_t metric;
} ospf3_lsa_intra_area_prefix;
// OSPF3 LSA
typedef struct ospf3_lsa {
struct ospf3_lsa_hdr hdr;
union{
struct ospf3_lsa_rtr_hdr rtr_hdr; // jak se to tam zobrazuje hdr+rtr?
struct ospf3_lsa_net net;
struct ospf3_lsa_inter_area_prefix_hdr ia_p_hdr;
struct ospf3_lsa_inter_area_rtr ia_rtr;
struct ospf3_lsa_asext_hdr asext_hdr;
struct ospf3_lsa_link_hdr link_hdr;
struct ospf3_lsa_intra_area_prefix_hdr intra_p_hdr;
} data;
} ospf3_lsa;
//------
struct ospf3_db_item{
struct ospf3_lsa* lsa;
struct ospf3_db_item* next;
} ospf3_db_item;
struct ospf3_db_area{
// area id
u_int32_t area_id;
struct ospf3_db_item* rtr_ls;
struct ospf3_db_item* net_ls;
struct ospf3_db_item* ia_p_ls;
struct ospf3_db_item* ia_rtr_ls;
struct ospf3_db_item* asext_ls;
struct ospf3_db_item* link_ls;
struct ospf3_db_item* intra_p_ls;
struct ospf3_db_area* next;
} ospf3_db_area;
struct ospf3_db_instance{
u_int32_t instance_id;
struct ospf3_db_area* area_list;
struct ospf3_db_instance* next;
} ospf3_db_instance;
struct ospf3_db {
// id routeru
u_int32_t router_id;
// seznam instanci OSPFv3 na danem routeru
struct ospf3_db_instance* instance_list;
// ukazatel na dalsi databazi
struct ospf3_db* next;
} ospf3_db;
int main(int argc, char *argv[])
{
...
while((c = getopt(argc, argv, "hi:")) != -1){
switch(c){
case 'h':
print_help();
return(EXIT_SUCCESS);
break;
case 'i':
dev = optarg;
#ifdef DEBUG
printf("dev: %s", dev);
#endif
break;
default:
print_help();
return(EXIT_FAILURE);
break;
}
}
if(pcap_lookupnet(dev, &net, &mask, errbuf) == -1){
#ifdef DEBUG
fprintf(ERROUT, "Can't get netmask for device %s, %s\n", dev, errbuf);
#endif
net = 0;
mask = 0;
//return ERRDEV;
}
...
handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
if(handle == NULL){
fprintf(ERROUT, "Couldn't open device %s: %s\n", dev, errbuf);
return(EXIT_FAILURE);
}
if(pcap_datalink(handle) != DLT_EN10MB){
fprintf(ERROUT, "%s is not an Ethernet interface\n", dev);
exit(EXIT_FAILURE);
}
if(pcap_compile(handle, &fp, filter_exp, 0, net) == -1){
fprintf(ERROUT, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
return(EXIT_FAILURE);
}
if(pcap_setfilter(handle, &fp) == -1){
fprintf(ERROUT, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
return(EXIT_FAILURE);
}
pcap_loop(handle, NUMPACKETS, got_packet, NULL);
pcap_freecode(&fp);
pcap_close(handle);
return(EXIT_SUCCESS);
}
If you need the complete source code, please add the WeChat number (c17865354792)
使用Wireshark可以捕获网络中传输的OSPF数据包,包括Hello包、数据库描述包(DBD)、链路状态请求包(LSR)、链路状态更新包(LSU)和链路状态确认包(LSAck)。
总结
OSPF协议作为互联网中重要的路由协议,其安全运行对整个互联网的稳定性至关重要。通过使用网络嗅探工具,如Wireshark,安全专家能够监控和分析OSPF协议的运行状态,及时发现并处理可能的安全威胁,保证网络的安全和稳定。
参考:RFC 2328、RFC 2740、、RFC 5340、RFC 826、RFC 1122、RFC 1191、RFC 4632
Welcome to follow WeChat official account【程序猿编码】