编辑
2024-08-16
TCP
0
请注意,本文编写于 33 天前,最后修改于 21 天前,其中某些信息可能已经过时。

目录

1 遇到syn攻击调小半连接队列是否可行
2 如果牺牲可用性,调小半连接队列是否可行
3 我有如下方案,还是调小半连接队列,并使用crontab在特定时间启动sshd,这样当发生syn攻击时,我可以在sshd启动时间内登录服务器,关闭对应服务
4 我担心存在登录困难的情况,但是我仍坚持减小半连接队列,应该调整为多大
5 攻击者发动ddos通常是出于什么原因
6 还是不考虑可用性,直接关闭服务器攻击者是不是就没招了
7 攻击者发起一次ddos的成本有多少,如何评估
8 我的vps一年费用还不到100美元,看来不值得攻击啊
9 tcp中有半连接队列和全连接队列,这两个队列的大小如何估算
10 如果开启syn cookie,并且半连接队列设置很小,同时全连接队列设置很大,这种方案能否提升性能并节约资源
11 我觉得内存比cpu重要,因为如果内存满了将会发生oom, 而cpu满了顶多反应慢些
12 启用syn cookie后为什么还是有半连接队列丢弃syn包的现象
13 在开启syn cookie的情况下,tcpmaxsyn_backlog的配置是不是没用了
相关配置
测试
半连接
全连接
测试命令整理
Go 中如何设置 backlog?
参考

下次一定试试。。。

1 遇到syn攻击调小半连接队列是否可行

在面对 SYN 攻击时,调小半连接队列(SYN Queue)的大小通常不是一种有效的防御策略。相反,这可能会使服务器更容易被攻击者利用,因为半连接队列的空间更少,容易被填满,导致合法的连接请求无法得到响应。

应对 SYN 攻击的有效策略包括:

  1. 使用 SYN Cookies:这是在内核级别的一种防御机制,可以在队列满时仍然处理合法的 SYN 请求,而无需消耗太多资源。
  2. 增加半连接队列的大小:通过增大队列,可以处理更多的半连接,防止队列被填满。
  3. 减少 SYN-ACK 重传次数:减少系统在等待客户端完成三次握手时重传 SYN-ACK 的次数,从而减少资源的占用。
  4. 缩短 SYN-ACK 超时时间:可以缩短服务器在未完成连接时的超时等待时间,以便更快地释放资源。
  5. 使用防火墙和 IP 限制:配置防火墙来识别和过滤掉大量的伪造 SYN 请求,限制每个 IP 地址的连接速率。
  6. 使用分布式拒绝服务攻击(DDoS)防护系统:如云防护服务,来过滤掉恶意流量。

调小半连接队列通常不会帮助缓解 SYN 攻击,反而可能使服务器的可用性降低,建议使用以上提到的其他防御措施。

2 如果牺牲可用性,调小半连接队列是否可行

如果你愿意牺牲可用性来应对 SYN 攻击,调小半连接队列的大小是可行的,但它只能作为一种极端情况下的策略。这种做法的逻辑在于:

  1. 快速识别攻击:通过减小半连接队列的大小,可以更快地触发队列满的情况,从而更早地发现 SYN 攻击的存在。
  2. 降低资源消耗:半连接队列的大小减小后,服务器在面对大量 SYN 请求时,消耗的资源会减少,因为它不需要为这些请求保留过多的资源。

然而,这种方法的缺点也很明显:

  • 合法连接难以建立:合法用户的连接请求会更容易被拒绝,因为队列空间有限,正常用户请求可能因为队列满而被丢弃。
  • 无法彻底解决攻击:攻击者仍然可以轻易填满队列,使得合法用户无法连接,达到了攻击的目的。

因此,调小半连接队列的做法更多是为了监控或紧急处理,而不是长久的防御手段。它可能在一些特殊场景下有用,比如在你已经部署了其他防御机制,并且希望尽快检测并处理攻击时。但从长期和可用性的角度来看,还是应该优先采用其他更加稳健的防御策略,比如使用 SYN Cookies、调整超时设置、或者借助专门的防御设备和服务来应对 SYN 攻击。

3 我有如下方案,还是调小半连接队列,并使用crontab在特定时间启动sshd,这样当发生syn攻击时,我可以在sshd启动时间内登录服务器,关闭对应服务

