ping.go 3.0 KB

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