我正在用 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 key 和证书是自签名的,是用 OpenSSL 生成的。
为了进行测试,我使用了上面链接的 StackOverflow 问题中建议的两种方法:openssl s_client -starttls smtp -crlf [-tls1] -connect localhost:25
和一个简单的 net/smtp .SendMail()
调用。我正在针对 Go 1.2.1 (linux/amd64) 进行编译。
我也试过用 Wireshark 嗅探,确实它让我知道我上面说的是什么。此外,调用 Handshake() 显然不是真正的握手。
我做错了什么?
最佳答案
尝试将您的 TLS 连接存储在 *tls.Conn
类型的新变量中。启动握手并检查 ConnectionState()
告诉的内容。
关于ssl - 通过 tls.Server 连接读写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23092678/