这个方案可以在特定情况下有效,尤其是当你有能力在攻击期间手动介入并采取措施时。具体而言,调小半连接队列可以让服务器在遭受 SYN 攻击时迅速显现问题,而通过定时启动 sshd 允许你在预定时间窗口内登录服务器,进行维护或关闭受影响的服务。

优点:

  1. 控制登录窗口:通过 crontab 定时启动 sshd,你可以限制攻击者在非授权时间访问服务器,减少暴露面。
  2. 资源节省:调小半连接队列可以减少系统资源消耗,让你更快意识到攻击的存在并及时响应。
  3. 灵活应对:可以在 sshd 启动的时间段登录服务器,对系统进行手动调整或关闭服务。

缺点:

  1. 有限的可用性:合法用户在 sshd 非启动时间将无法访问服务器,这可能会影响正常运维和管理。
  2. 手动操作依赖:这个策略依赖于你手动介入,如果你无法在预定时间登录并采取行动,攻击仍可能导致系统瘫痪。
  3. 潜在的登录困难:在 SYN 攻击的高峰期,即使 sshd 启动了,登录服务器可能仍然困难,因为 SYN 攻击会影响到你连接的稳定性。

这个方案适合需要极度控制风险的环境,特别是当你无法部署更先进的防御措施时。然而,作为长期解决方案,它仍然存在局限性。你可能还需要考虑结合其他自动化监控和防护工具,以减少手动干预的依赖性并提高系统的整体防护能力。

4 我担心存在登录困难的情况,但是我仍坚持减小半连接队列,应该调整为多大

调小半连接队列的大小确实可以让你更早发现 SYN 攻击,但同时也可能导致合法连接被拒绝。队列大小的调整取决于你的服务器负载和使用情况,但如果你坚持这样做,以下是一些调整建议:

调整原则:

  1. 根据平时流量决定:你可以通过监控平时服务器的正常流量情况来决定。理想情况下,队列大小应至少能容纳平时高峰期的一半连接数。
  2. 逐步减小:可以从当前队列大小的 50% 开始尝试,如果队列默认是 1024,你可以尝试调整到 512 甚至更低。但要在测试环境下进行,确保不会严重影响正常的服务。
  3. 定期监控:在调整之后,密切监控服务器的连接情况,查看是否有合法连接因为队列满而被拒绝。

备用方案: 考虑到你担心登录困难,你也可以配置一个备用端口用于 SSH 登录,并通过防火墙或 IP 限制控制访问,以便在主端口被攻击时仍能进行管理。

总结: 最终的队列大小应根据你服务器的实际情况和流量特征来决定,并需要通过测试和监控不断调整。建议从较保守的设置开始,然后根据实际情况逐步优化。

5 攻击者发动ddos通常是出于什么原因

DDoS(分布式拒绝服务)攻击的动机因攻击者的目的和背景而异,常见的原因包括:

经济利益

  • 敲诈勒索:攻击者可能会通过DDoS攻击威胁企业,要求支付赎金以停止攻击。这种攻击通常针对依赖在线服务的公司,如电商网站、金融服务等。
  • 商业竞争:竞争对手可能雇佣攻击者对目标公司的网站或服务进行DDoS攻击,扰乱其业务,特别是在关键的销售或交易时间。

政治和社会动机

  • 黑客活动主义(Hacktivism):某些攻击者出于政治或社会原因,利用DDoS攻击表达抗议或反对某些组织、政府或企业的政策和行为。例如,攻击政府网站以抗议某项法律或政策。
  • 国家级攻击:某些国家可能会发动DDoS攻击作为一种网络战手段,目的是削弱敌国的关键基础设施或通信网络。

网络报复

  • 个人恩怨:个人之间的冲突,尤其是在网络游戏社区或社交媒体中,可能引发报复性DDoS攻击。
  • 黑客社区争端:黑客团体之间的冲突或竞争可能导致DDoS攻击,用以打击对手或展示力量。

技术炫耀

  • 展示技术能力:一些黑客或黑客组织可能会通过发起DDoS攻击来展示他们的技术能力和影响力,在黑客社区中获得声望。
  • 测试攻击工具:开发DDoS工具的黑客可能会在实际环境中测试他们的工具,以观察其效果。

随机破坏

  • 恶意破坏:有些攻击者只是为了破坏或制造混乱而发起DDoS攻击,没有特定的目标或理由。
  • 恶作剧:尤其在年轻的黑客中,有时DDoS攻击只是为了恶作剧,目标可能是朋友的网站、学校的服务器等。

