uokadaの見逃し三振は嫌いです

ここで述べられていることは私の個人的な意見に基づくものであり、私が所属する組織には一切の関係はありません。

tlsプロトコルの検証用のサーバーをgoで書いてみた。

ブラウザのSSLプロトコルの対応状況を調べるためにSSLプロトコルを簡単に切り替えられるサーバーをGoで書いてみた。

SSLv3は脆弱性がみつかってるので最新のブラウザだとデフォルト無効化されはじめているんだけど、 SSLv3を切り捨てると通信できなくなるブラウザもいくつかあるわけで切り捨てる前の検証用にサーバーを書いてみた感じ。

ちなみに、TlSConfig.MaxVersionの設定が優先されてTlSconfig.MaxVersionがSSL3.0でTLSCOnfig.MinVersionがTLS1.2ならSSL3.0が勝つって振る舞いをする。

package main

import (
    "crypto/tls"
    "flag"
    "fmt"
    "log"
    "net/http"
    "time"
)

type BaseHandler struct{}

func (bh *BaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hey World!")
}

var keyfile, crtfile string
var port int
var minprtcl, maxprtcl string

func init() {
    flag.IntVar(&port, "port", 443, "listen port")
    flag.StringVar(&keyfile, "keyfile", "server.key", "ssl server.key")
    flag.StringVar(&crtfile, "crtfile", "server.crt", "ssl server.crt")
    flag.StringVar(&minprtcl, "minprotocol", "tls10", "minimum negotiation protocol: ssl30, tls10, tls11,tls12")
    flag.StringVar(&maxprtcl, "maxprotocol", "tls12", "maximum negotiation protocol: ssl30, tls10, tls11,tls12")

    flag.Parse()
}

func convertTlSNumber(protocol string) uint16 {
    var version uint16

    switch protocol {
    case "ssl30":
        version = tls.VersionSSL30
    case "tls10":
        version = tls.VersionTLS10
    case "tls11":
        version = tls.VersionTLS11
    case "tls12":
        version = tls.VersionTLS12
    default:
        log.Fatal("Unknown Protocol: ", protocol)
    }
    return version
}

func main() {
    mux := http.NewServeMux()

    bh := &BaseHandler{}
    mux.Handle("/hey", bh)
    mux.Handle("/", http.RedirectHandler("/hey", http.StatusFound))

    addr := fmt.Sprintf(":%d", port)
    config := &tls.Config{
        // ClientAuth: tls.RequireAnyClientCert,
        MinVersion: convertTlSNumber(minprtcl),
        MaxVersion: convertTlSNumber(maxprtcl),
        // Info: MAXのバージョンが優先される => Cap
    }
    config.CipherSuites = []uint16{tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
        tls.TLS_RSA_WITH_AES_128_CBC_SHA,
        tls.TLS_RSA_WITH_AES_256_CBC_SHA,
        tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
        tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
        tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
        tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
        tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
        tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
        tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
    }

    svr := http.Server{
        Addr:           addr,
        Handler:        mux,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
        TLSConfig:      config,
    }
    log.Printf("Listening on " + svr.Addr)
    // err := svr.ListenAndServe()
    err := svr.ListenAndServeTLS(crtfile, keyfile)

    if err != nil {
        log.Fatal(err)
    }
}