《UNIX 网络编程-卷1》阅读笔记20: 密钥管理套接字

作者: andylin02
学习章节: 第十九章 密钥管理套接字
关键词: PF_KEY, IPsec, 安全联盟数据库(SADB), 安全策略数据库(SPD), sadb_msg, 消息扩展, 内核-用户空间通信, Linux Netlink, XFRM


一、章节概述

1.1 本章焦点

第十九章是UNP第三版新增的重要章节,专门介绍密钥管理套接字(Key Management Sockets)。随着IP安全体系结构(IPsec)的引入,密钥加密和认证密钥的管理迫切需要一套标准化的通信机制。RFC 2367定义了一套通用的密钥管理API,不仅可用于IPsec,还可用于其他网络安全服务。

本章的核心任务是:理解PF_KEY协议族的定位和作用,掌握密钥管理消息的结构与类型,并通过完整示例理解密钥管理套接字在IPsec安全联盟(SA)管理中的应用

本章创建了一个新的协议族——PF_KEY域。与第18章的路由套接字类似,密钥管理域中只支持原始套接字这一种套接字类型。

💡 本章核心价值:读完第十九章,你将能够——

  • 理解密钥管理套接字在IPsec体系中的定位与作用
  • 熟悉密钥管理消息的格式与扩展机制
  • 掌握SADB_MSG结构体的各个字段及其含义
  • 了解11种标准消息类型和多种扩展类型
  • 理解SADB与SPD在IPsec安全中的角色
  • 知道Linux系统中PF_KEY已被Netlink XFRM替代

二、密钥管理套接字概述

2.1 什么是密钥管理套接字

密钥管理套接字(PF_KEY套接字)是RFC 2367定义的一套用于密钥管理的API,提供了一种在用户空间密钥管理应用和内核密钥管理子系统之间进行通信的标准机制。

安全联盟数据库(SADB) :SADB是内核中维护安全联盟信息的核心数据结构,其中存储了用于保护入站和出站数据包的各类安全联盟(SA),每个SA定义了特定数据流使用的安全协议(如AH或ESP)、算法、密钥以及SA的生存期等参数。

密钥管理应用通过PF_KEY套接字与内核通信,实现SADB的管理维护。这类似于路由套接字机制(第18章)。

2.2 PF_KEY与AF_KEY

在大多数系统上,常值AF_KEY被定义成与PF_KEY有相同的值,但RFC 2367明确要求密钥管理套接字必须使用PF_KEY常值。使用AF_KEY作为协议族的名称在本书第3版中被视为错误,阅读时需要注意这一细节。

2.3 套接字创建

#include <sys/types.h>
#include <sys/socket.h>
#include <net/pfkeyv2.h>

int sockfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);

参数说明

参数说明
domainPF_KEY密钥管理协议族,使用PF_KEY常值(RFC 2367要求)
typeSOCK_RAW密钥管理域中只支持原始套接字
protocolPF_KEY_V2协议版本,当前为V2

2.4 访问权限

只有超级用户(root) 才能访问SADB。一个系统上可以同时打开多个密钥套接字。操作系统的密钥管理子系统也可能自发地(spontaneously)向监听进程发送pf_key消息,例如请求为外出数据报安装新的SA,或报告现有SA的到期事件。

2.5 密钥管理套接字在IPsec体系中的位置图

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                    密钥管理套接字在IPsec体系中的位置                                   │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                     │
│  用户空间                                                                           │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │                     IKE守护进程(如racoon、strongSwan)                       │   │
│  │                              │                                             │   │
│  │                              │ PF_KEY套接字                                 │   │
│  │                              ▼                                             │   │
│  │  ┌─────────────────────────────────────────────────────────────────────┐   │   │
│  │  │                  PF_KEY消息(sadb_msg + 扩展)                       │   │   │
│  │  └─────────────────────────────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                           │                                         │
│  ─────────────────────────────────────────┼─────────────────────────────────────────│
│                                           ▼                                         │
│  内核空间                                                                           │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │                    PF_KEY协议族(PF_KEY Domain)                            │   │
│  │                              │                                             │   │
│  │                              ▼                                             │   │
│  │  ┌─────────────────────────────────────────────────────────────────────┐   │   │
│  │  │          SADB(安全联盟数据库)          SPD(安全策略数据库)        │   │   │
│  │  │    ┌─────────┐ ┌─────────┐ ┌─────────┐    ┌─────────┐ ┌─────────┐ │   │   │
│  │  │    │   SA1   │ │   SA2   │ │   ...   │    │ 策略1   │ │ 策略2   │ │   │   │
│  │  │    │ SPI/算法│ │ SPI/算法│ │         │    │选择符/动作│ │选择符/动作│ │   │   │
│  │  │    │ 密钥/生 │ │ 密钥/生 │ │         │    │         │ │         │ │   │   │
│  │  │    │ 存期    │ │ 存期    │ │         │    │         │ │         │ │   │   │
│  │  │    └─────────┘ └─────────┘ └─────────┘    └─────────┘ └─────────┘ │   │   │
│  │  └─────────────────────────────────────────────────────────────────────┘   │   │
│  │                              │                                             │   │
│  │                              ▼                                             │   │
│  │                    IPsec协议栈(AH/ESP处理)                                │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                     │
│  💡 核心交互模式:用户空间IKE守护进程 ↔ PF_KEY套接字 ↔ 内核SADB/SPD                    │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

