SSD Nodes Learn 🎉 VPS $5.50/నెల నుండి

nginxలో mTLSతో client certificates ఎలా అమర్చాలి

openssl తో private CA సృష్టించి client certificates జారీ చేయడం, nginx లో మూడు directives అమర్చడం, certificate లేని లేదా మీ CA జారీ చేయని వారిని తిరస్కరించడం తెలుసుకోండి.

mTLS ఏమి చేస్తుంది

Mutual TLS ను సాధారణంగా mTLS అని రాస్తారు. ఇది ప్రతి client ను certificate ఇవ్వమని nginx అడిగేలా చేస్తుంది. ఆ certificate లేకపోతే, లేదా మీరు నియంత్రించే certificate authority (CA) జారీ చేయకపోతే, request ను తిరస్కరిస్తుంది. ఈ తనిఖీ TLS (transport layer security) handshake లోనే జరుగుతుంది. అందువల్ల చెల్లుబాటు అయ్యే client certificate లేని caller మీ application వరకు అసలు చేరుకోలేడు. ఇదే దీని ప్రధాన ప్రయోజనం. Admin panel లేదా metrics endpoint ను public internet పై login page లేకుండానే ఉంచవచ్చు. Bot ఊహించడానికి కూడా ఏదీ ఉండదు.

దీని నిర్మాణం చిన్నదే. openssl తో సృష్టించిన ఒక private CA, ప్రతి వ్యక్తికి ఒక certificate, nginx server block లో మూడు directives. ఇది ఒక సంవత్సరం పాటు సజావుగా పనిచేస్తుందా అనేది operational నిర్వహణపై ఆధారపడి ఉంటుంది. అందుకే ఈ guide లో ఎక్కువ భాగం certificate lifetimes, revocation, ప్రతి వ్యక్తికి ప్రత్యేక certificates, అలాగే client ను తిరస్కరించినప్పుడు కారణం ఎవరికీ కనిపించకపోతే ఏం చేయాలి అనే అంశాలను వివరిస్తుంది.

రెండు చైన్‌లు, ఒక్కటి కాదు

mTLS సెటప్‌లో రెండు certificate chains ఉంటాయి. వాటికి ఒకదానితో మరొకదానికి సంబంధం ఉండదు. ఈ రెండింటినీ ఒకటిగా భావించడం దాదాపు అందరూ చేసే మొదటి తప్పు.

మొదటి chain server‌కు సంబంధించినది. మీ VPS, Let's Encrypt వంటి public CA జారీ చేసిన admin.example.com certificate ను అందిస్తుంది. Browser ఈ certificate ను operating system తో వచ్చే root store తో సరిపోల్చి తనిఖీ చేస్తుంది. mTLS వల్ల ఈ భాగంలో ఎలాంటి మార్పు ఉండదు. certbot ఈరోజు మీ కోసం ఆ certificate ను జారీ చేస్తే, దాన్ని ఉన్నట్లుగానే ఉంచండి: certbot తో nginx కోసం Let's Encrypt certificate జారీ చేయడం చూడండి.

రెండవ chain client‌కు సంబంధించినది. మీరు స్వంతంగా ఒక చిన్న CA సృష్టించి, అనుమతించాల్సిన ప్రతి వ్యక్తికి ఒక certificate జారీ చేస్తారు. Clients ను తనిఖీ చేసేటప్పుడు nginx ఆ CA ను మాత్రమే trust చేయాలని, ఇతర CAలను trust చేయకూడదని నిర్దేశిస్తారు. Public root store లో మీ CA గురించి ఏ సమాచారం ఉండదు. దాని అవసరం కూడా లేదు. ssl_client_certificate file ద్వారా దాన్ని trust చేయాల్సిన ఏకైక భాగం nginx.

అందువల్ల ssl_client_certificate, nginx అందించే certificate పై ఎలాంటి ప్రభావం చూపదు. అలాగే Let's Encrypt chain వల్ల ఏ clients కు అనుమతి ఇవ్వాలో నిర్ణయించబడదు. ssl_client_certificate ను fullchain.pem కు చూపించడం, కనిపించే విధంగా పనిచేయదు. ఆ directive, client certificate ఏ issuers నుంచి రావచ్చో పేర్కొంటుంది. ఇది connection యొక్క మరొక చివరను సూచిస్తుంది. Server తన outbound పనుల కోసం మీ CA ను trust చేయాలంటే అది వేరే పని. దాని గురించి Ubuntu trust store కు మీ స్వంత CA ను జోడించడం లో వివరించబడింది. Client ను verify చేసేటప్పుడు nginx చదివేది system trust store కాదు.

openssl తో మీ స్వంత client CA ను సృష్టించండి

CA ను web server కు భిన్నమైన ప్రదేశంలో సృష్టించండి. nginx కు CA యొక్క public certificate మాత్రమే అవసరం. CA private key కొత్త client certificates పై సంతకం చేస్తుంది. అందువల్ల దాన్ని internet-facing server లో ఉంచితే, ఒక్క breach జరిగినా దాడి చేసేవారు తమకు కావాల్సినన్ని చెల్లుబాటు అయ్యే clients ను సృష్టించగలరు.

