ping.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package tls
  2. import (
  3. "crypto/tls"
  4. "crypto/x509"
  5. "encoding/base64"
  6. "fmt"
  7. "net"
  8. "github.com/v2fly/v2ray-core/v4/main/commands/base"
  9. v2tls "github.com/v2fly/v2ray-core/v4/transport/internet/tls"
  10. )
  11. // cmdPing is the tls ping command
  12. var cmdPing = &base.Command{
  13. UsageLine: "{{.Exec}} tls ping [-ip <ip>] <domain>",
  14. Short: "Ping the domain with TLS handshake",
  15. Long: `
  16. Ping the domain with TLS handshake.
  17. Arguments:
  18. -ip
  19. The IP address of the domain.
  20. `,
  21. }
  22. func init() {
  23. cmdPing.Run = executePing // break init loop
  24. }
  25. var (
  26. pingIPStr = cmdPing.Flag.String("ip", "", "")
  27. )
  28. func executePing(cmd *base.Command, args []string) {
  29. if cmdPing.Flag.NArg() < 1 {
  30. base.Fatalf("domain not specified")
  31. }
  32. domain := cmdPing.Flag.Arg(0)
  33. fmt.Println("Tls ping: ", domain)
  34. var ip net.IP
  35. if len(*pingIPStr) > 0 {
  36. v := net.ParseIP(*pingIPStr)
  37. if v == nil {
  38. base.Fatalf("invalid IP: %s", *pingIPStr)
  39. }
  40. ip = v
  41. } else {
  42. v, err := net.ResolveIPAddr("ip", domain)
  43. if err != nil {
  44. base.Fatalf("Failed to resolve IP: %s", err)
  45. }
  46. ip = v.IP
  47. }
  48. fmt.Println("Using IP: ", ip.String())
  49. fmt.Println("-------------------")
  50. fmt.Println("Pinging without SNI")
  51. {
  52. tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443})
  53. if err != nil {
  54. base.Fatalf("Failed to dial tcp: %s", err)
  55. }
  56. tlsConn := tls.Client(tcpConn, &tls.Config{
  57. InsecureSkipVerify: true,
  58. NextProtos: []string{"http/1.1"},
  59. MaxVersion: tls.VersionTLS12,
  60. MinVersion: tls.VersionTLS12,
  61. // Do not release tool before v5's refactor
  62. // VerifyPeerCertificate: showCert(),
  63. })
  64. err = tlsConn.Handshake()
  65. if err != nil {
  66. fmt.Println("Handshake failure: ", err)
  67. } else {
  68. fmt.Println("Handshake succeeded")
  69. printCertificates(tlsConn.ConnectionState().PeerCertificates)
  70. }
  71. tlsConn.Close()
  72. }
  73. fmt.Println("-------------------")
  74. fmt.Println("Pinging with SNI")
  75. {
  76. tcpConn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: 443})
  77. if err != nil {
  78. base.Fatalf("Failed to dial tcp: %s", err)
  79. }
  80. tlsConn := tls.Client(tcpConn, &tls.Config{
  81. ServerName: domain,
  82. NextProtos: []string{"http/1.1"},
  83. MaxVersion: tls.VersionTLS12,
  84. MinVersion: tls.VersionTLS12,
  85. // Do not release tool before v5's refactor
  86. // VerifyPeerCertificate: showCert(),
  87. })
  88. err = tlsConn.Handshake()
  89. if err != nil {
  90. fmt.Println("handshake failure: ", err)
  91. } else {
  92. fmt.Println("handshake succeeded")
  93. printCertificates(tlsConn.ConnectionState().PeerCertificates)
  94. }
  95. tlsConn.Close()
  96. }
  97. fmt.Println("Tls ping finished")
  98. }
  99. func printCertificates(certs []*x509.Certificate) {
  100. for _, cert := range certs {
  101. if len(cert.DNSNames) == 0 {
  102. continue
  103. }
  104. fmt.Println("Allowed domains: ", cert.DNSNames)
  105. }
  106. }
  107. func showCert() func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
  108. return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
  109. hash := v2tls.GenerateCertChainHash(rawCerts)
  110. fmt.Println("Certificate Chain Hash: ", base64.StdEncoding.EncodeToString(hash))
  111. return nil
  112. }
  113. }