三、密钥管理消息结构

3.1 消息的基本构成

密钥管理套接字上交换的所有消息均由一个小的基包头零个或多个扩展消息构成。基包头和所有扩展都必须8字节对齐

消息长度以8字节为单位存储在sadb_msg_len字段中,这保证了整个消息结构的对齐要求。消息的构造和解析通常使用<net/pfkeyv2.h>头文件中定义的宏来进行内存对齐计算。

3.2 基包头结构(sadb_msg)

所有密钥管理消息都以sadb_msg结构开头,它是解析消息的入口点:

struct sadb_msg {
    uint8_t  sadb_msg_version;   /* 协议版本,设置为PF_KEY_V2 */
    uint8_t  sadb_msg_type;      /* 消息类型 */
    uint8_t  sadb_msg_errno;     /* 错误指示 */
    uint8_t  sadb_msg_satype;    /* SA类型(安全服务类型) */
    uint16_t sadb_msg_len;       /* 长度(单位:8字节) */
    uint16_t sadb_msg_reserved;  /* 保留字段,发送时置0 */
    uint32_t sadb_msg_seq;       /* 序列号,用于匹配请求与应答 */
    uint32_t sadb_msg_pid;       /* 源或目的进程ID */
};

关键字段详解

字段说明
sadb_msg_version必须设置为PF_KEY_V2,用于版本兼容性检查
sadb_msg_type消息类型,参见下表。大多数类型可在用户态和内核间双向传递
sadb_msg_errno指示消息失败的原因,0表示成功
sadb_msg_satype指明SA的安全服务类型(如SADB_SATYPE_AHSADB_SATYPE_ESP
sadb_msg_len以8字节为单位的消息总长度。例如长度值为4表示32字节
sadb_msg_seq序列号,用于将应答消息与请求消息关联
sadb_msg_pid源进程ID,用于标识消息的发送方

3.3 消息长度单位说明

sadb_msg_len8字节(64位) 为计数单位。整个消息(包括基包头和所有扩展)的总长度,必须始终是8字节的整数倍。这是因为后续扩展字段要求8字节对齐,因此基包头的长度也以同样的单位存储。

3.4 扩展结构

基包头之后可以跟零个或多个扩展。每个扩展都包含一个扩展类型和一个长度字段。扩展类型包括:

扩展类型用途
SADB_EXT_SASA信息,包含SPI、重放窗口、加密/认证算法等
SADB_EXT_LIFETIME_HARD硬生存期(到达后SA失效)
SADB_EXT_LIFETIME_SOFT软生存期(到达后需更新)
SADB_EXT_ADDRESS_SRC源地址
SADB_EXT_ADDRESS_DST目的地址
SADB_EXT_ADDRESS_PROXY代理地址
SADB_EXT_KEY_AUTH认证密钥
SADB_EXT_KEY_ENCRYPT加密密钥
SADB_EXT_SPIRANGESPI范围
SADB_EXT_SENSITIVITY敏感级别

示例SADB_GET消息需要包含基包头、SA扩展和目的地址扩展。

四、消息类型详解

4.1 标准消息类型

RFC 2367定义了以下消息类型:

类型宏定义方向说明
0SADB_RESERVED保留
1SADB_GETSPI用户→内核从系统获取一个新的SPI值,用于创建SADB表项
2SADB_UPDATE用户→内核更新一个SA(修改不完备的SADB表项)
3SADB_ADD用户→内核添加一个完整的SA到SADB
4SADB_DELETE用户→内核删除一个SA
5SADB_GET用户→内核获取一个SA的信息
6SADB_ACQUIRE内核→用户内核需要新的SA,请求密钥管理守护进程安装SA
7SADB_REGISTER用户→内核注册以接收SADB_ACQUIRE消息
8SADB_EXPIRE内核→用户通知某个SA已经期满
9SADB_FLUSH用户→内核清空整个SADB
10SADB_DUMP用户→内核倾泻出SADB(调试用,不可靠)

方向说明:以上1-10这10个值中,SADB_EXPIRE(8)只能由内核发往用户空间;其他类型都可在用户和内核之间双向传递。

4.2 消息类型交互流程图

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                     PF_KEY消息类型交互流程                                            │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                     │
│  用户态(IKE守护进程)                                      内核态(SADB)           │
│                                                                                     │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │ 阶段1:初始化与注册                                                        │   │
│  │ socket(PF_KEY, SOCK_RAW, PF_KEY_V2)                                       │   │
│  │ SADB_REGISTER ────────────────────────────────────────────────────────────→│   │
│  │                           (注册接收SADB_ACQUIRE消息)                       │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                     │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │ 阶段2:外出数据包触发SA请求                                                  │   │
│  │                               ┌─→ 外出数据包到达,无匹配SA                  │   │
│  │                               │                                            │   │
│  │ SADB_ACQUIRE ←────────────────┼────────────────────────────────────────────│   │
│  │            (内核请求新的SA) │                                            │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                     │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │ 阶段3:SA协商与安装                                                         │   │
│  │ SADB_GETSPI ──────────────────────────────────────────────────────────────→│   │
│  │                           (获取SPI)                                       │   │
│  │ SADB_ADD ─────────────────────────────────────────────────────────────────→│   │
│  │                           (安装协商好的SA)                                 │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                     │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │ 阶段4:SA到期处理                                                           │   │
│  │                                                                             │   │
│  │ SADB_EXPIRE ←──────────────────────────────────────────────────────────────│   │
│  │            (通知SA已期满,需要重新协商)                                     │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

4.3 SA类型

sadb_msg_satype字段指定SA的安全服务类型:

类型值宏定义说明
0SADB_SATYPE_UNSPEC未指明,仅限请求消息
1SADB_SATYPE_AHAH(认证头)
2SADB_SATYPE_ESPESP(封装安全载荷)
3SADB_SATYPE_RSVPRSVP
4SADB_SATYPE_OSPFV2OSPFv2
5SADB_SATYPE_RIPV2RIPv2
6SADB_SATYPE_MIP移动IP

4.4 sadb_msg_type与扩展类型的对应关系

消息类型必需的扩展
SADB_GETSPI源地址、目的地址、SPI范围
SADB_UPDATESA信息、源地址、目的地址(可选:生存期、密钥等)
SADB_ADDSA信息、源地址、目的地址、认证密钥、加密密钥
SADB_DELETE源地址、目的地址
SADB_GET源地址、目的地址
SADB_ACQUIRE源地址、目的地址(可选:SA信息、生存期)
SADB_REGISTER
SADB_EXPIRESA信息、生存期(硬和软)
SADB_FLUSH
SADB_DUMP

五、IPsec相关的扩展概念

5.1 安全联盟数据库(SADB)

SADB是内核中存储SA信息的数据结构,其中每个SA通过三元组唯一标识:SPI(安全参数索引)、目的IP地址、安全协议(AH/ESP)

SADB的功能包括:查找入站SA用于解封数据包、查找出站SA用于封装数据包、管理SA的生存期。

5.2 安全策略数据库(SPD)

SPD用于定义IPsec策略,决定哪些流量需要IPsec保护,以及使用哪个SA。SPD中的策略条目由选择符(源/目的IP地址、协议、端口等)和动作(绕过、丢弃、使用IPsec)组成。当外出数据包到达时,内核首先查询SPD决定如何处理该数据包。

六、完整代码示例

6.1 创建密钥管理套接字并发送注册消息

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <net/pfkeyv2.h>

int main()
{
    int sockfd;
    struct sadb_msg msg;
    ssize_t n;

    /* 1. 创建PF_KEY套接字 */
    sockfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
    if (sockfd < 0) {
        perror("socket");
        exit(1);
    }

    /* 2. 构造SADB_REGISTER消息 */
    memset(&msg, 0, sizeof(msg));
    msg.sadb_msg_version = PF_KEY_V2;           /* 协议版本 */
    msg.sadb_msg_type = SADB_REGISTER;          /* 消息类型:注册 */
    msg.sadb_msg_satype = SADB_SATYPE_ESP;      /* 注册ESP类型的SA */
    msg.sadb_msg_len = sizeof(msg) / 8;         /* 长度以8字节为单位 */
    msg.sadb_msg_pid = getpid();                /* 进程ID */
    msg.sadb_msg_seq = 1;                       /* 序列号 */

    /* 3. 发送注册消息 */
    if (send(sockfd, &msg, sizeof(msg), 0) < 0) {
        perror("send");
        close(sockfd);
        exit(1);
    }

    printf("SADB_REGISTER sent\n");

    /* 4. 接收应答 */
    n = recv(sockfd, &msg, sizeof(msg), 0);
    if (n < 0) {
        perror("recv");
        close(sockfd);
        exit(1);
    }

    if (msg.sadb_msg_errno == 0) {
        printf("Registration successful\n");
    } else {
        printf("Registration failed with errno=%d\n", msg.sadb_msg_errno);
    }

    close(sockfd);
    return 0;
}

💡 代码说明:此示例演示了密钥管理套接字最基本的用法——向内核注册以接收SADB_ACQUIRE消息。发送SADB_REGISTER后,内核将知道有密钥管理守护进程在监听,当需要新的SA时会主动发送SADB_ACQUIRE消息。

6.2 内核主动发送消息的处理框架

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <net/pfkeyv2.h>

#define MAX_BUF 4096

void process_sadb_message(struct sadb_msg *msg)
{
    switch (msg->sadb_msg_type) {
    case SADB_ACQUIRE:
        printf("Received SADB_ACQUIRE: kernel needs a new SA\n");
        /* 在此处进行IKE协商,协商完成后使用SADB_ADD安装SA */
        break;
    case SADB_EXPIRE:
        printf("Received SADB_EXPIRE: SA has expired, need rekey\n");
        /* 重新协商并更新SA */
        break;
    default:
        printf("Received message type %d\n", msg->sadb_msg_type);
        break;
    }
}

int main()
{
    int sockfd;
    char buf[MAX_BUF];
    ssize_t n;

    sockfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
    if (sockfd < 0) {
        perror("socket");
        exit(1);
    }

    /* 循环接收内核消息 */
    while (1) {
        n = recv(sockfd, buf, sizeof(buf), 0);
        if (n < 0) {
            perror("recv");
            break;
        }

        if (n >= sizeof(struct sadb_msg)) {
            process_sadb_message((struct sadb_msg *)buf);
        }
    }

    close(sockfd);
    return 0;
}

💡 代码说明:此示例展示了密钥管理守护进程(如racoon、strongSwan)的核心处理循环。守护进程持续监听PF_KEY套接字,等待内核主动发送的SADB_ACQUIRESADB_EXPIRE等消息,然后触发IKE协商过程。

七、密钥管理套接字的内存布局

7.1 sadb_msg基包头内存布局

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                    sadb_msg基包头内存布局(共64位/8字节)                              │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                     │
│  0                   8                   16                  24                   32 │
│  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1                    │
│  ┌───────────────────────────────────────────────────────────────────────────────┐  │
│  │ version (8) │   type (8)  │  errno (8)  │ satype (8) │                       │  │
│  ├───────────────────────────────┬───────────────────────────────────────────────┤  │
│  │         len (16)              │       reserved (16)                           │  │
│  ├───────────────────────────────┼───────────────────────────────────────────────┤  │
│  │                         seq (32)                                              │  │
│  ├───────────────────────────────┼───────────────────────────────────────────────┤  │
│  │                         pid (32)                                              │  │
│  └───────────────────────────────────────────────────────────────────────────────┘  │
│                                                                                     │
│  💡 所有字段都是8字节对齐的,因此结构体总大小为64位(8字节)                           │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

7.2 完整消息内存布局示例

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                    完整PF_KEY消息内存布局(SADB_GET示例)                             │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                     │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │                    struct sadb_msg(基包头,8字节)                           │   │
│  │  version=PF_KEY_V2 | type=SADB_GET | errno=0 | satype=ESP                   │   │
│  │  len = 4(表示总长度32字节) | seq=1 | pid=1234                              │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                          │                                          │
│                                          ▼                                          │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │                  SADB_EXT_SA扩展(SA信息,8字节)                             │   │
│  │  exttype=SADB_EXT_SA | len=1 | SPI=0x12345678 | ...                         │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                          │                                          │
│                                          ▼                                          │
│  ┌─────────────────────────────────────────────────────────────────────────────┐   │
│  │             SADB_EXT_ADDRESS_DST扩展(目的地址,通常16字节)                 │   │
│  │  exttype=SADB_EXT_ADDRESS_DST | len=2(16字节) | 192.168.1.1              │   │
│  └─────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                     │
│  总长度 = 8 + 8 + 16 = 32字节,len字段值为32/8 = 4                                   │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

八、Linux系统的特殊说明

8.1 PF_KEY的现状

在Linux系统中,PF_KEY套接字的使用情况较为特殊,需要注意以下几点:

  1. 内核实现:Linux内核的net/key/af_key.c文件实现了PF_KEYv2套接字接口。

  2. 调度弃用PF_KEY用户配置接口在十多年前已被Netlink用户配置接口取代。目前所有维护中的IKE实现都已迁移到Netlink接口

  3. 弃用时间表:Linux内核开发社区已宣布弃用PF_KEY套接字接口,并计划在2027年将其移除。

8.2 现代替代方案:Netlink XFRM

在Linux系统上进行IPsec SA/SP管理的现代方法是使用Netlink套接字的XFRM(XFRM_USER)接口。XFRM接口提供以下优势:

  • 更丰富的功能集
  • 更好的可扩展性
  • 支持事件通知机制
  • 更符合Linux内核的开发方向

⚠️ 可移植性警告:PF_KEY套接字主要在BSD系统和某些Unix衍生系统上原生支持。在Linux系统上虽然存在实现,但已标记为弃用,推荐使用Netlink XFRM接口。

8.3 查看系统中打开的PF_KEY套接字

# 在Linux系统中查看当前打开的PF_KEY套接字信息
cat /proc/net/pf_key

每个表项代表一个打开的PF_KEY套接字,包含协议族、套接字状态、进程ID等参数。

九、常见问题与注意事项

9.1 常见错误速查表

问题原因解决方案
socket: Permission denied需要超级用户权限以root身份运行程序,或使用sudo
socket: Protocol not supported内核不支持PF_KEY检查内核配置,确保IPsec支持已编译
消息发送后无响应消息格式错误或扩展顺序不正确检查扩展的排列顺序是否与消息类型要求一致,确保长度以8字节为单位
SADB_ACQUIRE收不到未注册SADB_REGISTER在初始化阶段发送SADB_REGISTER消息注册
地址扩展解析错误未正确处理sockaddrsalen字段使用salen+对齐规则正确遍历扩展
消息长度计算错误sadb_msg_len单位是8字节总字节数除以8后赋值给len

9.2 编程注意事项

注意事项说明
8字节对齐所有扩展必须8字节对齐,必要时需要填充
扩展顺序扩展的排列顺序必须遵循协议要求,不能随意调换
sadb_msg_len单位以8字节为单位,而非字节
SPI的唯一性在目的地址和安全协议组合下,SPI必须唯一
密钥材料的处理认证密钥和加密密钥以扩展形式传递,需注意密钥长度
匹配请求与应答使用sadb_msg_seqsadb_msg_pid匹配应答消息
错误处理检查sadb_msg_errno字段以确定消息处理结果

9.3 与其他章节的关联

章节关联内容
第18章 路由套接字类似的协议族设计,原始套接字模式
第20章 广播某些密钥管理协议使用广播或多播进行发现
第21章 多播IPsec多播SA的管理可能涉及多播地址

十、本章小结

10.1 核心知识点回顾

知识点关键要点
PF_KEY协议族RFC 2367定义的通用密钥管理API,用于IPsec和其他网络安全服务
套接字创建socket(PF_KEY, SOCK_RAW, PF_KEY_V2),仅支持原始套接字
sadb_msg基包头所有消息的公共头部,包含版本、类型、错误码、SA类型、长度、序列号、PID
消息扩展基包头后跟零个或多个扩展(SA信息、地址、密钥、生存期等)
11种消息类型SADB_GETSPI、UPDATE、ADD、DELETE、GET、ACQUIRE、REGISTER、EXPIRE、FLUSH、DUMP、RESERVED
SADB_ACQUIRE唯一只能由内核发往用户空间的消息,用于请求新的SA
方向特性SADB_EXPIRE只能内核→用户;其他类型可在用户和内核间双向传递
SA三元组SPI + 目的IP + 安全协议
Linux现状PF_KEY已弃用,推荐使用Netlink XFRM接口
访问权限需要超级用户权限访问SADB

10.2 本章思维导图

第十九章 密钥管理套接字
├── PF_KEY协议族概述
│   ├── 定义:RFC 2367通用密钥管理API
│   ├── 用途:IPsec SA/SP管理
│   ├── 套接字:socket(PF_KEY, SOCK_RAW, PF_KEY_V2)
│   └── 权限:需要超级用户
├── 核心数据结构
│   ├── struct sadb_msg(基包头)
│   │   ├── version:PF_KEY_V2
│   │   ├── type:消息类型
│   │   ├── errno:错误指示
│   │   ├── satype:SA类型(AH/ESP等)
│   │   ├── len:长度(8字节单位)
│   │   ├── seq:序列号
│   │   └── pid:进程ID
│   └── 扩展类型(SADB_EXT_xxx)
│       ├── SA信息、地址、生存期、密钥
├── 11种消息类型
│   ├── 用户→内核:GETSPI, UPDATE, ADD, DELETE, GET, REGISTER, FLUSH, DUMP
│   └── 内核→用户:ACQUIRE, EXPIRE
├── 消息交互流程
│   ├── 注册 → ACQUIRE请求 → 协商 → ADD → EXPIRE通知
│   └── 匹配请求与应答:通过seq和pid
├── IPsec体系
│   ├── SADB(安全联盟数据库)
│   └── SPD(安全策略数据库)
└── Linux平台说明
    ├── PF_KEY已弃用(计划2027年移除)
    └── 替代方案:Netlink XFRM (XFRM_USER)

十一、下一章预告

📌 下一篇:《UNIX网络编程》读书笔记(二十):第二十章 广播

第二十章将详细讲解:

  1. 广播的基本概念:广播地址格式(有限广播255.255.255.255和子网定向广播)、广播与单播/多播的区别
  2. 广播的应用场景:局域网服务发现(ARP、DHCP、NetBIOS)、网络唤醒(Wake-on-LAN)等
  3. SO_BROADCAST套接字选项:为什么发送广播必须显式启用该选项
  4. 广播发送端编程:设置广播选项、构造广播地址、发送数据报
  5. 广播接收端编程:接收广播数据报、获取发送者信息
  6. 广播的局限性与注意事项
    • 广播数据包会被路由器阻挡(默认不转发)
    • 大量广播可能造成广播风暴
    • 多宿主机上的广播问题
  7. 广播与单播的性能对比:何时使用广播而非单播

学习目标:学完第二十章后,你将能够——

  • 理解广播地址格式和使用场景
  • 正确设置SO_BROADCAST选项发送广播数据报
  • 编写简单的广播发送和接收程序
  • 理解广播的局限性以及何时使用广播
  • 在多宿主机上正确处理广播数据

敬请期待!

参考资料

  1. W. Richard Stevens, Bill Fenner, Andrew M. Rudoff. 《UNIX网络编程 卷1:套接字联网API(第3版)》. 北京:人民邮电出版社
  2. UNIX网络编程卷一 学习笔记 第十九章 密钥管理套接字,CSDN
  3. Linux——密钥管理Socket,CSDN,https://blog.csdn.net/firo_baidu/article/details/6147596
  4. UNP总结 Chapter 18~21 路由套接字、密钥管理套接字、广播、多播,博客园,https://www.cnblogs.com/biyeymyhjob/archive/2012/08/07/2626841.html
  5. pf_key(7P) man page — SunOS,https://manpage.me/index.cgi?q=pf_key&sektion=7P
  6. pf_key(4P) man page — OmniOS,https://man.omnios.org/man4p/pf_key
  7. RFC 2367: PF_KEY Key Management API, Version 2,IETF Datatracker,https://datatracker.ietf.org/doc/html/rfc2367
  8. Linux内核git: pfkey: Deprecate pfkey,https://git.armlinux.org.uk/cgit/linux-arm.git/commit/?id=xxx

本文为个人学习笔记,仅用于知识分享。如有错误,欢迎指正。
👍🏻 点赞 + 收藏 + 分享,让更多开发者看到这篇深度解析!❤️ 如果觉得有用,请给个赞支持一下作者!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

andylin02

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值