Print connection information
This commit is contained in:
父節點
ea34fe6e16
當前提交
4837945b4d
80
README.md
80
README.md
@ -7,7 +7,85 @@
|
||||
Example:
|
||||
|
||||
```
|
||||
./tlshandshake www.fbi.com:443 -cipher X25519:P256:CECPQ2
|
||||
> go run cmd/tlshandshake/tlshandshake.go -tls_min 1.2 -tls_max 1.3 -groups X25519-SIDHp503 pqcrypto.uk
|
||||
| TLS-Session:
|
||||
-----------------------------------------------------------------
|
||||
Protocol : 1.3
|
||||
Cipher : TLS_AES_128_GCM_SHA256
|
||||
Negotiated Group : X25519-SIDHp503
|
||||
Connection ID : d0129f4dea986b72
|
||||
SCTs : []
|
||||
Connection resumed : FALSE
|
||||
EMS used : FALSE
|
||||
Stapled OCSP response : 308201350a0100a082012e3082012a06092b0601...
|
||||
|
||||
| Connection:
|
||||
-----------------------------------------------------------------
|
||||
Local address : 10.0.1.242:51536
|
||||
Remote address : 198.41.214.162:443
|
||||
|
||||
| Server Certificates:
|
||||
-----------------------------------------------------------------
|
||||
|
||||
Depth : 0
|
||||
Issuer : CN=DigiCert ECC Extended Validation Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 13836083707412516537413894398330316720 (0xa68bb984a507399f4716e809a44a7b0)
|
||||
Signature Algorithm: ECDSA-SHA256
|
||||
Issuer: C=US,O=DigiCert Inc,OU=www.digicert.com,CN=DigiCert ECC Extended Validation Server CA
|
||||
Validity
|
||||
Not Before: Oct 30 00:00:00 2018 UTC
|
||||
Not After : Nov 3 12:00:00 2020 UTC
|
||||
Subject: UnknownOID=2.5.4.15,UnknownOID=1.3.6.1.4.1.311.60.2.1.3,UnknownOID=1.3.6.1.4.1.311.60.2.1.2,UnknownOID=2.5.4.5,C=US,ST=California,UnknownOID=2.5.4.7,O=Cloudflare, Inc.,CN=cloudflare.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: ECDSA
|
||||
Public-Key: (256 bit)
|
||||
X:
|
||||
ce:d7:61:49:49:fd:4b:35:8b:1b:86:bc:a3:c5:bc:
|
||||
d8:20:6e:31:17:2d:92:8a:b7:34:f4:db:11:70:4e:
|
||||
49:16
|
||||
Y:
|
||||
61:fc:ae:fa:7f:ba:6f:0c:05:53:74:c6:79:7f:81:
|
||||
12:8a:f7:e2:5e:6c:f5:fa:10:69:6b:67:d9:d5:96:
|
||||
51:b0
|
||||
Curve: P-256
|
||||
X509v3 extensions:
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:F8:25:D9:A6:39:C7:C3:81:87:25:3E:30:54:91:18:21:40:9B:17:9D
|
||||
X509v3 Subject Key Identifier:
|
||||
DE:7F:7F:E6:7C:ED:ED:61:43:60:47:67:5D:86:2F:84:FD:A6:78:AD
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:cloudflare.com, DNS:www.cloudflare.com
|
||||
X509v3 Key Usage: critical
|
||||
Digital Signature
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
X509v3 CRL Distribution Points:
|
||||
|
||||
Full Name:
|
||||
URI:http://crl3.digicert.com/DigiCertECCExtendedValidationServerCA.crl, URI:http://crl4.digicert.com/DigiCertECCExtendedValidationServerCA.crl
|
||||
|
||||
X509v3 Certificate Policies:
|
||||
Policy: 2.16.840.1.114412.2.1
|
||||
Policy: 2.23.140.1.1
|
||||
Authority Information Access:
|
||||
OCSP - URI:http://ocsp.digicert.com
|
||||
CA Issuers - URI:http://cacerts.digicert.com/DigiCertECCExtendedValidationServerCA.crt
|
||||
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:FALSE
|
||||
Unknown extension 1.3.6.1.4.1.11129.2.4.2
|
||||
|
||||
Signature Algorithm: ECDSA-SHA256
|
||||
30:65:02:30:1e:1b:3d:10:9a:50:23:2e:e6:86:11:13:46:a8:
|
||||
1d:e8:63:f8:2f:60:96:43:49:0a:49:30:73:55:f8:25:63:1d:
|
||||
46:59:da:a9:4b:98:68:99:3d:50:a8:c4:fc:52:0f:e3:02:31:
|
||||
00:d2:64:cc:ad:f8:92:b6:6b:fe:b7:a9:4e:8c:06:3b:fb:d3:
|
||||
08:9f:d9:04:10:80:b9:52:97:0a:14:24:a4:5a:8a:d7:27:3c:
|
||||
1e:86:cb:b7:a8:be:c3:c0:98:fa:4a:91:ae
|
||||
|
||||
```
|
||||
|
||||
# Installation
|
||||
|
@ -3,13 +3,27 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
hs "github.com/henrydcase/tlshandshake"
|
||||
trs "github.com/henrydcase/trs"
|
||||
"github.com/henrydcase/trs"
|
||||
)
|
||||
|
||||
var tls_min, tls_max, named_groups, named_ciphers string
|
||||
var dst_port string
|
||||
|
||||
// Parse flags
|
||||
func init() {
|
||||
flag.StringVar(&tls_min, "tls_min", "1.0", "TLS version to use - minimal")
|
||||
flag.StringVar(&tls_max, "tls_max", "1.3", "TLS version to use - maximal")
|
||||
flag.StringVar(&named_groups, "groups", "", "ECDH group name to use for KEX")
|
||||
flag.StringVar(&named_ciphers, "ciphers", "", "Named cipher IDs to use")
|
||||
flag.StringVar(&dst_port, "port", "443", "Destination port number")
|
||||
}
|
||||
|
||||
func getIDByName(m map[uint16]string, name string) (uint16, error) {
|
||||
for key, value := range m {
|
||||
if value == name {
|
||||
@ -19,51 +33,68 @@ func getIDByName(m map[uint16]string, name string) (uint16, error) {
|
||||
return 0, errors.New("Unknown value")
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s [options] server:port\n", path.Base(os.Args[0]))
|
||||
fmt.Fprintf(os.Stderr, "Flags:\n")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// Usage client args host:port
|
||||
func main() {
|
||||
var tls_version, named_groups, named_ciphers string
|
||||
|
||||
flag.StringVar(&tls_version, "tls_version", "1.3", "TLS version to use")
|
||||
flag.StringVar(&named_groups, "groups", "X25519:P-256:P-384:P-521", "NamedGroups IDs to use")
|
||||
flag.StringVar(&named_ciphers, "ciphers", "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384", "Named cipher IDs to use")
|
||||
// parse flags
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
usage()
|
||||
}
|
||||
|
||||
client := hs.NewClient()
|
||||
client.Addr = flag.Arg(0)
|
||||
if !strings.Contains(client.Addr, ":") {
|
||||
client.Addr += ":443"
|
||||
client.Addr += ":" + dst_port
|
||||
}
|
||||
|
||||
// Set requested DH groups
|
||||
client.TLS.CurvePreferences = []trs.CurveID{}
|
||||
for _, ng := range strings.Split(named_groups, ":") {
|
||||
id, err := getIDByName(hs.NamedGroupsToName, ng)
|
||||
if err != nil {
|
||||
panic("Wrong group name provided")
|
||||
if len(named_groups) != 0 {
|
||||
for _, ng := range strings.Split(named_groups, ":") {
|
||||
id, err := getIDByName(hs.NamedGroupsToName, ng)
|
||||
if err != nil {
|
||||
panic("Wrong group name provided")
|
||||
}
|
||||
client.TLS.CurvePreferences = append(client.TLS.CurvePreferences, trs.CurveID(id))
|
||||
}
|
||||
client.TLS.CurvePreferences = append(client.TLS.CurvePreferences, trs.CurveID(id))
|
||||
}
|
||||
|
||||
// Perform TLS handshake with each each requested CipherSuite
|
||||
tlsID, err := getIDByName(hs.TlsVersionToName, tls_version)
|
||||
// TLS min
|
||||
tlsID, err := getIDByName(hs.TlsVersionToName, tls_min)
|
||||
if err != nil {
|
||||
panic("Unknown TLS version")
|
||||
}
|
||||
client.TLS.MinVersion = tlsID
|
||||
|
||||
// TLS max
|
||||
tlsID, err = getIDByName(hs.TlsVersionToName, tls_max)
|
||||
if err != nil {
|
||||
panic("Unknown TLS version")
|
||||
}
|
||||
client.TLS.MaxVersion = tlsID
|
||||
|
||||
cn := strings.Split(named_ciphers, ":")
|
||||
if len(cn) == 0 {
|
||||
panic("Cipher can't be null")
|
||||
}
|
||||
|
||||
id, err := getIDByName(hs.CipherSuiteIdToName, cn[0])
|
||||
if err != nil {
|
||||
panic("Wrong cipher name provided")
|
||||
if len(named_ciphers) != 0 {
|
||||
id, err := getIDByName(hs.CipherSuiteIdToName, cn[0])
|
||||
if err != nil {
|
||||
panic("Wrong cipher name provided")
|
||||
}
|
||||
client.TLS.CipherSuites = []uint16{id}
|
||||
}
|
||||
client.SetMinMaxTLS(tlsID)
|
||||
client.TLS.CipherSuites = []uint16{id}
|
||||
|
||||
client.TLS.InsecureSkipVerify = true
|
||||
// Let's go
|
||||
client.Run()
|
||||
}
|
||||
|
53
lib.go
53
lib.go
@ -2,10 +2,16 @@ package tlshandshake
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
trs "github.com/henrydcase/trs"
|
||||
"github.com/henrydcase/trs"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
TLS trs.Config
|
||||
Addr string
|
||||
}
|
||||
|
||||
var TlsVersionToName = map[uint16]string{
|
||||
trs.VersionTLS10: "1.0",
|
||||
trs.VersionTLS11: "1.1",
|
||||
@ -14,11 +20,31 @@ var TlsVersionToName = map[uint16]string{
|
||||
}
|
||||
|
||||
var CipherSuiteIdToName = map[uint16]string{
|
||||
trs.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
trs.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
trs.TLS_AES_128_GCM_SHA256: "TLS_AES_128_GCM_SHA256",
|
||||
trs.TLS_AES_256_GCM_SHA384: "TLS_AES_256_GCM_SHA384",
|
||||
trs.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256",
|
||||
trs.TLS_RSA_WITH_RC4_128_SHA: "TLS_RSA_WITH_RC4_128_SHA",
|
||||
trs.TLS_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
trs.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
trs.TLS_RSA_WITH_AES_256_CBC_SHA: "TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
trs.TLS_RSA_WITH_AES_128_CBC_SHA256: "TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
trs.TLS_RSA_WITH_AES_128_GCM_SHA256: "TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
trs.TLS_RSA_WITH_AES_256_GCM_SHA384: "TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||
trs.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
||||
trs.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
trs.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
trs.TLS_ECDHE_RSA_WITH_RC4_128_SHA: "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
||||
trs.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
trs.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
trs.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
trs.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
trs.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
trs.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
trs.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
trs.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
trs.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
trs.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
trs.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
}
|
||||
|
||||
var NamedGroupsToName = map[uint16]string{
|
||||
@ -30,13 +56,6 @@ var NamedGroupsToName = map[uint16]string{
|
||||
uint16(trs.CurveP521): "P-521",
|
||||
}
|
||||
|
||||
var failed uint
|
||||
|
||||
type Client struct {
|
||||
TLS trs.Config
|
||||
Addr string
|
||||
}
|
||||
|
||||
func NewClient() *Client {
|
||||
var c Client
|
||||
c.TLS.InsecureSkipVerify = true
|
||||
@ -44,18 +63,13 @@ func NewClient() *Client {
|
||||
}
|
||||
|
||||
func (c *Client) Run() {
|
||||
fmt.Printf("TLS %s with %s\n", TlsVersionToName[c.TLS.MinVersion], CipherSuiteIdToName[c.TLS.CipherSuites[0]])
|
||||
|
||||
con, err := trs.Dial("tcp", c.Addr, &c.TLS)
|
||||
if err != nil {
|
||||
fmt.Printf("handshake failed: %v\n\n", err)
|
||||
failed++
|
||||
return
|
||||
os.Exit(1)
|
||||
}
|
||||
defer con.Close()
|
||||
|
||||
fmt.Printf("[TLS: %s]\n", TlsVersionToName[con.ConnectionState().Version])
|
||||
fmt.Println("OK\n")
|
||||
printTlsState(con)
|
||||
}
|
||||
|
||||
func (c *Client) Clone() *Client {
|
||||
@ -64,8 +78,3 @@ func (c *Client) Clone() *Client {
|
||||
clone.Addr = c.Addr
|
||||
return &clone
|
||||
}
|
||||
|
||||
func (c *Client) SetMinMaxTLS(ver uint16) {
|
||||
c.TLS.MinVersion = ver
|
||||
c.TLS.MaxVersion = ver
|
||||
}
|
||||
|
53
utils.go
Normal file
53
utils.go
Normal file
@ -0,0 +1,53 @@
|
||||
package tlshandshake
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/grantae/certinfo"
|
||||
trs "github.com/henrydcase/trs"
|
||||
)
|
||||
|
||||
var tf = map[bool]string{
|
||||
true: "TRUE",
|
||||
false: "FALSE",
|
||||
}
|
||||
|
||||
func toHex(b []byte) string {
|
||||
str := make([]byte, hex.EncodedLen(len(b)))
|
||||
hex.Encode(str, b[:])
|
||||
return string(str)
|
||||
}
|
||||
|
||||
func printTlsState(con *trs.Conn) {
|
||||
state := con.ConnectionState()
|
||||
fmt.Println("| TLS-Session:")
|
||||
fmt.Println("-----------------------------------------------------------------")
|
||||
fmt.Printf("\tProtocol\t\t: %s\n", TlsVersionToName[state.Version])
|
||||
fmt.Printf("\tCipher\t\t\t: %s\n", CipherSuiteIdToName[state.CipherSuite])
|
||||
fmt.Printf("\tNegotiated Group\t: %s\n", NamedGroupsToName[uint16(state.Group)])
|
||||
fmt.Printf("\tConnection ID\t\t: %s\n", toHex(state.ConnectionID))
|
||||
fmt.Printf("\tSCTs\t\t\t: %s\n", state.SignedCertificateTimestamps)
|
||||
fmt.Printf("\tConnection resumed\t: %s\n", tf[state.DidResume])
|
||||
//fmt.Printf("\tNext protocol\t\t: %s\n", state.NegotiatedProtocol)
|
||||
fmt.Printf("\tEMS used\t\t: %s\n", tf[con.UsedEMS()])
|
||||
fmt.Printf("\tStapled OCSP response\t: %s\n", toHex(state.OCSPResponse))
|
||||
|
||||
fmt.Println("\n| Connection:")
|
||||
fmt.Println("-----------------------------------------------------------------")
|
||||
fmt.Printf("\tLocal address\t\t: %s\n", con.LocalAddr())
|
||||
fmt.Printf("\tRemote address\t\t: %s\n", con.RemoteAddr())
|
||||
|
||||
fmt.Println("\n| Server Certificates:")
|
||||
fmt.Println("-----------------------------------------------------------------")
|
||||
for i, cert := range state.PeerCertificates {
|
||||
fmt.Printf("Depth : %d\n", i)
|
||||
fmt.Printf("Issuer : %s\n", cert.Issuer)
|
||||
res, err := certinfo.CertificateText(cert)
|
||||
if err != nil {
|
||||
panic("Error parsing received server certificate")
|
||||
}
|
||||
fmt.Println(res)
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user