File
Blob: src/workerd/api/tests/starttls-nodejs-server.js
| 1 | // Copyright (c) 2017-2024 Cloudflare, Inc. |
| 2 | // Licensed under the Apache 2.0 license found in the LICENSE file or at: |
| 3 | // https://opensource.org/licenses/Apache-2.0 |
| 4 | |
| 5 | /* |
| 6 | * This file serves a server that tries to upgrade tls connections and send messages. |
| 7 | * This file is designed to run as a sidecar |
| 8 | */ |
| 9 | |
| 10 | const net = require('node:net'); |
| 11 | const tls = require('node:tls'); |
| 12 | const assert = require('node:assert'); |
| 13 | |
| 14 | // Create a self-signed certificate for TLS with proper SAN extension |
| 15 | function createSelfSignedCert() { |
| 16 | const key = `-----BEGIN PRIVATE KEY----- |
| 17 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDIWfGy2tRsqANt |
| 18 | J1F/52bIDzMDxlmSkDpu3U3Ehq6TmH2hNBcLOWuWLvG8Np9artnzk8QnodfN8yEJ |
| 19 | 0HRzZ6mRjVIUHJOb3+L1+0ePOM8dtWvG0AOd95K0T0imJRLPR18UjHl5OLE7mMS9 |
| 20 | CGHa6mDTGKzTcdxtpkjiyoNgfdKKSKzLplga5if36leGJ2+mEhOAc/cV1kqOx+hP |
| 21 | VGAOz5p3OnkgolC8hZ3WTsAFEYMU0QoPNs7jVCVNGH9t3qPiWV2/7XaNQoMnMHgq |
| 22 | yyljcvDo0O0dw0HKtBVIMhz5xHHGZqJNM/R36MeHzO+cIYhJz+ncknu62+IlQOCY |
| 23 | eyHuxvpRAgMBAAECggEAB3SXYqsze+6doAZ2SS7se3XbVWDgbOyKjB0Wm4FShkIG |
| 24 | rMTCNcP3fbF2A+W5dNesWxzM0Be87thFCrcz2iaJoBW07/QnRwXkDXjCDzGTPX0G |
| 25 | i3GqrMptbmHD55DaHBYBEwPuMkVajQfwjEM/VvThUQGqTrz+MaNeM3hLPsA34Tbl |
| 26 | wigHK+4tyAFLkYkvsxXYHs1F23ey2ubFUyBI8gvfayOvr4MOVfEbQZsmz3IB5jjk |
| 27 | oK5EaMJuhty65pb9Pi6ncSbfVQ2aciNgHjZs/is/WQfQPB2jYBPpmaFQbZc2pseZ |
| 28 | 8zTLvF+GKZng4hQE1F+F6DUf9sxb54Eu1XqzqGlrdQKBgQDkQc5fJj72rF9RkiBN |
| 29 | zeEK0Ngihm9Jzsb544i7DT/4jPWwa1+dt+kNVqguDbcxi4tCi+P8BwTnfX5M31d2 |
| 30 | /Si9nDBpP+WLLRHjFq2AQf05JvFc1/7s4KvWBrfKbwiN+uxrstB2lDuFp386B20U |
| 31 | stsCBu/nawjt5lYY7S0zPokkJQKBgQDgs9rTJNnRuaaEpUxqRdR6zR3z0Qe1B1Ga |
| 32 | y6z8OqiX3N+wM9uAcrTzGOtPKvB4glcJZrrQp0NSxkJVsFBzPBCfUfjIV/IiOqS1 |
| 33 | nE/rrEKEG7ZVkxDUsdeS8KiVKBJjLch/hrT0udgv4vndXqeaJuNzbD1yfiKbPnY5 |
| 34 | yGC78uqvvQKBgGUGMx6twMRQekeSEzYcXvP4hxCQy4SxPiOvbv7K2HtbeApDG6ik |
| 35 | k0NSDVGExIXrKxGi9J7BRIxoYJQJbZ6+YV+6VzreCuxUYExP5y6TBk5bTAw5lRym |
| 36 | O6eYhZPVHMYqPqVUGSvCY629+nNmggLdPk1hYKDeIK+aeJTDtHOvw+b5AoGAZI74 |
| 37 | wf8+34WWyMv026ZuhZpf6ipEqbYhxgWaX7KcmoHFNWSvudcbtaMUQ3Sy8ytZaiKo |
| 38 | PhJspZGGRDTIfBmIUtRrYrVA7iKSbZgLiCuqBNcmDTvoj1cbY24B8+Zf/DSUAsY1 |
| 39 | G0RERIHuUiw3E1yN86yf/yoFsLYOUKOk7teyQX0CgYBFUzUeVszODI/1NeKuGdoR |
| 40 | 1uJk2gt7hH4t7GdX4G78h3i6P5pa7qSyUXqBm53nXrYhEFRiVgDh5BoRnoKKWomj |
| 41 | IDidHZX3fMoQvdKAT8sUbT/Q3KKWPFqGv7frdpQe+JM0DwwjjPrMtUWhuve455XW |
| 42 | bCKgoxoaqEPUzY9CyI+RZg== |
| 43 | -----END PRIVATE KEY-----`; |
| 44 | |
| 45 | const cert = `-----BEGIN CERTIFICATE----- |
| 46 | MIIDmTCCAoGgAwIBAgIUFdaq1aN7zHoSsmLp6ItxnM1VOPEwDQYJKoZIhvcNAQEL |
| 47 | BQAwTjELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3Qx |
| 48 | DTALBgNVBAoMBFRlc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yNTA3MjYwNjI3 |
| 49 | MDZaFw0yNjA3MjYwNjI3MDZaME4xCzAJBgNVBAYTAlVTMQ0wCwYDVQQIDARUZXN0 |
| 50 | MQ0wCwYDVQQHDARUZXN0MQ0wCwYDVQQKDARUZXN0MRIwEAYDVQQDDAlsb2NhbGhv |
| 51 | c3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIWfGy2tRsqANtJ1F/ |
| 52 | 52bIDzMDxlmSkDpu3U3Ehq6TmH2hNBcLOWuWLvG8Np9artnzk8QnodfN8yEJ0HRz |
| 53 | Z6mRjVIUHJOb3+L1+0ePOM8dtWvG0AOd95K0T0imJRLPR18UjHl5OLE7mMS9CGHa |
| 54 | 6mDTGKzTcdxtpkjiyoNgfdKKSKzLplga5if36leGJ2+mEhOAc/cV1kqOx+hPVGAO |
| 55 | z5p3OnkgolC8hZ3WTsAFEYMU0QoPNs7jVCVNGH9t3qPiWV2/7XaNQoMnMHgqyylj |
| 56 | cvDo0O0dw0HKtBVIMhz5xHHGZqJNM/R36MeHzO+cIYhJz+ncknu62+IlQOCYeyHu |
| 57 | xvpRAgMBAAGjbzBtMB0GA1UdDgQWBBQ6R0NLwjufqWjT75cFdzHW9bh2DDAfBgNV |
| 58 | HSMEGDAWgBQ6R0NLwjufqWjT75cFdzHW9bh2DDAPBgNVHRMBAf8EBTADAQH/MBoG |
| 59 | A1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAToR4 |
| 60 | CaI9HAfSSXE+6fPthp+qrwPmfx3rW0RskpjKuqemZmIK7ydU9pcYuGtc6CPen614 |
| 61 | RfFoaWtPltbNU0KV79P4zTRNYxqTKcEyhsjyAGbLA+bJtJE3hlDrfPGVyepZETXE |
| 62 | 7Ig4XPyXi4M+WmvLboAF2dHC+H1XoWp3agIN45VRnr5uPVNX19dTbr0gc3WxLEUH |
| 63 | N839sKGVB9GVaQhF/4Z8ia0bluirf+6SNAaN/veJA40ixGEkHN3gqX4ZTZWl5rji |
| 64 | 3cLdth83wmueKxiBp8ov78ubmdPiBsyIVrsb8jEsxRPAKX8gEx09S/yIIs1ZEGi9 |
| 65 | wG73FlfFCc09zjmYww== |
| 66 | -----END CERTIFICATE-----`; |
| 67 | |
| 68 | return { key, cert }; |
| 69 | } |
| 70 | |
| 71 | const serverCA = net |
| 72 | .createServer((s) => { |
| 73 | console.log('ServerCA: New connection received'); |
| 74 | |
| 75 | // Send initial greeting |
| 76 | s.write('HELLO\n'); |
| 77 | |
| 78 | // Wait for one response then upgrade to TLS |
| 79 | s.once('data', (data) => { |
| 80 | const response = data.toString().trim(); |
| 81 | console.log('ServerCA: Received response:', response); |
| 82 | |
| 83 | if (response === 'HELLO_BACK') { |
| 84 | s.write('START_TLS\n', () => { |
| 85 | console.log('ServerCA: Sent START_TLS, upgrading to TLS'); |
| 86 | |
| 87 | // Small delay to ensure START_TLS is sent |
| 88 | console.log('serverCA: Creating TLS socket'); |
| 89 | const tlsSocket = new tls.TLSSocket(s, { |
| 90 | isServer: true, |
| 91 | server: serverCA, |
| 92 | secureContext: tls.createSecureContext(createSelfSignedCert()), |
| 93 | requestCert: false, |
| 94 | SNICallback: (hostname, callback) => { |
| 95 | console.log('serverCA: SNI callback for hostname:', hostname); |
| 96 | assert.strictEqual(hostname, 'localhost'); |
| 97 | callback(null, null); |
| 98 | }, |
| 99 | }); |
| 100 | |
| 101 | console.log('serverCA: Setting up TLS event handlers'); |
| 102 | |
| 103 | tlsSocket.on('secure', () => { |
| 104 | console.log('serverCA: TLS handshake complete'); |
| 105 | |
| 106 | // Handle TLS data |
| 107 | tlsSocket.on('data', (data) => { |
| 108 | const message = data.toString().trim(); |
| 109 | console.log('serverCA: Received TLS message:', message); |
| 110 | |
| 111 | if (message === 'ping') { |
| 112 | console.log('serverCA: Sending pong response'); |
| 113 | tlsSocket.write('pong\n', (err) => { |
| 114 | if (err) { |
| 115 | console.log('serverCA: Error writing pong:', err); |
| 116 | } else { |
| 117 | console.log('serverCA: Pong sent successfully'); |
| 118 | } |
| 119 | }); |
| 120 | } |
| 121 | }); |
| 122 | }); |
| 123 | |
| 124 | tlsSocket.on('error', (err) => { |
| 125 | console.log('ServerCA TLS error:', err.message); |
| 126 | }); |
| 127 | |
| 128 | tlsSocket.on('close', () => { |
| 129 | console.log('serverCA: TLS socket closed'); |
| 130 | }); |
| 131 | |
| 132 | console.log('serverCA: TLS socket created, waiting for handshake'); |
| 133 | |
| 134 | // The TLS handshake should start when the client initiates it |
| 135 | }); |
| 136 | } |
| 137 | }); |
| 138 | |
| 139 | s.on('error', (err) => { |
| 140 | console.log('ServerCA socket error:', err.message); |
| 141 | }); |
| 142 | }) |
| 143 | .listen(process.env.STARTTLS_CA_PORT, () => { |
| 144 | console.info(`ServerCA listening on port ${serverCA.address().port}`); |
| 145 | }); |