掩护其他攻击

  • 分散注意力:DDoS攻击有时会作为其他更复杂攻击的掩护手段,使得目标的安全团队将注意力集中在DDoS上,而忽略了更隐蔽的入侵行为,如数据窃取或网络渗透。

不同的攻击者可能出于多种动机发起DDoS攻击,具体原因往往取决于攻击者的背景、目标,以及他们希望从攻击中获得的收益或效果。

6 还是不考虑可用性,直接关闭服务器攻击者是不是就没招了

直接关闭服务器确实可以使攻击者无法继续进行 DDoS 攻击,因为服务器已不再响应任何请求,这相当于完全切断了攻击目标。但这种做法有以下几点需要考虑:

优点:

  1. 立即终止攻击效果:关闭服务器后,攻击流量无法到达目标,攻击的直接效果被消除。
  2. 保护服务器资源:当服务器关闭时,CPU、内存等资源不会再被攻击流量消耗。
  3. 安全数据和系统:如果服务器在攻击期间处于关闭状态,可以防止潜在的安全漏洞被利用。

缺点:

  1. 完全丧失可用性:所有合法用户的访问也将被切断,这对于需要持续在线的服务或应用来说代价非常高。
  2. 可能影响恢复时间:关闭服务器后,恢复上线可能需要一些时间,特别是对于需要手动检查和重启的服务。
  3. 无法阻止攻击:攻击者可能会持续发送攻击流量,当你重新启动服务器时,攻击可能会立即恢复。

可行性:

  • 应急策略:作为一种应急策略,这在面对大规模攻击且没有其他可行防御措施时是有效的,尤其是当你的目标是保护服务器免受损坏或防止更大的问题时。
  • 攻击者的应对:虽然关闭服务器确实可以立即解除当前攻击的影响,但如果攻击者监控到了服务器的关闭,他们可能会等待服务器重新上线,继续发动攻击。因此,在重新启动服务器时,需要做好其他防御准备。

更好的方案:

  • 动态保护:在关闭服务器的同时,可以考虑将流量重定向到一个抗 DDoS 服务或云平台,或者通过防火墙限制攻击来源 IP。
  • 配合计划停机:如果你有计划的停机维护时间,可以在此时间段进行服务器关闭和攻击处理,避免在高峰期影响服务。

总的来说,关闭服务器是应对 DDoS 攻击的一种极端策略,适合在无法采取其他更复杂措施时使用。它能迅速解除攻击影响,但也会带来可用性上的巨大牺牲。

7 攻击者发起一次ddos的成本有多少,如何评估

评估攻击者发起一次 DDoS 攻击的成本需要考虑多个因素,包括攻击的类型、使用的资源、攻击的规模以及攻击者的技术水平。以下是一些影响 DDoS 攻击成本的主要因素:

攻击类型

  • 僵尸网络(Botnet):攻击者通常通过控制大量被感染的设备(僵尸网络)来发起 DDoS 攻击。如果攻击者拥有或租用了一个庞大的僵尸网络,他们的成本主要与维护这个网络有关。租用僵尸网络的成本根据规模和时长不同,一般从几百美元到几千美元不等。
  • 应用层攻击:这种攻击通常需要更少的流量,但需要更复杂的请求来耗尽目标服务器的资源。成本可能会较高,因为需要更高的技术水平或更复杂的工具。
  • 放大攻击:这种攻击利用反射器(如 DNS 服务器)发送大量放大后的流量。使用公开的服务作为放大器可以降低攻击者的成本,但也有可能因为流量较大而增加成本。

资源成本

  • 设备和带宽:如果攻击者使用自己的服务器或云资源,成本主要包括服务器的租赁费用和带宽成本。云平台的资源成本通常较高,具体费用取决于使用的时间和流量大小。
  • 攻击工具:一些攻击者可能会购买或租用专门的 DDoS 工具和服务,这些服务可以按时间或攻击量收费。基于现有市场,租用 DDoS 服务的价格通常在每小时几十到几百美元不等,取决于攻击的复杂性和规模。

技术水平

  • 自制工具 vs. 市场购买:技术高超的攻击者可能会自行开发攻击工具,这样可以节省购买工具的成本,但开发和维护这些工具本身需要时间和专业知识。如果攻击者选择购买或租用现成的工具或服务,成本会因工具的功能和攻击规模而有所不同。

