FreeBSD 中文社区 2025 第二季度问卷调查
FreeBSD 中文社区(CFC)
VitePress 镜像站QQ 群 787969044视频教程Ⅰ视频教程Ⅱ
  • FreeBSD 从入门到追忆
  • 中文期刊
  • 状态报告
  • 发行说明
  • 手册
  • 网络文章集锦
  • 笔记本支持报告
  • Port 开发者手册
  • 架构手册
  • 开发者手册
  • 中文 man 手册
  • 文章
  • 书籍
  • FreeBSD 中文期刊
  • 编辑日志
  • 2025-123 下游项目
    • FreeBSD 发布工程:新主管上任
    • GhostBSD:从易用到挣扎与重生
    • BSD Now 与将来
    • 字符设备驱动教程(第三部分)
    • 学会走路——连接 GPIO 系统
    • FreeBSD 中对 SYN 段的处理
    • FreeBSD 2024 年秋季峰会
  • 2024-1112 虚拟化
    • 字符设备驱动程序教程(第二部分)
    • 面向 Linux 和 Windows 用户的 bhyve
    • Xen 与 FreeBSD
    • Wifibox:一种嵌入式虚拟化无线路由器
    • 嵌入式 FreeBSD:Fabric——起步阶段
    • DGP:一种新的数据包控制方法
    • 会议报告:我在都柏林的 EuroBSDCon 体验
  • 2024-0910 内核开发
    • 字符设备驱动程序教程
    • VPP 移植到了 FreeBSD:基础用法
    • 利用 Kyua 的 Jail 功能提升 FreeBSD 测试套件的并行效率
    • FreeBSD 上的 Valgrind
    • 嵌入式 FreeBSD:探索 bhyve
    • TCP/IP 历险记:FreeBSD TCP 协议栈中的 Pacing
    • 实用软件:实现无纸化(Paperless)
  • 2024-0708 存储与文件系统
    • FreeBSD 中的 NVMe-oF
    • FreeBSD iSCSI 入门
    • 使用 ZFS 原生加密保护数据
    • 嵌入式 FreeBSD:打造自己的镜像
    • TCP LRO 简介
    • 基于 Samba 的时间机器备份
  • 2024-0506 配置管理对决
    • 基本系统中的 mfsBSD
    • rdist
    • Hashicorp Vault
    • 在 GitHub 上向 FreeBSD 提交 PR
    • 悼念 Mike Karels
    • 2024 年 5-6 月来信
    • 嵌入式 FreeBSD 面包板
    • TCP/IP 历险记:TCP BBLog
    • 实用软件:开发定制 Ansible 模块
  • 2024-0304 开发工作流与集成
    • FreeBSD 内核开发工作流程
    • FreeBSD 与 KDE 持续集成(CI)
    • 更现代的内核调试工具
    • 从零开始的 ZFS 镜像及 makefs -t zfs
    • 提升 Git 使用体验
  • 2024-0102 网络(十周年)
    • FreeBSD 中的 RACK 栈和替代 TCP 栈
    • FreeBSD 14 中有关 TCP 的更新
    • if_ovpn 还是 OpenVPN
    • SR-IOV 已成为 FreeBSD 的重要功能
    • FreeBSD 接口 API(IfAPI)
    • BATMAN:更优的可移动热点网络方式
    • 配置自己的 VPN——基于 FreeBSD、Wireguard、IPv6 和广告拦截
    • 实用软件:使用 Zabbix 监控主机
  • 2023-1112 FreeBSD 14.0
    • LinuxBoot:从 Linux 启动 FreeBSD
    • FreeBSD 容器镜像
    • 现在用 Webhook 触发我
    • 新的 Ports 提交者:oel Bodenmann (jbo@freebsd.org)
  • 2023-0910 Port 与软件包
    • 回忆录:与 Warner Losh(@imp)的访谈
    • 在你自己的仓库中定制 Poudriere 源
    • Wazuh 和 MITRE Caldera 在 FreeBSD Jail 中的使用
    • PEP 517
    • CCCamp 2023 旅行报告
  • 2023-0708 容器与云
    • 在 Firecracker 上的 FreeBSD
    • 使用 pot 和 nomad 管理 Jail
    • 会议报告:C 与 BSD 正如拉丁语与我们——一位神学家的旅程
    • 抒怀之旅:与 Doug Rabson 的访谈
    • 基于 Jail 的广告拦截教程
    • 我们收到的来信
  • 2023-0506 FreeBSD 三十周年纪念特刊
    • CheriBSD 近十多年的历程
    • AArch64:成为 FreeBSD 新的一级架构
    • 岁月如梭:我个人的时间线
    • 安装 FreeBSD 1.0:回顾 30 年前
    • ZFS 是如何进入 FreeBSD 的呢?
    • 我不是来自约克郡的,我保证!
    • 回忆录:采访 David Greenman Lawrence
    • FreeBSD 和早期的 Unix 社区
    • 早期的 FreeBSD 移植
    • FreeBSD 30 周年:成功的秘诀
    • FreeBSD 在日本:回忆之旅与今日之实
  • 2023-0304 嵌入式
    • CheriBSD port 和软件包
    • 让我们来试试 ChatGPT
    • GPU 直通
  • 2023-0102 构建 FreEBSD Web 服务器
    • ZFS 的原子 I/O 与 PostgreSQL
    • 虚拟实验室——BSD 编程研讨会
    • ZFS 简介
    • 会议报告:落基山庆祝女性计算机科学家
    • 进行中的工作/征求反馈:数据包批处理
    • 基金会与 FreeBSD 桌面
  • 2022-1112 可观测性和衡量标准
    • 在 FreeBSD 的 DDB 内核调试器中编写自定义命令
    • DTrace:老式跟踪系统的新扩展
    • 基于证书的 Icinga 监控
    • 活动监控脚本(activitymonitor.sh)
    • 实用 IPv6(第四部分)
    • EuroBSDCon 会议报道
    • 实用 Port:Prometheus 的安装与配置
    • 书评:《用火解决问题:管理老化的计算机系统(并为现代系统保驾护航)》Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones)
  • 2022-0910 安全性
    • CARP 简介
    • 重构内核加密服务框架
    • PAM 小窍门
    • SSH 小窍门
    • 实用 IPv6(第三部分)
    • 书评:Understanding Software Dynamics(深入理解软件性能——一种动态视角)—— Richard L. Sites 著
    • 访谈:保障 FreeBSD 安全性
    • MCH 2022 会议报告
  • 2022-0708 科研、系统与 FreeBSD
    • 在 FreeBSD 上构建 Loom 框架
    • 教授本科生 Unix 课程
    • FreeBSD 入门研讨会
    • 实用 IPv6(第二部分)
    • 在 2022 年及以后推广 FreeBSD
    • 进行中的工作/征求反馈:Socket 缓冲区
    • FreeBSD 开发者峰会报告
    • 支持 Electromagnetic Field 2022
  • 2022-0506 灾难恢复
    • 使用 FreeBSD 构建高弹性的私有云
    • LLDB 14 —— FreeBSD 新调试器
    • 实用 IPv6(第一部分)
    • 利用 netdump(4) 进行事后内核调试
    • 进行中的工作/征求反馈:FreeBSD 启动性能
    • 实用 Port:在 OpenZFS 上设置 NFSv4 文件服务器
  • 2022-0304 ARM64 是一级架构
    • FreeBSD/ARM64 上的数据科学
    • Pinebook Pro 上的 FreeBSD
    • 嵌入式控制器的 ACPI 支持
    • 进行中的工作/征求反馈:Lumina 桌面征集开发人员
    • 实用 Port:如何设置 Apple 时间机器
  • 2022-0102 软件与系统管理
    • 为 FreeBSD Ports 做贡献
    • 使用 Git 贡献到 FreeBSD Ports
    • CBSD:第一部分——生产环境
    • 将 OpenBSD 的 pf syncookie 代码移植到 FreeBSD 的 pf
    • 进行中的工作/征求反馈:mkjail
    • 《编程智慧:编程鬼才的经验和思考》(The Kollected Kode Vicious)书评
    • 会议报告:EuroBSDCon 2021 我的第一次 EuroBSDCon:一位新组织者的视角
  • 2021-1112 存储
    • 开放通道 SSD
    • 构建 FreeBSD 社区
    • 与完美操作系统同行 27 年
    • 进行中的工作/征求反馈:OccamBSD
    • 通过 iSCSI 导入 ZFS ZIL——不要在工作中这样做——就像我做的那样
  • 2021-0910 FreeBSD 开发
    • FreeBSD 代码审查与 git-arc
    • 如何为 FreeBSD 实现简单的 USB 驱动程序
    • 内核开发技巧
    • 程序员编程杂谈
  • 2021-0708 桌面/无线网
    • 通往 FreeBSD 桌面的直线路径
    • FreeBSD 13 中的人机接口设备 (HID) 支持
    • Panfrost 驱动程序
    • 用 Git 更新 FreeBSD
    • FreeBSD 的新面孔
    • 想给你的桌面加点佐料?
  • 2021-0506 安全
    • 七种提升新安装 FreeBSD 安全性的方法
    • copyinout 框架
    • 使用 TLS 改善 NFS 安全性
    • Capsicum 案例研究:Got
    • 对 Jail 进行安全扫描
  • 2021-0304 FreeBSD 13.0
    • 展望未来
    • FreeBSD 13.0 工具链
    • FreeBSD 13.0 中有新加载器吗?
    • TCP Cubic 准备起飞
    • OpenZFS 中的 Zstandard 压缩
    • 会议报告:FreeBSD 供应商峰会
    • Git 不够吗?
  • 2021-0102 案例研究
    • Tarsnap 的 FreeBSD 集群
    • BALLY WULFF
    • Netflix Open Connect
    • FreeBSD 的新面孔
    • 写作学者的 FreeBSD
    • 在世界之巅
  • 2020-1112 工作流/持续集成(CI)
    • FreeBSD Git 快速入门
    • 使用 syzkaller 进行内核 Fuzzing
    • Mastering Vim Quickly 书评
    • 线上会议实用技巧
    • 在控制台上进行网络监控
  • 2020-0910 贡献与入门
    • 采访:Warner Losh,第 2 部分
    • 代码审查
    • 撰写良好的提交消息
    • 如何在不是程序员的情况下做出贡献——成为 FreeBSD 译者
    • 如何成为文档提交者
    • 谷歌编程之夏
    • 为 FreeBSD 期刊撰写文章
    • 你为什么使用 FreeBSD
    • FreeBSD 的新面孔
  • 2020-0708 基准测试/调优
    • FreeBSD Friday
    • 采访:Warner Losh,第 1 部分
    • 构建和运行开源社区
    • 在 FreeBSD 上轻松搭建我的世界(Minecraft)服务器
    • FreeBSD 的新面孔
  • 2020-0506 网络性能
    • 内核中的 TLS 卸载
    • 访谈:Michael W Lucas
    • FreeBSD 桌面发行版
    • 使用 Poudriere 进行 Port 批量管理
    • FreeBSD 的新面孔
