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 MIIFYDCCA0igAwIBAgIJAPpBgIvtQb1EMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV 253 BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX 254 aWRnaXRzIFB0eSBMdGQwHhcNMTgwMjEzMjAxNjA3WhcNMTkwMjEzMjAxNjA3WjBF 255 MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 256 ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 257 CgKCAgEAr4xgdmB4DaEh8zRFmg/1ZxYhQZMUP0iQX/Y8nDWxNlcd42p3TgpY1biz 258 jrq58ln9Om4U/GAn2RmtBAynSBXIlR5oVa44JeMM8Ka8R/dMKyHpF0Nj2EJB9unb 259 TC33PfzOlnKQxATwevnnhI6tGluWmwvxXUi7WnX0di+nQg9HrIVom3KrmRr2/41y 260 g497ccYUuNnKE6sewGdGzw045oWZpMDA2Us+MFo1IywOurjaM9bueRhPTcIiQ8RE 261 h7qb+FRwfxaj9ynZA2PCM7WMSSWCiZJV0uj/pshYF2lvtJcJef4dhwnsYBpc+mgx 262 2q9qcUBeo3ZHbi1/PRqjwSmcW3yY5cQRbpYp6xFmgmX3oHQkVXS0UlpNVZ+morcS 263 HEpaK8b76fCFcL5yFsAJkPPfny1IKU+CfaVq60dM/mxbEW6J4mZT/uAiqrCilMC+ 264 FyiATCZur8Ks7p47eZy700DllLod7gWTiuZTgHeQFVoX+jxbCZKlFn5Xspu8ALoK 265 Mla/q83mICRVy3+eMUsD7DNvoWYpCAYy/oMk0VWfrQ48JkCGbBW2PW/dU2nmqVhY 266 /11rurkr+1TUvYodnajANtXvUjW1DPOLb4dES4Qc4b7Fw8eFXrARhl5mXiL5HFKR 267 /VnRshiJ+QwTVkxl+KkZHEm/WS8QD+Zd8leAxh9MCoaU/XrBUBkCAwEAAaNTMFEw 268 HQYDVR0OBBYEFKUinuD1xRvcNd2Wti/PnBJp7On1MB8GA1UdIwQYMBaAFKUinuD1 269 xRvcNd2Wti/PnBJp7On1MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD 270 ggIBAJdJrNBftqkTs2HyuJ3x5RIsTxYh85hJYwNOdFLyzVG6HER9jRCnvmNTjG0O 271 I5wz5hQvDpwXs4BCCXHQZrTLAi3BEjq3AjrmR/XeGHulbWh3eh8LVu7MiLRgt+Ys 272 GnL2IaERrbkje24nCCMNPbI3fGDQEhTIYmmX8RJp+5BOJgCycKk6pFgfrjJv2C+d 273 78pcjlYII6M4vPnr/a08M49Bq6b5ADvIfe5G2KrUvD/+vwoAwv6d/daymHCQ2rY5 274 kmdVk9VUp3Q4uKoeej4ENJSAUNTV7oTu346oc7q9sJffB5OltqbrE7ichak7lL+v 275 EjArZHElAhKNFXRZViCMvGDs+7JztqbsfT8Xb6Z27e+WyudB2bOUGm3hKuTIl06D 276 bA7yUskwEhmkd1CJqO5RLEJjKitOqe6Ye0/GsmPQNDK8GvyXTyGQK5OqBuzEexF0 277 mlPoIhpSVH3K9SkRTTHvvcbdYlaQLi6gKq2uhbk4PnS2nfBtXqYIy9mxcgBJzLiB 278 /ydfLcf3GClwgvO1JHp6qAl4CO7oe8jqHpoGuznwi1aqkTyNkQWh0OXq3MS+dyqB 279 2yXFCFIeKCx18TE1OtuTD3ppBDjpyd0o/a6kYR3FDmdks/J33bGwLsLH3lbN6VjF 280 PNfNkaE1tfkpSGYsuT1DPxX8aAT4JLUfZ1Si6iO+E0Sj9LXA 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 )