我有一台服务器正在使用TcpListener.BeginAcceptTcpClient()
方法监听客户端。当客户端连接时,EndAcceptTcpClient
方法会为我提供TcpClient
对象,然后我将该客户端流调用NetworkStream.BeginRead()
来侦听从客户端传输的数据。
在客户端(期望服务器支持SSL)尝试连接到(不安全)服务器之前,一切正常。当客户端尝试进行SSL握手时从NetworkStream.BeginRead()
回调中检索到的数据当然是胡言乱语,但是在读取数据与正常&#34之后检测此握手的正确方法是什么? 34;来自客户的消息?
SSL握手是否具有已知的标头/签名标识符,我可以通过查看收到的消息的前几个字节来检查正常消息和SSL握手之间的区别?从检查收到的字节,看起来可能是ASCII 0x16 0x03 0x01 0x00
(a.k.a <SYN><ETX><SOH><NUL>
)。
如果有一个已知的标题,是否有响应我可以发送给客户端告诉它认证失败(通过NetworkStream)?
答案 0 :(得分:1)
我找到了一些有关SSL协议的信息(参考1,2),我可以找到一个标准标题:
来自IBM参考站点2:
Byte 0 = SSL record type = 22 (SSL3_RT_HANDSHAKE)
Bytes 1-2 = SSL version (major/minor)
Bytes 3-4 = Length of data in the record (excluding the header itself).
Byte 5 = Handshake type
Bytes 6-8 = Length of data to follow in this record
Bytes 9-n = Command-specific data
所以我可以查找以0x16 [0x?? 0x??] [0x?? 0x??] 0x01
开头的消息(SSL“Client Hello”消息)。
对于拒绝消息,看起来我可以发送0x15 0x?? 0x?? 0x00 0x02 0x02 0x28
转换为<NACK>
,(2byte版本),这是一个2字节长的消息,致命警报,“握手失败”{ {3}}
答案 1 :(得分:0)
SSL / TLS客户端将通过发送Client Hello消息发起握手。
在XDR表示法中,这是:
struct {
ProtocolVersion client_version;
Random random;
SessionID session_id;
CipherSuite cipher_suites<2..2^16-2>;
CompressionMethod compression_methods<1..2^8-1>;
select (extensions_present) {
case false:
struct {};
case true:
Extension extensions<0..2^16-1>;
};
} ClientHello;
在这里,您之前看到的是:对于具有协议TLS 1.0(0x16
)的握手消息(0x0301
),它是record layer。它后面应该是一个长度,然后0x01
表示“Client Hello”和一个版本(可能不同:客户端支持的最高值)。
从实际角度来看,使用Wireshark查看实际数据包(例如在HTTPS上)是值得的。有一些示例捕获和示例on this page(尽管您不需要破解您尝试执行的操作的流量)。