MIB中的IPAddress编码为什么与我在WireShark中解码的不匹配?

huangapple go评论95阅读模式
英文:

Why does MIB encoding of IPAddress not match what I decode in WireShark?

问题

RFC1155, 3.2.3.2定义了IpAddress如下:

这个应用程序范围的类型表示32位的互联网地址。它以4字节长度的八位字节字符串表示,按网络字节顺序排列。

再次,在第6节中:

IpAddress ::=
     [APPLICATION 0] -- 按网络字节顺序排列
        IMPLICIT OCTET STRING (SIZE (4))

此外,RFC 1156, 5.4.1定义了一个ipAddrEntry,其中包含ipAdEntAddr作为IpAddress。

好吧,然后,回溯到这个“(NOT)Simple Network Message Protocol”,应该清楚了,IPAddress是4字节的,按网络字节顺序排列(大端序)。

RFC1156, 5.4.1定义了一个ipAddrEntry为一个包含ipAdEntAddr等内容的SEQUENCE,其中ipAdEntAddr是一个IpAddress... 这是在最后一个RFC中定义的。

那么,在Wireshark中,当我检查OID请求时,IP地址192.168.1.21被编码为

81  40  81  28  01  15

这不是4个八位字节。它甚至不是TLV编码。它是一种其他的7位编码,其中第8位用于表示“不是最后一个八位字节”(我认为这是VLQ吗?)

1000 0001 0100 0000  =>  1100 0000
1000 0001 0010 1000  =>  1010 1000

如果它应该是VLQ,那么在哪里有文档记录呢?

为什么我在Wireshark中看到的与我在RFC中看到的不一样?

英文:

RFC1155, 3.2.3.2 defines an IpAddress as:

This application-wide type represents a 32-bit internet address. It
is represented as an OCTET STRING of length 4, in network byte-order.

And again, in section 6

IpAddress ::=
     [APPLICATION 0] -- in network-byte order
        IMPLICIT OCTET STRING (SIZE (4))

Also RFC 1156, 5.4.1 defines an ipAddrEntry as a SEQUENCE containing an ipAdEntAddr as an IpAddress.

Okay then, backpedaling through this "(NOT)Simple Network Message Protocol", it should be clear that an IPAddress is 4 byte, network byte order (Big Endian)

RFC1156, 5.4.1 defines an ipAddrEntry to be a SEQUENCE containing among other things, ipAdEntAddr as an IpAddress... Which was defined in the last RFC.

Why then, in Wireshark, when I examine the OID request, the IP address 192.168.1.21 is encoded as

81  40  81  28  01  15

MIB中的IPAddress编码为什么与我在WireShark中解码的不匹配?

Which isn't 4 octets. It's not even TLV encoding. It's some other 7 bit encoding where the 8th bit is used to indicate "Not the last octet" (I think it's VLQ? )

1000 0001 0100 0000  =>  1100 0000
1000 0001 0010 1000  =>  1010 1000

If it is supposed to be VLQ, where is that documented?

Why is what I read on Wireshark not what I read in the RFCs?

答案1

得分: 1

SNMP协议和Wireshark都是正确的,但你误解了SNMP表和OID的基本概念。

从文本中,你可能在Wireshark的解码树视图中随处看到192.168.1.21,但你必须了解它的实际实体,以了解它是如何编码的。

在屏幕截图中,你可以看到高亮显示的192.168.1.21是OID 1.3.6.1.2.1.4.20.1.2.192.168.1.21的一部分。这是用于表格的典型OID模式,其中索引192.168.1.21与表格列OID 1.3.6.1.2.1.4.20.1.2结合在一起,表示实际的单元格。

因此,它的字节遵循BER编码,与任何其他OID一样,而不是IpAddress

https://stackoverflow.com/questions/5929050/how-does-asn-1-encode-an-object-identifier

这就是为什么这些字节与你最初的想法看起来不同的原因。

英文:

SNMP protocol and Wireshark are both correct, but you misunderstand the basic concept of SNMP table and OIDs.

While from the text, you might see 192.168.1.21 anywhere in Wireshark's decoded tree view, you must be aware of its actual entity so as to understand how it was encoded.

In the screen shot you can see that 192.168.1.21 highlighted was part of an OID 1.3.6.1.2.1.4.20.1.2.192.168.1.21. This is a typical OID pattern used in tables, where the index 192.168.1.21 is combined with the table column OID 1.3.6.1.2.1.4.20.1.2 to represent the actual cell.

Thus, its bytes are encoded following BER like any other OIDs, not IpAddress,

https://stackoverflow.com/questions/5929050/how-does-asn-1-encode-an-object-identifier

That's why the bytes look different from your initial thought.

答案2

得分: 0

你可能记得我的上一个答案,在那里我解释了对象的每个实例都有一个“名称”和一个INDEX。我引用了ifTable来展示ifIndex是如何用来引用每一行实例的。虽然许多(如果不是大多数)SNMP表使用单个INTEGER作为INDEX,但实际上可以使用任何组合的原始数据类型(有些表在索引中包括OID,给您一个OID内的OID)。重要的是INDEX对于每一行都是唯一的。

根据您截图中的OID,看起来您正在处理ipAdEntIfIndex(来自RFC 1213的IP-MIB)。如果您查看MIB,您将找到ipAddrEntry的定义(表示ipAddrTable中的一行):

ipAddrEntry OBJECT-TYPE
    SYNTAX     IpAddrEntry
    MAX-ACCESS not-accessible
    STATUS     deprecated
    DESCRIPTION
           "The addressing information for one of this entity's IPv4
            addresses."
    INDEX      { ipAdEntAddr }
    ::= { ipAddrTable 1 }

