Linux网络协议栈7--ipsec收发包流程

Linux网络协议栈7--ipsec收发包流程,第1张

流程路径:ip_rcv() -->ip_rcv_finish() -->ip_local_deliver() --> ip_local_deliver_finish()

解封侧一定是ip报文的目的端,ip_rcv_finish中查到的路由肯定是本机路由(RTCF_LOCAL),调用 ip_local_deliver 处理。

下面是贴的网上的一张图片。

ip_local_deliver_finish中 根据上次协议类型,调用对应的处理函数。inet_protos 中挂载了各类协议的 *** 作集,对于AH或者ESP来说,是xfrm4_rcv,对于ipsec nat-t情况下,是udp协议的处理函数udp_rcv,内部才是封装的ipsec报文(AH或者ESP)。

xfrm4_rcv -->xfrm4_rcv_spi -->xfrm4_rcv_encap -->xfrm_input

最终调用 xfrm_input 做收包解封装流程。

1、创建SKB的安全路径;

2、解析报文,获取daddr、spi,加上协议类型(esp、ah等),就可以查询到SA了,这些是SA的key,下面列出了一组linux ipsec的state(sa)和policy,方便一眼就能看到关键信息;

3、调用SA对应协议类型的input函数,解包,并返回更上层的协议类型,type可为esp,ah,ipcomp等。对应的处理函数esp_input、ah_input等;

4、解码完成后,再根据ipsec的模式做解封处理,常用的有隧道模式和传输模式。对应xfrm4_mode_tunnel_input 和 xfrm4_transport_inout,处理都比较简单,隧道模式去掉外层头,传输模式只是设置一些skb的数据。

5、协议类型可以多层封装,如ESP+AH,所以需要再次解析内存协议,如果还是AH、ESP、COMP,则解析新的spi,返回2,查询新的SA处理报文。

6、经过上面流程处理,漏出了用户数据报文(IP报文),根据ipsec模式:

流程路径如下图,这里以转发流程为例,本机发送的包主要流程类似。

转发流程:

ip_forward 函数中调用xfrm4_route_forward,这个函数:

1、解析用户报文,查找对应的Ipsec policy(__xfrm_policy_lookup);

2、再根据policy的模版tmpl查找对应最优的SA(xfrm_tmpl_resolve),模版的内容以及和SA的对应关系见上面贴出的ip xfrm命令显示;

3、最后根据SA生成安全路由,挂载再skb的dst上; 一条用户流可以声明多个安全策略(policy),所以会对应多个SA,每个SA处理会生成一个安全路由项struct dst_entry结构(xfrm_resolve_and_create_bundle),这些安全路由项通过 child 指针链接为一个链表,其成员 output挂载了不同安全协议的处理函数,这样就可以对数据包进行连续的处理,比如先压缩,再ESP封装,再AH封装。

安全路由链的最后一个路由项一定是普通IP路由项,因为最终报文都得走普通路由转发出去,如果是隧道模式,在tunnel output封装完完成ip头后还会再查一次路由挂载到安全路由链的最后一个。

注: SA安全联盟是IPsec的基础,也是IPsec的本质。 SA是通信对等体间对某些要素的约定,例如使用哪种协议、协议的 *** 作模式、加密算法、特定流中保护数据的共享密钥以及SA的生存周期等。

然后,经过FORWARD点后,调用ip_forward_finish()-->dst_output,最终调用skb_dst(skb)->output(skb),此时挂载的xfrm4_output

本机发送流程简单记录一下,和转发流程殊途同归:

查询安全路由: ip_queue_xmit -->ip_route_output_flow -->__xfrm_lookup

封装发送:ip_queue_xmit -->ip_local_out -->dst_output -->xfrm4_output

注:

1). 无论转发还是本地发送,在查询安全路由之前都会查一次普通路由,如果查不到,报文丢弃,但这条路由不一定需要指向真实的下一跳的出接口,只要能匹配到报文DIP即可,如配置一跳其它接口的defualt。