mkdir -p ~/client-ca/certs ~/client-ca/newcerts ~/client-ca/private ~/client-ca/csr
cd ~/client-ca
chmod 700 private
touch index.txt
echo 1000 > serial
echo 1000 > crlnumber

index.txt, serial మరియు crlnumber CA database. ఇవి లేకుండా openssl ca అమలు కాదు. తరువాత revocation సాధ్యమయ్యేది కూడా వీటి వల్లే. Revocation list లో serial numbers ఉంటాయి. కాబట్టి ఏ serial number ఎవరికి కేటాయించబడిందో CA గుర్తుంచుకోవాలి.

~/client-ca/openssl.cnf ను రాయండి. dir ను ఆ directory యొక్క నిజమైన path కు సెట్ చేయండి, ఎందుకంటే openssl ca, ~ ను expand చేయదు.

[ ca ]
default_ca = client_ca

[ client_ca ]
dir               = /home/you/client-ca
database          = $dir/index.txt
new_certs_dir     = $dir/newcerts
certificate       = $dir/ca.crt
private_key       = $dir/private/ca.key
serial            = $dir/serial
crlnumber         = $dir/crlnumber
default_md        = sha256
default_days      = 365
default_crl_days  = 30
policy            = policy_loose
rand_serial       = no
unique_subject    = no
email_in_dn       = no

[ policy_loose ]
commonName              = supplied
countryName             = optional
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
emailAddress            = optional

[ client_ext ]
basicConstraints        = CA:FALSE
keyUsage                = critical, digitalSignature, keyEncipherment
extendedKeyUsage        = clientAuth
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid,issuer

ఇప్పుడు CA key మరియు దాని self-signed certificate ను సృష్టించండి:

openssl genrsa -aes256 -out private/ca.key 4096
chmod 600 private/ca.key
openssl req -x509 -new -key private/ca.key -sha256 -days 3650 \
  -subj "/O=Example Ops/CN=Example Ops Client CA" \
  -addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
  -addext "keyUsage=critical,keyCertSign,cRLSign" \
  -out ca.crt

-aes256 CA key కు passphrase ను అమలు చేస్తుంది. అందువల్ల ప్రతి signing run సమయంలో అది passphrase ను అడుగుతుంది. అదే దీని ఉద్దేశ్యం. మీరు సృష్టించినదాన్ని పరిశీలించండి:

openssl x509 -in ca.crt -noout -subject -dates -ext basicConstraints

Subject మీ CA అయి ఉండాలి. Validity పది సంవత్సరాల పాటు ఉండాలి. Extension line CA:TRUE, pathlen:0 గా ఉండాలి. pathlen:0 అంటే ఈ CA end certificates పై సంతకం చేయవచ్చు, కానీ మరో CA పై సంతకం చేయకూడదు. దీని వల్ల chain సరిగ్గా ఒక స్థాయిలోనే ఉంటుంది మరియు మీరు ssl_verify_depth ను అలాగే ఉంచవచ్చు.

ప్రతి వ్యక్తికి ఒక client certificate జారీ చేయండి

ప్రతి వ్యక్తికి ఒక certificate ఉండాలి. బృందం మొత్తం ఉపయోగించే ఒక shared certificate‌ను ఎప్పుడూ ఉపయోగించవద్దు. Shared certificate‌ను revoke చేస్తే అందరికీ access నిలిచిపోతుంది. అలాగే ఎవరు అభ్యర్థన పంపారో అది తెలియదు.

openssl genrsa -out private/alice.key 2048
openssl req -new -key private/alice.key -out csr/alice.csr \
  -subj "/O=Example Ops/CN=alice"
openssl ca -config openssl.cnf -extensions client_ext \
  -days 365 -notext -in csr/alice.csr -out certs/alice.crt

openssl ca సంతకం చేయబోయే certificate‌ను చూపిస్తుంది, CA passphrase‌ను అడుగుతుంది, నిర్ధారణను రెండుసార్లు అడుగుతుంది, తరువాత index.txt కు ఒక line‌ను జతచేస్తుంది. దీన్ని script‌లో ఉపయోగించినప్పుడు -batch ను జోడించండి. client_ext section ముఖ్యమైనది. అందులోని ఒక line కారణంగా ఇది అవసరం: extendedKeyUsage = clientAuth. serverAuth మాత్రమే ఉన్న extended key usage జాబితాను కలిగిన certificate client authentication‌కు అనుకూలం కాదని తిరస్కరించబడుతుంది. కాబట్టి ఉద్దేశ్యాన్ని స్పష్టంగా పేర్కొనండి.

ఏదైనా అందజేయడానికి ముందు CA‌తో certificate pair‌ను verify చేయండి:

openssl verify -CAfile ca.crt certs/alice.crt

ఇది certs/alice.crt: OK ను print చేస్తుంది. వేరే ఏ output వచ్చినా certificate మరియు CA సరిపోలడం లేదని అర్థం. ఏ nginx configuration కూడా ఈ సమస్యను పరిష్కరించదు.

