【问题标题】:Python telnetlib and console connection cisco nodePython telnetlib 和控制台连接cisco node
【发布时间】:2014-08-02 17:16:54
【问题描述】:

我正在尝试通过 cisco 终端/通信服务器连接到 cisco 节点的控制台连接。 为此,我远程登录到特定端口上的 cisco 终端/通信服务器的 IP 地址,让我们说 X.X.X.X - 端口 2068。 当我通过 CLI 从我的计算机执行此操作时,它看起来像这样:

[user@computer]$ telnet X.X.X.X 2068
Trying X.X.X.X...
Connected to X.X.X.X (X.X.X.X).
Escape character is '^]'.

Username: <user>
Password: 

console-cisco-node>

所以通过我计算机上的 CLI 没有问题。 但是当我在我的计算机上运行下面的 Python 代码时,它似乎不起作用......

#! /usr/bin/env python

import telnetlib

tn = telnetlib.Telnet("X.X.X.X",2068)
tn.set_debuglevel(8)
data = tn.read_some()
tn.close()
if data == '':
  print 'variable data is EMPTY'
else:
  print data
  print "variable data is FILLED !!!"

当我运行这段代码时,我只看到了这个,看起来'tn.read_some()' 只是永远等待,因为没有任何东西来自 cisco 终端/通信服务器? [与 tn.read_all() 相同]

PS。我通过按 CTRL-C

停止了正在运行的代码
[user@computer]$ ./test.py   
Telnet(X.X.X.X,2068): recv '\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f'
Telnet(X.X.X.X,2068): IAC WILL 1
Telnet(X.X.X.X,2068): IAC WILL 3
Telnet(X.X.X.X,2068): IAC DO 24
Telnet(X.X.X.X,2068): IAC DO 31
Telnet(X.X.X.X,2068): recv '\xff\xfc\x01'
Telnet(X.X.X.X,2068): IAC WONT 1
Telnet(X.X.X.X,2068): recv '\xff\xfc\x03'
Telnet(X.X.X.X,2068): IAC WONT 3
Telnet(X.X.X.X,2068): recv '\xff\xfe\x18'
Telnet(X.X.X.X,2068): IAC DONT 24
Telnet(X.X.X.X,2068): recv '\xff\xfe\x1f'
Telnet(X.X.X.X,2068): IAC DONT 31

Traceback (most recent call last):
  File "./test.py", line 7, in ?
    data = tn.read_some()
  File "/usr/lib64/python2.4/telnetlib.py", line 345, in read_some
    self.fill_rawq()
  File "/usr/lib64/python2.4/telnetlib.py", line 521, in fill_rawq
    buf = self.sock.recv(50)
KeyboardInterrupt

当我将代码中的 'tn.read_some()' 更改为 'tn.read_eager()' 或 'tn.read_very_eager()' 或 'tn.read_lazy()' 或 'tn.read_very_lazy()' 和再次运行代码,它会告诉我:

[user@computer]$ ./test.py
variable data is EMPTY

当我将python代码更改为不是连接到cisco节点的控制台连接而是连接到cisco节点的管理连接(普通端口23上的另一个IP地址YYYY)时,它工作得很好,我看到了这个输出:

[user@computer]$ ./test1.py 
Telnet(Y.Y.Y.Y,23): recv '\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f'
Telnet(Y.Y.Y.Y,23): IAC WILL 1
Telnet(Y.Y.Y.Y,23): IAC WILL 3
Telnet(Y.Y.Y.Y,23): IAC DO 24
Telnet(Y.Y.Y.Y,23): IAC DO 31
Telnet(Y.Y.Y.Y,23): recv '\r\n************************************************'

************************************************
variable data is FILLED !!!

所以我认为 Python 代码还可以。 只是 cisco 终端/COMM 服务器 (X.X.X.X) 的反应方式与正常情况不同,我认为 Python telnetlib 很困惑。

有人经历过类似的事情吗?

【问题讨论】:

  • 您可以使用wireshark确认行为。
  • 在这种情况下不容易做到:[user@computer] 在另一个国家,然后我...(我通过 ssh 连接到这个 [user@computer])

标签: python telnetlib


【解决方案1】:

您似乎在端口 2068 上没有真正的 telnet 协议。从 telnet man 连接到非标准端口时, telnet 忽略任何自动启动 TELNET 选项。什么时候 端口号前面有一个减号,初始 选项协商完成。。但是 telnetlib 假设如果你使用它,你需要一个 telnet 协议。正如您所说,在连接上使用wireshark 并不容易,您可以尝试使用CLI telnet 到端口-2068 来验证您是否遇到与使用telnetlib 相同的问题。

