• TFTP协议解析及C/C++代码实现


    TFTP 用于以非常简单的方式传输文件。与其他文件传输协议(如:FTP 或 HTTP)相比,TFTP 更简单,代码量也更小,因此更易于实现。

    通常,TFTP 使用 UDP 作为其传输协议。众所周知的 TFTP 流量 UDP 端口是 69。

    什么是 TFTP? (普通文件传输协议)

    普通文件传输协议是一种在网络设备之间传输文件的技术,是更强大的文件传输协议的简化版本。 TFTP 是在 1970 年代为缺乏足够内存或磁盘空间以提供完整 FTP 支持的计算机开发的。

    与 FTP 一样,TFTP 使用客户端和服务器软件在两个设备之间建立连接。 从 TFTP 客户端,可以将单个文件上传到服务器或从服务器下载。 服务器托管文件,客户端请求或发送文件。

    TFTP 协议如何工作?

    要启动传输过程,主要要求是服务器形成连接,以便它可以读取或写入要传输的文件。一旦建立连接,发送文件的过程就开始了。这些文件以 512 字节的固定长度块的小数据包传输。

    这些数据包进一步分为块,每个包由一个块组成。

    一旦发送了一个数据包,它需要在发送另一个数据包之前由确认包确认。

    现在要完全传输并得到确认,数据包至少应为 512 字节。如果数据包的大小小于 512 字节,则导致数据包终止。反过来,这会导致传输过程超时,发送方必须重新传输数据包。

    该过程中涉及的两台机器都被视为发送者和接收者。这是因为当一个发送数据并接收确认时,另一个发送确认并接受数据。

    TFTP 存在的安全隐患

    由于 TFTP 是为简单易用而设计的,因此通常用于保护数据的任何机制都没有在其协议中实现。

    这导致了许多安全问题。因为所有 TFTP 数据包都是通过网络以明文形式发送的,没有数据加密。


    任何在与 TFTP 会话相同的网段上捕获网络流量的人都可以轻松收集传输的数据并重新创建原始文件。

    如果文件包含敏感数据,例如用户名和密码,那么任何捕获流量的人都可以轻松使用它。

    TFTP 三种传输模式

    目前支持三种传输方式:

    1、 netascii
    2、octet
    3、mail

    支持三种不同的传输模式:“netascii”,“octet"和"mail”,前两种符合FTP协议中的"ASCII"和"image(binary)"模式;第三种从来很少使用,当前已经废弃。

    TFTP 协议格式

    TFTP共定义了五种类型的包格式,格式的区分由包数据前两个字节的Opcode字段区分,分别是:

    读文件请求包:Read request,简写为RRQ,对应Opcode字段值为1
    写文件请求包:Write requst,简写为WRQ,对应Opcode字段值为2
    文件数据包:Data,简写为DATA,对应Opcode字段值为3
    回应包:Acknowledgement,简写为ACK,对应Opcode字段值为4
    错误信息包:Error,简写为ERROR,对应Opcode字段值为5
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Opcode字段区分:

    #define RRQ 01 /* read request */
    #define WRQ 02 /* write request */
    #define DATA 03 /* data packet */
    #define ACK 04 /* acknowledgement */
    #define ERROR 05 /* error code */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 读/写请求包

    1.操作码(2字节),它用来表示当前数据包的类型(取值1表示该数据包是个读请求,2表示该数据包是写请求);
    2.可变长字段,它用来表示要读取或上传的文件名,它使用ASCII码并以0表示结尾;
    3.Mode,也是可变长字段,用来表示传输文件的数据类型,如果传输的是字符串文件,那么它填写字符串”netascii”,如果传输的是二进制文件,那么它填写字符串”octet”,这些字符串都以0结尾。

    RRQ 和 WRQ 数据包(分别为操作码 1 和 2)具有以下格式



    文件名是netascii中的字节序列以零字节终止。 模式字段包含字符串“netascii”、“octet”或“mail”

    • 数据包格式
      数据实际上以数据包的形式传输。

      数据包(操作码 = 3)具有块号和数据字段。 块数据包上的数字从 1 开始,每增加一个新的数据块。 此限制允许程序使用单个区分新数据包和重复数据包的编号。 数据字段长度为 0 到 512 个字节。 如果它是 512 字节长,则block 不是最后一个数据块; 如果它是从零到 511 字节长,它表示传输结束。

    传输数据块的DATA数据包,它头2字节也是操作码,取值3用于表示数据包用于数据块传输,接下来的2字节用于表示数据块编号,最后是可变长字段Data,用于装载数据块。

    • ACK包

    ACK 数据包由 DATA 或 ERROR 数据包确认。ACK包(Acknowledgement)用于确认数据包已收到,和接收到的数据包数据块号相同。ACK包的操作码为4。

    当接收方收到一个数据包后,会向发送方发送一个ACK包;而发送方则会在收到一个ACK包后继续发送下一个包。若发送完未能收到ACK包,则会使用超时机制,重新发送刚才的数据包。

    • 错误包


    错误ERROR数据包,它开始的2字节表示操作码,取值5;接下来2字节表示错误码;最后的是可变长字段,它用字符串的形式描述具体错误。

    TFTP协议解析及C/C++代码实现

    static bool dissect_embeddedtftp_heur(u_char  *tvb, packet_info *pinfo)
    {
    
      conversation_t   *conversation;
      unsigned short  opcode;
    
      if (tvb_captured_length(tvb) < MIN_HDR_LEN)
        return FALSE;
    
      opcode = tvb_get_ntohs(tvb, 0);
    
      switch (opcode) 
      {
        case TFTP_RRQ:
        case TFTP_WRQ:
          if (!is_valid_requerest_body(tvb))
            return FALSE;
        case TFTP_DATA:
        case TFTP_ACK:
        case TFTP_OACK:
        case TFTP_INFO:
          break;
        case TFTP_ERROR:
          switch (tvb_get_ntohs(tvb, 2)) {
            case TFTP_ERR_NOT_DEF:
            case TFTP_ERR_NOT_FOUND:
            case TFTP_ERR_NOT_ALLOWED:
            case TFTP_ERR_DISK_FULL:
            case TFTP_ERR_BAD_OP:
            case TFTP_ERR_BAD_ID:
            case TFTP_ERR_EXISTS:
            case TFTP_ERR_NO_USER:
            case TFTP_ERR_OPT_FAIL:
              break;
            default:
              return FALSE;
          }
          break;
        default:
          return FALSE;
      }
    
      dissect_tftp_message(tftp_info_for_conversation(conversation), tvb, pinfo);
      return TRUE;
    }
    
    static void dissect_tftp_message(tftp_conv_info_t *tftp_info,
                                     u_char *tvb, packet_info *pinfo,)
    {
    
    
      switch (opcode) {
    
      case TFTP_RRQ:
        ...
        break;
    
      case TFTP_WRQ:
        ...
        break;
    
      case TFTP_INFO:
        ...
        break;
    
      case TFTP_DATA:
         ...
        break;
    
      case TFTP_ACK:
        ...
        break;
    
      case TFTP_ERROR:
        ...
        break;
    
      case TFTP_OACK:
        ...
        break;
    
      default:
        ...
        break;
    
      }
      ...
    }
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    运行结果:

    在这里插入图片描述

    FTP 与 TFTP 协议

    尽管这两种协议都用于将文件从一台计算机传输到另一台计算机,但它们之间仍然存在一些显着差异。 一些变化点如下:

    1、FTP 使用 TCP(传输控制协议),而 TFTP 使用 UDP(用户数据报协议)。
    2、FTP 协议适用于两个端口,即。 20 和 21,而 TFTP 协议在单个端口(69)上工作。
    3、与 TFTP 协议相比,FTP 协议非常复杂。
    4、FTP 协议提供了许多消息,而 TFTP 协议只有五个消息。

    总结

    TFTP 是一种非常有用的技术,用于服务器和客户端之间的文件通信。它可以轻松使用,因为它需要更少的编码,更少的内存使用,并且由于不需要身份验证和安全机制,因此可以轻松使用。

    参考:RFC1350

    欢迎关注微信公众号【程序猿编码】,需要 TFTP协议解析完整源码 的添加本人微信号(c17865354792)

  • 相关阅读:
    构建白平衡色温坐标系
    PHP8中删除数组中的重复元素-PHP8知识详解
    ConfigurationProperties配置绑定
    Windows/Ubuntu双系统给Ubuntu磁盘扩容核心步骤
    Python函数详解(二)——函数的参数传递基础
    lstm时间序列 深度学习
    MySQL之数据库维护
    Spring自动配置原理
    2022/09/12、13、14 day02/03/04:HTML和CSS(二)
    Mybatis-Plus实现乐观锁
  • 原文地址:https://blog.csdn.net/chen1415886044/article/details/126275764