自己署名サーバー証明書を使用してTLS接続を確立しようとしています。
このサンプルコードで証明書を生成しました: http://golang.org/src/pkg/crypto/tls/generate_cert.go
関連するクライアントコードは次のようになります。
// server cert is self signed -> server_cert == ca_cert
CA_Pool := x509.NewCertPool()
severCert, err := ioutil.ReadFile("./cert.pem")
if err != nil {
log.Fatal("Could not load server certificate!")
}
CA_Pool.AppendCertsFromPEM(severCert)
config := tls.Config{RootCAs: CA_Pool}
conn, err := tls.Dial("tcp", "127.0.0.1:8000", &config)
if err != nil {
log.Fatalf("client: dial: %s", err)
}
そして、そのような関連するサーバーコード:
cert, err := tls.LoadX509KeyPair("./cert.pem", "./key.pem")
config := tls.Config{Certificates: []tls.Certificate{cert}}
listener, err := tls.Listen("tcp", "127.0.0.1:8000", &config)
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("server: accept: %s", err)
break
}
log.Printf("server: accepted from %s", conn.RemoteAddr())
go handleConnection(conn)
}
サーバー証明書は自己署名されているため、サーバーとクライアントCA_Poolに同じ証明書を使用しますが、常にこのエラーが発生するため、これは機能していないようです:
client: dial: x509: certificate signed by unknown authority
(possibly because of "x509: invalid signature: parent certificate
cannot sign this kind of certificate" while trying to verify
candidate authority certificate "serial:0")
私の間違いは何ですか?
最終的にx509.CreateCertificateに組み込まれたgoで動作しました。問題はIsCA:trueフラグを設定しなかった、x509.KeyUsageCertSignを設定しただけ自己署名証明書は機能しますが、証明書チェーンの検証中にクラッシュしました。
問題は、サーバー側の設定で [〜#〜] ca [〜#〜] 証明書が必要であり、このCAがサーバーの証明書に署名している必要があることです。
generate CA証明書となるGoコードをいくつか作成しましたが、これは誰にもレビューされておらず、主にクライアント証明書をいじるおもちゃです。最も安全な方法は、おそらく openssl ca
証明書を生成して署名します。基本的な手順は次のとおりです。
tls.Config
RootCAs
tls.Config
サーバーキーと署名付き証明書。カイル、正しいです。このツールはあなたが望むことを行い、プロセス全体を簡素化します:
https://github.com/deckarep/EasyCert/releases (opensslツールを内部で使用するため、OSXのみがサポートされます)
およびソース:
https://github.com/deckarep/EasyCert
基本的にこのツールを使用すると、ファイルのバンドルが生成されますが、完了時に出力される3つが必要になります。
Golangでmysqlクライアントを使用すると、同じエラーが表示されました。
Failed to connect to database: x509: cannot validate certificate for 10.111.202.229 because it doesn't contain any IP SANs
InsecureSkipVerify
をtrue
に設定すると(証明書の検証をスキップするため)解決されました:
https://godoc.org/crypto/tls#Config
次のコードは私のために働いた:
package main
import (
"fmt"
"github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
)
func main() {
rootCertPool := x509.NewCertPool()
pem, err := ioutil.ReadFile("/usr/local/share/ca-certificates/ccp-root-ca.crt")
if err != nil {
log.Fatal(err)
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
log.Fatal("Failed to append root CA cert at /usr/local/share/ca-certificates/ccp-root-ca.crt.")
}
mysql.RegisterTLSConfig("custom", &tls.Config{
RootCAs: rootCertPool,
InsecureSkipVerify: true,
})
db, err := gorm.Open("mysql", "ccp-user:I6qnD6zNDmqdDLXYg3HqVAk2P@tcp(10.111.202.229:3306)/ccp?tls=custom")
defer db.Close()
}
私の場合、追加した証明書はpem形式で正しくエンコードされていません。 keytoolsを使用している場合、キーストアから証明書をエクスポートするときに-rfcを追加するようにしてください。エンコードされたpemはテキストエディターで開いて表示できます。
-----BEGIN CERTIFICATE----- MIIDiDCCAnCgAwIBAgIEHKSkvDANBgkqhkiG9w0BAQsFADBi...
InsecureSkipVerifyフラグを使用する必要があります。 https://groups.google.com/forum/#!topic/golang-nuts/c9zEiH6ixyw を参照してください。
この投稿の関連コード(ページがオフラインの場合):
smtpbox := "mail.foo.com:25"
c, err := smtp.Dial(smtpbox)
Host, _, _ := net.SplitHostPort(smtpbox)
tlc := &tls.Config{
InsecureSkipVerify: true,
ServerName: Host,
}
if err = c.StartTLS(tlc); err != nil {
fmt.Printf(err)
os.Exit(1)
}
// carry on with rest of smtp transaction
// c.Auth, c.Mail, c.Rcpt, c.Data, etc