规模和持续时间

  • 流量大小:攻击流量越大,攻击的成本越高。大规模的 DDoS 攻击可能需要大量的带宽和计算资源,从而增加成本。
  • 攻击持续时间:攻击持续的时间越长,所需的资源和成本越高。如果攻击需要持续数小时或数天,成本将显著增加。

黑市行情

  • 在黑市中,可以很容易地找到 DDoS 攻击服务,价格通常从几十美元到几千美元不等,具体取决于目标、攻击强度和持续时间。

估算成本的示例:

  • 小规模攻击:使用租用的僵尸网络或便宜的工具发起一次短时间的 DDoS 攻击,可能仅需 100-500 美元。
  • 大规模攻击:发起针对大型企业或关键基础设施的长时间大流量攻击,成本可能在几千到几万美元之间。

总结: DDoS 攻击的成本因攻击者使用的手段和规模而异,从几百美元的小规模攻击到数万美元的大规模、复杂攻击不等。成本评估需要结合攻击类型、使用资源和技术水平来综合考虑。

8 我的vps一年费用还不到100美元,看来不值得攻击啊

确实,对于每年费用不到 100 美元的 VPS,发动大规模 DDoS 攻击在经济上对攻击者来说可能不划算。攻击者通常会选择那些能够带来更大收益或影响的目标,如金融机构、大型企业或有政治意义的网站。

然而,即便成本较低的小型攻击,攻击者有时也可能出于其他动机,如测试攻击工具、恶作剧或随机破坏。但总的来说,如果你的 VPS 不是一个高流量或高价值的目标,遭受大规模 DDoS 攻击的可能性相对较低。

你可以采取一些基本的防护措施,降低受到攻击的风险,比如启用基本的防火墙规则,限制 SSH 访问,或者使用免费的 DDoS 防护服务。这样即使遇到小规模攻击,也能最大程度地保护你的 VPS。

9 tcp中有半连接队列和全连接队列,这两个队列的大小如何估算

在 TCP 中,半连接队列和全连接队列的大小估算对系统的网络性能和抗攻击能力至关重要。以下是如何估算这两个队列大小的指导:

半连接队列(SYN Queue)

半连接队列用于存放那些正在等待完成三次握手的连接,即已经接收到客户端的 SYN 报文并发送了 SYN-ACK,但还未收到客户端的 ACK 确认。

估算方法:

  • 流量分析:估算半连接队列的大小需要了解你的服务器通常在高峰期会处理多少并发连接请求。如果你的服务器在高峰时段每秒处理 100 个新的连接请求,并且每个连接平均需要 3 秒来完成握手,那么你需要一个至少 300 的队列大小。

    公式:队列大小 = 每秒新建连接数 × 平均握手时间(秒)

  • 硬件能力:半连接队列的大小也取决于你的系统资源,尤其是 CPU 和内存。对于 2 核 CPU 和 2 GB 内存的 VPS,建议半连接队列大小在 512 到 1024 之间。这为系统提供足够的缓冲空间以处理高峰负载。

  • 安全性考虑:如果你担心 SYN Flood 攻击,启用 SYN Cookies 是必要的,这样即使队列大小不足,也能确保合法连接不被轻易拒绝。

全连接队列(Accept Queue)

全连接队列是已经完成三次握手的连接等待应用程序处理的地方。如果应用程序不能及时处理这些连接,队列就会变满,新的连接将会被拒绝。

估算方法:

  • 应用处理能力:全连接队列的大小取决于应用程序处理连接的速度。如果你的应用每秒可以处理 200 个连接,且在高峰期系统最多有 2 秒的延迟,那么队列大小至少应为 400。

    公式:队列大小 = 每秒处理的连接数 × 处理延迟时间(秒)

  • 硬件与并发要求:2 核 2 GB 内存的 VPS 一般建议全连接队列大小设置为 256 到 1024,根据实际应用的并发需求进行调整。对于轻量级应用,256 可能足够,而对于更高并发的应用,1024 是一个较好的初始值。

综合考虑:

  • 平衡:如果设置过大的队列,可能导致内存占用过高,影响其他系统资源;而设置过小,可能导致在高并发下连接被拒绝。因此,在调整半连接和全连接队列大小时,需要结合服务器性能和应用需求找到一个平衡点。
  • 监控与调整:部署后,通过监控队列使用情况、应用响应时间和系统负载,动态调整队列大小,以适应不同的负载条件。