由 GitBook 提供支持
LogoLogo

FreeBSD 中文社区(CFC) 2025

在本页
  • SYN cookies
  • 缺点
  • 历史
  • 实现笔记
  • 配置
  • 结论
在GitHub上编辑
导出为 PDF
  1. 2022-0102 软件与系统管理

将 OpenBSD 的 pf syncookie 代码移植到 FreeBSD 的 pf

上一页CBSD:第一部分——生产环境下一页进行中的工作/征求反馈:mkjail

最后更新于2个月前

  • 原文链接:

  • 作者:KRISTOF PROVOST

互联网可以是一个无序的地方,我们的在线服务可能会受到各种方式的攻击。我们运行的防火墙是我们保护系统的一部分,但事实证明它们也可能成为攻击的渠道。

一种攻击服务的方式是通过伪装成打开连接来耗尽系统资源。这通常被称为 SYN 洪水攻击,这是一种相当隐蔽的攻击。让我们先回顾一下 TCP 连接的工作原理。打开一个 TCP 连接是一个三步过程:

  1. SYN:客户端发送一个 SYN 数据包,表示它希望打开连接。它在 SYN 数据包中设置一个初始的序列号。

  2. SYN+ACK:服务器回应,确认客户端的序列号,并设置自己的序列号。

  3. ACK:客户端确认连接已经打开,并确认服务器的序列号。