可以选择使用简单的套接字吗?

s = socket.create_connection(('X.X.X.X', 2068))
data = s.recv(1024)
...

【讨论】:

  • 感谢您的回答... CLI telnet 到端口 -2068 不起作用,这是因为无法使用此 telnet 选项('telnet X.X.X.X -2068')。但是 telnet 也有一些命令,并且使用 open 命令,前面的减号是可能的。所以这就是我尝试过的。有或没有前面的减号都行
  • 我现在正在处理您对套接字选项的建议。我必须说我认为这将是一个可能的解决方案。当事情变得更好时,我会告诉你我喜欢它。
【解决方案2】:

我找到了另一种方法(感谢Serge Ballesta)

在我的例子中,telnetlib 对象是不可能的,所以我不得不使用套接字对象通过 cisco 终端/通信服务器连接到 cisco 节点的控制台连接。 下面的原始基本代码让我可以开始编写我需要的程序。

#! /usr/bin/env python

import socket
import time

try:
   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   s.connect(("X.X.X.X",2068))
   data1 = s.recv(1024)
   #
   # when the connection with the server is made the server sends some (IAC) commands
   #
   #    '\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f'
   #
   # as far as I know this means the following:
   #
   #     IAC WILL ECHO
   #     IAC WILL SUPRESS GO AHEAD
   #     IAC DO   TERMINAL TYPE
   #     IAC DO   WINDOW SIZE
   #
   # WILL means the server wants to use the indicated facility if the client has the possibilty to use this facility
   # (client can reply with DO or DONT)
   #
   # DO means the server has the possibility for the indicated facility and asks the client if he wants to use this facility
   # (client can reply with WILL or WONT)
   #
   #
   # PS.
   #      WILL = xFB = 251
   #      WONT = xFC = 252
   #      DO   = xFD = 253
   #      DONT = xFE = 254
   #
   #
   #
   # Python is going to answer as follwos:
   #
   #     IAC DONT ECHO
   #     IAC DO   SUPRESS GO AHEAD
   #     IAC WONT TERMINAL TYPE
   #     IAC WONT WINDOW SIZE
   #

   s.sendall('\xff\xfe\x01\xff\xfd\x03\xff\xfc\x18\xff\xfc\x1f')

   data2 = s.recv(1024) # server sends '\xff\xfc\x01' = IAC WONT ECHO as a reply back

   # send an enter to make the hop from the terminal server to the console connection of the node we want to be on
   s.send('\r')

   data3 = ''
   while not 'Username: ' in data3:
      data3 = s.recv(2048)

   s.send('<USERNAME>\r')
   time.sleep(0.1)

   s.recv(1024)
   s.send('<PASSWORD>\r')
   time.sleep(0.1)
   data5 = s.recv(1024)
   s.send('exit\r')

   s.close()

   #print repr(data1)   # '\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f' from the server
   #print repr(data2)   # '\xff\xfc\x01' from the server
   #print data3         # banner and Username: from the console connection of the node we want to be on  

   prompt_console = data5.split()[-1]
   print 'prompt van de console = %s' %prompt_console[:len(prompt_console)-1]

except socket.error, e:
   print e

except socket.timeout, e:
   print e

【讨论】:

  • 你在哪里查到终端服务器发回的十六进制代码的含义?
【解决方案3】:

我还与 Cisco(和其他路由器)进行交互。对于 telnet 通信,我扩展了 Telnet 类并添加了一个 read 方法,如下所示:

 def read(self, timeout):
    s = time.time()
    resp = ""
    while True:
        res = self.read_eager()
        if not res and resp:
            return resp
        resp += res
        if time.time() - s >= timeout:
            return resp
        time.sleep(0.001)

所以基本上“问题”是各种read_* 方法没有给出“全部”,基本上是因为没有“全部”的定义,它会返回“缓冲区”中的任何内容,或者他们'将填充缓冲区然后返回内容,具体取决于您调用的方法。我的方法是“在还有要阅读的内容时阅读(当我阅读“”时停止)或直到它超过 timeout 秒。 此外,您应该查看 read_until 方法的工作原理与预期的差不多。

    def read_until(self, match, timeout=None):
        """Read until a given string is encountered or until timeout.

        When no match is found, return whatever is available instead,
        possibly the empty string.  Raise EOFError if the connection
        is closed and no cooked data is available.

        """

【讨论】:

    猜你喜欢
    • 2013-09-08
    • 1970-01-01
    • 2011-12-31
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-11
    • 2017-07-31
    相关资源
    最近更新 更多