前言
我们正在测试一些基于主机的 IPS。在这个测试用例中,我们的应用程序正在侦听环回,并且应用程序正在以明文形式接收流量。我们使用 nginx 或 haproxy 来终止公共接口上的 TLS。我们的 IDP 将监视环回,以便它可以看到未加密的流量。
我们的 IDP 看到格式错误/不正确的日期,因此我们开始深入挖掘。
[更新 2]正如@kasperd 提到的,tcpdump 正在从操作系统获取时间戳。也就是说,事实证明,除了 tcpdump 之外,这个 bug 实际上还会触发 IDP。它看到了 connection_established,但没有看到有效的 http 会话,因为 syn-ack 无效。
已在 redhat.com 和 centos.org 上提交了一个错误。
观察
环回上的第一个同步确认总是有一个接近纪元开始的日期,或者在虚拟机上的 2 年内。从1970 年 12 月到1973年 2 月,这在 VM 上变化很大,而在裸机 Xeon 服务器上则远未到来。 NTP在我们所有的虚拟机和裸机服务器上都是正确的,漂移小于 50 毫秒。
这只发生在环回上。我们从未在服务器上的 bond0 或 VM 上的 eth0 上看到这一点。
测试服务器和笔记本电脑
操作系统: CentOS 7
平台:
戴尔 20 核至强服务器(裸机主机操作系统)
HP 20 Core Xeon 服务器(裸机主机操作系统)
MacOS 上的 VirtualBox
具有 6 个虚拟内核的 Lenovo P50 上的 Windows 10 Enterprise 上的 Hyper-V。
一台基于 Celeron 4 Core 1.6 GHz 的路由器(无法在 Celeron 上重现)
重现步骤
在每个平台上,我们在环回的 80 端口上启动一个 Web 侦听器。
./simple_python 127.0.0.1 &
上面的代码在这里
然后我们启动tcpdump
tcpdump -p -NNnn -XXxx -tttt -vv -s0 -c2 -i lo &
然后我们 curl 到 localhost
curl -s -o /dev/null http://127.0.0.1/
输出
2018-04-10 21:05:30.087769 IP (tos 0x0, ttl 127, id 49233, offset 0, flags [DF], proto TCP (6), length 60)
127.0.0.1.25134 > 127.0.0.1.80: Flags [S], cksum 0xfe30 (incorrect -> 0xce27), seq 4053136920, win 65495, options [mss 65495,sackOK,TS val 22951497 ecr 0,nop,wscale 13], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c c051 4000 7f06 3d68 7f00 0001 7f00 .<.Q@...=h......
0x0020: 0001 622e 0050 f195 f618 0000 0000 a002 ..b..P..........
0x0030: ffd7 fe30 0000 0204 ffd7 0402 080a 015e ...0...........^
0x0040: 3649 0000 0000 0103 030d 6I........
1973-02-14 22:12:10.785902 IP (tos 0x0, ttl 127, id 0, offset 0, flags [DF], proto TCP (6), length 60)
127.0.0.1.80 > 127.0.0.1.25134: Flags [S.], cksum 0xfe30 (incorrect -> 0x2f28), seq 3928063281, ack 4053136921, win 65483, options [mss 65495,sackOK,TS val 22951497 ecr 22951497,nop,wscale 13], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c 0000 4000 7f06 fdb9 7f00 0001 7f00 .<..@...........
0x0020: 0001 0050 622e ea21 7d31 f195 f619 a012 ...Pb..!}1......
0x0030: ffcb fe30 0000 0204 ffd7 0402 080a 015e ...0...........^
0x0040: 3649 015e 3649 0103 030d 6I.^6I....
在任何情况下,syn-ack 在 VM 上总是在 1970 到 1973 年之间的某个日期,而在 Xeon 上则是未来的某个日期。
- 我可以在每个平台上100%地重现这个,除了赛扬。我们不在数据中心使用赛扬。我只是想找到一些不受影响的东西。
我还试图让这一切消失吗?
- 我曾尝试使用
taskset
. - 我尝试设置影响 libc 的不同变量,例如 TZ、LANG、LC_ALL 等...
- 我已经尝试禁用接口的所有卸载功能,尽管它是一个环回并且那些实际上不应该做任何事情。
- 我尝试了一些不同的 sysctl 设置。
- 我尝试在 tcpdump 中使用不同的 snaplen。(我知道有关 snaplength 的一些历史问题)
- 我验证了硬件时钟是正确的。
我没有尝试过的
- 我没有尝试设置接收流转向,因为我们不会在没有充分理由的情况下在我们的数据中心执行此操作。
- 可能还有很多其他的事情我可以尝试,但这看起来真的像是某种 libc / 缓冲区 / 竞争条件错误。
关于这可能发生在 Linux 代码中的什么位置的任何想法?由于我不是 C 开发人员,因此我对深入研究 glibc 犹豫不决。
[更新] @jackthecoiner似乎发现了其他人也遇到了这个问题,并且到目前为止还没有收到关于 Redhat 网站的任何反馈。
我在CentOS 错误跟踪器中提交了此文件,并很快得到确认,他们建议我将其移至Redhat 内核错误跟踪器
从那里,Redhat 开发人员指出此错误是 bz1473533 的欺骗,已在kernel-3.10.0-703.el7中修复。对于 CentOS,已确认这已在 7.5 beta 内核 (830.el7) 中得到修复。