当服务器收到初始的 SYN 时,它会设置内部数据结构以支持新的连接。这需要 CPU 时间和内存。

这意味着恶意客户端可以生成 SYN 数据包(这些数据包很小,且容易生成),消耗服务器的可用内存和 CPU 资源。更糟糕的是,攻击者只需要发送一个 SYN 数据包。攻击者无需接收服务器的 SYN+ACK 回复。这意味着源 IP 地址可以伪造,使这些攻击难以过滤掉。它们还可以针对服务的主要 TCP 端口(例如,Web 服务器的 443 端口),使攻击与真实客户端请求难以区分。

SYN cookies

1996 年,Daniel J. Bernstein 和 Eric Schenk 提出了抵御此类攻击的方法,称为 SYN cookies。简而言之,SYN cookies 确保服务器在接收到 SYN 数据包时不会为新连接分配任何内存,从而避免内存耗尽。

我们仍然生成一个 SYN+ACK 回复,但在客户端用 ACK 回复我们的 SYN+ACK 之前,服务器不会创建服务器端的状态。这确保客户端确实存在(即源 IP 地址没有被伪造)。

这个方法的明显问题是,我们仍然需要在 SYN 数据包到达时通常会保存的信息。这些信息包括最大报文段大小(MSS)和窗口缩放(WSCALE)。虽然这些选项是... 可选的,但它们对 TCP 性能很重要,我们不希望拒绝它们。