2). strongswan是一款用的比较多的ipsec开源软件,协商完成后可以看到其创建了220 table,经常有人问里面的路由有啥用、为什么有时有有时无。这里做个测试记录: 1、220中貌似只有在tunnel模式且感兴趣流是本机发起(本机配置感兴趣流IP地址)的时候才会配置感兴趣流相关的路由,路由指定了source;2、不配置也没有关系,如1)中所说,只要存在感兴趣流的路由即可,只不过ping的时候需要指定source,否者可能匹配不到感兴趣流。所以感觉220这个表一是为了保证

ipsec封装发送流程:

xfrm4_output-->xfrm4_output_finish-->xfrm_output-->xfrm_output2-->xfrm_output_resume-->xfrm_output_one

xfrm4_output 函数先过POSTROUTING点,在封装之前可以先做SNAT。后面则调用xfrm_output_resume-->xfrm_output_one 做IPSEC封装最终走普通路由走IP发送。

贴一些网上的几张数据结构图

1、安全路由

2、策略相关协议处理结构

3、状态相关协议处理结构

Linux是一套免费使用和自由传播的类Unix *** 作系统,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的 *** 作系统。伴随着互联网的发展,Linux得到了来自全世界软件爱好者、组织、公司的支持。它除了在服务器 *** 作系统方面保持着强劲的发展势头以外,在个人电脑、嵌入式系统上都有着长足的进步。使用者不仅可以直观地获取该 *** 作系统的实现机制,而且可以根据自身的需要来修改完善这个 *** 作系统,使其最大化地适应用户的需要。

Linux不仅系统性能稳定,而且是开源软件。其核心防火墙组件性能高效、配置简单,保证了系统的安全。在很多企业网络中,为了追求速度和安全,Linux *** 作系统不仅仅是被网络运维人员当作服务器使用,Linux既可以当作服务器,又可以当作网络防火墙是Linux的 一大亮点。

Linux与其他 *** 作系统相比 ,具有开放源码、没有版权、技术社区用户多等特点 ,开放源码使得用户可以自由裁剪,灵活性高,功能强大,成本低。尤其系统中内嵌网络协议栈 ,经过适当的配置就可实现路由器的功能。这些特点使得Linux成为开发路由交换设备的理想开发平台。

socket - Linux 套接字接口

本手册页描述了 Linux 网络套接字层用户接口。 套接字是用户进程和内核中网络协议栈之间的统一接口。 协议模块分为协议族(protocol families)(如 AF_INET、AF_IPX 和 AF_PACKET)和套接字类型(socket types)(如 SOCK_STREAM 或 SOCK_DGRAM)。 有关families和types的更多信息,请参阅 socket(2) 。

用户进程使用这些函数来发送或接收数据包以及执行其他套接字 *** 作。 有关更多信息,请参阅它们各自的手册页。

socket(2) 创建套接字,connect(2) 将套接字连接到远程套接字地址,bind(2) 函数将套接字绑定到本地套接字地址,listen(2) 告诉套接字应接受新连接, accept(2) 用于获取具有新传入连接的新套接字。 socketpair(2) 返回两个连接的匿名套接字(仅为少数本地families如 AF_UNIX 实现)

send(2)、sendto(2) 和sendmsg(2) 通过套接字发送数据,而recv(2)、recvfrom(2)、recvmsg(2) 从套接字接收数据。 poll(2) 和 select(2) 等待数据到达或准备好发送数据。 此外,还可以使用 write(2)、writev(2)、sendfile(2)、read(2) 和 readv(2) 等标准 I/O *** 作来读取和写入数据。

getsockname(2) 返回本地套接字地址, getpeername(2) 返回远程套接字地址。 getsockopt(2) 和 setsockopt(2) 用于设置或获取套接字层或协议选项。 ioctl(2) 可用于设置或读取一些其他选项。

close(2) 用于关闭套接字。 shutdown(2) 关闭全双工套接字连接的一部分。

套接字不支持使用非零位置查找或调用 pread(2) 或 pwrite(2)。

