您绝对可以阅读 telnet 协议,但请查看下面链接底部的答案,其中涉及使用 WireShark 实际查看来回飞行的内容。
http://www.codeproject.com/Questions/147555/Telnet-client-using-TCP
如果您从未使用过数据包嗅探器,那么它非常有启发性(就像对我一样)。以下是我通过 TCP 套接字连接进行 telnet 的步骤。
(1) 按照上述链接中的说明捕获网络上的流量,同时准确执行您希望使用所需应用程序/脚本最终执行的命令,从创建 telnet 连接开始,到关闭它结束
(2) 停止捕获会话后,您可能会在捕获的过程中看到同时在您的网络上发生的许多其他流量,因此请使用 ip.addr == xxx.xxx.xxx.xxx 将其过滤掉,其中你当然使用远程计算机的IP地址
(3) 现在,当您查看在您的计算机和远程计算机之间来回传输的所有内容时,您可以看到应用程序如何为每条消息分离出不同的通信层。您要特别注意带有“Telnet”协议的消息,这意味着它是最高层。当您在 WireShark 窗口的最顶部窗格中突出显示一条消息时,您会在第二个窗格中看到它如何将该消息分成不同的层。在第二个窗格中,如果您突出显示 Telnet 层,您可以看到在第三个窗格中,实现 telnet 协议的消息字节如何被突出显示。花一些时间来分析回传的消息。你可以更直接地看到,
(4) 现在您只想在应用程序中基本模拟您可以在 Wireshark 中看到的通信。请记住,由于您在应用程序中打开 TCP 套接字,因此您的应用程序在幕后处理所有 TCP 和下行通信内容,因此您只需担心将 telnet 字节/数据/命令读/写到 TCP 套接字.
这种方法根本不需要很长时间,并且不需要在您的系统上添加任何额外的东西,如果您正在处理系统资源有限/非常简单的操作系统/根本没有操作系统的设备,这非常棒。例如,我设备上的 mini Linux 系统没有安装 Expect,也没有简单的安装方法。我的意思是它可以做到,但我们在这里谈论非常烦人的东西。此外,即使在盒子上安装东西的方式不太疯狂,我已经有 50 个在我已经设置为自动更新到我肯定放在服务器上的任何新二进制文件的字段中,但他们并不期望还必须从我的服务器下载脚本。同样,他们没有安装允许他们运行该脚本的操作系统。所以我们在这里谈论的是相对较低级别的东西,保持简单不是一种选择,而是一种要求。我的最终 C 函数让我的串行设备服务器 telnet 到自己(访问自己的命令行界面的唯一方法——这是制造商的选择)并向自己发出必要的命令,如下所示:
turnoff_watchdog
{
// telnetsock, TCP socket to 127.0.0.1 at port 23, has already been set previously
char negotiation_1[] = {0xFF,0xFC,0X18,0xFF,0xFC,0x20,0xFF,0xFC,0x23,0xFF,0xFC,0x27,0xFF,0xFD,0x03};
char negotiation_2[] = {0xFF,0xFC,0x01,0xFF,0xFC,0x1F,0xFF,0xFE,0x05,0xFF,0xFB,0x21};
char telnet_login_name[] = "admin\r\n";
char telnet_login_password[] = "password\r\n";
char set_command[] = "set watchdog off\r\n";
char save_command[] = "save\r\n";
char confirm[] = "y\n";
char escape[] = {0x5E,0x5D,0x0A}; // ^]
char quit[] = "quit\n";
sleep(2);
write(telnetsock,&negotiation_1[0],15);
sleep(2);
write(telnetsock,&negotiation_2[0],12);
sleep(2);
write(telnetsock,&telnet_login_name[0],7);
sleep(2);
write(telnetsock,&telnet_login_password[0],10);
sleep(2);
write(telnetsock,&set_command[0],18);
sleep(2);
write(telnetsock,&save_command[0],6);
sleep(2);
write(telnetsock,&confirm[0],2);
sleep(2);
write(telnetsock,&escape[0],3);
sleep(2);
write(telnetsock,&quit[0],5);
sleep(2);
return(0);
}
就那么简单。最困难的部分是原始(我使用 Wireshark 捕获的)telnet 协商要长一些,但在查看了正在协商的选项后,我意识到我不需要大部分,所以我砍了大幅下降。顺便说一句,如果你被字节吓倒了,不要害怕。没什么大不了的。你看到如何在negotiation_1
和negotiation_2
above, 0xFF keeps popping up every 3 bytes? Well all those two negotiations are are strings of commands/negotiations each 3 bytes in length starting with 0xFF, trying to communicate what it will and won't do during the telnet session. And the second byte in each chunk of 3 bytes (either 0xFB, 0xFC, 0xFD or 0xFE) is just communicating whether it WILL or WON'T do something or whether it wants the other guy to DO or DON'T something. The last byte is just the option each is willing or not willing to do or going to do or not do. You'll see it in Wireshark how it all gets broken down. It's actually pretty funny the language of it. I didn't include the lines I originally had where I was reading the socket to see the responses to the negotiations (which I had done all that testing and stuff in ruby since I could just run it in irb super easy), but you must do that and basically just negotiate as little as you can until you get sent the login prompt and then as you can see it's super straightforward. Make sure in testing to determine the first negotiation you will write to the socket, that when you open the socket, you read in whatever telnet control sequences are sent FIRST. Then you only want to respond to those sequences--mostly in the negative to reduce the amount of negotiation. Have fun!