此外,我们还需要某种方法来确保客户端 ACK 中的确认号与我们在 SYN+ACK 消息中使用的序列号匹配。如果我们不进行检查,恶意客户端只需发送一个 SYN,稍等片刻,然后盲目地发送一个 ACK,也就是说,无需实际接收服务器的 SYN+ACK,只需使用一个随机的确认号。

那么,我们如何做到这一点呢?我们通过将所有选项编码到 SYN+ACK 数据包的序列号中来实现这一点。

在 pf 实现中,这是通过 pf_syncookie_generate() 函数完成的:

uint32_t
pf_syncookie_generate(struct mbuf *m, int off, struct pf_pdesc *pd,
    uint16_t mss)
{
    uint8_t i, wscale;
    uint32_t iss, hash;
    union pf_syncookie cookie;
    PF_RULES_RASSERT();
    cookie.cookie = 0;

    /* 映射 MSS(最大报文段大小) */
    for (i = nitems(pf_syncookie_msstab) - 1;
        pf_syncookie_msstab[i] > mss && i > 0; i--)
        /* 无操作 */;
    cookie.flags.mss_idx = i;

    /* 映射 WSCALE(窗口缩放因子) */
    wscale = pf_get_wscale(m, off, pd->hdr.tcp.th_off, pd->af);
    for (i = nitems(pf_syncookie_wstab) - 1;
        pf_syncookie_wstab[i] > wscale && i > 0; i--)
        /* 无操作 */;
    cookie.flags.wscale_idx = i;
    
    cookie.flags.sack_ok = 0; /* XXX */

    cookie.flags.oddeven = V_pf_syncookie_status.oddeven;

    /* 计算哈希值 */
    hash = pf_syncookie_mac(pd, cookie, ntohl(pd->hdr.tcp.th_seq));

    /*
     * 将标志值放入哈希中,并对其进行异或操作,以获得更好的 ISS(初始序列号)数值变异。
     * 这不会增强加密强度,目的是防止 8 个 cookie 位直接显示在网络上。
     */
    iss = hash & ~0xff;
    iss |= cookie.cookie ^ (hash >> 24);
    
    return (iss);
}

