github.com/Psiphon-Labs/tls-tris@v0.0.0-20230824155421-58bf6d336a9a/_dev/tris-localserver/server.go (about)

     1  package main
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"encoding/hex"
     7  	"errors"
     8  	"flag"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"log"
    12  	"net/http"
    13  	"os"
    14  	"strings"
    15  	"time"
    16  )
    17  
    18  type ZeroRTT_t int
    19  type PubKeyAlgo_t int
    20  
    21  // Bitset
    22  const (
    23  	ZeroRTT_None   ZeroRTT_t = 0
    24  	ZeroRTT_Offer            = 1 << 0
    25  	ZeroRTT_Accept           = 1 << 1
    26  )
    27  
    28  type server struct {
    29  	Address string
    30  	ZeroRTT ZeroRTT_t
    31  	TLS     tls.Config
    32  }
    33  
    34  var tlsVersionToName = map[uint16]string{
    35  	tls.VersionTLS10: "1.0",
    36  	tls.VersionTLS11: "1.1",
    37  	tls.VersionTLS12: "1.2",
    38  	tls.VersionTLS13: "1.3",
    39  }
    40  
    41  func NewServer() *server {
    42  	s := new(server)
    43  	s.ZeroRTT = ZeroRTT_None
    44  	s.Address = "0.0.0.0:443"
    45  	s.TLS = tls.Config{
    46  		GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) {
    47  			// If we send the first flight too fast, NSS sends empty early data.
    48  			time.Sleep(500 * time.Millisecond)
    49  			return nil, nil
    50  		},
    51  		MaxVersion: tls.VersionTLS13,
    52  		ClientAuth: tls.NoClientCert,
    53  	}
    54  
    55  	return s
    56  }
    57  
    58  func (s *server) start() {
    59  	var err error
    60  	if (s.ZeroRTT & ZeroRTT_Offer) == ZeroRTT_Offer {
    61  		s.TLS.Max0RTTDataSize = 100 * 1024
    62  	}
    63  
    64  	if keyLogFile := os.Getenv("SSLKEYLOGFILE"); keyLogFile != "" {
    65  		s.TLS.KeyLogWriter, err = os.OpenFile(keyLogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
    66  		if err != nil {
    67  			log.Fatalf("Cannot open keylog file: %v", err)
    68  		}
    69  		log.Println("Enabled keylog")
    70  	}
    71  
    72  	s.TLS.ClientCAs = x509.NewCertPool()
    73  	s.TLS.ClientCAs.AppendCertsFromPEM([]byte(rsaCa_client))
    74  	s.TLS.Accept0RTTData = ((s.ZeroRTT & ZeroRTT_Accept) == ZeroRTT_Accept)
    75  	s.TLS.NextProtos = []string{"npn_proto"}
    76  
    77  	httpServer := &http.Server{
    78  		Addr:      s.Address,
    79  		TLSConfig: &s.TLS,
    80  	}
    81  	log.Fatal(httpServer.ListenAndServeTLS("", ""))
    82  }
    83  
    84  // setServerCertificateFromArgs sets server certificate from an argument provided by the caller. Possible values
    85  // for arg_cert:
    86  // * "rsa": sets hardcoded RSA keypair
    87  // * "ecdsa": sets hardcoded ECDSA keypair
    88  // * FILE1:FILE2: Uses private key from FILE1 and public key from FILE2. Both must be in PEM format. FILE2 can
    89  //   be single certificate or certificate chain.
    90  // * nil: fallbacks to "rsa"
    91  //
    92  // Function generate a panic in case certificate can't be correctly set
    93  func (s *server) setServerCertificateFromArgs(arg_cert *string) {
    94  	var certStr, keyStr []byte
    95  	var cert tls.Certificate
    96  	var err error
    97  
    98  	if arg_cert == nil {
    99  		// set rsa by default
   100  		certStr, keyStr = []byte(rsaCert), []byte(rsaKey)
   101  	} else {
   102  		switch *arg_cert {
   103  		case "rsa":
   104  			certStr, keyStr = []byte(rsaCert), []byte(rsaKey)
   105  		case "ecdsa":
   106  			certStr, keyStr = []byte(ecdsaCert), []byte(ecdsaKey)
   107  		default:
   108  			files := strings.Split(*arg_cert, ":")
   109  			if len(files) != 2 {
   110  				err = errors.New("Wrong format provided after -cert.")
   111  				goto err
   112  			}
   113  			keyStr, err = ioutil.ReadFile(files[0])
   114  			if err != nil {
   115  				goto err
   116  			}
   117  			certStr, err = ioutil.ReadFile(files[1])
   118  			if err != nil {
   119  				goto err
   120  			}
   121  		}
   122  	}
   123  
   124  	cert, err = tls.X509KeyPair(certStr, keyStr)
   125  	if err != nil {
   126  		goto err
   127  	}
   128  
   129  	s.TLS.Certificates = []tls.Certificate{cert}
   130  err:
   131  	if err != nil {
   132  		// Not possible to proceed really
   133  		log.Fatal(err)
   134  		panic(err)
   135  	}
   136  }
   137  
   138  func main() {
   139  
   140  	s := NewServer()
   141  
   142  	arg_addr := flag.String("b", "0.0.0.0:443", "Address:port used for binding")
   143  	arg_cert := flag.String("cert", "rsa", "Public algorithm to use:\nOptions [rsa, ecdsa, PrivateKeyFile:CertificateChainFile]")
   144  	arg_zerortt := flag.String("rtt0", "n", `0-RTT, accepts following values [n: None, a: Accept, o: Offer, oa: Offer and Accept]`)
   145  	arg_confirm := flag.Bool("rtt0ack", false, "0-RTT confirm")
   146  	arg_clientauth := flag.Bool("cliauth", false, "Performs client authentication (RequireAndVerifyClientCert used)")
   147  	flag.Parse()
   148  
   149  	s.Address = *arg_addr
   150  
   151  	s.setServerCertificateFromArgs(arg_cert)
   152  
   153  	if *arg_zerortt == "a" {
   154  		s.ZeroRTT = ZeroRTT_Accept
   155  	} else if *arg_zerortt == "o" {
   156  		s.ZeroRTT = ZeroRTT_Offer
   157  	} else if *arg_zerortt == "oa" {
   158  		s.ZeroRTT = ZeroRTT_Offer | ZeroRTT_Accept
   159  	}
   160  
   161  	if *arg_clientauth {
   162  		s.TLS.ClientAuth = tls.RequireAndVerifyClientCert
   163  	}
   164  
   165  	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
   166  		tlsConn := r.Context().Value(http.TLSConnContextKey).(*tls.Conn)
   167  
   168  		with0RTT := ""
   169  		if !tlsConn.ConnectionState().HandshakeConfirmed {
   170  			with0RTT = " [0-RTT]"
   171  		}
   172  		if *arg_confirm || r.URL.Path == "/confirm" {
   173  			if err := tlsConn.ConfirmHandshake(); err != nil {
   174  				log.Fatal(err)
   175  			}
   176  			if with0RTT != "" {
   177  				with0RTT = " [0-RTT confirmed]"
   178  			}
   179  			if !tlsConn.ConnectionState().HandshakeConfirmed {
   180  				panic("HandshakeConfirmed false after ConfirmHandshake")
   181  			}
   182  		}
   183  
   184  		resumed := ""
   185  		if r.TLS.DidResume {
   186  			resumed = " [resumed]"
   187  		}
   188  
   189  		http2 := ""
   190  		if r.ProtoMajor == 2 {
   191  			http2 = " [HTTP/2]"
   192  		}
   193  
   194  		fmt.Fprintf(w, "<!DOCTYPE html><p>Hello TLS %s%s%s%s _o/\n", tlsVersionToName[r.TLS.Version], resumed, with0RTT, http2)
   195  	})
   196  
   197  	http.HandleFunc("/ch", func(w http.ResponseWriter, r *http.Request) {
   198  		w.Header().Set("Content-Type", "text/plain")
   199  		fmt.Fprintf(w, "Client Hello packet (%d bytes):\n%s", len(r.TLS.ClientHello), hex.Dump(r.TLS.ClientHello))
   200  	})
   201  
   202  	s.start()
   203  }
   204  
   205  const (
   206  	rsaKey = `-----BEGIN RSA PRIVATE KEY-----
   207  MIIEpAIBAAKCAQEA1DHcIM3SThFqy8nAkPQFX0E7ph8jqh8EATXryjKHGuVjR3Xh
   208  OQ0BSPoJxyfdg/VEwevFrtmZAfz0WCbxvP2SVCmf7oobg4V2KPSo3nNt9vlBFUne
   209  RtIyHRQ8YRnGSWaRHzJbX6ffltnG2aD+8qUfk161rdZgxBA9G0Ga47IkwQhT2Hqu
   210  H3dW2Uu4W2WMyt6gX/tdyEAV57MOPcoceknr7Nb2kfiuDPR7h6wFrW3I6eoj8oX2
   211  SkIOuVNt1Z31BAUcPJDUjqopI0o9tolM/7X13M8dEY0OJQVr7FQYDF9JeSYeEMyb
   212  wizjBaHDm48mSghP1o5UssQBbNNC83btXCjiLQIDAQABAoIBACzvGgRAUYaCnbDl
   213  2kdXxUN0luMIuQ6vXrO67WF17bI+XRWm2riwDlObzzJDON9Wsua1vLjYD1SickOw
   214  i4RP1grIfbuPt1/UhT8LAC+LFgA0rBmL+OvaWw5ZWKffQ2QLujN3AG5zKB/Tog43
   215  z4UmfldAuQxE11zta2M4M0qAUNQnQj1oiuI8RUdG0VvvLw8Htdi1ogH0CI5R669z
   216  NjHt+JV+2gzKx6EX0s8mQL3yXGkC2xXItRbFclyCMJEhPS7QbBu+tru35N6WpzAq
   217  BCl2Q7LQogvSA6MXuMOx6CyuExVfgmhbfeoheLE8gmXwl0Y37n/g6ZBZFAtpCjcs
   218  UckPv0ECgYEA1orl7RwgIsZljMap6vWtMGoRIHKmT91DGpMmkh4suZe+yAk85maU
   219  49Vd+8ZfIN41AH37yrsGOcPHgz5o5QufELpoub6DCsQ7u9F1vQp55cp+qyBWzAgz
   220  b/xUuVnIyv3kLan3fpk7ZGCBXFBpLG0QXMFOHtda3Mlk5SmuoEYaYRkCgYEA/TLR
   221  u4neKqyqwsqMuRJGC1iKFVmfCjZeNMtPNbTWpdqez/vvT8APnEpIumUGt8YROLGZ
   222  8biUr5/ViOkmaP3wmQbO9m2/cE01lMTYv75w1cw2KVQe6kAHJkOx+JEx9xg53RJ/
   223  QlFtG5MQUy2599Gxp8BMGaXLH5yo4qwvNvY6CDUCgYEArxr7AwX7rKZlZ/sV4HHY
   224  gzVu+R7aY0DibiRATO5X7rrNuhLgI+UCDNqvNLn6FqeGdvpcsmDneeozQwmDL77G
   225  ey7KHyBBcF4tquQQxtRwHX+i1yUz8p+W7AX1WLrRSezjeenJ2QhUE1849hGjZeE2
   226  g546lq2Kub2enfPhVWsiSLECgYEA72T5QCPeVuLioUH5Q5Kvf1K7W+xcnr9A2xHP
   227  Vqwgtre5qFQ/tFuXZuIlWXbjnyY6aiwhrZYjntm0f7pRgrt2nHj/fafOdVPK8Voc
   228  xU4+SSbHntPWVw0qtVcUEjzVzRauvwMaJ43tZ0DpEnwNdO5i1oTObwF+x+jLFWZP
   229  TdwIinECgYBzjZeCxxOMk5SlPpTsLUtgC+q3m1AavXhUVNEPP2gKMOIPTETPbhbG
   230  LBxB2vVbJiS3J7itQy8gceT89O0vSEZnaTPXiM/Ws1QbkBJ8yW7KI7X4WuzN4Imq
   231  /cLBRXLb8R328U27YyQFNGMjr2tX/+vx5FulJjSloWMRNuFWUngv7w==
   232  -----END RSA PRIVATE KEY-----`
   233  	rsaCert = `-----BEGIN CERTIFICATE-----
   234  MIIC+jCCAeKgAwIBAgIRANBDimJ/ww2tz77qcYIhuZowDQYJKoZIhvcNAQELBQAw
   235  EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA5MjQxNzI5MTlaFw0yNjA5MjIxNzI5
   236  MTlaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
   237  ggEKAoIBAQDUMdwgzdJOEWrLycCQ9AVfQTumHyOqHwQBNevKMoca5WNHdeE5DQFI
   238  +gnHJ92D9UTB68Wu2ZkB/PRYJvG8/ZJUKZ/uihuDhXYo9Kjec232+UEVSd5G0jId
   239  FDxhGcZJZpEfMltfp9+W2cbZoP7ypR+TXrWt1mDEED0bQZrjsiTBCFPYeq4fd1bZ
   240  S7hbZYzK3qBf+13IQBXnsw49yhx6Sevs1vaR+K4M9HuHrAWtbcjp6iPyhfZKQg65
   241  U23VnfUEBRw8kNSOqikjSj22iUz/tfXczx0RjQ4lBWvsVBgMX0l5Jh4QzJvCLOMF
   242  ocObjyZKCE/WjlSyxAFs00Lzdu1cKOItAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
   243  oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
   244  CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAygPV4enmvwSuMd1JarxOXpOK
   245  Z4Nsk7EKlfCPgzxQUOkFdLIr5ZG1kUkQt/omzTmoIWjLAsoYzT0ZCPOrioczKsWj
   246  MceFUIkT0w+eIl+8DzauPy34o8rjcApglF165UG3iphlpI+jdPzv5TBarUAbwsFb
   247  ClMLEiNJQ0OMxAIaRtb2RehD4q3OWlpWf6joJ36PRBqL8T5+f2x6Tg3c64UR+QPX
   248  98UcCQHHdEhm7y2z5Z2Wt0B48tZ+UAxDEoEwMghNyw7wUD79IRlXGYypBnXaMuLX
   249  46aGxbsSQ7Rfg62Co3JG7vo+eJd0AoZHrtFUnfM8V70IFzMBZnSwRslHRJe56Q==
   250  -----END CERTIFICATE-----`
   251  	rsaCa_client = `-----BEGIN CERTIFICATE-----
   252  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
   281  -----END CERTIFICATE-----`
   282  	ecdsaCert = `-----BEGIN CERTIFICATE-----
   283  MIIBbTCCAROgAwIBAgIQZCsHZcs5ZkzV+zC2E6j5RzAKBggqhkjOPQQDAjASMRAw
   284  DgYDVQQKEwdBY21lIENvMB4XDTE2MDkyNDE3NTE1OFoXDTI2MDkyMjE3NTE1OFow
   285  EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDTO
   286  B3IyzjYfKCp2HWy+P3QHxhdBT4AUGYgwTiSEj5phumPIahFNcOSWptN0UzlZvJdN
   287  MMjVmrFYK/FjF4abkNKjSzBJMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr
   288  BgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggq
   289  hkjOPQQDAgNIADBFAiEAp9W157PM1IadPBc33Cbj7vaFvp+rXs/hSuMCzP8pgV8C
   290  IHCswo1qiC0ZjQmWsBlmz5Zbp9rOorIzBYmGRhRdNs3j
   291  -----END CERTIFICATE-----`
   292  	ecdsaKey = `-----BEGIN EC PRIVATE KEY-----
   293  MHcCAQEEIFdhO7IW5UIwpB1e2Vunm9QyKvUHWcVwGfLjhpOajuR7oAoGCCqGSM49
   294  AwEHoUQDQgAENM4HcjLONh8oKnYdbL4/dAfGF0FPgBQZiDBOJISPmmG6Y8hqEU1w
   295  5Jam03RTOVm8l00wyNWasVgr8WMXhpuQ0g==
   296  -----END EC PRIVATE KEY-----`
   297  )