Browser import చేయగల ఒకే file‌లో key మరియు certificate‌ను కలపండి:

openssl pkcs12 -export -inkey private/alice.key -in certs/alice.crt \
  -name "alice at example ops" -out alice.p12

Export సమయంలో password అడుగుతుంది. ఇది file‌ను బదిలీ సమయంలో రక్షిస్తుంది. File మరియు password‌ను వేర్వేరు channels ద్వారా పంపండి. వ్యక్తులకు bare .key బదులుగా .p12 ఇవ్వండి. CA‌ను bundle‌లో చేర్చడానికి -certfile ca.crt ను జోడించవచ్చు. అయితే nginx‌కు అది అవసరం లేదు. nginx ఇప్పటికే ca.crt ను కలిగి ఉంది. అందువల్ల ఆ CA నేరుగా సంతకం చేసిన certificate దానంతటదే verify అవుతుంది.

Ubuntu 24.04తో వచ్చే OpenSSL 3 ప్రస్తుత encryption‌ను ఉపయోగించి PKCS#12 files‌ను రాస్తుంది. August 2026 నాటికి ఉపయోగంలో ఉన్న browsers మరియు operating systems వాటిని చదవగలవు. పాత importer file‌ను తిరస్కరిస్తే, -legacy ను జోడించి మళ్లీ export చేయండి. ఇది importer ఆశించే పాత algorithms‌కు fallback అవుతుంది. ఆ flag‌ను ఉపయోగించే ముందు importer ఇచ్చిన message‌ను చదవండి.

ssl_client_certificate మరియు ssl_verify_client తో nginx ను కాన్ఫిగర్ చేయండి

CA certificate ను మాత్రమే server కు copy చేయండి.

scp ca.crt user@admin.example.com:/tmp/client-ca.crt
ssh user@admin.example.com \
  'sudo install -o root -g root -m 644 /tmp/client-ca.crt /etc/nginx/client-ca.crt'

ఇక్కడ Mode 644 సరైనది. CA certificate public information. CA key మీ workstation లోనే ఉండాలి.

తర్వాత, ఇప్పటికే TLS termination చేసే server block కు మూడు directives జోడించండి:

server {
    listen 443 ssl;
    server_name admin.example.com;

    ssl_certificate     /etc/letsencrypt/live/admin.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/admin.example.com/privkey.pem;

    ssl_client_certificate /etc/nginx/client-ca.crt;
    ssl_verify_client      on;
    ssl_verify_depth       1;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

ssl_verify_depth 1 nginx default. ఆ file లోని CA ద్వారా client certificate నేరుగా sign అయి ఉండాలని ఇది నిర్దేశిస్తుంది. మీరు intermediate ను జోడించినప్పుడు మాత్రమే దీన్ని పెంచండి. Handshake సమయంలో nginx, ssl_client_certificate లోని subject names ను client కు కూడా పంపుతుంది. అందువల్ల browser తన వద్ద ఉన్న ఏ certificate ను అందించాలో తెలుసుకుంటుంది. ఇదే కారణంగా ssl_trusted_certificate బదులుగా ssl_client_certificate ను ఉపయోగించాలి. రెండూ ఒకే విధంగా verify చేస్తాయి, కానీ ssl_trusted_certificate ఎలాంటి list ను పంపదు.

Ubuntu 24.04లో nginx 1.24 అందుబాటులో ఉంటుంది. ఇందులో HTTP/2 ను listen line లో listen 443 ssl http2; గా పేర్కొంటారు. nginx 1.25.1 మరియు తరువాతి versions లో ఆ రూపం deprecated అయింది. HTTP/2 కోసం ప్రత్యేక directive http2 on; ను ఉపయోగించాలి. ఏ ఎంపిక చేసినా certificate check మారదు.

Reload చేసి ఫలితాన్ని చదవండి:

sudo nginx -t && sudo systemctl reload nginx
curl -i https://admin.example.com/

nginx -t, syntax is ok మరియు test is successful ను print చేస్తుంది. curl call ఎలాంటి certificate ను పంపదు. కాబట్టి అది 400 Bad Request గా, body లో No required SSL certificate was sent తో తిరిగి రావాలి. అంటే nginx తన స్వంత gate వద్ద request ను తిరస్కరించింది. Configuration active గా ఉందని, application కు request పంపలేదని ఇది నిర్ధారిస్తుంది. ఇప్పుడు సరైన విధంగా ప్రయత్నించండి:

curl --cert certs/alice.crt --key private/alice.key https://admin.example.com/

ఇది మీ application అందించే response ను తిరిగి ఇవ్వాలి.

సర్వర్ బ్లాక్‌లో gate ఎందుకు ఉండాలి

TLS handshake సమయంలో, nginx request line ను చదవకముందే certificate మార్పిడి జరుగుతుంది. అందువల్ల ఆ సమయంలో request ఏ location లోకి వెళ్తుందో nginx కు తెలియదు. ssl_verify_client on; ను location లో ఉంచడం ద్వారా connection మధ్యలో మళ్లీ negotiation చేయమని client ను అడిగినట్లవుతుంది. TLS 1.3 renegotiation ను తొలగించింది. HTTP/2 దాన్ని అనుమతించదు. కాబట్టి ప్రస్తుత stack లో ఈ నమూనా prompt చూపించకుండా విఫలమవుతుంది.

Scope ను మీరే నిర్ణయించండి. server స్థాయిలో certificate ను అభ్యర్థించండి. తరువాత ప్రతి location కు అనుగుణంగా నిర్ణయం తీసుకోండి:

ssl_verify_client optional;

location /metrics {
    if ($ssl_client_verify != SUCCESS) { return 403; }
    proxy_pass http://127.0.0.1:9090;
}

location /healthz {
    proxy_pass http://127.0.0.1:8080;
}

$ssl_client_verify లో SUCCESS ఉంటుంది. లేదా client ఏదీ పంపకపోతే NONE ఉంటుంది. లేకపోతే కారణంతో కూడిన FAILED: ఉంటుంది. optional తో nginx certificate ను అభ్యర్థిస్తుంది. కానీ certificate వచ్చినప్పుడు మాత్రమే దాన్ని verify చేస్తుంది. దీనివల్ల పైన ఉన్న public /healthz path పనిచేస్తుంది. అదే సమయంలో /metrics మూసి ఉంటుంది. పంపిన certificate verification లో విఫలమైతే, nginx దాన్ని ఆ దశలోనే తిరస్కరిస్తుంది. విఫలమైన certificate ను మీరు స్వయంగా పరిశీలించాలనుకుంటే, అది optional_no_ca. అప్పుడు SUCCESS కాకుండా మిగిలిన ప్రతి విలువను refusal గా మీ test పరిగణించాలి.

nginx దీనికి non-standard status codes ను ఉపయోగిస్తుంది. error_page వాటిని పట్టుకోగలదు. అందువల్ల తిరస్కరించబడిన visitor కు ఖాళీ 400 బదులుగా కారణం చూపించవచ్చు:

error_page 495 496 = @needcert;

location @needcert {
    default_type text/plain;
    return 200 "This host requires a client certificate. Ask ops for one.\n";
}

495 అంటే client certificate verification లో విఫలమైంది. 496 అంటే client ఎలాంటి certificate ను సమర్పించలేదు. ఆ page ను plain text గా ఉంచండి. దాన్ని చదివే వ్యక్తికి session లేదా account ఉండదు.

బ్రౌజర్‌లో client certificate ను ఎలా ఇన్‌స్టాల్ చేయాలి?

Firefox తన స్వంత certificate store ను ఉపయోగిస్తుంది: Settings, తరువాత Privacy and Security, తరువాత View Certificates, తరువాత Your Certificates tab, తరువాత Import ఎంచుకుని, .p12 ను ఎంచేసి దాని password ను నమోదు చేయండి.

Windows మరియు macOSలో Chrome, Edge operating system store ను ఉపయోగిస్తాయి. అందువల్ల .p12 file ను తెరిస్తే system import wizard ప్రారంభమవుతుంది. Linuxలో Chrome మీ home directory లోని ప్రత్యేక NSS (network security services) database ను చదువుతుంది. కాబట్టి command line tool ఉపయోగించడం నమ్మదగిన పద్ధతి:

sudo apt install -y libnss3-tools
pk12util -d sql:$HOME/.pki/nssdb -i alice.p12

తర్వాత site ను load చేయండి. ఏ certificate ను పంపాలో browser అడుగుతుంది. ప్రస్తుత browser session ముగిసే వరకు Chrome ఆ ఎంపికను గుర్తుంచుకుంటుంది. మళ్లీ అడగాలంటే browser ను restart చేయండి. Certificate ఒక machine లోని ఒక browser profile లో మాత్రమే ఉంటుంది. అందువల్ల Firefoxలో import చేసిన certificate Chromeలో కనిపించదు. అలాగే ఈ రెండింటిలో import చేసిన certificate మీ phoneలో కనిపించదు.

curl --cert తో పరీక్ష

curl తో debug చేయండి. అది తాను చేసిన చర్యలను తెలియజేస్తుంది.

curl -v --cert certs/alice.crt --key private/alice.key https://admin.example.com/

Certificate మరియు key ను ఒకే PEM file గా కలిపి, దాన్ని --cert alice.pem గా ఇవ్వవచ్చు. Key కు passphrase ఉంటే curl దాన్ని అడుగుతుంది. curl --cert alice.pem:passphrase ను కూడా అంగీకరిస్తుంది. అయితే అది మీ shell history లో నిలిచిపోతుంది. కాబట్టి prompt ను ఉపయోగించండి.

nginx ను తప్పుపట్టే ముందు రెండు తనిఖీలు చేయాలి. మొదట, certificate మరియు key ఒకే జతకు చెందినవై ఉండాలి:

openssl x509 -noout -pubkey -in certs/alice.crt | openssl sha256
openssl pkey -pubout -in private/alice.key | openssl sha256

రెండు hash విలువలు ఒకేలా ఉంటే, ఆ files పరస్పరం సరిపోతాయి. hash విలువలు వేర్వేరుగా ఉంటే, ఇద్దరు వేర్వేరు వ్యక్తులకు చెందిన files కలగలిసినట్లు అర్థం. ఆ కారణాన్ని ఏ client కూడా మీకు స్పష్టంగా చెప్పదు.

రెండవది, server మీ CA certificate ను అడగాలి:

openssl s_client -connect admin.example.com:443 -servername admin.example.com </dev/null

Output లో Acceptable client certificate CA names block కోసం చూడండి. ఆ block లో మీ CA subject ఉందో పరిశీలించండి. ఆ block పూర్తిగా కనిపించకపోతే, అభ్యర్థనను సమాధానపరిచిన server block లో nginx certificate ను అభ్యర్థించడం లేదు. అంటే మీ directives వేరే server block లోకి వెళ్లాయి. సాధారణంగా అది default server అవుతుంది.

అప్లికేషన్‌కు client CN ను పంపడం

Certificate ద్వారా ఎవరు అభ్యర్థన పంపారో తెలుస్తుంది. అయితే proxy వెనుక ఉన్న అప్లికేషన్‌కు TLS layer కనిపించదు. అందువల్ల nginx ఆ పేరును అప్లికేషన్‌కు పంపాలి.

map $ssl_client_s_dn $client_cn {
    default              "";
    "~,?CN=(?<cn>[^,]+)" $cn;
}

$ssl_client_s_dn లో subject distinguished name RFC 2253 రూపంలో ఉంటుంది. అది CN=alice,O=Example Ops లాగా కనిపిస్తుంది. map ద్వారా CN field ను $client_cn లోకి తీసుకువస్తుంది. CN ను సాధారణ username గా ఉంచండి. ఎందుకంటే ఆ రూపంలో CN లోని comma escape అవుతుంది. పై చిన్న regular expression ఆ escape ను నిర్వహించదు.

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host                 $host;
    proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto    $scheme;
    proxy_set_header X-Client-Cert-CN     $client_cn;
    proxy_set_header X-Client-Cert-Serial $ssl_client_serial;
}