目光敏锐的读者会注意到,对于 MSS 和 WSCALE,我们并没有真正编码正确的值,而是通过查找表找到最接近的匹配值。这减少了编码信息所需的位数,但仍然能够很好地近似真实值。稍微小一点的最大报文段大小(MSS)或窗口缩放因子(WSCALE)会稍微影响性能,但不会产生显著的影响。所选择的值是根据最常用的 MSS 或 WSCALE 值来表示的,因此对于大多数客户端,几乎没有性能损失。

这些信息被编码成一个经过认证的哈希值。也就是说,为了重建哈希,你需要输入信息(如 MSS、WSCALE 等)和一个秘密密钥。换句话说,攻击者无法预测哈希的结果,因此也无法预测服务器将选择的序列号。这一过程由 pf_syncookie_mac() 函数处理:

uint32_t
pf_syncookie_mac(struct pf_pdesc *pd, union pf_syncookie cookie, uint32_t seq)
{
    SIPHASH_CTX ctx;
    uint32_t siphash[2];
    PF_RULES_RASSERT();
    MPASS(pd->proto == IPPROTO_TCP);

    SipHash24_Init(&ctx);
    SipHash_SetKey(&ctx, V_pf_syncookie_status.key[cookie.flags.oddeven]);

    switch (pd->af) {
        case AF_INET:
            SipHash_Update(&ctx, pd->src, sizeof(pd->src->v4));
            SipHash_Update(&ctx, pd->dst, sizeof(pd->dst->v4));
            break;
        case AF_INET6:
            SipHash_Update(&ctx, pd->src, sizeof(pd->src->v6));
            SipHash_Update(&ctx, pd->dst, sizeof(pd->dst->v6));
            break;
        default:
            panic("unknown address family");
    }

    SipHash_Update(&ctx, pd->sport, sizeof(*pd->sport));
    SipHash_Update(&ctx, pd->dport, sizeof(*pd->dport));
    SipHash_Update(&ctx, &seq, sizeof(seq));
    SipHash_Update(&ctx, &cookie, sizeof(cookie));
    SipHash_Final((uint8_t *)&siphash, &ctx);

    return (siphash[0] ^ siphash[1]);
}

此时,pf 处理停止。我们不会创建状态,也不会对数据包进行任何进一步的检查。这也意味着,如果防火墙保护的是另一台主机(即它运行在客户端和服务器之间的路由器上),服务器将根本不会意识到客户端尝试发起新连接。我们希望这样做,因为这意味着服务器可以免受 SYN 洪水攻击,而无需任何代码或配置更改。

如果客户端从未回应,则什么也不会发生。服务器没有记住任何关于此特定 SYN 消息的信息,也没有为其分配任何内存。另一方面,如果客户端确实回应(即它是一个合法客户端,至少在本讨论中是如此),我们必须重建在接收到原始 SYN 消息时未保留的信息。

在接收到 SYN+ACK 消息后,我们首先在 pf_syncookie_validate() 中验证它:

