我只是想对此有所了解,因为我真的不明白为什么会出现这种情况。
再往下是网络服务器在收到正常 GET 请求时给出的“HTTP”响应的 TCPDUMP 输出(tcpdump -s0 -XXnni eth0 tcp port 80)。我尝试使用 Linux u32 tc 过滤器匹配 TCP ack 数据包的内容,在 TCP ack 数据包的数据有效负载中查找字符串“HTTP/1.[01] 200”(换句话说,查找典型的“HTTP/1.0 200 OK”响应或“HTTP/1.1 200 OK”响应)。
以下是 tc filter 命令的片段 - 这可能有助于理解上下文:
tc filter add dev eth0 parent ffff: protocol ip u32 \
match ip protocol 6 0xff \
match ip sport 80 0xffff \
match u8 0x10 0xff at 33 \
match u32 0x48545450 0xffffffff at 52 \
match u32 0x2f312e31 0xfffffffe at 56 \
match u32 0x20323030 0xffffffff at 60 \
<do something>
最后 3 个“match u32”行将匹配“HTTP/1.0 200”或“HTTP/1.1 200”,而 u8 行匹配 TCP ack 标志,其他行匹配源端口 80 协议 TCP。
我的问题是 - 为什么在两个不同的 Linux 机器上,我必须将数字 52、56 和 60 更改为 40、44 和 48?(从偏移量中减去 12)。似乎在我家里的 Slackware Linux 机器上,我必须使用 52、56 和 60,而在 RedHat/CentOS 服务器上,我必须使用 40、44 和 48。
原因很简单;比较每个服务器的这两个 TCPDUMP:
Slackware: 0x0000: 0040 63c9 c3a0 0018 7d05 dd11 0800 4500 .@c.....}.....E.
0x0010: 05be d41c 0000 3606 9ea2 4266 0963 c0a8 ......6...Bf.c..
0x0020: 000a 0050 a278 e948 dcdb fa41 ac84 8010 ...P.x.H...A....
0x0030: 0059 3cb2 0000 0101 080a 9380 9172 0008 .Y<..........r..
0x0040: 3bea 4854 5450 2f31 2e31 2032 3030 204f ;.HTTP/1.1.200.O
RedHat or: 0x0000: 0016 3e32 3fcf 0010 dbff 2050 0800 4500 ..>2?......P..E.
CentOs: 0x0010: 0554 cf64 0000 3706 e08b 4266 0969 0a64 .T.d..7...Bf.i.d
0x0020: 7881 0050 b316 c917 2062 b4a8 cff4 5018 x..P.....b....P.
0x0030: 005a a17f 0000 4854 5450 2f31 2e31 2034 .Z....HTTP/1.1.4
0x0040: 3034 204e 6f74 2046 6f75 6e64 0d0a 436f 04.Not.Found..Co
如您所见,两种情况下“HTTP”部分(数据包有效负载)的起始偏移点不同。这是为什么?又是什么原因造成的?
在此先感谢任何能向我解释这个谜团的人。
答案1
找到答案了。启用 TCP 时间戳会引入 12 字节的额外标头信息,从而导致偏移差异。
您可以通过以下步骤在 Linux 中打开/关闭它们:
echo 0 > /proc/sys/net/ipv4/tcp_timestamps
echo 1 > /proc/sys/net/ipv4/tcp_timestamps
还可以通过执行以下操作查看它们是否打开/关闭:
cat /proc/sys/net/ipv4/tcp_timestamps
答案2
我发现这也许能解决问题。
http://linux-tc-notes.sourceforge.net/tc/doc/cls_u32.txt
标题偏移
IP 标头(和其他标头)的长度是可变的。如果您尝试使用“match”查看后面标头中的值,就会出现问题 - 您不知道它在哪里。这并非不可能解决的问题,因为 IP 数据包中的每个标头都包含一个长度字段。u32 的“标头偏移”功能允许您从数据包中提取该长度,然后将其添加到“match”选项中指定的偏移量。
它的工作原理如下。回想一下,匹配选项如下所示:
match u32 VALUE MASK at OFFSET
我之前说过,OFFSET 告诉内核要将数据包中的哪个字与 VALUE 进行比较。该语句是一种简化。可以将另外两个值添加到 OFFSET 以确定要使用哪个字。这两个值都从 0 开始,但当“链接”选项调用另一个筛选器列表时,它们可以被修改。所做的任何修改仅适用于执行被调用的筛选器列表时,因为如果被调用的筛选器列表无法对数据包进行分类,则会恢复旧值。以下是两个值以及我给它们起的名字:
permoff This value is unconditionally added to every OFFSET
that is done in the destination link, ie that one
that is called. This includes calculations of new
permoff's and tempoff's. Permoff's are cumulative
in that if the destination link calls another link
and calculates a new permoff, the result is added to
this one.
tempoff A "match" option in the destination link can
optionally add this value its OFFSET. Tempoff's are
temporary, in that it does not apply to any links the
destination link calls. It also does not effect the
calculation of OFFSET's for new permoff's and
tempoff's.
举个例子。考虑这个命令:
# tc filter add dev eth0 parent 999:0 protocol ip prio 99 u32 \
link 1: offset at 0 mask 0f00 shift 6 plus 0 eat \
match ip protocol 6 ff
match 表达式选择 tcp 数据包(即 IP 协议 6)。如果我们有协议 6,我们将执行过滤器 1:0。现在来看看其余部分:
offset This signals that we want to modify permoff or tempoff
if the link is executed. If this is not present,
neither permoff nor tempoff are effected - in other
words the target of the link inherits the current
permoff and tempoff.
at 0 This says the 16 bit word that contains the value we
are going to use to calculate permoff or tempoff lives
offset 0 the IP packet - ie at the start of the packet.
This offset must be even. If not specified 0 is used.
mask 0f00 This mask (which is in hex) is bit-wise anded with the
16 bit word extracted from the packet header. It
isolates the header length from the rest of the
information in the word. If not specified 0 is used
for the extracted value.
shift 6 This says the word extracted is to be divided by 64
after being masked. If not present the value is not
shifted.
plus 0 After extracting the word, masking it and dividing it by
64, this value is now added to it. If not present is
assumed to be 0.
eat If this is present we are calculating permoff, and the
result of the calculation above is added to it. Tempoff
is set to 0 in this case. If this is not present we are
calculating tempoff, and the result of the calculation
becomes tempoff's new value. Permoff is not altered in
this case.