EasySNMP:将 OCTETSTR 转换为十六进制的不同输出

EasySNMP: Different output converting OCTETSTR to Hex

当我使用函数 encode 将 OCTET 转换为 Hex 时,一些不应该添加的字符被添加了。

示例:

Linux: snmpwalk -t 5 -v2c -c public 192.168.10.150 iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1

SNMPWALK 输出:iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.144 = Hex-STRING: AC 84 C6 5F 95 EF B0 4E 26 8B 1C C5 C0 4A 00 AE

代码:

session = Session(hostname='192.168.10.150', community='public', version=2)
description = session.walk('iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1')

for item in description:
    print '{oid}.{oid_index} {snmp_type} = {value}'.format(
         oid=item.oid,
         oid_index=item.oid_index,
         snmp_type=item.snmp_type,
         value=item.value.encode("hex"))

EasySNMP 输出:iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.144. OCTETSTR = c2acc284c3865fc295c3afc2b04e26c28b1cc385c3804a00c2ae59c293c2b04e26c28b4ec2ad

使用了一些OID,但输出与我预期的不同。 easysnmp的使用方法正确吗?

数据包捕获

SNMPWalk (Linux):

    192.168.10.214  192.168.10.150  get-next-request 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1 Value(NULL)
Simple Network Management Protocol
    version: v2c (1)
    community: public
    data: get-next-request (1)
        get-next-request
            request-id: 686772965
            error-status: noError (0)
            error-index: 0
            variable-bindings: 1 item
                1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1: Value (Null)
                    Object Name: 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1 (iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1)
                    Value (Null)

    192.168.10.150  192.168.10.214  get-response 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.51 
Value(00:02:18:a6:f7:65:88:f5:18:a6:f7:65:18:a6:f7:65:88:f5:b0:4e:26:8a:e3:cb:50:c7:bf:f2:db:95:b0:4e:26:ed:8d:c5:98:de:d0:76:e3:01:00:02:98:de:d0:76)
Simple Network Management Protocol
    version: v2c (1)
    community: public
    data: get-response (2)
        get-response
            request-id: 686772965
            error-status: noError (0)
            error-index: 0
            variable-bindings: 1 item
                1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5: 000218a6f76588f518a6f76518a6f76588f5b04e268ae3cb...
                    Object Name: 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5 (iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5)
                    Value (OctetString): 000218a6f76588f518a6f76518a6f76588f5b04e268ae3cb...


    192.168.10.214  192.168.10.150  get-next-request 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5 Value(NULL)
Simple Network Management Protocol
    version: v2c (1)
    community: public
    data: get-next-request (1)
        get-next-request
            request-id: 686772966
            error-status: noError (0)
            error-index: 0
            variable-bindings: 1 item
                1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5: Value (Null)
                    Object Name: 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5 (iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5)
                    Value (Null)


    192.168.10.150  192.168.10.214  get-response 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.2.48 Value(70:4f:57:4d:cc:cf:b0:4e:26:8b:45:11:ac:84:c6:1d:0e:c5:70:4f:57:3a:dd:5b:70:4f:57:4c:92:8f:b0:4e:26:8a:ef:99)
Simple Network Management Protocol
    version: v2c (1)
    community: public
    data: get-response (2)
        get-response
            request-id: 686772966
            error-status: noError (0)
            error-index: 0
            variable-bindings: 1 item
                1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.2.48: 704f574dcccfb04e268b4511ac84c61d0ec5704f573add5b...
                    Object Name: 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.2.48 (iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.2.48)
                    Value (OctetString): 704f574dcccfb04e268b4511ac84c61d0ec5704f573add5b...

EasySNMP:

    192.168.10.214  192.168.10.150  get-next-request 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1 Value(NULL)
Simple Network Management Protocol
    version: v2c (1)
    community: public
    data: get-next-request (1)
        get-next-request
            request-id: 1767019562
            error-status: noError (0)
            error-index: 0
            variable-bindings: 1 item
                1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1: Value (Null)
                    Object Name: 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1 (iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1)
                    Value (Null)


    192.168.10.150  192.168.10.214  get-response 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5 Value(00:02:18:a6:f7:65:88:f5:18:a6:f7:65:18:a6:f7:65:88:f5:b0:4e:26:8a:e3:cb:50:c7:bf:f2:db:95:b0:4e:26:ed:8d:c5:98:de:d0:76:e3:01:00:02:98:de:d0:76)
Simple Network Management Protocol
    version: v2c (1)
    community: public
    data: get-response (2)
        get-response
            request-id: 1767019562
            error-status: noError (0)
            error-index: 0
            variable-bindings: 1 item
                1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5: 000218a6f76588f518a6f76518a6f76588f5b04e268ae3cb...
                    Object Name: 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5 (iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5)
                    Value (OctetString): 000218a6f76588f518a6f76518a6f76588f5b04e268ae3cb...



    192.168.10.214  192.168.10.150  get-next-request 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5 Value(NULL)
