NAT网关自动去掉TCP syn包的时间戳

解决访问客户端位nat模式服务端syn握手失败的问题 阅读详情
                猛士设计了Netfilter,在失眠的时候就有事做了,安息日应守为圣日,否则会激怒神,因此双休日我一般不学习和工作,相反,我会在午夜玩一些自己喜欢的东西。我没有受过洗,不是因为不是笃信者,没有安息夜...

NAT和timestamps问题

这个问题就不多说了,总之,NAT设备将所有数据包的大量不同的源地址都转换为了单一的或者少数几个地址,这个转换动作和TCP服务器的PAWS机制一起工作的时候会导致无法新建连接的问题。

解决办法

简单的讲,解决办法有两个,一个是在客户端禁掉TCP的时间戳机制,另一个是在TCP服务端禁掉TCP的时间戳机制,可是一般而言,这两个地方都不是我们所能控制的,比如,你能禁掉每一个智能手机的TCP时间戳,也不能指望手机用户去做这件事,你同样也不能指望可以顺利地禁掉服务器的TCP时间戳,于是,第三个办法就出炉了,那就是在中间的NAT设备上修改掉TCP数据包,实际上只要修改TCP初始化的SYN包即可,将时间戳选项去掉,只所有这么做是可行的,归功于TCP协议和IP协议的协议头是规则且简单的。

关于TCP协议头的options与NOP

任何协议,如果没有被设计成可扩展性的,那它就不是一个好的协议。一个好的协议,在其基础部分应该取定长的格式,而其扩展的部分,应该是一定范围内的变长格式,不管是IP协议还是TCP协议,协议头都有一个“头长度”这么一个字段,该字段正是为了表示所谓的扩展协议头,否则如果都是定长的,也就不需要该字段了,因此可以说,IP协议和TCP协议都是比较好的协议。

        识别了协议好坏的标准之后,扩展字段如何布局就纯粹成了一个编码问题,一般而言,“类型-长度-值”的方式是首选,它可以很方便的编码任意类型,任意长度的扩展字段,在TCP的协议头扩展中,其名称叫做options,即TCP选项,它便是采用了上述的编码方式,每一个选项我可以称之为一个“块”,整个TCP options由多个块组成,每一个块由下面的结构组成:



注意,有一种TCP选项叫做NOP,它是为了确保TCP协议头结束在4字节对齐的位置,我们可以从RFC793的3.1节看出:
Padding:  variable
    The TCP header padding is used to ensure that the TCP header ends
    and data begins on a 32 bit boundary.  The padding is composed of
    zeros.

在本文中,我心爱的NOP并不是为了填充的,而是为了用其替换时间戳选项。我不知道别的系统怎么处理NOP,反正在Linux中,是直接忽略NOP,而这种忽略正是提供了一种将时间戳选项替换为NOP的可能性。

代码与解释

