8

私は開いている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サーバーを実装しており、フラグを使用してswak-tlsでテストしています。スワックの最終出力は次のとおりです

-> STARTTLS
<-  220 Start TLS
Segmentation fault: 11

swaksはテスト済みのツールであり、以前に持っていたnodeJS SMTP実装で動作したため、エラーがクライアント側にあるとは思われません。

私は何を間違えたのですか、それとも何が欠けていますか?

PS:TLS接続が既存の安全でない接続から開始された場合、正確には何が起こりますか?クライアントは別のポートで新しい接続を確立しますか、それとも接続は再利用されますか?

4

2 に答える 2

14

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でのコンバージョンの詳細

Goを非常に強力にするもう1つの理由は、コンバージョンだと思います。

http://golang.org/ref/spec#Conversions

http://golang.org/doc/effective_go.html#conversions

于 2012-10-31T10:44:06.010 に答える
1

捨てられたswaks、Go自身のsmtp.SendMailを使用してTLSをテストするための小さなツールを構築しました:

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)
  }
}
于 2012-10-29T18:23:52.460 に答える