Gmail SMTP在ClientHello上关闭套接字,使用十六进制15 03 01 00 02 02 16

时间:2018-03-06 15:01:01

标签: c++ ssl winapi smtp tls1.2

我正在构建自己的SMTP客户端(在WinAPI中使用C ++,但这无关紧要)。首先,我在端口25连接到smtp.gmail.com。它响应

220 smtp.gmail.com ESMTP f191sm4468458ite.4 - gsmtp

我发送EHLO消息,然后收到

250-smtp.gmail.com at your service, [<I blocked out my IP here>]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8

现在,我发送STARTTLS。响应:

220 2.0.0 Ready to start TLS

看起来不错,所以此时我假设我首先发送RFC5246中指定的ClientHello。所以我发送以下hexes(在将它们编码为字节后):

03 03 5a 9e 49 ff

前两个应该是ProtocolVersion,两个uint8字节,33。然后,接下来的四个字节应该是当前的UTC客户端纪元时间,作为大端的UNIX uint32。但在我发送剩余的ClientHello之前,Gmail的SMTP会立即用

关闭套接字
15 03 01 00 02 02 16

我不确定如何在RFC或其他方面找到有关此错误的信息。它似乎不是一个警报,因为RFC状态警报应该以1或2的字节开头.Gmail的SMTP响应意味着什么,我在前6个字节中做错了什么?

1 个答案:

答案 0 :(得分:3)

根据RFC 5246 Section 6.2.1,消息的结构是

struct {
    uint8 major;
    uint8 minor;
} ProtocolVersion;

enum {
    change_cipher_spec(20), alert(21), handshake(22),
    application_data(23), (255)
} ContentType;

struct {
    ContentType type;
    ProtocolVersion version;
    uint16 length;
    opaque fragment[TLSPlaintext.length];
} TLSPlaintext;

使用此功能,收到的消息可以解释为

15 : type = alert
03 : version.major = 3
01 : version.minor = 1
00
02 : length = 2
02 : fragment[0] = 0x02
16 : fragment[1] = 0x16

现在您可以使用RFC 5246 Section 7.2来解码片段部分。

02 : level = fatal
16 : description = record_overflow

您的错误似乎已发送ClientHello而未将其包含在TLSPlaintext

当我尝试将03 03 5a 9e 49 ff解释为TLSPlaintext时,它将是

03 : type = ?
03 : version.major = 3
5a : version.minor = 90
9e
49 : length = 0x9e49
ff : fragment[0] = 0xff

根据RFC 5246 Section 7.2.2record_overflow的说明,length字段不能超过2 ^ 14 + 2048字节,但0x9e49超出此限制。这应该是你遇到这个错误的原因。