Netfilter原则上可以将所有的数据包“偷走”,从标准协议栈偷走,这么极端的事它都可以做,还有什么不能做的呢?和往常一样,还是写一个iptables的module,包括两个组件,一个是内核模块,另一个是iptables的用户态模块。我依然将取名字这件事搁置,因此我的这个target姑且确定为YYY,内核模块代码如下:
/* *      xt_yyy - kernel module to drop TCP timestamps * *      Original author: Wanagran <marywangran@126.com> */#include <linux/module.h>#include <linux/netfilter/x_tables.h>#include <linux/netfilter.h>#include <linux/skbuff.h>#include <linux/tcp.h>#include <net/tcp.h>#include <linux/ip.h>#include "compat_xtables.h"MODULE_AUTHOR("Wanagran <marywangran@126.com>");MODULE_DESCRIPTION("Xtables: yyy match module");MODULE_LICENSE("GPL");MODULE_ALIAS("ipt_yyy");static unsigned intyyy_tg4(struct sk_buff **skb, const struct xt_action_param *par){        const struct iphdr *iph = (struct iphdr *)((*skb)->data);        struct tcphdr *hdr;        unsigned int hdroff = iph->ihl*4;        int datalen = (*skb)->len - hdroff;        int hdrsize = 8; /* TCP connection tracking guarantees this much */        const unsigned char *ptr;        unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];        int length;        int recalc = 0;        if (iph->protocol != IPPROTO_TCP) {                return XT_CONTINUE;        }        hdr = (struct tcphdr *)((*skb)->data + hdroff);        /**         *      以下这个判断不适合在代码中写死,因为:         *      iptables完全可以用TCP的flags match来完成这个判断         *         *      if (!hdr->syn) {         *              return XT_CONTINUE;         *      }         *         *      另外,很多人应该觉得检查一下conntrack是否已经加载,如果没有加载就         *      直接CONTINUE,但是我没有这么做,因为NAT的实现并不一定要基于conntrack         */        if ((*skb)->len >= hdroff + sizeof(struct tcphdr))                hdrsize = sizeof(struct tcphdr);        if (!skb_make_writable(skb, hdroff + hdrsize))                return XT_CONTINUE;        length = (hdr->doff*4) - sizeof(struct tcphdr);        ptr = skb_header_pointer(*skb, sizeof(struct tcphdr) + hdroff,                                 length, buff);        while (length > 0) {                int opcode=*ptr++;                int opsize;                switch (opcode) {                        case TCPOPT_EOL:                                returni XT_CONTINUE;                        case TCPOPT_NOP:        /* Ref: RFC 793 section 3.1 */                                length--;                                continue;                        case TCPOPT_TIMESTAMP:                        {                                int i = 0;                                char *base = ptr-1;                                opsize=*ptr;                                /**                                 *      为了减少数据移动以及指针移动,进而减少内存拷贝                                 *      我只是将时间戳替换成了NOP而已                                 */                                for (; i < opsize; i++, base++) {                                        *base = 0x01;                                }                                recalc = 1;                        }                        default:                                opsize=*ptr++;                                length -= opsize;                                ptr += opsize - 2;                }        }        /**         *      改变了TCP头后,重新计算校验码是必然的,但是以下的         *      代码太粗糙,因为它没有考虑硬件也有能力计算校验码         *      这么一件事!         */        if (recalc) {                hdr->check = 0;                hdr->check = tcp_v4_check(datalen,                                        iph->saddr, iph->daddr,                                        csum_partial(hdr,                                                datalen, 0));        }        return XT_CONTINUE;}static struct xt_target yyy_tg_reg[] __read_mostly = {        {                .name           = "YYY",                .revision       = 1,                .family         = NFPROTO_IPV4,                .target         = yyy_tg4,                .me             = THIS_MODULE,        },};static int __init xt_yyy_target_init(void){        int status = 0;        status = xt_register_targets(yyy_tg_reg, ARRAY_SIZE(yyy_tg_reg));        if (status < 0) {                printk("YYY: register target error\n");                goto err;        }err:        return status;}static void __exit xt_yyy_target_exit(void){        return xt_unregister_targets(yyy_tg_reg, ARRAY_SIZE(yyy_tg_reg));}module_init(xt_yyy_target_init);module_exit(xt_yyy_target_exit);


该有的解释都在注释里面了。用户态的模块就不贴出了了,例行公事而已,没有任何逻辑,毕竟目前的版本YYY target不需要任何参数。

YYY模块的使用

只需要简单地在NAT网关添加一个iptables规则:
iptables -A FORWARD -p tcp -......-j YYY
接下来的时间里,你将不会再面对NAT设备的TCP timestamps的问题了。值得注意的是,由于TCP服务端仅仅针对新建连接来做检查,因此可以不必对非SYN包来做YYY target,我自己在测试的时候,抓包结果如下:

新建连接的SYN包:




ESTABLISHED状态的非SYN包:



感悟

对于一个在IT领域从业5年以上的人而言,任何问题靠技术手段解决都不是个事,关键是如何彻底地解决,相比于每次重复相同的排障过程,一次性解决会好很多,当然,这也许会减少一些出头露面的机会。这个timestamps+NAT问题是如此简单,以至于百行量级的代码就能搞定,但是为何加入这项功能的设备却如此之少,反之,网上的这方面的文章却是汗牛充栋(当然我也贡献过几篇)。难道是因为有些服务器确实要用到timestamps吗?而正常的理由就是,不能改变TCP的语义!我想骂了,NAT保留IP的语义了吗?它为何后来成了标准的东西,原始的IP语义是希望任意IP主机可以仅依靠IP路由双向互联互通,结果有了状态NAT以后,事情复杂了,于是更加复杂的各种打洞技术被呼唤出来,几年前我曾经遇到过一个人,自诩他实现的打洞技术世界第一,我C-T-M-D,他就是一小丑!           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow

