skip to Main Content

I have a python code with telnetlib3 as follows:

import asyncio
import telnetlib3

async def foo():
    reader, writer = await telnetlib3.open_connection("192.168.200.10", 9000)
    data = await asyncio.wait_for(reader.read(4096), timeout=2)
    print(data)

asyncio.run(foo())

that is able to connect to a telnet service and returns the following expected output on a Linux and Windows system:

Terminal emulator detected (unknown), switching to interactive shell

Debug server connected. Waiting for commands (or 'exit')...
Supported client terminals: telnet, screen, PuTTY.

prompt >>

However, when I use telnetlib as in the following example:

import time
import telnetlib

session = telnetlib.Telnet("192.168.200.10", 9000, 2)
received = b""
t0 = time.time()
while time.time() - t0 < 2:
    data = session.read_very_eager()
    if data:
        received += data
        t0 = time.time()
print(received)

the output is something like

b'x1b[0Gx1b[0G'

on Linux and windows.

How can I modify the first code example (using telnetlib) so I receive the "interactive welcome message" as I do with telnetlib3 on Windows?

  • windows: windows10, python 3.10.11
  • linux (VM on windows): Ubuntu 20.04.6, python 3.8.10

2

Answers


  1. Note that telnetlib is deprecated since Python version 3.11, and will be removed in version 3.13.
    Your Python version is OK, but… don’t upgrade it too quickly!

    telnetlib is a bit lower-level than telnetlib3: it does not automatically handle some of the telnet protocol interactions that telnetlib3 does for you. The binary output you are seeing is likely part of the Telnet protocol negotiation that telnetlib3 is handling automatically, but telnetlib is not.

    You can try and mirror the functionality of your telnetlib3 version by manually handling the Telnet protocol negotiation, with telnetlib.Telnet.set_option_negotiation_callback. It does not handle all cases – it is only designed to work with your specific server.
    Inspired from "robot.libraries.Telnet", but… very much simplified.
    See also "Python telnetlib.WILL Examples "

    import time
    import telnetlib
    
    session = telnetlib.Telnet()
    
    # That is a helper function to handle Telnet options
    def handle_option(tsocket, command, option):
        if command == telnetlib.DO and option == telnetlib.TTYPE:
            tsocket.sendall(telnetlib.IAC + telnetlib.WILL + telnetlib.TTYPE)
            tsocket.sendall(telnetlib.IAC + telnetlib.SB + telnetlib.TTYPE + b'' + b'unknown' + telnetlib.IAC + telnetlib.SE)
        elif command in (telnetlib.DO, telnetlib.DONT):
            tsocket.sendall(telnetlib.IAC + telnetlib.WONT + option)
        elif command in (telnetlib.WILL, telnetlib.WONT):
            tsocket.sendall(telnetlib.IAC + telnetlib.DONT + option)
    
    session.set_option_negotiation_callback(handle_option)
    
    session.open("192.168.200.10", 9000)
    received = b""
    t0 = time.time()
    while time.time() - t0 < 2:
        data = session.read_very_eager()
        if data:
            received += data
            t0 = time.time()
    
    print(received.decode())
    

    The handle_option function is a callback that telnetlib will use to respond to Telnet option commands from the server. It essentially it is telling the server that we will handle terminal type (TTYPE) options and that we will not handle any other options.

    That code should give you similar results to your telnetlib3 version, but it is a bit more complex because telnetlib requires you to handle more of the protocol details manually.

    Also, I have used decode() method (as in this example) at the end to convert binary data into string. Do remove it if your data is not text.

    Login or Signup to reply.
  2. import time
    import telnetlib
    
    def negotiate_telnet_options(telnet_session):
        # Send the Telnet option negotiation
        telnet_session.sock.sendall(telnetlib.IAC + telnetlib.WILL + telnetlib.TERMINAL_TYPE)
        telnet_session.sock.sendall(telnetlib.IAC + telnetlib.DO + telnetlib.TERMINAL_TYPE)
    
        # Process Telnet option negotiation response
        telnet_session.read_until(telnetlib.IAC + telnetlib.DO + telnetlib.TERMINAL_TYPE, timeout=2)
        telnet_session.read_until(telnetlib.IAC + telnetlib.WILL + telnetlib.TERMINAL_TYPE, timeout=2)
    
    def read_until_prompt(telnet_session):
        received = b""
        t0 = time.time()
        while time.time() - t0 < 2:
            data = telnet_session.read_very_eager()
            if data:
                received += data
                if b'prompt >>' in received:
                    return received
                t0 = time.time()
        return received
    
    def main():
        session = telnetlib.Telnet("192.168.200.10", 9000, 2)
    
        # Perform Telnet option negotiation
        negotiate_telnet_options(session)
    
        # Wait for the welcome message or prompt
        received = read_until_prompt(session)
        print(received)
    
    if __name__ == "__main__":
        main()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search