我在Go中编写SMTP服务器。实现STARTTLS命令需要使用crypto/tls
包。
Here似乎我应该能够"转换" net.Conn对象为tls.Conn,然后我可以使用TLS提供的加密无缝读写。
但是,即使我能够完成上述的第一部分,当我尝试读取或写入受TLS保护的连接时,所调用的Read()和Write()函数也不是tls.Conn对象,但是底层的net.Conn对象。
我目前正在做的事情如下:
type Handler struct {
Conn net.Conn
}
//...
client := Handler{Conn: /*socket*/}
client.Conn.Write([]byte("Hello!")) //regular write
//the STARTTLS command has been received, switch to tls.Conn and handshake
client.Conn = tls.Server(client.Conn, &TlsConfig) //client.Conn should be now of type tls.Conn
//either casting or not give me the same results
client.Conn.Handshake() //not necessary, it is called on the first Read() or Write() by default
//...
client.Conn.Write([]byte("Hello again!")) //writes clear, unencrypted text
//...
rdr := bufio.NewReader(client.Conn) //might this be the culprit? I don't think it is, since it should just wrap the regular functions
line, err := rdr.ReadString/*or Line*/('\n')
//...
//line = something like À"À!27ÀÀ9ÀÀÀÀ and other client-encrypted text
我已经看到很多人(包括标准net/smtp
包)使用text/proto
包来解析客户端命令。但是,我想使用我自己的(并且也希望对此进行排序)。正如之前的评论一样,我不认为罪魁祸首在于此,因为它应该只包装函数,不应该吗?
可能是client.Conn = tls.Server(client.Conn, &TlsConfig)
对象切换?
我使用的SSL密钥和证书是自签名的,使用OpenSSL生成。
为了测试,我使用了上面链接的StackOverflow问题中建议的两种方法:openssl s_client -starttls smtp -crlf [-tls1] -connect localhost:25
和一个简单的net/smtp.SendMail()
调用。我正在编译Go 1.2.1(linux / amd64)。
我也试过用Wireshark嗅闻,事实上它让我知道我上面说的话。此外,调用握手()并不显然实际上是握手。
我做错了什么?
答案 0 :(得分:0)
尝试将TLS连接存储在*tls.Conn
类型的新变量中。发起握手并检查ConnectionState()
告诉的内容。