Linux同时开启tcp_tw_recycle和tcp_timestamps导致TCP syn有时不响应故障排查 问题描述 前几天,同事反馈从公司连接线上一台服务器有时候会失败,经过抓包发现,TCP握手过程失败。查了相关资料,发现是跟net.ipv4.tcp_tw_recycle和net.ipv4.tcp_timestamps两个参数有关,将net.ipv4.tcp_tw_recycle改为0,问题解决。 排查过程 在PC上通过wireshark抓包发现,失败的时候,TCP syn包是一直在重传的。在server端通过tcpdump抓包发现,PC侧发的syn包是已经到达,所以基本排除网络问题。tcpdump抓包中确实看 阅读详情

相关推荐

听懂TCP三次握手:从SYN到ESTABLISHED的实战真相

TCP连接不是简单的‘建立通道’,而是客户端与服务端通过序列号、窗口、时间戳等参数完成的状态同步与能力协商过程。其核心原理在于利用三次握手实现可靠初始化,抵御丢包、延迟与乱序干扰,从而为后续数据传输奠定可信基础。这一机制直接决定高并发建连成功率、IoT设备在线稳定性及直播首屏时延等关键指标。深入理解SYN/SYN-ACK/ACK每个报文携带的MSS、SACK、TSval等选项含义,结合ss、tcpdump、Wireshark等工具诊断真实链路行为,是网络调优与故障排查不可替代的技术能力。

aobai7842的博客 436

[转]NAT网络下TCP连接建立时可能SYN包被服务器忽略-tcp_tw_recycle

转自:http://chenzhenianqing.cn/articles/1150.html

dabang_007的专栏 998

深入TCP协议——tcp_tw_reuse和tcp_tw_recycle

我们已经知道TCP四次挥手中,主动方在收到被动方的FIN数据包之后会进入TIME_WAIT状态等待2MSL的时间后才进入CLOSED。在 Linux 操作系统下,TIME_WAIT 状态的持续时间是 60 秒,这意味着这 60 秒内,客户端一直会占用着这个端口,这是有一定的开销的。如果如果主动关闭连接方的 TIME_WAIT 状态过多,占满了所有端口资源,则会导致无法创建新连接。

qq_25046827的博客 7604

NAT环境下tcp_timestamps问题

tcp_tw_recycle参数用来快速回收TIME_WAIT连接,不过如果在NAT环境下会引发问题。 RFC1323中有如下一段描述: An additional mechanism could be added to the TCP, a per-hostcache of the last timestamp received from any connection.Thi

〓☆〓 清风徐来918 (QQ:89617663) 3932

字节秋招二面:SYN报文什么情况下会被丢弃?我直接懵逼了

大家好,我是小林。 之前有个读者在秋招面试的时候,被问了这么一个问题:SYN 报文什么情况下会被丢弃? 好家伙,现在面试都问那么细节了吗? 不过话说回来,这个问题跟工作上也是有关系的,因为我就在工作中碰到这么奇怪的问题。 客户端向服务端发起了连接,但是连接并没有建立起来,通过抓包分析发现,服务端是收到 SYN 报文了,但是并没有回复 SYN+ACK(TCP 第二次握手),说明什么 SYN 报文被服务端忽略了,然后客户端就一直在超时重传 SYN 报文,直到达到最大的重传次数。 接下来,我就给

wdjnb的博客 1801

matlab2021a版本条件下安装spm

SPM (Statistical Parametric Mapping),中文名叫统计参数映射。统计参数映射是指构建和评估空间扩展的统计过程,用于测试关于功能成像数据的假设。这些想法已经在名为SPM的免费开源软件中得到了实例化。SPM软件包用于脑成像数据序列分析。目前的版本可以分析fMRI, PET, SPECT, EEG和MEG。 可能由于matlab版本更新的问题,按照之前教程所写的安装方法会出现错误,踩了一些坑,但好在最终解决了。。。 1、下载链接,如下 SPM12 Software -...

