读写tls.Server连接

huangapple go评论77阅读模式
英文:

Reading and writing over a tls.Server connection

问题

我正在使用Go语言编写一个SMTP服务器。实现STARTTLS命令需要使用crypto/tls包。在这里,我应该能够将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!")) //普通写入
//已接收到STARTTLS命令,切换到tls.Conn并进行握手
client.Conn = tls.Server(client.Conn, &TlsConfig) //client.Conn现在应该是tls.Conn类型
//无论是进行类型转换还是不进行类型转换,结果都是一样的
client.Conn.Handshake() //不是必需的,因为默认情况下会在第一次Read()或Write()时调用
//...
client.Conn.Write([]byte("Hello again!")) //写入明文、未加密的文本
//...
rdr := bufio.NewReader(client.Conn) //这可能是问题所在吗?我认为不是,因为它只是包装了常规函数
line, err := rdr.ReadString/*or Line*/('\n')
//...
//line = 类似于"�'�9����"和其他客户端加密文本

我看到很多人包括标准的`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进行抓包确实发现了我上面说的情况此外调用Handshake()似乎并没有实际进行握手

我做错了什么

<details>
<summary>英文:</summary>

I&#39;m writing an SMTP server in Go. Implementing the STARTTLS command requires usage of the `crypto/tls` package.
[Here](https://stackoverflow.com/questions/13110713/upgrade-a-connection-to-tls-in-go) seems like I should be able to &quot;convert&quot; the net.Conn object to a tls.Conn one, and then I&#39;d be able to seamlessly read and write using the encryption TLS provides.

However, even if I&#39;m able to do the first part of the above, when I try to read or write to the TLS-protected connection, the Read() and Write() functions called are not the ones of the tls.Conn object, but of the underlying net.Conn one.

What I&#39;m currently doing looks like this:

&lt;!-- language: go --&gt;

    type Handler struct {
        Conn net.Conn
    }
    //...
    client := Handler{Conn: /*socket*/}
    client.Conn.Write([]byte(&quot;Hello!&quot;)) //regular write
    //the STARTTLS command has been received, switch to tls.Conn and handshake
    client.Conn = tls.Server(client.Conn, &amp;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(&quot;Hello again!&quot;)) //writes clear, unencrypted text
    //...
    rdr := bufio.NewReader(client.Conn) //might this be the culprit? I don&#39;t think it is, since it should just wrap the regular functions
    line, err := rdr.ReadString/*or Line*/(&#39;\n&#39;)
    //...
    //line = something like &#192;&quot;&#192;!27&#192;&#192;9&#192;&#192;&#192;&#192; and other client-encrypted text

I&#39;ve seen that numerous people, including the standard `net/smtp` package, use the `text/proto` package to parse client commands. However, I want to use my own (and also want to sort this out). As in the comment earlier, I don&#39;t think the culprit lies here, since it should just wrap functions, shouldn&#39;t it?

Might it be the `client.Conn = tls.Server(client.Conn, &amp;TlsConfig)` object switch?

The SSL key and certificate I&#39;m using are selfsigned, generated with OpenSSL.
To test, I&#39;m using the two methods suggested in the StackOverflow question linked above: `openssl s_client -starttls smtp -crlf [-tls1] -connect localhost:25` and a simple `net/smtp.SendMail()` call. I&#39;m compiling against Go 1.2.1 (linux/amd64).

I&#39;ve also tried sniffing with Wireshark, and indeed it led me to know what I said above. Also, calling Handshake() doesn&#39;t apparently actually handshake.

What am I doing wrong?

</details>


# 答案1
**得分**: 0

尝试将你的TLS连接存储在一个新的类型为`*tls.Conn`的变量中发起握手并检查`ConnectionState()`返回的内容

<details>
<summary>英文:</summary>

Try storing your TLS connection in a new variable of type `*tls.Conn`. Initiate a handshake and check what `ConnectionState()` tells.

</details>



huangapple
  • 本文由 发表于 2014年4月16日 03:26:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/23092678.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定