总结:

  • 半连接队列:建议设置为 512 到 1024 之间,根据你的服务器流量和硬件能力进行调整。
  • 全连接队列:建议设置为 256 到 1024 之间,取决于应用的并发处理能力和延迟要求。

这两个队列的大小应该通过实际测试和监控来进行细化调整,确保系统在面对高负载和潜在攻击时依然能够稳定运行。

10 如果开启syn cookie,并且半连接队列设置很小,同时全连接队列设置很大,这种方案能否提升性能并节约资源

开启 SYN Cookies,并将半连接队列设置得很小、全连接队列设置得很大,这种方案确实可以在特定场景下提升性能并节约资源,但它也有一些局限性。以下是这种方案的优缺点和适用情况:

优点:

  1. 资源节约
    • 减少半连接队列资源占用:开启 SYN Cookies 后,半连接队列的大小可以设得很小,因为 SYN Cookies 会使系统在半连接队列满的情况下,仍然能够处理新的连接请求。这样可以减少系统为维护半连接队列而消耗的内存资源。
    • 更高的全连接队列容量:你可以将更多的资源分配给全连接队列,确保更多的已建立连接可以等待应用程序处理,这对于高并发场景非常有利。
  2. 抗攻击能力增强
    • 防御 SYN Flood 攻击:SYN Cookies 的主要作用就是防御 SYN Flood 攻击。当半连接队列被填满时,系统不会简单地拒绝新的连接请求,而是通过 SYN Cookies 继续处理这些请求,从而有效地减轻 SYN Flood 攻击的影响。
  3. 更快处理合法连接
    • 加快连接建立速度:通过减小半连接队列,合法连接可以更快地从 SYN 阶段进入全连接状态(因为 SYN Cookies 直接跳过了某些验证),这在一定程度上加快了连接的建立。

缺点和局限性:

  1. 潜在的性能开销
    • SYN Cookies 的计算开销:虽然 SYN Cookies 能防御 SYN Flood 攻击,但其实现需要额外的计算操作,尤其是在高负载情况下,这可能带来一定的 CPU 开销。
  2. 连接特性受限
    • TCP 选项支持受限:在 SYN Cookies 模式下,某些 TCP 选项(如窗口缩放、时间戳等)不能被正确协商,这可能会影响某些应用的性能或可靠性。
  3. 极端高并发下的表现
    • 极端高并发连接的情况下,即便全连接队列很大,如果应用程序不能快速处理这些连接,请求可能会积压在全连接队列中,最终导致队列溢出和连接丢失。

适用场景:

  1. 资源有限的小型服务器:在资源有限的 VPS(如你的 2 核 2 GB VPS)上,这种方案可以节省内存和 CPU 资源,同时为高并发连接提供更好的处理能力。
  2. 面对小型 DDoS 攻击:这种配置在面对小型 DDoS(尤其是 SYN Flood 攻击)时表现较好,因为 SYN Cookies 可以有效防御队列耗尽的问题。
  3. 短时间内高峰流量:当服务器需要处理短时间内大量连接请求时,这种配置能够通过大容量的全连接队列来容纳更多合法连接,从而提升整体服务的可用性。

总结:

开启 SYN Cookies 并结合小的半连接队列和大的全连接队列确实可以在特定场景下优化性能,节约资源,并增强抗攻击能力。然而,这种方案的效果依赖于具体的应用场景和服务器负载情况。建议在实际应用中进行测试和监控,根据负载和性能表现进一步调整配置,以找到最佳平衡点。

11 我觉得内存比cpu重要,因为如果内存满了将会发生oom, 而cpu满了顶多反应慢些

你的观点是合理的。在服务器的资源管理中,内存的确通常比 CPU 更为关键,尤其是对于轻量级的 VPS 配置(例如 2 核 2 GB 内存的环境)。当内存耗尽时,系统可能会触发 OOM Killer 来释放内存,这会导致进程被强制终止,甚至可能影响到系统的稳定性和可用性。

优先考虑内存的策略:

  • 降低内存占用:在优化服务器时,优先确保内存使用不会过高,特别是在面对高并发请求时。通过减小半连接队列,可以减少内存占用,而开启 SYN Cookies 则能够有效防御连接泛滥带来的内存压力。
  • 合理配置全连接队列:虽然增大全连接队列能够提升并发处理能力,但需要确保该配置不会导致内存消耗过高。你可以根据实际负载情况,逐步调整全连接队列大小,并监控内存使用情况,以避免 OOM 的发生。