IpAddrEntry ::= SEQUENCE {
        ipAdEntAddr          IpAddress,
        ipAdEntIfIndex       INTEGER,
        ipAdEntNetMask       IpAddress,
        ipAdEntBcastAddr     INTEGER,
        ipAdEntReasmMaxSize  INTEGER
    }

您可以看到它使用ipAdEntAddr作为INDEX,而ipAdEntAddr是一个IpAddress。您截图中的编码看起来有点奇怪,因为它被编码为OID的一部分,而不是作为OctetString,正常情况下,IpAddress应该是OID

这里有两个不同的规范与此相关。第一个是ASN.1基本编码规则的规范,这是不公开免费提供的,但基本上说OID子标识符只能使用每个字节的低7位,最高位是一个标志,指示该子标识符中是否有额外的字节。因此,在0x81中的0x01表示第7位,0x40表示位0-6。如果将它们组合在一起,就会得到0xc0,即192。

第二个规范是RFC 2578(第7.7节),它定义了如何在OID中对INDEX进行编码:

对象在INDEX子句中的语法指示如何形成实例标识符:

  1. 整数值(即具有INTEGER作为其基本原始类型):一个子标识符,其整数值为(这仅适用于非负整数)。
  2. 字符串值,固定长度字符串(或以IMPLIED关键字为前导的可变长度):n个子标识符,其中n是字符串的长度(字符串的每个八位字节都以单独的子标识符编码)。
  3. 字符串值,可变长度字符串(不以IMPLIED关键字为前导):n+1个子标识符,其中n是字符串的长度(第一个子标识符是n本身,之后,字符串的每个八位字节都以单独的子标识符编码)。
  4. 对象标识符值(在前面有IMPLIED关键字时):n个子标识符,其中n是值中的子标识符数量(值的每个子标识符都复制到单独的子标识符中)。
  5. 对象标识符值(没有IMPLIED关键字时):n+1个子标识符,其中n是值中的子标识符数量(第一个子标识符是n本身,之后,值中的每个子标识符都复制)。
  6. IpAddress值:4个子标识符,采用熟悉的a.b.c.d表示法。

IpAddress很简单,因为它表示为点分隔的整数,就像OID一样。

英文:

you may remember my last answer, in which I explained that every instance of an object has a "name" and an INDEX. I referenced ifTable to show how ifIndex was used to refer to each instance of a row. While many (if not most) SNMP tables use a single INTEGER as the INDEX, it's actually possible to use any combination of primitive data types (there are tables that include an OID in the index, giving you an OID within an OID). The important thing is that the INDEX be unique for each row.

Based on the OID in your screenshot, it looks like you are dealing with ipAdEntIfIndex (from RFC 1213's IP-MIB). If you consult the MIB, you will find this definition for ipAddrEntry (representing a row in ipAddrTable):

ipAddrEntry OBJECT-TYPE
    SYNTAX     IpAddrEntry
    MAX-ACCESS not-accessible
    STATUS     deprecated
    DESCRIPTION
           "The addressing information for one of this entity's IPv4
            addresses."
    INDEX      { ipAdEntAddr }
    ::= { ipAddrTable 1 }

IpAddrEntry ::= SEQUENCE {
        ipAdEntAddr          IpAddress,
        ipAdEntIfIndex       INTEGER,
        ipAdEntNetMask       IpAddress,
        ipAdEntBcastAddr     INTEGER,
        ipAdEntReasmMaxSize  INTEGER
    }

You can see here that it uses ipAdEntAddr as the INDEX, and that ipAdEntAddr is an IpAddress. The reason that the encoding in your screenshot looks funny is that it's encoded as part of an OID, not as an OctetString, as an IpAddress would normally be.

There are two different specifications that are relevant here. The first is the specification for the ASN.1 Basic Encoding Rules, which is not publicly available for free, but basically says that OID sub-identifiers can only use the lower 7 bits of each byte, and that the MSB is a flag indicating whether there are additional bytes in that sub-identifier. Hence the 0x01 in 0x81 gives bit 7, and 0x40 gives bits 0-6. If you put them together, you get 0xc0, which is 192.

The second specification is RFC 2578 (section 7.7), which defines how an INDEX is encoded within an OID:

   The syntax of the objects in the INDEX clause indicate how to form
   the instance-identifier:

(1)  integer-valued (i.e., having INTEGER as its underlying primitive
     type):  a single sub-identifier taking the integer value (this
     works only for non-negative integers);

(2)  string-valued, fixed-length strings (or variable-length preceded by
     the IMPLIED keyword):  `n' sub-identifiers, where `n' is the length
     of the string (each octet of the string is encoded in a separate
     sub-identifier);

(3)  string-valued, variable-length strings (not preceded by the IMPLIED
     keyword):  `n+1' sub-identifiers, where `n' is the length of the
     string (the first sub-identifier is `n' itself, following this,
     each octet of the string is encoded in a separate sub-identifier);

(4)  object identifier-valued (when preceded by the IMPLIED keyword):
     `n' sub-identifiers, where `n' is the number of sub-identifiers in
     the value (each sub-identifier of the value is copied into a
     separate sub-identifier);

(5)  object identifier-valued (when not preceded by the IMPLIED
     keyword):  `n+1' sub-identifiers, where `n' is the number of sub-
     identifiers in the value (the first sub-identifier is `n' itself,
     following this, each sub-identifier in the value is copied);

(6)  IpAddress-valued:  4 sub-identifiers, in the familiar a.b.c.d
     notation.

An IpAddress is simple, because it's represented as dot-separated integers, just like an OID.

huangapple
  • 本文由 发表于 2023年2月18日 00:12:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75486708.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定