Simple Network Management Protocol
    version: v2c (1)
    community: public
    data: get-next-request (1)
        get-next-request
            request-id: 1767019563
            error-status: noError (0)
            error-index: 0
            variable-bindings: 1 item
                1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5: Value (Null)
                    Object Name: 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5 (iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.1.5)
                    Value (Null)


    192.168.10.150  192.168.10.214  get-response 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.2.48 VALUE(70:4f:57:4d:cc:cf:b0:4e:26:8b:45:11:ac:84:c6:1d:0e:c5:70:4f:57:3a:dd:5b:70:4f:57:4c:92:8f:b0:4e:26:8a:ef:99)
Simple Network Management Protocol
    version: v2c (1)
    community: public
    data: get-response (2)
        get-response
            request-id: 1767019563
            error-status: noError (0)
            error-index: 0
            variable-bindings: 1 item
                1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.2.48: 704f574dcccfb04e268b4511ac84c61d0ec5704f573add5b...
                    Object Name: 1.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.2.48 (iso.3.6.1.4.1.25355.3.2.6.4.2.5.1.7.1.1.2.48)
                    Value (OctetString): 704f574dcccfb04e268b4511ac84c61d0ec5704f573add5b...

好的。我们可以告诉以下内容:

  • 两位经理提出的要求完全相同
  • 对两个请求的响应是相同的

这意味着 Net-SNMP 输出被“破坏”/转换,或者 EasySNMP 输出被“破坏”/转换。

不幸的是,数据包捕获没有显示 post 原始版本中描述的交互,因此我们无法立即判断是哪个管理器出了问题。但是,可以根据我们看到的值进行扣除。

您的 Python 脚本的输出几乎是 snmpwalk 输出的超集:

  • Net-SNMP:

    • AC 84 C6 5F 95 EF B0 4E 26 8B 1C C5 C0 4A 00AE
  • Python 脚本:

    • C2 AC C2 84 C3 86 5F C2 95 C3 AF C2 B0 4E 26 C2 8B 1C C3 85 C3 80 4A 00 C2 AE 59 C2 93 C2 B0 4E 26 C2 8B 4E C2 AD

那么为什么添加了额外的字节,又为什么丢失了一些字节?这听起来像是对源数据的重新编码,对吧?

我们可以观察到字节C2弹出了很多。那是什么?它是字符 Â 的“扩展 ASCII”(实际上没有这样的东西,但在许多代码页中)。啊哈,红旗。为什么是红旗?因为this is commonly evidence of misinterpreted UTF-8。 (我可以更详细地解释 为什么 这是,但如果你愿意,我会让你单独研究 Unicode 编码。)

因此,使用 an online tool or two,让我们将第二个字节流解码为 UTF-8 并查看我们得到的逻辑代码点:

U+AC U+84 U+C6 U+5F U+95 U+EF U+B0 U+4E U+26 U+8B U+1C U+C5 U+C0 U+4A U+AE U+59 U+93 U+B0 U+4E U+26 U+8B U+4E U+AD

嘿,这看起来很眼熟! (同样,我将与 Net-SNMP 输出匹配的位加粗。)U+00 丢失(大概是因为 that is a "null" byte much as in ASCII) and there's still a bunch of noise at the end (if you're interested, they render like this: "Y°N&N­"), but we can now at least see what's going on: your original byte stream has been re-encoded as a UTF-8 string. Indeed, Python 3's default encoding is UTF-8.

像 C6 这样的字节完全消失的原因是它们落在 ASCII 范围之外,因此在 Unicode 中映射“不干净”。 ASCII C6,事实证明,is U+00C6, which is represented in UTF-8 by C3 86,所以现在我们也知道未加粗的字节来自哪里。

因此,EasySNMP 将您的步行结果视为 字符串 而不是不透明的字节序列,因此 Python 对其进行了破坏。然后,当你写 .encode("hex") 时,你得到了这个新的、伪造的 UTF-8 字符串的十六进制对表示。

这应该不会发生。 SNMP 响应清楚地表示为“OctetString”,并且规范告诉我们 "The OCTET STRING type represents arbitrary binary or textual data". The MIB (which you do not appear to be using, or at least have not provided) for the agent with which you are communicating may provide further encoding information; in the absence of that information, there's no way to know for sure how an OCTET STRING should be displayed. For example, this Net-SNMP bug 在适用时从字面上讨论进行 guess

总之,一切都很有趣,但我们能做些什么呢?

EasySNMP 文档相当薄,但我们可以稍微浏览一下源代码(并且在此过程中发现 EasySNMP is actually just a Python wrapper around Net-SNMP!) and on the EasySNMP issues list, where it turns out someone's complained about this before.

那么,我们又能做些什么呢?

嗯,我不确定我们可以做些什么。这是目前 EasySNMP 的一个缺陷。事物是 Unicodised(通过 EasySNMP 本身,通过转换为 Python 字符串,或通过前面描述的 Net-SNMP 兼容模块),即使它们不应该是。

但是,this chap has suggested a workaround 您可以尝试:

session = Session(
   hostname='192.168.10.150',
   community='public',
   version=2,
   use_sprint_value=False
)

新的最终参数应该关闭值转换。但是,我不服气,因为per the docs默认已经是False了。

除了尝试之外,我认为最好的办法是增加相关问题报告的权重,并向开发人员施加压力,要求他们提出解决方案。对不起。

为了获得正确的十六进制值,我正在使用它。

     def toRaw(s):
       x = [ord(i) for i in list(s)]
       return bytearray(x)
     
     print(toRaw(item.value).hex().upper())