An app port must answer whatever the browser asks for: an HTTP dashboard embeds http://host:PORT, an HTTPS one embeds https://host:PORT, and an HTTPS page cannot embed an HTTP frame at all. So the choice is per-node, not per-fleet, and a second port number would mean every manifest changes and torrc doubles. Instead the gate peeks the first byte. A TLS ClientHello is 0x16; no HTTP method starts with it. peek() leaves the bytes in the socket buffer, so the acceptor still sees a complete, untouched ClientHello. TLS and plain share one generic serve_http(), so authentication, proxying and upgrade handling cannot drift apart by scheme. EXISTING NODES ARE UNAFFECTED BY CONSTRUCTION. Anything that is not a TLS handshake takes the identical path as before, and a node with no certificate serves plain HTTP exactly as today — TLS is strictly additive. rustls does NOT verify that a private key matches its certificate. Established by test, not assumed: with_single_cert accepted a pair from two different keys and would only have failed mid-handshake in a user's browser — a security control that reports success and does nothing, the exact shape this module's own docs warn about. So the pairing is now proven explicitly (sign a fixed message with the key, verify against the certificate's public key) and a mismatch refuses to serve. Also: cert and key mtimes are stamped as a PAIR, because reissuing writes them separately and keying on one would serve a certificate that no longer matches its key; a 15s first-byte timeout closes the slowloris window one step earlier than the existing header-read timeout; PKCS#8 and PKCS#1 keys are both accepted so a hand-made key does not silently downgrade a working node. Deps pinned to the rustls 0.21 line reqwest already resolves — no new vendor, no second rustls major. Test fixtures are throwaway (localhost SANs only), not any node's identity. 38/38 appgate tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
29 lines
1.7 KiB
Plaintext
29 lines
1.7 KiB
Plaintext
-----BEGIN PRIVATE KEY-----
|
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCy2KgVkOYSz0QO
|
|
QxXA0ENomMr0Butuh4Yv5KT9RzrTxrsf/GfiJPX5fjtANwUXniojMNClxLGGep5v
|
|
55Sy0wXgj1HHX00eeWfMIW3A7pYKy2geM3gY3/Xull7Ny2A1+aa4XzK9jIZXqkLj
|
|
zSd+zdkkrxa0JTdv/kVFX198pvx5w79KBx706NLgY8T6YqAIerturvwclL3uWvYm
|
|
kB2CirwYAR4XO+6RxAqe+msjxn877h5bUSxwtfL7OzdcuyilGBG2FeB9FSm7r7h2
|
|
zLJcch3WCwHBWbLK6n5pprrYXLFgTJjC/VlNjGmv9ZAG7HPnAw9J0Ck+JT3s+7mf
|
|
pWiNzPePAgMBAAECggEANcLsEAONLcVRY2omHV5djRE1HRMBbanenAIC2MIzPFsG
|
|
gDB7N989c8DO5dhENxvL9eUkK1iLtu2gN+po6DKIFz9t6V1MDOeY3KOF3xO5Vchc
|
|
ZYu6Q9v7DTv1hq5mnwMLa2vukE0wSyT604iloTgW2LCrRf7UAd3xC9AGH64Awkcl
|
|
TxWeuXDf1Z9ndTXwTcyWJwxs69eDhxHJdNi8Pit0sowuQJMsmj+uxWsAXb5DvmHV
|
|
HxihzZ8tQpq7ZCuJBcpqcYZ3/XYxfYcGez42+1nIUHtcIaywQCZUk3WmL3wxEMRA
|
|
N5LoJuI1a6EYNRZdtwmD3aoNwOapPSIeIyf1AuVV8QKBgQDZABBmxMecLq1sYYjG
|
|
2vaS2aHtg4qaeoQV97vkbOceNHX54gCi/Oj6ocm+jKDoNG0LRITBTMc0fivpccUu
|
|
dNnW7niTQFUqQ3XS7ONMUbMZNUaiiYaQu2Pzsvq+FVDbLD0VVIqd4mQFNY8wOAMi
|
|
VImPvFUuV2tBW9Od/bZTAIP4kQKBgQDS/SxRc7NJ7sb8D6LKQcUN3RQ6/Yi9caBN
|
|
+PbC7rLALM8CIFStiSTVH0jO1aEwLoNSlOG7IBLOPaVxp3sauqs2VHHLrPS3ter0
|
|
UQt5WDdsgNtJVAZ9GKw10pZ5EQJHTxDVIyFAyOpkLm1DdUsRCShheW5HaFRGrYhA
|
|
XV3hYxL+HwKBgFGNepyE29fQmxCeXz8Mz5pE/Fw9EXwZC0cOQakJXJq3cJcm3sJi
|
|
dlSrNRzN0TMzcL/JUnMrHbqWqH4lacuZ0ry6BsqgZOFrVP6eVJY8JikVIqS3NsFy
|
|
C5Bs9Vs2u5qDN7mqeiX4DUr/4/5lLphaWRCR4Rl3dTGtBwzbawgqq25hAoGAEQOz
|
|
oDnpWmv0Bf2ozhCxuGV8rSkm7sgL+l26YIvpRFAYvX4n9fqaSsmEEJHvtrf5hR5W
|
|
ecWjXphgECNGbShiiDYVGyyua2YzNVKXz0hK5+gYRviMsWfc81YxJkA149Q/ckCr
|
|
/NJ2/G82Bnud+xi29e1Z9E44hZ6W30HoQTXBIVcCgYApBXtQzue+jSRZXhpgw+ps
|
|
9H7eTHsA6zsxtqk4O/tijkkcsv+LepJ81nJNN8G4aqbdAb132w5bHqh9ir0DFtKj
|
|
2Eqae15OFYKfYV83TOAcc/IW3aZi8jkNyux08k43gIn3Lzo5T09jUSFFV5FazVNi
|
|
RxnrHeKUcS43Z346QXYrsg==
|
|
-----END PRIVATE KEY-----
|