综合考虑:

  • 监控和调优:通过监控内存和 CPU 的使用情况,了解系统在不同负载下的表现,根据实际需要动态调整配置。

总之,考虑到你的环境和需求,优先保护内存资源是一个明智的策略。通过精细的配置和调整,可以在提升系统性能的同时,确保内存占用始终在安全范围内。

12 启用syn cookie后为什么还是有半连接队列丢弃syn包的现象

即使启用了 SYN Cookies,半连接队列仍然可能丢弃 SYN 包,这通常是由以下几个原因引起的:

半连接队列的物理限制

  • 初始队列满了:当半连接队列已经满了时,即使启用了 SYN Cookies,新的连接请求(SYN 包)最初仍然会被放入半连接队列。如果队列满了,这些 SYN 包会被丢弃。
  • SYN Cookies 是备用机制:SYN Cookies 作为一种备用机制,只有在半连接队列满的时候才会生效。如果服务器在启用 SYN Cookies 的情况下仍然丢弃了 SYN 包,说明这些包在队列满之前已经被丢弃,或者在队列满之前没有触发 SYN Cookies 的使用。

网络拥塞或延迟

  • 网络层的问题:在网络层,拥塞或延迟可能导致一些 SYN 包在到达服务器之前就被丢弃。这种情况与服务器的配置无关,而是由网络环境引起的。

系统资源限制

  • CPU或内存不足:在高负载情况下,即使启用了 SYN Cookies,系统的 CPU 或内存可能不足以处理大量的连接请求,导致系统无法及时响应,从而丢弃了一些 SYN 包。
  • 网络接口队列溢出:如果网络接口的接收队列(例如 NIC 的硬件队列)已满,那么到达的 SYN 包可能会在进入半连接队列之前就被丢弃。

攻击导致资源耗尽

  • 攻击的持续性:如果服务器遭受持续的 SYN Flood 攻击,可能会使得系统资源消耗过多,即便启用了 SYN Cookies,也会因为资源耗尽或系统响应迟缓而导致 SYN 包被丢弃。

配置问题

  • SYN Cookies 的有效性:检查是否正确启用了 SYN Cookies 以及相关的网络参数配置是否合理。错误的配置可能导致 SYN Cookies 不能正确工作,或使得队列溢出后没有触发 SYN Cookies。
  • 内核版本或系统特性:不同的内核版本或操作系统可能对 SYN Cookies 的实现有不同的处理方式,检查系统的内核版本和 SYN Cookies 的配置是确保其有效性的关键。

排查与优化建议:

  1. 检查队列配置:确认半连接队列和全连接队列的配置是否合理,适当增加半连接队列的大小,以减少 SYN 包被丢弃的可能性。
  2. 监控系统资源:使用系统监控工具(如 netstatsssar 等)查看队列使用情况、系统负载和资源使用情况,以找出潜在的瓶颈。
  3. 调优网络参数:可以通过调整 tcp_max_syn_backlogsomaxconn 等参数来优化队列行为,确保系统能更高效地处理高并发连接请求。
  4. 分析网络流量:使用流量分析工具(如 Wireshark、tcpdump)捕捉并分析网络包,查看是否有异常的丢包现象,以及是否有异常的流量模式,可能需要调整防火墙规则或其他安全策略。

总结: 启用 SYN Cookies 能有效防御 SYN Flood 攻击,但它不能完全解决所有导致 SYN 包丢失的问题。丢包现象可能与队列设置、系统资源限制、网络环境等多种因素有关。通过针对性的监控和优化配置,可以减少 SYN 包的丢失,提升系统的抗压能力。

13 在开启syn cookie的情况下,tcp_max_syn_backlog的配置是不是没用了

在启用 SYN Cookies 的情况下,tcp_max_syn_backlog 的配置仍然有一定的作用,但它的作用会有所不同。

正常情况下的作用

  • 当 SYN Cookies 没有被触发时,tcp_max_syn_backlog 仍然决定了半连接队列的大小。当收到一个 SYN 包时,内核会将该连接放入半连接队列,等待三次握手的完成。
  • 如果半连接队列的大小(即 tcp_max_syn_backlog 设置的值)被填满,新来的 SYN 包就会被丢弃,除非启用了 SYN Cookies。