అభ్యర్థన పంపిన వ్యక్తి పంపిన అదే పేరుగల header ను proxy_set_header భర్తీ చేస్తుంది. అందువల్ల ఈ location ద్వారా ఎవరూ X-Client-Cert-CN ను నకిలీగా పంపలేరు. ఈ నియమం అమలులో ఉండటానికి రెండు పరిస్థితులు అవసరం. లోపలి level లో స్వంత proxy_set_header ఏదీ నిర్వచించనప్పుడు మాత్రమే nginx బయటి level నుంచి దాన్ని inherit చేస్తుంది. కాబట్టి ఒక రెండో location లో ఒక్క proxy_set_header line ఉన్నా, దాని పైన సెట్ చేసిన ప్రతి header నిశ్శబ్దంగా కోల్పోతుంది. ఇందులో ఉన్న header కూడా కోల్పోతుంది. అలాగే అప్లికేషన్‌ను nginx ద్వారా తప్ప మరే మార్గంలోనూ చేరుకోలేని విధంగా ఉంచాలి. అంటే దాన్ని 0.0.0.0 కు బదులుగా 127.0.0.1 కు bind చేయాలి. Public port పై అప్లికేషన్ నడిస్తే, internet నుంచి నేరుగా పంపిన forged header ను అది చదువుతుంది. Proxy వైపు configuration ను nginx reverse proxy configuration ను line by line వివరించడం లో చూడవచ్చు. అప్లికేషన్‌కు పేరు కాకుండా మొత్తం certificate కావాలంటే, $ssl_client_escaped_cert దాన్ని URL-encoded రూపంలో header లో సురక్షితంగా తీసుకువెళుతుంది.

ఒక client certificate ను ఎలా revoke చేయాలి?

ఎవరైనా సంస్థను విడిచిపెట్టవచ్చు లేదా laptop కనిపించకుండా పోవచ్చు. అప్పుడు ఆ ఒక్క certificate ను revoke చేయవచ్చు. మిగతా అందరూ పని కొనసాగిస్తారు. ఒక్కో వ్యక్తికి ఒక్క certificate జారీ చేయడానికి ఇదే ప్రధాన కారణం.

cd ~/client-ca
openssl ca -config openssl.cnf -revoke certs/alice.crt
openssl ca -config openssl.cnf -gencrl -out crl.pem

మొదటి command index.txt లోని ఆ serial కు సంబంధించిన line ను V నుంచి R కు మార్చుతుంది. రెండవ command certificate revocation list (CRL) ను రాస్తుంది. ఇది revoke చేసిన serial numbers ను పేర్కొనే signed file. దాన్ని deploy చేసి, ఇతర directives పక్కనే ssl_crl /etc/nginx/client-ca.crl; తో nginx కు దాని path చూపించండి.

