mirror of
https://github.com/3proxy/3proxy.git
synced 2026-09-02 21:05:49 +08:00
Fix the certificate recipes in the howtos
The CA was created with no extensions, so it is not usable as a CA and clients report that they cannot get the local issuer certificate. Add basicConstraints, keyCertSign and a subject key identifier, in a file rather than through -addext, which LibreSSL - the openssl on macOS and some BSDs - does not apply the same way. Ask for the key identifiers on the signed certificates too: OpenSSL 3 adds them when it signs and LibreSSL does not, and Python has verified strictly since 3.13, refusing a chain whose certificate carries no authorityKeyIdentifier. Finish with openssl verify -x509_strict, which is the check the client will make. Both recipes were run against OpenSSL 3.6 and LibreSSL 3.3: the old one fails strict verification, the new one passes on both.
This commit is contained in:
parent
e8d6aa555a
commit
fc544c4dff
@ -828,12 +828,32 @@ This creates an HTTPS proxy (ssl_serv) that accepts TLS connections from clients
|
|||||||
# Generate CA private key
|
# Generate CA private key
|
||||||
openssl genrsa -out ca.key 4096
|
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)
|
# 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" \
|
-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
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
|
The extensions are not optional. Without <b>basicConstraints=CA:TRUE</b> and
|
||||||
|
<b>keyCertSign</b> the certificate is not accepted as a CA, and clients report
|
||||||
|
that they cannot get the local issuer certificate. <b>subjectKeyIdentifier</b>
|
||||||
|
is what certificates signed by this CA point back at.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
They are given in a file rather than with <b>-addext</b> because LibreSSL, the
|
||||||
|
<b>openssl</b> command on macOS and some BSDs, does not apply -addext the same
|
||||||
|
way OpenSSL does. The form above behaves the same on both.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
For MITM, import ca.crt into client browsers/OS as a trusted root CA.
|
For MITM, import ca.crt into client browsers/OS as a trusted root CA.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -866,8 +886,18 @@ EOF
|
|||||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
||||||
-CAcreateserial -out server.crt -days 365 -sha256 \
|
-CAcreateserial -out server.crt -days 365 -sha256 \
|
||||||
-extfile server.ext
|
-extfile server.ext
|
||||||
|
|
||||||
|
# Check it the way a current client will
|
||||||
|
openssl verify -x509_strict -CAfile ca.crt server.crt
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
|
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
|
||||||
|
<b>authorityKeyIdentifier</b>; other clients are moving the same way.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
For a public https:// proxy, use a CA like Let's Encrypt instead of self-signed.
|
For a public https:// proxy, use a CA like Let's Encrypt instead of self-signed.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -886,6 +916,8 @@ cat > client.ext << 'EOF'
|
|||||||
basicConstraints=CA:FALSE
|
basicConstraints=CA:FALSE
|
||||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
|
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
|
||||||
extendedKeyUsage = clientAuth
|
extendedKeyUsage = clientAuth
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Sign with CA
|
# Sign with CA
|
||||||
@ -908,8 +940,14 @@ Import client1.p12 into the client browser or OS certificate store.
|
|||||||
|
|
||||||
# CA
|
# CA
|
||||||
openssl genrsa -out ca.key 4096
|
openssl genrsa -out ca.key 4096
|
||||||
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
|
cat > ca.ext << 'EOF'
|
||||||
-subj "/CN=3proxy CA" -out ca.crt
|
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
|
# Server
|
||||||
openssl genrsa -out server.key 2048
|
openssl genrsa -out server.key 2048
|
||||||
@ -919,6 +957,8 @@ basicConstraints=CA:FALSE
|
|||||||
keyUsage = keyEncipherment
|
keyUsage = keyEncipherment
|
||||||
extendedKeyUsage = serverAuth
|
extendedKeyUsage = serverAuth
|
||||||
subjectAltName = DNS:localhost,DNS:proxy,IP:127.0.0.1
|
subjectAltName = DNS:localhost,DNS:proxy,IP:127.0.0.1
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
EOF
|
EOF
|
||||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
||||||
-CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext
|
-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'
|
cat > client.ext << 'EOF'
|
||||||
basicConstraints=CA:FALSE
|
basicConstraints=CA:FALSE
|
||||||
extendedKeyUsage = clientAuth
|
extendedKeyUsage = clientAuth
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
EOF
|
EOF
|
||||||
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
|
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
|
||||||
-CAcreateserial -out client.crt -days 365 -sha256 -extfile client.ext
|
-CAcreateserial -out client.crt -days 365 -sha256 -extfile client.ext
|
||||||
openssl pkcs12 -export -out client.p12 -passout pass: \
|
openssl pkcs12 -export -out client.p12 -passout pass: \
|
||||||
-inkey client.key -in client.crt -certfile ca.crt
|
-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
|
||||||
</pre>
|
</pre>
|
||||||
<li><a name="PCRE"><i>How to use PCRE filtering (regular expressions)</i></a>
|
<li><a name="PCRE"><i>How to use PCRE filtering (regular expressions)</i></a>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@ -838,12 +838,32 @@ ssl_nocli
|
|||||||
# Генерация закрытого ключа CA
|
# Генерация закрытого ключа CA
|
||||||
openssl genrsa -out ca.key 4096
|
openssl genrsa -out ca.key 4096
|
||||||
|
|
||||||
|
# Расширения, без которых сертификат не годится как CA
|
||||||
|
cat > ca.ext << 'EOF'
|
||||||
|
basicConstraints=critical,CA:TRUE
|
||||||
|
keyUsage=critical,keyCertSign,cRLSign
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
EOF
|
||||||
|
|
||||||
# Генерация сертификата CA (действителен 10 лет)
|
# Генерация сертификата 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" \
|
-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
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
|
Расширения обязательны. Без <b>basicConstraints=CA:TRUE</b> и
|
||||||
|
<b>keyCertSign</b> сертификат не принимается как CA, и клиент сообщает, что не
|
||||||
|
может получить сертификат издателя. <b>subjectKeyIdentifier</b> — то, на что
|
||||||
|
ссылаются подписанные этим CA сертификаты.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Расширения задаются файлом, а не через <b>-addext</b>, потому что LibreSSL —
|
||||||
|
команда <b>openssl</b> в macOS и некоторых BSD — обрабатывает -addext иначе,
|
||||||
|
чем OpenSSL. Приведённый вариант одинаково работает в обоих.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
Для MITM импортируйте ca.crt в браузеры/ОС клиентов как доверенный корневой CA.
|
Для MITM импортируйте ca.crt в браузеры/ОС клиентов как доверенный корневой CA.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -876,8 +896,18 @@ EOF
|
|||||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
||||||
-CAcreateserial -out server.crt -days 365 -sha256 \
|
-CAcreateserial -out server.crt -days 365 -sha256 \
|
||||||
-extfile server.ext
|
-extfile server.ext
|
||||||
|
|
||||||
|
# Проверка так же, как это делает современный клиент
|
||||||
|
openssl verify -x509_strict -CAfile ca.crt server.crt
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
|
Проверять следует строго, потому что именно так проверяет клиент. OpenSSL 3
|
||||||
|
добавляет идентификаторы ключей при подписании, а LibreSSL — нет, поэтому файл
|
||||||
|
расширений запрашивает их явно. Python начиная с 3.13 проверяет строго и
|
||||||
|
отвергает сертификат без <b>authorityKeyIdentifier</b>; другие клиенты идут тем
|
||||||
|
же путём.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
Для публичного https:// прокси используйте CA вроде Let's Encrypt вместо самоподписанного.
|
Для публичного https:// прокси используйте CA вроде Let's Encrypt вместо самоподписанного.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -896,6 +926,8 @@ cat > client.ext << 'EOF'
|
|||||||
basicConstraints=CA:FALSE
|
basicConstraints=CA:FALSE
|
||||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
|
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
|
||||||
extendedKeyUsage = clientAuth
|
extendedKeyUsage = clientAuth
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Подписание CA
|
# Подписание CA
|
||||||
@ -918,8 +950,14 @@ openssl pkcs12 -export -out client1.p12 \
|
|||||||
|
|
||||||
# CA
|
# CA
|
||||||
openssl genrsa -out ca.key 4096
|
openssl genrsa -out ca.key 4096
|
||||||
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
|
cat > ca.ext << 'EOF'
|
||||||
-subj "/CN=3proxy CA" -out ca.crt
|
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
|
openssl genrsa -out server.key 2048
|
||||||
@ -929,6 +967,8 @@ basicConstraints=CA:FALSE
|
|||||||
keyUsage = keyEncipherment
|
keyUsage = keyEncipherment
|
||||||
extendedKeyUsage = serverAuth
|
extendedKeyUsage = serverAuth
|
||||||
subjectAltName = DNS:localhost,DNS:proxy,IP:127.0.0.1
|
subjectAltName = DNS:localhost,DNS:proxy,IP:127.0.0.1
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
EOF
|
EOF
|
||||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
||||||
-CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext
|
-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'
|
cat > client.ext << 'EOF'
|
||||||
basicConstraints=CA:FALSE
|
basicConstraints=CA:FALSE
|
||||||
extendedKeyUsage = clientAuth
|
extendedKeyUsage = clientAuth
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
EOF
|
EOF
|
||||||
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
|
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
|
||||||
-CAcreateserial -out client.crt -days 365 -sha256 -extfile client.ext
|
-CAcreateserial -out client.crt -days 365 -sha256 -extfile client.ext
|
||||||
openssl pkcs12 -export -out client.p12 -passout pass: \
|
openssl pkcs12 -export -out client.p12 -passout pass: \
|
||||||
-inkey client.key -in client.crt -certfile ca.crt
|
-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
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<li><a name="PCRE"><i>Как использовать PCRE-фильтрацию (регулярные выражения)</i></a>
|
<li><a name="PCRE"><i>Как использовать PCRE-фильтрацию (регулярные выражения)</i></a>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user