-
-
Notifications
You must be signed in to change notification settings - Fork 671
Description
Bug Description
When using an encrypted connection for a proxy with the ProxyAgent the hostname from the actual request is used instead of the hostname from the proxy URI.
Reproducible By
Run the following script and observe that the first client hello contains the hostname of the request URL.
import { ProxyAgent, fetch } from 'undici'
import fs from 'fs/promises'
const proxyHostname = 'proxy.internal'
const requestHostname = 'example.com'
const caPath = '~/ca.pem'
const enableTrace = true
const test = async (): Promise<unknown> => {
const ca = await fs.readFile(caPath)
const response = fetch('https://'+requestHostname, {
dispatcher: new ProxyAgent({
uri: 'https://'+proxyHostname+':8080',
connect: { ca, servername: proxyHostname, host: proxyHostname, enableTrace },
proxyTls: { ca, servername: proxyHostname, host: proxyHostname, enableTrace },
requestTls: { ca, servername: requestHostname, host: requestHostname, enableTrace }
})
})
return (await response).text()
}
test().then(r => console.log('Respone', r)).catch(e => console.error('fetch failed', e))Expected Behavior
Expect is that the first client hello contains the SNI name from proxy.
Logs & Screenshots
Example Output
Sent Record
Header:
Version = TLS 1.0 (0x301)
Content Type = Handshake (22)
Length = 379
ClientHello, Length=375
client_version=0x303 (TLS 1.2)
Random:
gmt_unix_time=0x0DA529B7
random_bytes (len=28): DA63174BCBFEF26D17359C3A9E7CC94C93DDBCD4A754763905798CB8
session_id (len=32): 17331EF37F92BB7BD08EF7E3CFD80501113B73D680E82EE9F2DB861DD00CC0BA
cipher_suites (len=118)
{0x13, 0x02} TLS_AES_256_GCM_SHA384
{0x13, 0x03} TLS_CHACHA20_POLY1305_SHA256
{0x13, 0x01} TLS_AES_128_GCM_SHA256
{0xC0, 0x2F} TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
{0xC0, 0x2B} TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
{0xC0, 0x30} TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
{0xC0, 0x2C} TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
{0x00, 0x9E} TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
{0xC0, 0x27} TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
{0x00, 0x67} TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
{0xC0, 0x28} TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
{0x00, 0x6B} TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
{0x00, 0xA3} TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
{0x00, 0x9F} TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
{0xCC, 0xA9} TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
{0xCC, 0xA8} TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
{0xCC, 0xAA} TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
{0xC0, 0xAF} TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
{0xC0, 0xAD} TLS_ECDHE_ECDSA_WITH_AES_256_CCM
{0xC0, 0xA3} TLS_DHE_RSA_WITH_AES_256_CCM_8
{0xC0, 0x9F} TLS_DHE_RSA_WITH_AES_256_CCM
{0xC0, 0x5D} TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384
{0xC0, 0x61} TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384
{0xC0, 0x57} TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384
{0xC0, 0x53} TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384
{0x00, 0xA2} TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
{0xC0, 0xAE} TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
{0xC0, 0xAC} TLS_ECDHE_ECDSA_WITH_AES_128_CCM
{0xC0, 0xA2} TLS_DHE_RSA_WITH_AES_128_CCM_8
{0xC0, 0x9E} TLS_DHE_RSA_WITH_AES_128_CCM
{0xC0, 0x5C} TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256
{0xC0, 0x60} TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256
{0xC0, 0x56} TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256
{0xC0, 0x52} TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256
{0xC0, 0x24} TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
{0x00, 0x6A} TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
{0xC0, 0x23} TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
{0x00, 0x40} TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
{0xC0, 0x0A} TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
{0xC0, 0x14} TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
{0x00, 0x39} TLS_DHE_RSA_WITH_AES_256_CBC_SHA
{0x00, 0x38} TLS_DHE_DSS_WITH_AES_256_CBC_SHA
{0xC0, 0x09} TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
{0xC0, 0x13} TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
{0x00, 0x33} TLS_DHE_RSA_WITH_AES_128_CBC_SHA
{0x00, 0x32} TLS_DHE_DSS_WITH_AES_128_CBC_SHA
{0x00, 0x9D} TLS_RSA_WITH_AES_256_GCM_SHA384
{0xC0, 0xA1} TLS_RSA_WITH_AES_256_CCM_8
{0xC0, 0x9D} TLS_RSA_WITH_AES_256_CCM
{0xC0, 0x51} TLS_RSA_WITH_ARIA_256_GCM_SHA384
{0x00, 0x9C} TLS_RSA_WITH_AES_128_GCM_SHA256
{0xC0, 0xA0} TLS_RSA_WITH_AES_128_CCM_8
{0xC0, 0x9C} TLS_RSA_WITH_AES_128_CCM
{0xC0, 0x50} TLS_RSA_WITH_ARIA_128_GCM_SHA256
{0x00, 0x3D} TLS_RSA_WITH_AES_256_CBC_SHA256
{0x00, 0x3C} TLS_RSA_WITH_AES_128_CBC_SHA256
{0x00, 0x35} TLS_RSA_WITH_AES_256_CBC_SHA
{0x00, 0x2F} TLS_RSA_WITH_AES_128_CBC_SHA
{0x00, 0xFF} TLS_EMPTY_RENEGOTIATION_INFO_SCSV
compression_methods (len=1)
No Compression (0x00)
extensions, length = 184
extension_type=server_name(0), length=16 << I expect
0000 - 00 0e 00 00 0b 65 78 61-6d 70 6c 65 2e 63 6f .....example.co << proxy.internal
000f - 6d m << here
extension_type=ec_point_formats(11), length=4
uncompressed (0)
ansiX962_compressed_prime (1)
ansiX962_compressed_char2 (2)
extension_type=supported_groups(10), length=22
ecdh_x25519 (29)
secp256r1 (P-256) (23)
ecdh_x448 (30)
secp521r1 (P-521) (25)
secp384r1 (P-384) (24)
ffdhe2048 (256)
ffdhe3072 (257)
ffdhe4096 (258)
ffdhe6144 (259)
ffdhe8192 (260)
extension_type=session_ticket(35), length=0
extension_type=application_layer_protocol_negotiation(16), length=11
http/1.1
extension_type=encrypt_then_mac(22), length=0
extension_type=extended_master_secret(23), length=0
extension_type=signature_algorithms(13), length=42
ecdsa_secp256r1_sha256 (0x0403)
ecdsa_secp384r1_sha384 (0x0503)
ecdsa_secp521r1_sha512 (0x0603)
ed25519 (0x0807)
ed448 (0x0808)
rsa_pss_pss_sha256 (0x0809)
rsa_pss_pss_sha384 (0x080a)
rsa_pss_pss_sha512 (0x080b)
rsa_pss_rsae_sha256 (0x0804)
rsa_pss_rsae_sha384 (0x0805)
rsa_pss_rsae_sha512 (0x0806)
rsa_pkcs1_sha256 (0x0401)
rsa_pkcs1_sha384 (0x0501)
rsa_pkcs1_sha512 (0x0601)
ecdsa_sha224 (0x0303)
rsa_pkcs1_sha224 (0x0301)
dsa_sha224 (0x0302)
dsa_sha256 (0x0402)
dsa_sha384 (0x0502)
dsa_sha512 (0x0602)
extension_type=supported_versions(43), length=5
TLS 1.3 (772)
TLS 1.2 (771)
extension_type=psk_key_exchange_modes(45), length=2
psk_dhe_ke (1)
extension_type=key_share(51), length=38
NamedGroup: ecdh_x25519 (29)
key_exchange: (len=32): 98B6544EAFE554DF8119970FE13A5555895668249400330F5DDDD4B821590214
Received Record
Header:
Version = TLS 1.2 (0x303)
Content Type = Handshake (22)
Length = 122
ServerHello, Length=118
server_version=0x303 (TLS 1.2)
Random:
gmt_unix_time=0x06CBA8C8
random_bytes (len=28): A02145755E1FE3E03A7C9E25D10A59AD74540932172C2682B6CDA595
session_id (len=32): 17331EF37F92BB7BD08EF7E3CFD80501113B73D680E82EE9F2DB861DD00CC0BA
cipher_suite {0x13, 0x01} TLS_AES_128_GCM_SHA256
compression_method: No Compression (0x00)
extensions, length = 46
extension_type=supported_versions(43), length=2
TLS 1.3 (772)
extension_type=key_share(51), length=36
NamedGroup: ecdh_x25519 (29)
key_exchange: (len=32): 9B70EE06D06FAD20478885A21F07491341C211A129D9B51D850116AF8F80A903
Received Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ChangeCipherSpec (20)
Length = 1
Received Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 38
Inner Content Type = Handshake (22)
EncryptedExtensions, Length=17
extensions, length = 15
extension_type=application_layer_protocol_negotiation(16), length=11
http/1.1
Received Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 896
Inner Content Type = Handshake (22)
Certificate, Length=875
context (len=0):
certificate_list, length=871
ASN.1Cert, length=866
------details-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
e1:a1:b2:9b:cb:f7:7f:6c:8d:19:b7:79:24:d4:d7:5b
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = TRAEFIK DEFAULT CERT
Validity
Not Before: Mar 5 20:38:57 2024 GMT
Not After : Mar 5 20:38:57 2025 GMT
Subject: CN = TRAEFIK DEFAULT CERT
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:ab:45:e5:b7:3e:4c:44:28:cf:be:ec:c5:27:fb:
98:83:a6:1d:d2:33:86:16:ca:56:2f:4a:86:5f:7c:
ef:22:c5:3d:ba:15:8a:bb:8d:23:81:e7:96:24:87:
08:4b:aa:be:4a:1a:e1:14:38:61:a6:27:ec:55:79:
5f:ba:ec:f5:9e:ca:19:f9:3e:68:1e:76:89:6f:42:
8c:0a:19:ca:5e:d8:80:20:5f:ef:08:49:b7:1b:b4:
73:e5:81:df:02:bd:a3:47:2d:dd:71:d1:c1:f9:4d:
4c:0e:b0:e6:e0:f6:f2:41:5e:53:8a:2a:52:41:3f:
61:1e:4e:78:1d:f4:14:ef:2a:50:e8:88:b8:b8:9c:
c2:a5:d5:f9:b5:8e:bd:ea:2f:7d:fb:1f:33:03:96:
7c:3e:e0:6b:3e:c7:02:54:01:e8:0d:16:16:98:f6:
e4:0c:60:0c:1e:0a:66:64:6f:c6:d8:be:5d:63:fa:
3f:89:d3:22:cc:ec:c9:77:8b:2a:0d:56:1b:ae:92:
c4:f6:7a:08:e4:de:4e:9e:bd:d9:65:a3:b5:86:10:
a5:68:cc:dc:ce:94:70:11:5b:85:ac:7f:6b:b3:dc:
6d:0e:71:4c:28:d1:b9:46:c9:50:42:10:a4:22:20:
c8:5c:9c:d1:af:3e:0d:41:8e:d6:fd:a0:db:b1:24:
37:e3
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment, Data Encipherment, Key Agreement
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name:
DNS:5ee1ac8c84cad765fe44ef7ccd47dec3.74c4aef601a7ad8758f94566a17ae0b7.traefik.default
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
a0:3d:91:02:dd:ae:82:ab:53:42:36:35:e1:d3:cd:a2:af:a9:
3c:23:59:f3:8b:82:6d:54:04:e5:92:49:e0:78:fb:ad:23:36:
0d:82:10:f0:d8:17:5f:6c:9c:84:20:bb:38:32:fd:aa:ab:ef:
13:67:d5:23:82:bd:5f:6f:3b:77:66:1c:d9:18:fc:66:64:95:
21:ca:74:54:4e:a4:94:2e:b5:ed:88:f6:5b:4a:af:3b:8f:d5:
7b:09:a4:91:e1:b1:10:c9:b4:ee:71:d9:d1:ae:e1:d7:70:dd:
8c:c7:dd:fa:25:de:50:14:17:91:92:53:49:ac:86:32:e9:14:
94:6b:55:da:58:23:11:16:e0:e2:8c:6a:69:32:d2:04:93:27:
f9:28:67:7d:e4:56:56:b8:e1:08:00:df:97:97:e4:6c:7f:0f:
95:c7:82:9d:69:ec:0a:78:38:36:f4:19:c3:d6:c7:9b:a7:e8:
64:20:10:c7:46:00:e7:7e:db:b8:36:8a:bb:4c:4d:f7:78:e1:
f1:1b:cd:bf:c2:3c:9f:14:25:de:f9:d6:36:78:00:90:13:e5:
28:02:2a:b3:d7:5e:be:79:db:ec:9c:b9:a3:c7:7b:79:95:c5:
99:af:1f:1a:3b:19:62:e7:a4:11:25:d1:4a:14:d3:a7:79:ac:
d4:bb:65:0a
-----BEGIN CERTIFICATE-----
MIIDXjCCAkagAwIBAgIRAOGhspvL939sjRm3eSTU11swDQYJKoZIhvcNAQELBQAw
HzEdMBsGA1UEAxMUVFJBRUZJSyBERUZBVUxUIENFUlQwHhcNMjQwMzA1MjAzODU3
WhcNMjUwMzA1MjAzODU3WjAfMR0wGwYDVQQDExRUUkFFRklLIERFRkFVTFQgQ0VS
VDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtF5bc+TEQoz77sxSf7
mIOmHdIzhhbKVi9Khl987yLFPboViruNI4HnliSHCEuqvkoa4RQ4YaYn7FV5X7rs
9Z7KGfk+aB52iW9CjAoZyl7YgCBf7whJtxu0c+WB3wK9o0ct3XHRwflNTA6w5uD2
8kFeU4oqUkE/YR5OeB30FO8qUOiIuLicwqXV+bWOveovffsfMwOWfD7gaz7HAlQB
6A0WFpj25AxgDB4KZmRvxti+XWP6P4nTIszsyXeLKg1WG66SxPZ6COTeTp692WWj
tYYQpWjM3M6UcBFbhax/a7PcbQ5xTCjRuUbJUEIQpCIgyFyc0a8+DUGO1v2g27Ek
N+MCAwEAAaOBlDCBkTAOBgNVHQ8BAf8EBAMCA7gwEwYDVR0lBAwwCgYIKwYBBQUH
AwEwDAYDVR0TAQH/BAIwADBcBgNVHREEVTBTglE1ZWUxYWM4Yzg0Y2FkNzY1ZmU0
NGVmN2NjZDQ3ZGVjMy43NGM0YWVmNjAxYTdhZDg3NThmOTQ1NjZhMTdhZTBiNy50
cmFlZmlrLmRlZmF1bHQwDQYJKoZIhvcNAQELBQADggEBAKA9kQLdroKrU0I2NeHT
zaKvqTwjWfOLgm1UBOWSSeB4+60jNg2CEPDYF19snIQguzgy/aqr7xNn1SOCvV9v
O3dmHNkY/GZklSHKdFROpJQute2I9ltKrzuP1XsJpJHhsRDJtO5x2dGu4ddw3YzH
3fol3lAUF5GSU0mshjLpFJRrVdpYIxEW4OKMamky0gSTJ/koZ33kVla44QgA35eX
5Gx/D5XHgp1p7Ap4ODb0GcPWx5un6GQgEMdGAOd+27g2irtMTfd44fEbzb/CPJ8U
Jd751jZ4AJAT5SgCKrPXXr552+ycuaPHe3mVxZmvHxo7GWLnpBEl0UoU06d5rNS7
ZQo=
-----END CERTIFICATE-----
No extensions
Received Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 281
Inner Content Type = Handshake (22)
CertificateVerify, Length=260
Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
Signature (len=256): 063E55F5F6FA34450CF12DDECB3AF0DA37670FC69B60AEBFB6A5A809A39F4D28CC8E8B0115A53F3335A399E53D4B5CDD2B25AFA55E988A34D41FC7A3A4772DC97A83B0A0C05E672CBD0EAD09022ED3BA32940FFB46B5E0784B3608C83EABFDB45C161F6E96A38D01611F0C31AB5E993BEAC6C6036DA5E0748A5945F2DBE3F82A098A25A41386807A532986D100EE582D25B82273839E7BE6D02141FBD1F1C728EC2EE5DB1B195281035101E5E88E3B5677832837FCACD27B8342305E35CD5BC4A35EC8A1E9C6B115172AD65CC4383C97DBB86690286B4D0CE2BE8038BB9FE961920A92FC4466E0C4A15B1252E9BBFAA39F2FD135435DA21EF366931263C0A0AB
Received Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 53
Inner Content Type = Handshake (22)
Finished, Length=32
verify_data (len=32): 5E8F9ACE5560F2D1FCF05B383BCBA0D9629472B2E9FEC13FCCDD64002E48F394
Sent Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ChangeCipherSpec (20)
Length = 1
change_cipher_spec (1)
Sent Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 53
Inner Content Type = Handshake (22)
Finished, Length=32
verify_data (len=32): 2F0ED8A1804E61E620C7B2B98F2ACCB02C195F4019B6A5B5A0F11003C48C5685
fetch failed TypeError: fetch failed
at fetch (/home/user/git/pld/node_modules/.pnpm/[email protected]/node_modules/undici/index.js:103:13)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
[cause]: Error: self-signed certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34)
at TLSSocket.emit (node:events:518:28)
at TLSSocket.emit (node:domain:488:12)
at TLSSocket._finishInit (node:_tls_wrap:1085:8)
at ssl.onhandshakedone (node:_tls_wrap:871:12) {
code: 'DEPTH_ZERO_SELF_SIGNED_CERT'
}
}
Received Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 139
Environment
[email protected]
node v20.11.1
Pop!_OS 22.04 LTS
Additional context
A hacky workaround that allowed my setup to work, is to ignore the servername from line 91 in the connect.js if the httpSocket is not defined
if(httpSocket === undefined){
servername = options.servername || util.getServerName(host) || null
}Lines 91 to 101 in 03a2d43
| servername = servername || options.servername || util.getServerName(host) || null | |
| const sessionKey = servername || hostname | |
| const session = sessionCache.get(sessionKey) || null | |
| assert(sessionKey) | |
| socket = tls.connect({ | |
| highWaterMark: 16384, // TLS in node can't have bigger HWM anyway... | |
| ...options, | |
| servername, |