scp crl.pem user@admin.example.com:/tmp/client-ca.crl
ssh user@admin.example.com 'sudo install -m 644 /tmp/client-ca.crl /etc/nginx/client-ca.crl && sudo nginx -t && sudo systemctl reload nginx'

ఇక్కడ అందరి access ను నిలిపివేసే సమస్య ఉంది. CRL లో nextUpdate date ఉంటుంది. దీన్ని default_crl_days నిర్ధారిస్తుంది. పై configuration లో ఆ విలువ 30. ఆ date దాటిన తర్వాత OpenSSL ఆ జాబితాను stale గా పరిగణిస్తుంది. అప్పుడు revoke చేసిన certificate కు మాత్రమే కాకుండా ప్రతి client certificate కు CRL has expired తో verification విఫలమవుతుంది. nginx configuration ను load చేసినప్పుడు file ను చదువుతుంది. అందువల్ల disk పై కొత్త CRL ఉంచడం మాత్రమే సరిపోదు; reload చేయాలి. window లోపల సురక్షితంగా ఉండే schedule పై CRL ను regenerate చేసి reload చేయండి. 30 days window కోసం weekly schedule సరిపోతుంది. Copy చేయడానికి ముందు dates ను తనిఖీ చేయండి:

openssl crl -in crl.pem -noout -lastupdate -nextupdate

కొద్దిమంది users మాత్రమే ఉంటే చిన్నదైన మరో మార్గం ఉంది. CA మీ నియంత్రణలోనే ఉంది కాబట్టి nginx serial ను నేరుగా తిరస్కరించగలదు. అప్పుడు CRL విధానం అవసరం ఉండదు:

map $ssl_client_serial $revoked {
    default 0;
    "1002"  1;
}

దీనితో పాటు location లో if ($revoked) { return 403; } ను జత చేయండి. దీనికి expiry date ఉండదు. అయితే ఈ నియమం ఇతర చోట్లకు పంపబడదు. కాబట్టి మీ CA పై నమ్మకం ఉంచే మరే ఇతర సేవకూ దీని గురించి తెలియదు. ఒక application ముందు ఒక nginx మాత్రమే ఉంటే, ఇదే సరళమైన మరియు స్పష్టమైన పరిష్కారం. ఒకటి కంటే ఎక్కువ gates ఉన్నప్పుడు CRL విధానానికి మారండి.

క్లయెంట్ సర్టిఫికెట్లు ఎంతకాలం చెల్లుబాటులో ఉండాలి?

క్లయెంట్ సర్టిఫికెట్లను ఒక సంవత్సరం పాటు చెల్లుబాటులో ఉంచండి. Reissue పనిని భరించగలిగితే అంతకంటే తక్కువ కాలాన్ని ఎంచుకోవచ్చు. ఇక్కడ expiry నిశ్శబ్దంగా వైఫల్యానికి కారణమవుతుంది, ఎందుకంటే ముందుగానే certificate holder ను హెచ్చరించే వ్యవస్థ ఉండదు. ఒక ఉదయం వారు panel ను తెరిచినప్పుడు nginx connection ను నిరాకరిస్తుంది. Browser ఆ నిరాకరణను తన స్వంత పదాలతో వివరిస్తుంది. ఆ వివరణలో expired అనే పదం సాధారణంగా ఉండదు. CA ను పది సంవత్సరాల పాటు చెల్లుబాటులో ఉంచండి. దాని expiry date ను మీరు నిజంగా పరిశీలించే చోట నమోదు చేయండి. CA certificate expiry అయిన రోజే దాని కింద ఉన్న ప్రతి certificate verification విఫలమవుతుంది.

ఈ రెండు commands ఉపయోగిస్తే మీరు ముందుగానే సిద్ధంగా ఉండవచ్చు:

openssl x509 -in certs/alice.crt -noout -subject -serial -enddate
awk -F'\t' '{print $1, $2, $4}' ~/client-ca/index.txt

index.txt లోని మొదటి column status ను చూపిస్తుంది: చెల్లుబాటులో ఉన్నదానికి V, revoke చేసినదానికి R, expiry అయినదానికి E. రెండవ column YYMMDDHHMMSSZ రూపంలో expiry ను చూపిస్తుంది. నాలుగవ column serial ను చూపిస్తుంది. ఎవరి వద్ద ఏ certificate ఉందో నమోదు చేసే ఏకైక record ఆ file. అందువల్ల దాన్ని CA key తో కలిసి backup చేయండి. ఈ రెండింటినీ secrets గా పరిగణించండి.

Renewal అంటే కొత్త certificate ను సృష్టించడం. ఇది certificate extension కాదు. కొత్త key మరియు CSR (certificate signing request) ను generate చేయండి, sign చేయండి, certificate ను సంబంధిత వ్యక్తికి అందించండి. కొత్త certificate సరిగ్గా పనిచేస్తుందని ఆ వ్యక్తి నిర్ధారించిన తరువాత పాత certificate ను revoke చేయండి.