通过使用 fcntl(2) 在套接字文件描述符上设置 O_NONBLOCK 标志,可以在套接字上执行非阻塞 I/O。 然后所有会阻塞的 *** 作(通常)将返回 EAGAIN( *** 作应稍后重试); connect(2) 将返回 EINPROGRESS 错误。 然后用户可以通过 poll(2) 或 select(2) 等待各种事件。

如果不使用poll(2) 和 select(2) ,还让内核通过 SIGIO 信号通知应用程序有关事件的信息。 为此,必须通过 fcntl(2) 在套接字文件描述符上设置 O_ASYNC 标志,并且必须通过 sigaction(2) 安装有效的 SIGIO 信号处理程序。 请参阅下面的信号讨论。

每个套接字域(families)都有自己的套接字地址格式,具有特定于域的地址结构。 这些结构的首字段都是整数类型的“家族”字段(类型为 sa_family_t),即指出自己的套接字域或者说是protocol families。 这允许对所有套接字域可以使用统一的系统调用(例如,connect(2)、bind(2)、accept(2)、getsockname(2)、getpeername(2)),并通过套接字地址来确定特定的域。

为了允许将任何类型的套接字地址传递给套接字 API 中的接口,定义了类型 struct sockaddr。 这种类型的目的纯粹是为了允许将特定于域的套接字地址类型转换为“通用”类型,以避免编译器在调用套接字 API 时发出有关类型不匹配的警告。

struct sockaddr 以及在AF_INET常用的地址结构struct sockaddr_in如下所示,sockaddr_in.sin_zero是占位符:

此外,套接字 API 提供了数据类型 struct sockaddr_storage。 这种类型适合容纳所有支持的特定于域的套接字地址结构; 它足够大并且正确对齐。 (特别是它足够大,可以容纳 IPv6 套接字地址。)同struct sockaddr一样,该结构体包括以下字段,可用于标识实际存储在结构体中的套接字地址的类型: sa_family_t ss_family

sockaddr_storage 结构在必须以通用方式处理套接字地址的程序中很有用(例如,必须同时处理 IPv4 和 IPv6 套接字地址的程序)。

下面列出的套接字选项可以使用setsockopt(2) 设置并使用getsockopt(2) 读取。

当写入已关闭(由本地或远程端)的面向连接的套接字时,SIGPIPE 被发送到写入进程并返回 EPIPE。 当写调用指定 MSG_NOSIGNAL 标志时,不发送信号。

当使用 FIOSETOWN fcntl(2) 或 SIOCSPGRP ioctl(2) 请求时,会在 I/O 事件发生时发送 SIGIO。 可以在信号处理程序中使用 poll(2) 或 select(2) 来找出事件发生在哪个套接字上。 另一种方法(在 Linux 2.2 中)是使用 F_SETSIG fcntl(2) 设置实时信号; 实时信号的处理程序将使用其 siginfo_t 的 si_fd 字段中的文件描述符调用。 有关更多信息,请参阅 fcntl(2)。

在某些情况下(例如,多个进程访问单个套接字),当进程对信号做出反应时,导致 SIGIO 的条件可能已经消失。 如果发生这种情况,进程应该再次等待,因为 Linux 稍后会重新发送信号。

核心套接字网络参数可以通过目录 /proc/sys/net/core/ 中的文件访问。

These operations can be accessed using ioctl(2):

error = ioctl(ip_socket, ioctl_type, &value_result)

Valid fcntl(2) operations:

Linux assumes that half of the send/receive buffer is used for internal kernel structuresthus the values in the corresponding /proc files are twice what can be observed on the wire. Linux will allow port reuse only with the SO_REUSEADDR option when this option was set both in the previous program that performed a bind(2) to the port and in the program that wants to reuse the port. This differs from some implementations (e.g., FreeBSD) where only the later program needs to set the SO_REUSEADDR option. Typically this difference is invisible, since, for example, a server program is designed to always set this option.


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/6077842.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-14
下一篇 2023-03-14

发表评论

登录后才能评论

评论列表(0条)

保存