uint8_t
pf_syncookie_validate(struct pf_pdesc *pd)
{
    uint32_t hash, ack, seq;
    union pf_syncookie cookie;

    MPASS(pd->proto == IPPROTO_TCP);
    PF_RULES_RASSERT();

    seq = ntohl(pd->hdr.tcp.th_seq) - 1;
    ack = ntohl(pd->hdr.tcp.th_ack) - 1;
    cookie.cookie = (ack & 0xff) ^ (ack >> 24);

    /* 我们在设置 cookie(联合体)之前不知道 oddeven。*/
    if (atomic_load_64(&V_pf_status.syncookies_inflight[cookie.flags.oddeven]) == 0)
        return (0);

    hash = pf_syncookie_mac(pd, cookie, seq);

    if ((ack & ~0xff) != (hash & ~0xff))
        return (0);

    counter_u64_add(V_pf_status.lcounters[KLCNT_SYNCOOKIES_VALID], 1);
    atomic_add_64(&V_pf_status.syncookies_inflight[cookie.flags.oddeven], -1);

    return (1);
}

我们检查 cookie 是否包含正确的认证字符串。如果是,我们继续进入 pf_syncookie_recreate(),在那里我们重建原始的 SYN 包。这对于 syncookie 系统本身来说并不是严格要求的,但我们需要告诉 pf 关于我们最初丢弃的 SYN 包,以便它可以创建相关的状态条目。

这还允许 pf 继续处理,并可能将重建的 SYN 包转发到远程服务器。远程服务器随后会以不同的序列号回复其自己的 SYN+ACK 包。pf 必须修改客户端和服务器之间所有流量的序列号和确认号。幸运的是,这是 pf 的标准功能。

此时,连接已在双方完全建立,并且与没有使用 syncookies 设置的连接没有显著差异。关闭连接时不需要采取特殊的操作,因为这不会为恶意客户端生成内存压力提供新的机会。

缺点

到目前为止,我们已经讨论了 syncookies 如何帮助我们,但我们并没有花太多时间讨论任何缺点。这是否意味着没有缺点?遗憾的是,不是。

我们已经谈到了 MSS 和 WSCALE。使用 syncookies 时,我们无法完全忠实地反映客户端提出的值。这可能意味着对于某些客户端,我们会损失一些 TCP 性能。通常情况下,这并不值得担心。

另一个缺点是 syncookies 工作方式中隐含的问题:我们无条件地对 SYN 包回复 SYN+ACK。即使端口实际上是关闭的。这意味着客户端可能认为连接正在工作,直到它完全建立,然后收到一个 RST。那并不理想,可能会引发客户端的意外行为。也就是说,这可能会让用户觉得连接失败的表现与“正常”失败不同。

通过确保防火墙立即拒绝发送到关闭端口的包,这种情况可以大大减轻。无论如何,这通常是一个好主意,如果启用了 syncookies,更是如此。

另一个缺点是,丢失的 SYN+ACK 包没有重传机制。因为待我们发送了 SYN+ACK,我们就会忘记关于它的所有信息,无法进行重传。这并不太令人担心,因为客户端会假设它的 SYN 包丢失,并重新发送 SYN 包。这将导致服务器生成一个新的 SYN+ACK,希望这次不会丢失。

最后需要注意的是,syncookies 并非魔法。它们对抗 SYN flood 攻击非常有效,但无法防止其他类型的攻击。例如,如果一个特殊构造的 HTTP 请求消耗了 Web 服务器的过多系统资源,这种情况是 syncookies 无法阻止的。

此外,没有任何机制可以阻止攻击者从多个不同的客户端 IP 地址发起连接,而不伪造源地址。在这种情况下,攻击者仍然有可能打开足够多的连接来耗尽服务器的资源。然而,syncookies 使得攻击者的代价大大增加。单个攻击主机就可以执行 SYN flood 攻击,且带宽需求适中。而使用非伪造的 TCP 连接进行相同效果的攻击将需要更多的攻击主机。

历史

OpenBSD pf 的 syncookie 代码基于 FreeBSD TCP 栈中的 syncookie 代码,最初由 Jonathan Lemon 于 2001 年开发(a9c96841638186f2e8d10962b80e8e9f683d0cbc)。