mTLS ఏ వాటి నుంచి రక్షిస్తుంది, ఏ వాటి నుంచి రక్షించదు

ఇది తొలగించేది authentication లేని చేరువ. మీ hostname ను కనుగొన్న scanner కు handshake సమయంలోనే నిరాకరణ లభిస్తుంది. అందువల్ల అది HTTP request పంపలేను, login form చూడలేను, దొంగిలించిన password ను దానిపై ప్రయత్నించలేను. Credential stuffing చేయడానికి credential లే ఉండవు. Certificate లేని ఎవరూ application login flow లోని vulnerability ను చేరుకోలేరు. వ్యక్తులు chat లో copy-paste చేసే shared secret కూడా అవసరం ఉండదు. ఎందుకంటే private key అనేది అనుకోకుండా copy చేయడం కష్టమైన file.

Compromised client విషయంలో ఇది ఏమీ చేయదు. Laptop లోని malware కు key file ఉంటుంది. యజమాని దాన్ని type చేసిన క్షణం malware కు passphrase కూడా లభిస్తుంది. ఆ attacker server కు చట్టబద్ధమైన user లాగే కనిపిస్తాడు. Certificate ఒక file తమ వద్ద ఉందని మాత్రమే నిరూపిస్తుంది; ఆ file వెనుక నిజమైన వ్యక్తి ఉన్నాడని నిరూపించదు. .p12 password మరియు full disk encryption ఇప్పటికీ ముఖ్యమైన రక్షణలే.

ఇది authorization కూడా కాదు. మీరు $client_cn ను తనిఖీ చేసి, దాని విలువ ఆధారంగా చర్య తీసుకోకపోతే, ఆ server block అందించే ప్రతిదానినీ ప్రతి చెల్లుబాటు అయ్యే certificate చేరుకోగలదు. Default గా రెండు certificate holders కు ఒకే విధమైన access ఉంటుంది.

ఇది nginx ద్వారా వెళ్లే మార్గాన్నే రక్షిస్తుంది. Application public port లో కూడా listening చేస్తే, దాని ముందు mTLS ఉండటం కేవలం అలంకారం మాత్రమే. App ను 127.0.0.1 కు bind చేసి, దాని port పై firewall ను మూసి ఉంచండి. అదే server కు వెళ్లే మరో మార్గం SSH. దానికీ ఇదే స్థాయి శ్రద్ధ అవసరం. దీని గురించి మీ VPS లో SSH access ను harden చేయడం లో వివరించాం.

చివరి పరిమితి startup రోజునే సమస్యగా మారవచ్చు. Certificate అందించలేని ఏదైనా పని చేయడం ఆపేస్తుంది: uptime monitor, payment provider నుంచి వచ్చే webhook, RSS reader, లేదా మీరు చేరుకోగల certificate store లేని mobile app. ssl_verify_client on ను సెట్ చేయడానికి ముందు వీటి గురించి నిర్ణయం తీసుకోండి. ఎందుకంటే వైఫల్యం పూర్తిగా ఉంటుంది, అలాగే వారి వైపు ఎలాంటి సందేశం లేకుండానే జరగవచ్చు.

క్లయింట్ తిరస్కరించబడినప్పుడు, క్లయింట్ చూపించే సమాచారాన్ని చదవండి

తిరస్కరణకు గురైన క్లయింట్ చూపించే సందేశం browser, curl version మరియు కింద ఉపయోగించే TLS library పై ఆధారపడి ఉంటుంది. అందువల్ల ఎక్కడో రాసి ఉన్న సందేశంతో సరిపోల్చకుండా, మీ క్లయింట్ చూపించే సమాచారాన్ని చదవండి. ఉపయోగకరమైన వివరాలు server పై ఉంటాయి.

sudo tail -n 50 /var/log/nginx/error.log

తిరస్కరించబడిన certificate లో client SSL certificate verify error తో ప్రారంభమయ్యే ఒక line ఉంటుంది. దాని తరువాత OpenSSL ఇచ్చిన కారణం కనిపిస్తుంది. చర్య తీసుకోవాల్సిన అసలు సమాచారం అదే కారణం. సాధారణంగా కారణం కొన్ని వాటిలో ఒకటి ఉంటుంది. ssl_client_certificate లో పేర్కొన్న file కంటే వేరే CA నుంచి certificate వచ్చింది. Certificate validity dates పరిధికి వెలుపల ఉంది. Server లోని CRL తన nextUpdate దాటింది. అందువల్ల ఇప్పుడు ఒక client మాత్రమే కాకుండా ప్రతి client విఫలమవుతుంది.

Browser అసలు certificate ను పంపకపోతే, సమస్య verification కంటే ముందరి దశలో ఉంటుంది. Handshake సమయంలో nginx అనుమతించే issuer పేర్లను పంపుతుంది. Browser తన store లో సరిపోలే దాన్ని కనుగొనలేదు. అందువల్ల పంపడానికి దాని వద్ద certificate లేదు. మీరు నిజంగా browsing చేస్తున్న profile లోకి .p12 ను మళ్లీ import చేయండి.

