github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/core/cs/client/client.go (about)

     1  package client
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"encoding/pem"
     7  	"errors"
     8  	"fmt"
     9  	"net"
    10  	"strconv"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/AntonOrnatskyi/goproxy/core/dst"
    15  	"github.com/AntonOrnatskyi/goproxy/core/lib/kcpcfg"
    16  	compressconn "github.com/AntonOrnatskyi/goproxy/core/lib/transport"
    17  	encryptconn "github.com/AntonOrnatskyi/goproxy/core/lib/transport/encrypt"
    18  	kcp "github.com/xtaci/kcp-go"
    19  )
    20  
    21  func TlsConnectHost(host string, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) {
    22  	h := strings.Split(host, ":")
    23  	port, _ := strconv.Atoi(h[1])
    24  	return TlsConnect(h[0], port, timeout, certBytes, keyBytes, caCertBytes)
    25  }
    26  
    27  func TlsConnect(host string, port, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) {
    28  	conf, err := getRequestTlsConfig(certBytes, keyBytes, caCertBytes)
    29  	if err != nil {
    30  		return
    31  	}
    32  	_conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), time.Duration(timeout)*time.Millisecond)
    33  	if err != nil {
    34  		return
    35  	}
    36  	return *tls.Client(_conn, conf), err
    37  }
    38  func TlsConfig(certBytes, keyBytes, caCertBytes []byte) (conf *tls.Config, err error) {
    39  	return getRequestTlsConfig(certBytes, keyBytes, caCertBytes)
    40  }
    41  func getRequestTlsConfig(certBytes, keyBytes, caCertBytes []byte) (conf *tls.Config, err error) {
    42  
    43  	var cert tls.Certificate
    44  	cert, err = tls.X509KeyPair(certBytes, keyBytes)
    45  	if err != nil {
    46  		return
    47  	}
    48  	serverCertPool := x509.NewCertPool()
    49  	caBytes := certBytes
    50  	if caCertBytes != nil {
    51  		caBytes = caCertBytes
    52  
    53  	}
    54  	ok := serverCertPool.AppendCertsFromPEM(caBytes)
    55  	if !ok {
    56  		err = errors.New("failed to parse root certificate")
    57  	}
    58  	block, _ := pem.Decode(caBytes)
    59  	if block == nil {
    60  		panic("failed to parse certificate PEM")
    61  	}
    62  	x509Cert, _ := x509.ParseCertificate(block.Bytes)
    63  	if x509Cert == nil {
    64  		panic("failed to parse block")
    65  	}
    66  	conf = &tls.Config{
    67  		RootCAs:            serverCertPool,
    68  		Certificates:       []tls.Certificate{cert},
    69  		InsecureSkipVerify: true,
    70  		ServerName:         x509Cert.Subject.CommonName,
    71  		VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
    72  			opts := x509.VerifyOptions{
    73  				Roots: serverCertPool,
    74  			}
    75  			for _, rawCert := range rawCerts {
    76  				cert, _ := x509.ParseCertificate(rawCert)
    77  				_, err := cert.Verify(opts)
    78  				if err != nil {
    79  					return err
    80  				}
    81  			}
    82  			return nil
    83  		},
    84  	}
    85  	return
    86  }
    87  
    88  func TCPConnectHost(hostAndPort string, timeout int) (conn net.Conn, err error) {
    89  	conn, err = net.DialTimeout("tcp", hostAndPort, time.Duration(timeout)*time.Millisecond)
    90  	return
    91  }
    92  
    93  func TCPSConnectHost(hostAndPort string, method, password string, compress bool, timeout int) (conn net.Conn, err error) {
    94  	conn, err = net.DialTimeout("tcp", hostAndPort, time.Duration(timeout)*time.Millisecond)
    95  	if err != nil {
    96  		return
    97  	}
    98  	if compress {
    99  		conn = compressconn.NewCompConn(conn)
   100  	}
   101  	conn, err = encryptconn.NewConn(conn, method, password)
   102  	return
   103  }
   104  
   105  func TOUConnectHost(hostAndPort string, method, password string, compress bool, timeout int) (conn net.Conn, err error) {
   106  	udpConn, err := net.ListenUDP("udp", &net.UDPAddr{})
   107  	if err != nil {
   108  		panic(err)
   109  	}
   110  	// Create a DST mux around the packet connection with the default max
   111  	// packet size.
   112  	mux := dst.NewMux(udpConn, 0)
   113  	conn, err = mux.Dial("dst", hostAndPort)
   114  	if compress {
   115  		conn = compressconn.NewCompConn(conn)
   116  	}
   117  	conn, err = encryptconn.NewConn(conn, method, password)
   118  	return
   119  }
   120  func KCPConnectHost(hostAndPort string, config kcpcfg.KCPConfigArgs) (conn net.Conn, err error) {
   121  	kcpconn, err := kcp.DialWithOptions(hostAndPort, config.Block, *config.DataShard, *config.ParityShard)
   122  	if err != nil {
   123  		return
   124  	}
   125  	kcpconn.SetStreamMode(true)
   126  	kcpconn.SetWriteDelay(true)
   127  	kcpconn.SetNoDelay(*config.NoDelay, *config.Interval, *config.Resend, *config.NoCongestion)
   128  	kcpconn.SetMtu(*config.MTU)
   129  	kcpconn.SetWindowSize(*config.SndWnd, *config.RcvWnd)
   130  	kcpconn.SetACKNoDelay(*config.AckNodelay)
   131  	if *config.NoComp {
   132  		return kcpconn, err
   133  	}
   134  	return compressconn.NewCompStream(kcpconn), err
   135  }