SYN Cookies 被触发时的作用

  • 触发条件:SYN Cookies 只有在半连接队列满了的情况下才会被触发。一旦触发,内核不再依赖半连接队列来存储未完成的连接状态,而是通过计算出一个加密的 SYN Cookie 来代替保存状态信息。
  • 作用变小:当 SYN Cookies 被触发时,tcp_max_syn_backlog 的大小对新 SYN 包的处理不再有直接影响,因为新的连接不再需要占用半连接队列。
  • 恢复期作用:一旦 SYN Cookies 不再被触发(例如,负载降低,半连接队列再次有空位),tcp_max_syn_backlog 又会恢复其作用,控制半连接队列的大小。

实际配置建议

  • 配置仍然重要:尽管在 SYN Cookies 触发时,tcp_max_syn_backlog 不再直接限制新连接,但在系统正常运行且未触发 SYN Cookies 的情况下,tcp_max_syn_backlog 仍然决定着半连接队列的容量。因此,合理设置这个值依然很重要,特别是在轻载或正常负载下。
  • 合理设定:在启用了 SYN Cookies 的情况下,tcp_max_syn_backlog 的值可以设为一个适中大小,例如 512 或 1024,以便在负载增加时有足够的缓冲空间,延迟 SYN Cookies 的触发时间。

总结: 启用 SYN Cookies 后,tcp_max_syn_backlog 的配置在正常情况下仍然有作用,因为它决定了在未触发 SYN Cookies 时半连接队列的容量。一旦 SYN Cookies 被触发,tcp_max_syn_backlog 的影响会暂时减小,但它依然是系统配置的一部分,并在负载降低时重新发挥作用。因此,合理设置 tcp_max_syn_backlog 是必要的,即使在启用 SYN Cookies 的情况下。

相关配置

编辑 /etc/sysctl.conf,添加如下配置

SYN Cookies

shell
# 默认开启 net.ipv4.tcp_syncookies = 1 # 减小 syn+ack 重发次数,默认5次 net.ipv4.tcp_synack_retries = 5

半连接队列

shell
net.ipv4.tcp_max_syn_backlog = 128

全连接队列

shell
# 0 :如果 accept 队列满了,那么 server 扔掉 client 发过来的 ack ; # 1 :如果 accept 队列满了,server 发送一个 RST 包给 client,表示废掉这个握手过程和这个连接; net.ipv4.tcp_abort_on_overflow = 1 # 调整全连接队列长度 net.core.somaxconn = 1024

tcp挥手优化

shell
# FIN_WAIT1 net.ipv4.tcp_orphan_retries = 8 # 发送fin后等待ack的时长 net.ipv4.tcp_max_orphans = 16384 # 该状态下的最大数量 # FIN_WAIT2 net.ipv4.tcp_fin_timeout = 60 # 60s,等待对端fin的时长 # TIME_WAIT net.ipv4.tcp_max_tw_buckets = 5000# 超过后,新关闭的连接就不再经历 TIME_WAIT 而直接关闭 net.ipv4.tcp_tw_reuse = 1 # 只在客户端有用 复用处于 TIME_WAIT 状态的连接 net.ipv4.tcp_timestamps = 1 # 配合 tcp_tw_reuse 使用

使配置生效

shell
$ sysctl -p

测试

半连接

使用如下配置

shell
net.ipv4.tcp_syncookies=1 net.ipv4.tcp_synack_retries=5 net.ipv4.tcp_max_syn_backlog=128 net.core.somaxconn=4096

模拟syn flood

shell
# client 在国内 $ hping -S -p 443 --flood my-ip

服务器查看半连接队列大小

shell
# server 在日本 $ netstat -natp | grep SYN_RECV | wc -l # nginx 默认 backlog 为511 < 4096(somaxconn) 511

使用top观察各种指标,确发现 dashboard 毫无波澜。。。

全连接

使用如下配置

shell
net.ipv4.tcp_syncookies=1 net.ipv4.tcp_synack_retries=5 net.ipv4.tcp_max_syn_backlog=128 net.core.somaxconn=4096