qq_42356925的博客 8405

SYN 包在什么场景下会被丢弃?

大家好,我是小林。 之前有个读者在秋招面试的时候,被问了这么一个问题:SYN 报文什么时候情况下会被丢弃? 好家伙,现在面试都问那么细节了吗? 不过话说回来,这个问题跟工作上也是有关系的,因为我就在工作中碰到这么奇怪的时候,客户端向服务端发起了连接,但是连接并没有建立起来,通过抓包分析发现,服务端是收到 SYN 报文了,但是并没有回复 SYN+ACK(TCP 第二次握手),说明 SYN 报文被服务端忽略了,然后客户端就一直在超时重传 SYN 报文,直到达到最大的重传次数。 接下来,我就给出我遇到过 SYN

小林coding 1万+

电镀技术:微型制造的原子级加法工艺与核心优势

电镀是一种利用电解原理在基材表面沉积金属层的表面处理技术,其本质是通过电场控制溶液中金属离子的迁移与还原,实现原子级的可控沉积。这一过程的核心在于对电流密度、温度、添加剂等参数的精密调控,从而实现对镀层结晶结构、性能的“编程”。从技术价值看,电镀作为一种“加法制造”工艺,在微观尺度上具有无与伦比的保形性和材料灵活性,能够实现复杂三维结构的均匀覆盖与功能复合。在应用场景上,它尤其契合现代微型化制造的需求,例如在集成电路的铜互连填充、高密度PCB板微孔金属化、MEMS传感器电极制备以及柔性电子器件制造中发挥着不

weixin_42524842的博客 527

客户端第二次连接失败,SYN包发了,没有收到服务端回 SYN+ACK ,SYN包被丢弃了

一、问题 最近测试一个音视频项目,APP在第一次流程中,所有信令都走完了,然后断掉连接,清理现场后。第二次重新连接服务,进行第二次业务的时候缺失败了。 测试1: 使用WEB测试,在不同分公司电脑打开是可以连接服务器的,成功。 测试2: 在本地局域网打开APP,然后打开web连接测试,失败。 测试3: 在本地局域网打开APP,然后手机使用wifi打开web连接测试,失败。 测试4: 在本地局域网打开APP,然后手机使用4G网络打开web连接测试,成功。 测试5: 在别的服务器机器,正常

thehunters的专栏 3745

教你搞懂RT-Thread的移植和配置ENV工具环境

RT-Thread的移植和配置ENV工具环境

Troubadour~的博客 8259

Visual studio 2013 配置 Halcon 13 (非抄袭)

Visual studio 2013 配置 Halcon 13.0.2.2 (其他版本适用) 针对网上抄袭的配置方法均不可用,写了一篇亲试可行的配制方法。如下: 1.下载Halcon安装后(C:\Program Files\MVTec\HALCON-13.0) 添加环境变量,(按下win按键,键入“环境变量”,出现 “编辑系统环境变量”后按下enter即可打开,下方找到“环境变量”按钮)的系...

huyanjackson的专栏 1039

Linux默认开启TCP时间戳导致syn-ack不能返回(不能返回响应数据)

Linux默认开启TCP时间戳导致syn-ack不能返回(不能返回响应数据)

HaleyTiger的博客 3688

LittleFS+NANDFLASH软硬件配置详情

littleFS文件系统说明及移植过程

weixin_43200844的博客 2368

TCP SYN报文什么情况下会被丢弃?

TCP SYN报文什么情况下会被丢弃? SYN 报文被丢弃的两种场景: 开启 tcp_tw_recycle 参数,并且在 NAT 环境下,造成 SYN 报文被丢弃 accpet 队列满了,造成 SYN 报文被丢弃 tcp_tw_recycle 我们知道对于TIME_WAIT状态,Linux 操作系统提供了两个可以系统参数来快速回收处于 TIME_WAIT 状态的连接,这两个参数都是默认关闭的: net.ipv4.tcp_tw_reuse,如果开启该选项的话,客户端(连接发起方) 在调用 connec

qq_41105501的博客 1027

GIS常用符号化色带(超级色带)根据python制作

