mirror of
https://github.com/3proxy/3proxy.git
synced 2026-09-02 12:55: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
|
||||
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
|
||||
</pre>
|
||||
<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.
|
||||
</p>
|
||||
<p>
|
||||
@ -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
|
||||
</pre>
|
||||
<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.
|
||||
</p>
|
||||
<p>
|
||||
@ -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
|
||||
</pre>
|
||||
<li><a name="PCRE"><i>How to use PCRE filtering (regular expressions)</i></a>
|
||||
<p>
|
||||
|
||||
@ -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
|
||||
</pre>
|
||||
<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.
|
||||
</p>
|
||||
<p>
|
||||
@ -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
|
||||
</pre>
|
||||
<p>
|
||||
Проверять следует строго, потому что именно так проверяет клиент. OpenSSL 3
|
||||
добавляет идентификаторы ключей при подписании, а LibreSSL — нет, поэтому файл
|
||||
расширений запрашивает их явно. Python начиная с 3.13 проверяет строго и
|
||||
отвергает сертификат без <b>authorityKeyIdentifier</b>; другие клиенты идут тем
|
||||
же путём.
|
||||
</p>
|
||||
<p>
|
||||
Для публичного https:// прокси используйте CA вроде Let's Encrypt вместо самоподписанного.
|
||||
</p>
|
||||
<p>
|
||||
@ -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
|
||||
</pre>
|
||||
|
||||
<li><a name="PCRE"><i>Как использовать PCRE-фильтрацию (регулярные выражения)</i></a>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user