http压测(nginx直接返回200 return 200 'hello world'

shell
# 6线程 3万个连接 持续60s $ wrk -t 6 -c 30000 -d 60s https://my-ip:443

服务器查看全连接队列大小

shell
$ ss -lnt | grep ":443" LISTEN 0 511 0.0.0.0:443 0.0.0.0:* # Recv-Q 始终是0

查看全连接队列溢出情况

shell
$ date;netstat -s |grep overflowed Sat Aug 17 09:14:17 AM CST 2024 1867 times the listen queue of a socket overflowed $ date;netstat -s |grep overflowed Sat Aug 17 09:14:28 AM CST 2024 2062 times the listen queue of a socket overflowed # 后续查看仍是2062

从整个测试情况来看,Recv-Q 始终是0,说明 nginx accep 的速度非常快,但是全连接队列在刚启动压测的一点时间内发生溢出,后续对半连接队列的观察发现也有溢出,半/全连接队列在溢出一定数量后均没有继续增加。对于这种现象不清楚具体是什么原因,请看 ChatGPT 对话12。

经过一系列的脑补我修改了 sysctl.conf

shell
net.ipv4.tcp_syncookies = 2

经过测试,还是存在半连接队列丢syn的情况。

但是我又联想到全连接队列也出现丢包现象,我猜是因为nginx没准备好accept。我没有看过linux内核源码,也不想看,我现在怀疑半连接队列受全连接队列的影响,如果全连接队列满了,即使有syn cookie也没用,该丢还是丢,下一步操作应该增大全连接队列的最大限制(不要忘了syn cookie 的值此时是2)

shell
# /etc/sysctl.conf net.core.somaxconn=30000 # nginx listen 443 ssl backlog=30000;

重新测试

shell
# 1 测试半连接队列 # 观察半连接队列溢出 $ netstat -s | grep "SYNs to LISTEN" 4351 SYNs to LISTEN sockets dropped # 启动http压测 $ wrk -t 6 -c 30000 -d 60s https://my-ip:443 # 再次观察半连接队列溢出 4351 SYNs to LISTEN sockets dropped # 2 观察全连接队列 $ ss -lnt | grep ":443" LISTEN 31 30000 0.0.0.0:443 0.0.0.0:* # 省略http压测命令。。。 # 再次观察全连接队列 LISTEN 0 30000 0.0.0.0:443 0.0.0.0:* # 3 观察全连接队列溢出 $ date;netstat -s |grep overflowed Sat Aug 17 10:32:00 AM CST 2024 4337 times the listen queue of a socket overflowed # 省略http压测命令。。。 # 再次观察全连接队列溢出 $ date;netstat -s |grep overflowed Sat Aug 17 10:32:18 AM CST 2024 4337 times the listen queue of a socket overflowed

结果令我欣喜,半/全连接队列没有发生溢出,并且观察到全连接队列有堆积,然后堆积就消失了。我又使用free查看了内存没有明显变化,可能是因为nginx没有复杂业务逻辑的原因。

测试命令整理

shell
# 查看全连接队列 # -l 显示正在监听的socket # -n 不解析服务名称 # -t 只显示tcp socket # Recv-Q 全连接队列大小 # Send-Q 全连接队列最大大小 $ ss -lnt # 查看全连接队列溢出情况 $ date;netstat -s |grep overflowed # 查看半连接队列 $ netstat -natp | grep SYN_RECV | wc -l # 查看半连接队列溢出 $ netstat -s | grep "SYNs to LISTEN" # http压测 # 6线程 3万个连接 持续60s $ wrk -t 6 -c 30000 -d 60s https://my-ip:443 # 模拟 syn flood $ hping -S -p 443 --flood ip

Go 中如何设置 backlog?

Go现在还不能直接使用net包设置,以下是使用syscall包来自定义listen

go
package main import ( "fmt" "net" "os" "syscall" ) func main() { // 使用 syscall 创建套接字 fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err != nil { fmt.Println("Error creating socket:", err) os.Exit(1) } // 绑定地址和端口 addr := syscall.SockaddrInet4{Port: 8080} copy(addr.Addr[:], net.ParseIP("0.0.0.0").To4()) err = syscall.Bind(fd, &addr) if err != nil { fmt.Println("Error binding socket:", err) os.Exit(1) } // 设置 backlog 大小 backlog := 1024 err = syscall.Listen(fd, backlog) if err != nil { fmt.Println("Error listening on socket:", err) os.Exit(1) } // 将文件描述符转换为 net.Listener f := os.NewFile(uintptr(fd), "") ln, err := net.FileListener(f) if err != nil { fmt.Println("Error creating listener:", err) os.Exit(1) } defer ln.Close() fmt.Println("Listening on :8080 with backlog size", backlog) for { conn, err := ln.Accept() if err != nil { fmt.Println("Error accepting connection:", err) continue } go handleConnection(conn) } } func handleConnection(conn net.Conn) { defer conn.Close() // 处理连接 }

参考

本文作者:jdxj

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!