diff --git a/doc/html/howtoe.html b/doc/html/howtoe.html index 117e460..14b9747 100644 --- a/doc/html/howtoe.html +++ b/doc/html/howtoe.html @@ -828,12 +828,32 @@ This creates an HTTPS proxy (ssl_serv) that accepts TLS connections from clients # Generate CA private key openssl genrsa -out ca.key 4096 +# Extensions that make the certificate usable as a CA +cat > ca.ext << 'EOF' +basicConstraints=critical,CA:TRUE +keyUsage=critical,keyCertSign,cRLSign +subjectKeyIdentifier=hash +EOF + # Generate CA certificate (valid for 10 years) -openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \ +openssl req -new -nodes -key ca.key \ -subj "/C=US/ST=State/L=City/O=MyOrg/CN=My CA" \ - -out ca.crt + -out ca.csr +openssl x509 -req -in ca.csr -signkey ca.key -sha256 -days 3650 \ + -extfile ca.ext -out ca.crt
+The extensions are not optional. Without basicConstraints=CA:TRUE and +keyCertSign the certificate is not accepted as a CA, and clients report +that they cannot get the local issuer certificate. subjectKeyIdentifier +is what certificates signed by this CA point back at. +
++They are given in a file rather than with -addext because LibreSSL, the +openssl command on macOS and some BSDs, does not apply -addext the same +way OpenSSL does. The form above behaves the same on both. +
+For MITM, import ca.crt into client browsers/OS as a trusted root CA.
@@ -866,8 +886,18 @@ EOF openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out server.crt -days 365 -sha256 \ -extfile server.ext + +# Check it the way a current client will +openssl verify -x509_strict -CAfile ca.crt server.crt
+Verify strictly, because that is what the client does. OpenSSL 3 adds the +subject and authority key identifiers when it signs and LibreSSL does not, +which is why the extensions file asks for them by name. Python has verified +strictly since 3.13 and refuses a certificate carrying no +authorityKeyIdentifier; other clients are moving the same way. +
+For a public https:// proxy, use a CA like Let's Encrypt instead of self-signed.
@@ -886,6 +916,8 @@ cat > client.ext << 'EOF' basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment extendedKeyUsage = clientAuth +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer EOF # Sign with CA @@ -908,8 +940,14 @@ Import client1.p12 into the client browser or OS certificate store. # CA openssl genrsa -out ca.key 4096 -openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \ - -subj "/CN=3proxy CA" -out ca.crt +cat > ca.ext << 'EOF' +basicConstraints=critical,CA:TRUE +keyUsage=critical,keyCertSign,cRLSign +subjectKeyIdentifier=hash +EOF +openssl req -new -nodes -key ca.key -subj "/CN=3proxy CA" -out ca.csr +openssl x509 -req -in ca.csr -signkey ca.key -sha256 -days 3650 \ + -extfile ca.ext -out ca.crt # Server openssl genrsa -out server.key 2048 @@ -919,6 +957,8 @@ basicConstraints=CA:FALSE keyUsage = keyEncipherment extendedKeyUsage = serverAuth subjectAltName = DNS:localhost,DNS:proxy,IP:127.0.0.1 +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer EOF openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext @@ -929,11 +969,17 @@ openssl req -new -key client.key -subj "/CN=client" -out client.csr cat > client.ext << 'EOF' basicConstraints=CA:FALSE extendedKeyUsage = clientAuth +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer EOF openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out client.crt -days 365 -sha256 -extfile client.ext openssl pkcs12 -export -out client.p12 -passout pass: \ -inkey client.key -in client.crt -certfile ca.crt + +# Both must pass the checks a current client applies +openssl verify -x509_strict -CAfile ca.crt server.crt +openssl verify -x509_strict -CAfile ca.crt client.crt
diff --git a/doc/html/howtor.html b/doc/html/howtor.html index 2e55ad0..4513e2b 100644 --- a/doc/html/howtor.html +++ b/doc/html/howtor.html @@ -838,12 +838,32 @@ ssl_nocli # Генерация закрытого ключа CA openssl genrsa -out ca.key 4096 +# Расширения, без которых сертификат не годится как CA +cat > ca.ext << 'EOF' +basicConstraints=critical,CA:TRUE +keyUsage=critical,keyCertSign,cRLSign +subjectKeyIdentifier=hash +EOF + # Генерация сертификата CA (действителен 10 лет) -openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \ +openssl req -new -nodes -key ca.key \ -subj "/C=RU/ST=Region/L=City/O=MyOrg/CN=My CA" \ - -out ca.crt + -out ca.csr +openssl x509 -req -in ca.csr -signkey ca.key -sha256 -days 3650 \ + -extfile ca.ext -out ca.crt
+Расширения обязательны. Без basicConstraints=CA:TRUE и +keyCertSign сертификат не принимается как CA, и клиент сообщает, что не +может получить сертификат издателя. subjectKeyIdentifier — то, на что +ссылаются подписанные этим CA сертификаты. +
++Расширения задаются файлом, а не через -addext, потому что LibreSSL — +команда openssl в macOS и некоторых BSD — обрабатывает -addext иначе, +чем OpenSSL. Приведённый вариант одинаково работает в обоих. +
+Для MITM импортируйте ca.crt в браузеры/ОС клиентов как доверенный корневой CA.
@@ -876,8 +896,18 @@ EOF openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out server.crt -days 365 -sha256 \ -extfile server.ext + +# Проверка так же, как это делает современный клиент +openssl verify -x509_strict -CAfile ca.crt server.crt
+Проверять следует строго, потому что именно так проверяет клиент. OpenSSL 3 +добавляет идентификаторы ключей при подписании, а LibreSSL — нет, поэтому файл +расширений запрашивает их явно. Python начиная с 3.13 проверяет строго и +отвергает сертификат без authorityKeyIdentifier; другие клиенты идут тем +же путём. +
+Для публичного https:// прокси используйте CA вроде Let's Encrypt вместо самоподписанного.
@@ -896,6 +926,8 @@ cat > client.ext << 'EOF' basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment extendedKeyUsage = clientAuth +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer EOF # Подписание CA @@ -918,8 +950,14 @@ openssl pkcs12 -export -out client1.p12 \ # CA openssl genrsa -out ca.key 4096 -openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \ - -subj "/CN=3proxy CA" -out ca.crt +cat > ca.ext << 'EOF' +basicConstraints=critical,CA:TRUE +keyUsage=critical,keyCertSign,cRLSign +subjectKeyIdentifier=hash +EOF +openssl req -new -nodes -key ca.key -subj "/CN=3proxy CA" -out ca.csr +openssl x509 -req -in ca.csr -signkey ca.key -sha256 -days 3650 \ + -extfile ca.ext -out ca.crt # Сервер openssl genrsa -out server.key 2048 @@ -929,6 +967,8 @@ basicConstraints=CA:FALSE keyUsage = keyEncipherment extendedKeyUsage = serverAuth subjectAltName = DNS:localhost,DNS:proxy,IP:127.0.0.1 +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer EOF openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext @@ -939,11 +979,17 @@ openssl req -new -key client.key -subj "/CN=client" -out client.csr cat > client.ext << 'EOF' basicConstraints=CA:FALSE extendedKeyUsage = clientAuth +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer EOF openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out client.crt -days 365 -sha256 -extfile client.ext openssl pkcs12 -export -out client.p12 -passout pass: \ -inkey client.key -in client.crt -certfile ca.crt + +# Оба должны пройти проверку, которую делает современный клиент +openssl verify -x509_strict -CAfile ca.crt server.crt +openssl verify -x509_strict -CAfile ca.crt client.crt