看起来 OpenBSD 的提交信息在归功于 Andre Oppermann 时是错误的。Andre 确实在 2013 年对 syncookie 代码做出了重大改进(81d392a09de0f2eeabaf68787896863eb9c370a8),这可能是误解的来源。

实现笔记

虽然 OpenBSD 和 FreeBSD 的 pf 版本多年来已经有所不同,但相似性仍然远远超过差异。因此,将 OpenBSD pf 特性移植到 FreeBSD 通常是相对简单的。主要的障碍是锁定策略的不同。OpenBSD 的 pf,像 OpenBSD 的网络栈一样,受到单一锁(NET_LOCK)的保护。这有一个很大的优点,就是简单性,但也带来了一些性能上的缺点。

FreeBSD 的 pf 采用了更复杂的锁定策略,但在性能上得到了更好的回报。

这在自适应模式中尤为重要。syncookie 代码的其他部分与现有的锁定方法很好地契合。然而,OpenBSD 采用的是递增和递减一个单一计数器的方式来跟踪半开状态和正在传输的 syncookie 包。这在 FreeBSD 中需要使用原子操作,因为没有等效的 NET_LOCK,并且多个核心可以同时处理 TCP SYN 或其他包。

虽然这确保了我们不会低估或高估半开状态或正在传输的 syncookie 包的数量,但它仍然不完美。虽然值的检索是原子的,但由于我们检索多个值,它们并不总是能反映一个完美的快照。幸运的是,这里并不要求严格的准确性。最坏的情况是我们稍微提前或稍晚地启用或禁用 syncookies。由于 syncookie 介导的连接和正常连接可以同时建立,因此对用户来说,这不是一个显著的问题。

配置

经过上述讨论,读者可能会认为配置 syncookies 是一项复杂的工作,但实际上并非如此。只需在 pf.conf 的选项部分添加一行即可:

set syncookies always

或

set syncookies adaptive

第一个模式将始终对 SYN 数据包做出响应,并返回一个 syncookie SYN+ACK。在自适应模式下,pf 只有在大量连接处于半开状态时才会这样做。也就是说,我们已对 ACK 消息回复 SYN+ACK,并在等待对方的 ACK 响应。理想情况下,这结合了两者的优点:我们既能获得正常 TCP 连接处理的所有优点(即完全的选项协商,当连接无法打开时可以立即得到反馈),又能在一定程度上防范 SYN flood 攻击。

自适应模式、低水位和高水位标记(即分别启用和禁用 syncookies 的位置)也可以进行配置:

set syncookies adaptive (start 25%, end 12%)

这些值以状态表大小的百分比表示。如果没有配置 syncookie 行,功能将默认为禁用。这意味着除非用户明确启用 syncookies,否则行为不会改变。

结论

syncookies 适合你吗?如果你的系统遭遇 SYN flood 攻击,它们可能会适合你。如果没有,你可能想保持它们禁用,但即便如此,了解它们的存在也是好的。SYN flood 攻击是一种非常古老的攻击方式,但只要它们偶尔有效,攻击者可能会决定使用它们。防御者必须准备好合适的工具。

新的 pf syncookie 功能已经在最近的 12.3 版本中出现,并将在即将发布的 13.1 版本中提供。

将 OpenBSD pf syncookie 代码移植到 FreeBSD 的 pf 的工作得到了 Modirum MDPay 的赞助。


KRISTOF PROVOST 是一位自由职业的嵌入式软件工程师,专注于网络和视频应用。他是 FreeBSD 的提交者,FreeBSD 中 pf 防火墙的维护者,也是 EuroBSDCon 基金会的董事会成员。Kristof 不幸地有一种倾向,总是会遇到 uClibc 的 bug,对 FTP 怀有强烈的厌恶。不要和他谈论 IPv6 分片。

Porting OpenBSD’s pf syncookie Code to FreeBSD’s pf