మరో ముఖ్యమైన పరిస్థితి కూడా ఉంది. మీ CA సంతకం చేసిన client certificate బదులుగా, ఒంటరి self-signed client certificate తో పరీక్షిస్తే verification విజయవంతం కాదు. ఎందుకంటే nginx signature ను CA file తో తనిఖీ చేస్తుంది. Self-signed certificate ఆ file లో ఉండదు. Certificate తయారు చేసే విధానం Ubuntuలో self-signed certificateను రూపొందించడం లో ఉన్నదే. mTLS కోసం అదనంగా మీ CA దానిపై సంతకం చేసే దశ మాత్రమే అవసరం.

FAQ

mTLS ఉపయోగిస్తే నాకు ఇంకా Let's Encrypt certificate అవసరమా?

అవును. ఈ రెండు certificates కు పరస్పర సంబంధం లేదు. browser hostname ను నమ్మేలా చేయడానికి server తన స్వంత certificate ను అందిస్తుంది. ఆ certificate browser కు ఇప్పటికే తెలిసిన CA నుంచి పొందినదై ఉండాలి. మీ client CA వేరు private chain. దాన్ని ఎవరు connect అవుతున్నారో నిర్ధారించడానికి మాత్రమే ఉపయోగిస్తారు. ssl_client_certificate ను అమర్చడం వల్ల nginx అందించే certificate లో ఎలాంటి మార్పు ఉండదు. అది మీ Let's Encrypt chain ను సూచించకూడదు.

certificate ఎంచుకోవాలని నా browser ఎప్పుడూ ఎందుకు అడగదు?

handshake సమయంలో nginx ఆమోదయోగ్యమైన issuers జాబితాను పంపుతుంది. ఈ జాబితా ssl_client_certificate లోని file ఆధారంగా రూపొందుతుంది. issuer ఆ జాబితాలో ఉన్న certificates ను మాత్రమే browser చూపిస్తుంది. కాబట్టి prompt కనిపించకపోతే, browser లో మీ CA కి చెందిన certificate ఏదీ లేదని అర్థం. Certificate ను వేరే browser profile లో import చేసి ఉండవచ్చు, లేదా server లో install చేసిన CA కాకుండా వేరే CA certificate పై సంతకం చేసి ఉండవచ్చు. openssl s_client -connect admin.example.com:443 ను run చేసి, output లో ఆమోదయోగ్యమైన client certificate CA names ను చూడండి. దీని ద్వారా server నిజంగా ఏ CA ను కోరుతోందో తెలుస్తుంది.

ఒక URL కి మాత్రమే client certificate తప్పనిసరి చేయవచ్చా?

location లో ssl_verify_client on ను ఉపయోగించి అలా చేయలేరు. handshake సమయంలోనే certificate మార్పిడి జరుగుతుంది. ఆ సమయంలో nginx కు request path ఇంకా తెలియదు. దీనికి workaround గా ఉపయోగపడే renegotiation TLS 1.3 లో తొలగించబడింది, HTTP/2 లో నిషేధించబడింది. server block లో ssl_verify_client optional; ను అమర్చండి. తరువాత రక్షించాల్సిన ప్రతి location లో $ssl_client_verify ను పరీక్షించి, అది SUCCESS కాకపోతే 403 ను return చేయండి.

ఒక వ్యక్తి access ను ఎలా revoke చేయాలి?

openssl ca -revoke తో ఆ certificate ను revoke చేయండి. openssl ca -gencrl తో list ను మళ్లీ generate చేసి, దాన్ని server కు copy చేయండి. కొత్త file ను nginx చదివేలా nginx ను reload చేయండి. మిగతా అందరిపై ప్రభావం ఉండదు. అయితే ప్రతి వ్యక్తి shared certificate కాకుండా తన స్వంత certificate కలిగి ఉన్నప్పుడే ఇది పనిచేస్తుంది. CRL యొక్క nextUpdate date ను గమనించండి. CRL expire అయితే revoked clients కే కాకుండా ప్రతి client కు verification విఫలమవుతుంది.

mTLS login page స్థానాన్ని భర్తీ చేస్తుందా?

Application కు చేరుకునే విషయంలో అవును. Certificate లేకపోతే ఏదీ application వరకు చేరదు. అందువల్ల దాడి చేయడానికి form ఉండదు, ఊహించడానికి password ఉండదు. కానీ application లోని identity విషయంలో కాదు. Certificate ను కలిగి ఉన్న వ్యక్తి key file పై నియంత్రణ కలిగి ఉన్నాడని మాత్రమే అది నిరూపిస్తుంది. కాబట్టి దొంగిలించబడిన laptop ద్వారా చెల్లుబాటు అయ్యే user access లభించవచ్చు. CN ను upstream కు pass చేయండి. Application లో ఇప్పటికే ఉన్న accounts మరియు permissions ను కొనసాగించండి. Certificate ను వాటి ముందు ఉన్న access gate గా పరిగణించండి.

#tls#mtls#nginx#openssl#access-control