我有一个开放的TCP连接,并使用for循环读取它,如此
for {
// tx.Text is of type textproto.Conn
// the underlying connection is stored in tx.Conn
l, err := tx.Text.Reader.ReadLine()
// do stuff with the text line ...
}
现在我想像这样升级到TLS的连接(TlsConf
包含加载了tls.LoadX509KeyPair
的证书)
tx.Conn = tls.Server(tx.Conn, tx.Server.Conf.TlsConf)
tx.Text = textproto.NewConn(tx.Conn)
当我这样做时,我在服务器尝试握手时在客户端上出现分段错误。我正在实现一个SMTP服务器,并使用-tls
标志使用swaks对其进行测试。 swaks的终端输出如下
-> STARTTLS
<- 220 Start TLS
Segmentation fault: 11
由于swaks是一个经过测试的工具,并且使用过我之前使用的nodeJS SMTP实现,我不怀疑错误是在客户端。
我做错了什么或遗失了什么?
PS:从现有的不安全连接启动TLS连接时,究竟会发生什么?客户端是否在其他端口上建立新连接或重用连接?
答案 0 :(得分:12)
以下是将net.conn升级为tls.con的方法:
1)在代码中的某处,您已定义了这些变量
var TLSconfig *tls.Config
...
// conn is a normal connection of type net.Conn
conn, err := listener.Accept()
...
2)在上面的某处初始化TLSConfig,做这样的事情
cert, err := tls.LoadX509KeyPair("/path/to/cert", "/path/to/key")
if err != nil {
// ...
}
TLSconfig = &tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.VerifyClientCertIfGiven,
ServerName: "example.com"}
3)此时您正在读/写标准连接。
当客户端发出STARTTLS命令时,请在您的服务器中执行此操作:
// Init a new TLS connection. I need a *tls.Conn type
// so that I can do the Handshake()
var tlsConn *tls.Conn
tlsConn = tls.Server(client.socket, TLSconfig)
// run a handshake
tlsConn.Handshake()
// Here is the trick. Since I do not need to access
// any of the TLS functions anymore,
// I can convert tlsConn back in to a net.Conn type
conn = net.Conn(tlsConn)
接下来,您可能会使用新连接等更新缓冲区
像这样测试你的服务器:
openssl s_client -starttls smtp -crlf -connect example.com:25
这允许您通过tls连接与服务器交互,您可以发出一些命令等。
我认为转换是Go变得如此强大的另一个原因!
答案 1 :(得分:1)
Ditched swaks,使用Go自己的smtp构建了一个小工具来测试TLS.SendMail:
package main
import (
"fmt"
"net/smtp"
)
func main() {
err := smtp.SendMail(
"127.0.0.1:2525",
nil,
"src@test.local",
[]string{"dst@test.local"},
[]byte("Hello! Just testing."),
)
if err != nil {
panic(err)
}
}