GIS自带的色带比较单一,今天分享一款色带,应用之后大家出图的时候可以选择更多的配色,符号化/点击色块/样式引用/将样式添加至列表即可。色带类型比较多,大家可以自己尝试下不同的风格。简单符号化一下,看看效果。以中国县级行政区划为例,

J_Giser的博客 2636

AD22等长布线规则

本文介绍了PCB布线中实现信号线等长的详细操作步骤:1.创建网络类(NetClass),将需要等长的信号线归入同一组;2.设置高速布线规则(High-SpeedRule),定义等长容差等参数;3.进行交互式等长布线(InteractiveLengthTuning),使用蛇形线调整线长;4.实时调整与最终检查,确保所有网络满足等长要求。文中还提供了实用技巧,如使用快捷键调整蛇形线参数、为关键信号设置更严格规则等。操作需在PCB设计软件中完成,通过统一管理、规则设置和精确调整来实现信号同步传输。

whm128的博客 1556

SYN报文什么时候会被丢弃?

开启tcp_tw_recycle参数,并且在NAT环境下,造成syn包丢弃 tcp最后挥手时,需要发起关闭方等待2MSL时间后才能关闭,Linux提供了两个系统参数可以快速回收time_wait状态的连接,这两个参数都是默认关闭的。 net.ipv4.tcp_tw_reuse:如果开启该选项的话,tcp在新建连接时,会自动选择time_wait状态超过1s的连接来进行复用,该选项只适用于连接方 net.ipv4_tcp_tw_recycle:如果开启该选项的话,允许处于time_wait状态的连接快速回收

small_engineer的博客 2585

实战篇(七):使用Processing和PixelFlow库创建交互式流体太极动画

类:用于配置流体运动的参数,比如圆的位置、半径、运动的角度和速度以及颜色等。类:实现了接口,用于更新流体物理仿真的状态,同时整合声音输入作为流体动态变化的一部分。my_update方法:是流体物理仿真更新的核心,它计算流体粒子的速度和位置,并且将这些数据传递给流体库来模拟流动。现在,让我们进一步分析并解释每个部分的作用以及如何操作。float x;// 圆心位置xfloat y;// 圆心位置y// 半径// 是否是顺时针// 圆周运动,弧上的点位置,以及上一帧的点位置// 角度。

帅小柏的博客 1633

SYN 报文什么时候情况下会被丢弃?

客户端向服务端发起了连接,但是连接并没有建立起来,通过抓包分析发现,服务端是收到 SYN 报文了,但是并没有回复 SYN+ACK(TCP 第二次握手),说明 SYN 报文被服务端忽略了,然后客户端就一直在超时重传 SYN 报文,直到达到最大的重传次数。

wdj_yyds的博客 562

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

SYN被丢弃的场景分析

net.ipv4.tcp_tw_reuse,如果开启该选项的话,客户端(连接发起方) 在调用 connect() 函数时,**如果内核选择到的端口,已经被相同四元组的连接占用的时候,就会判断该连接是否处于 TIME_WAIT 状态,如果该连接处于 TIME_WAIT 状态并且 TIME_WAIT 状态持续的时间超过了 1 秒,那么就会重用这个连接,然后就可以正常使用该端口了。防止具有相同四元组的旧数据包被收到,也就是防止历史连接中的数据,被后面的连接接受,否则就会导致后面的连接收到一个无效的数据,

m0_63310537的博客 1166

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

SYN Cookie 分析

攻击者伪造大量源 IP 发送 SYN 包,服务器返回 SYN+ACK 后无法收到真实 ACK 响应,导致半连接队列被填满,资源耗尽无法处理正常请求。验证公式:Hash(Secret + S_IP + S_PORT + D_IP + D_PORT + Timestamp) == 序列号。通过将 SYN Cookie 与流量清洗、IP 信誉系统联动,可构建更完善的 DDoS 防御体系,在保证服务可用性的同时降低资源消耗。每次验证需执行哈希计算,比传统方案增加约 10% CPU 开销,但节省 90% 内存资源。

lxadccs的专栏 1261

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

上一篇: 关于TCP CORK的一个细节
下一篇: 闲来无事看两个好玩的C语言面试题
满舅舅
博客等级 码龄8年 71粉丝 218原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值