Ubuntu-এ Chrome-গ্রহণযোগ্য self-signed certificate তৈরি
Ubuntu 24.04-এ SAN-সহ একটি openssl command-এ TLS certificate তৈরি করুন, Nginx বা Apache-এ যুক্ত করুন এবং curl -k ছাড়াই client trust করান।
আপনি যা তৈরি করবেন
একটি self-signed TLS certificate, যা আধুনিক browser ও client সত্যিই গ্রহণ করে; সঠিক subjectAltName, নিরাপদ key permission, Nginx বা Apache-এ সংযুক্ত configuration, এবং প্রায় সব guide-এ বাদ পড়া গুরুত্বপূর্ণ অংশটি: আপনার client-গুলোকে certificate-টি সঠিকভাবে trust করানো। এতে warning এড়াতে বারবার click করতে হবে না এবং চিরদিন script-এ curl -k hard-code করেও রাখতে হবে না। শেষে থাকবে পাঁচটি command-এ তৈরি একটি private CA, যখন একটি internal service বেড়ে ছয়টি হয়।
প্রথমে সিদ্ধান্তটি নিন। Self-signed certificate যতবার ব্যবহার করা হয়, ততবার এটি সঠিক পছন্দ নয়। Service-টি যদি public Internet থেকে একটি আসল DNS name-এ পৌঁছানো যায়, তাহলে পড়া বন্ধ করে nginx-এ certbot ব্যবহার করে বিনামূল্যের Let's Encrypt certificate তৈরি করুন অথবা Apache-এর সমতুল্য পদ্ধতি ব্যবহার করুন। এর কোনো খরচ নেই, এটি নিজে নিজে renew হয়, এবং পৃথিবীর সব browser এটি আগে থেকেই trust করে। Public site-এ self-signed certificate ব্যবহার করলে ব্যবহারকারীরা security warning এড়িয়ে click করতে অভ্যস্ত হয়ে যায়। এটি plain HTTP ব্যবহারের চেয়েও খারাপ অভ্যাস।
Public Internet জড়িত না থাকলে self-signed certificate সঠিক পছন্দ। যেমন, আপনার VPS-এর WireGuard tunnel address-এ bind করা একটি admin panel, private network-এর staging box, backend-গুলোর মধ্যে service-to-service traffic, home-lab appliance, অথবা Webmin port 10000-এ নিজের জন্য তৈরি করা placeholder certificate প্রতিস্থাপন করা। Let's Encrypt যাই হোক 10.8.0.1 বা git.internal.lan-এর জন্য certificate issue করতে পারে না। কোনো public CA private IP বা তৈরি করা TLD certificate-এ যুক্ত করবে না। এসব name-এর ক্ষেত্রে আপনিই CA।
নিচের সব ধাপ fresh Ubuntu 24.04 box-এ চলে। এই সংস্করণে OpenSSL 3.0.x সরবরাহ করা হয় (নিশ্চিত করতে openssl version চালান)। এখানে Internet access-এর প্রয়োজন নেই। সবকিছু air-gapped পরিবেশেও কাজ করে।
পুরোনো one-liner কেন Chrome প্রত্যাখ্যান করে এমন certificate তৈরি করে
2017-এর আগের প্রতিটি tutorial-এ দেওয়া command সাধারণত এমন:
# Do not run this — shown so you recognise it in old guides
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout selfsigned.key -out selfsigned.crtএটি ধারাবাহিকভাবে interactive প্রশ্ন করে, আপনার hostname-কে Common Name field-এ বসায় এবং কোনো subjectAltName extension ছাড়াই certificate তৈরি করে। এই certificate শুরু থেকেই অকার্যকর। Chrome 2017 সালের April-এ version 58 থেকে Common Name পড়া বন্ধ করে। এর আগেই RFC 2818 2000 সালে CN matching বাতিল বলে চিহ্নিত করেছিল। Firefox, Safari, curl এবং Python-ও একইভাবে কাজ করে। Certificate তার server-কে SAN extension-এর মাধ্যমে শনাক্ত করে; তা না হলে শনাক্তই করতে পারে না। Browser ঠিক এই শব্দগুলোতে বিষয়টি জানায়:
NET::ERR_CERT_COMMON_NAME_INVALID
This server could not prove that it is git.internal.lan; its security
certificate does not specify Subject Alternative Names.Trust store পরিবর্তন করে এই error ঠিক করা যায় না, কারণ certificate-এ সত্যিই কোনো server name নেই। আপনি যদি এখন NET::ERR_CERT_COMMON_NAME_INVALID দেখেন, তাহলে আপনার certificate-এ SAN নেই অথবা ভুল SAN আছে। আপনাকে নতুন certificate তৈরি করতে হবে। সৌভাগ্যক্রমে, সমাধানটি একটি command।
ব্রাউজার গ্রহণ করবে এমন certificate তৈরি করুন: একটি command
OpenSSL 1.1.1 সংস্করণে -addext flag যুক্ত হয়েছে। তাই পুরোনো গাইডে SAN যোগ করার জন্য যে config file-ভিত্তিক জটিল পদ্ধতি ব্যবহার করা হতো, এখন আর তা প্রয়োজন নেই। Ubuntu 24.04-এ:
sudo openssl req -x509 -newkey rsa:4096 -sha256 -days 730 -noenc \
-keyout /etc/ssl/private/git.internal.key \
-out /etc/ssl/certs/git.internal.crt \
-subj "/CN=git.internal.lan" \
-addext "subjectAltName=DNS:git.internal.lan,IP:10.8.0.1"প্রতিটি flag-এর কাজ:
-x509signing request তৈরি না করে সরাসরি self-signed certificate তৈরি করে।-newkey rsa:4096একই ধাপে নতুন key তৈরি করে। RSA 4096 কোনো legacy client-এর সমস্যা তৈরি করে না। সংযোগকারী সব client আধুনিক হলে-newkey ec -pkeyopt ec_paramgen_curve:P-256আকারে ছোট এবং দ্রুত।-noencহলো OpenSSL 3.x-এ পুরোনো-nodes-এর লেখার ধরন: key-তে কোনো passphrase থাকবে না। উভয় লেখার ধরনই কাজ করে। passphrase-যুক্ত key থাকলে প্রতিবার boot-এর সময় nginx input-এর অপেক্ষায় আটকে থাকে। তাই server key-এর জন্য এটি ব্যবহার করুন।-days 730, দুই বছর। এই সংখ্যাটি সম্পর্কে expiry section-এ আরও বলা হয়েছে।-subjinteractive প্রশ্নগুলোর উত্তর command-এর মধ্যেই দেয়। এখন CN মূলত cosmetic, তবে এটিকে primary name হিসেবে সেট করুন; কিছু tool এটি দেখায়।-addext "subjectAltName=..."হলো সবচেয়ে গুরুত্বপূর্ণ flag। Client যে প্রতিটি name এবং প্রতিটি IP লিখবে, সব তালিকাভুক্ত করুন: hostname-এর জন্যDNS:entry (DNS:*.internal.lan-এর মতো wildcard ব্যবহার করা যায়), address-এর জন্যIP:entry। কেউ যদিhttps://10.8.0.1-এ browse করে, তাহলেIP:10.8.0.1entry অবশ্যই থাকতে হবে। শুধু DNS SAN থাকলে আবার তাদেরNET::ERR_CERT_COMMON_NAME_INVALIDদেখাবে।
কোনো configuration যুক্ত করার আগে SAN সত্যিই certificate-এ যোগ হয়েছে কি না নিশ্চিত করুন:
openssl x509 -in /etc/ssl/certs/git.internal.crt -noout -ext subjectAltNameসঠিক output:
X509v3 Subject Alternative Name:
DNS:git.internal.lan, IP Address:10.8.0.1এর পরিবর্তে যদি No extensions in certificate দেখা যায়, তাহলে certificate-এ SAN নেই এবং browser এটি প্রত্যাখ্যান করবে। কাজ এগিয়ে না নিয়ে certificate নতুন করে তৈরি করুন।
ক্রিপ্টোগ্রাফিক key সুরক্ষিত করুন
সার্ভারের প্রতিটি user যে private key পড়তে পারে, সেটি আর private key থাকে না। Ubuntu-তে /etc/ssl/private ইতিমধ্যে 710 root:ssl-cert হিসেবে থাকে। এতে সাধারণ user-দের অননুমোদিতভাবে দেখার সুযোগ থাকে না। তবু ফাইলটির permission সরাসরি নির্ধারণ করুন:
sudo chown root:root /etc/ssl/private/git.internal.key
sudo chmod 600 /etc/ssl/private/git.internal.keynginx এবং Apache উভয়ই privilege কমানোর আগে root হিসেবে certificate পড়ে। তাই root:root mode 600 তাদের জন্য কাজ করে। key-টি যদি নিজস্ব user হিসেবে চলা কোনো service নিজে load করে, যেমন Node app, Gitea বা Python daemon, chown সেটির service user-কে মালিক করুন এবং mode 600 রাখুন। যা কখনো করবেন না: mode 644 ব্যবহার করা, git repository-তে একটি কপি রাখা, অথবা /tmp-এ একটি কপি রাখা।
nginx-এর সঙ্গে এটি সংযুক্ত করুন
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name git.internal.lan;
ssl_certificate /etc/ssl/certs/git.internal.crt;
ssl_certificate_key /etc/ssl/private/git.internal.key;
location / {
proxy_pass http://127.0.0.1:3000;
}
}sudo nginx -t && sudo systemctl reload nginxreload কার্যকর হওয়ার আগে nginx -t-কে অবশ্যই syntax is ok এবং test is successful দেখাতে হবে। এর পরিবর্তে যদি SSL_CTX_use_PrivateKey_file() failed ... key values mismatch দেখায়, certificate এবং key দুটি ভিন্ন generation run থেকে এসেছে। failure-modes section দেখুন।
Apache-এ সংযুক্ত করুন
sudo a2enmod ssl proxy proxy_httpssl একা যথেষ্ট নয়: নিচের vhost-এ ProxyPass ব্যবহার করা হয়েছে, এবং mod_proxy ও mod_proxy_http না থাকলে configuration test Invalid command 'ProxyPass', perhaps misspelled or defined by a module not included in the server configuration ত্রুটিতে ব্যর্থ হবে। vhost-টি /etc/apache2/sites-available/git-internal.conf হিসেবে সংরক্ষণ করুন:
<VirtualHost *:443>
ServerName git.internal.lan
SSLEngine on
SSLCertificateFile /etc/ssl/certs/git.internal.crt
SSLCertificateKeyFile /etc/ssl/private/git.internal.key
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
</VirtualHost>sudo a2ensite git-internal
sudo apache2ctl configtest && sudo systemctl reload apache2configtest-এর Syntax OK-এ সাড়া দেওয়ার কথা। এবার একটি client machine থেকে পরীক্ষা করুন:
curl -v https://git.internal.lan/এবং আপনি একটি ত্রুটি পাবেন:
curl: (60) SSL certificate problem: self-signed certificateএটি কোনো bug নয়। TLS সঠিকভাবে কাজ করছে: curl আপনার certificate সম্পর্কে কিছু জানে না এবং যে server-কে authenticate করতে পারে না, তার সঙ্গে যোগাযোগ করতে অস্বীকার করে। পরের section-এ প্রকৃত সমাধান দেওয়া হয়েছে। এই মুহূর্তে Internet-এর অর্ধেক মানুষ যে পদ্ধতি ব্যবহার করে, এটি সেটি নয়।
ক্লায়েন্টকে এটি বিশ্বাস করাতে হবে, এবং যে anti-pattern প্রত্যাখ্যান করবেন
প্রথমে ভুল সমাধানগুলো এবং সেগুলোর প্রকৃত অর্থ দেখুন। কোনো script-এ curl -k (অথবা --insecure) যোগ করা, Python requests-এ verify=False ব্যবহার করা, বা Node-এ NODE_TLS_REJECT_UNAUTHORIZED=0 সেট করা—কোনোটিই certificate-কে trusted করে না। এগুলো certificate verification বন্ধ করে দেয়। এর ফলে client যেকোনো certificate উপস্থাপনকারী যেকোনো server-এর সঙ্গে সংযোগ করবে, যার মধ্যে আক্রমণকারী network path-এ বসানো certificate-ও থাকতে পারে। আপনি TLS-এর overhead বজায় রাখেন, কিন্তু TLS ব্যবহারের মূল authentication সুবিধা হারান। আরও খারাপ বিষয় হলো, এই flag-গুলো ছড়িয়ে পড়ে: একটি cron job-এ paste করার পর deploy script-এ, তারপর production code-এ চলে যায়। একসময় কেউ মনে রাখতে পারে না কোন connection সাময়িক হওয়ার কথা ছিল। যে debugging session থেকে কোনো verify=False তৈরি হয়েছে, সেটি যদি সেই session শেষ হওয়ার পরও থেকে যায়, তাহলে design-টি ভুল।
সঠিক সমাধান হলো প্রতিটি client OS-কে শেখানো যে এই certificate একটি trusted root। Ubuntu এবং Debian client-এ:
sudo cp git.internal.crt /usr/local/share/ca-certificates/git.internal.crt
sudo update-ca-certificatesOutput-এর গুরুত্বপূর্ণ line-টি হলো (এর পরে একটি Running hooks in /etc/ca-certificates/update.d... block থাকে):
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.এই line-গুলোতে দুটি বিষয় খেয়াল রাখতে হবে। File-এর শেষে অবশ্যই .crt থাকতে হবে। .pem extension নীরবে উপেক্ষা করা হয়, ফলে কোনো error message ছাড়াই 0 added পাওয়া যায়। Content অবশ্যই PEM হতে হবে; file-এর শুরুতে -----BEGIN CERTIFICATE----- থাকবে। DER binary হলে আগে openssl x509 -inform der -in file.der -out file.crt ব্যবহার করে convert করুন। Self-signed certificate-টিকেই root হিসেবে যোগ করা কার্যকর, কারণ একটি self-signed certificate নিজেই তার root।
এরপর curl, wget, git, apt এবং system bundle ব্যবহার করে OpenSSL-এর মাধ্যমে কাজ করা অন্য সব client কোনো flag ছাড়াই server-টিকে trusted হিসেবে গণ্য করবে। কিছু client নিজেদের trust store ব্যবহার করে এবং সেগুলোর জন্য আলাদা ব্যবস্থা প্রয়োজন:
- Linux-এ Chrome/Chromium system store নয়, NSS database পড়ে: প্রতি user-এর জন্য প্রথমে
sudo apt install libnss3-tools, তারপরcertutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "git.internal" -i git.internal.crtব্যবহার করুন। - Firefox-এর নিজস্ব store আছে: Settings → Privacy & Security → Certificates → Import ব্যবহার করুন। অথবা
about:config-এsecurity.enterprise_roots.enabledথেকেtrueপরিবর্তন করুন, যাতে এটি system store পড়ে। - Python requests নিজস্ব CA bundle (certifi) ব্যবহার করে এবং system store উপেক্ষা করে:
verify="/usr/local/share/ca-certificates/git.internal.crt"pass করুন অথবাREQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crtexport করুন। - Node.js:
NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/git.internal.crtexport করুন।
Windows client-এ .crt-এ double-click করে certificate-টি Trusted Root Certification Authorities-এ install করুন। macOS-এ Keychain Access ব্যবহার করে এটি System keychain-এ যোগ করুন এবং Always Trust নির্বাচন করুন।
একাধিক service-এর জন্য একটি root: ছোট private CA
প্রতি-certificate trust ব্যবস্থাপনা দ্রুতই অকার্যকর হয়ে যায়: ছয়টি service এবং চারটি client machine হলে মোট চব্বিশটি trust installation দরকার হয়, আর প্রতিটি নতুন service-এর জন্য আরও installation যোগ হয়। সমাধান হলো একটি private CA ব্যবহার করা। Client-গুলো শুধু একটি root trust করবে, এবং আপনি সেটি দিয়ে প্রতিটি service-এর certificate sign করবেন।
সহজ বিকল্প হলো mkcert। এটি Ubuntu 24.04-এর repo-তে আছে এবং update-ca-certificates যে NSS store-গুলোতে কাজ করে না, যেমন Chrome ও Firefox-এর store, সেগুলোও পরিচালনা করে:
sudo apt install -y mkcert libnss3-tools
mkcert -install
mkcert git.internal.lan "*.internal.lan" 10.8.0.1mkcert -install একটি root তৈরি করে এবং সেই machine-এর প্রতিটি trust store-এ সেটি নিবন্ধন করে। তৃতীয় command-টি git.internal.lan+2.pem এবং git.internal.lan+2-key.pem তৈরি করে, যা উপরের nginx বা Apache snippet-এ সরাসরি বসানো যায়। এর নকশা development machine ধরে নেওয়া হয়েছে। Root key যে machine-এ -install চালানো হয়েছে, সেখানেই থাকে। তাই এটি dev laptop-এর জন্য উপযোগী, কিন্তু server fleet-এর জন্য সঠিক পদ্ধতি নয়।
Server-এর ক্ষেত্রে plain OpenSSL পাঁচটি command-এই সম্পূর্ণ CA তৈরি করতে পারে:
openssl genrsa -out lab-ca.key 4096
openssl req -x509 -new -key lab-ca.key -sha256 -days 3650 \
-out lab-ca.crt -subj "/CN=Lab Internal CA" \
-addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
-addext "keyUsage=critical,keyCertSign,cRLSign"
openssl genrsa -out git.key 2048
openssl req -new -key git.key -out git.csr -subj "/CN=git.internal.lan" \
-addext "subjectAltName=DNS:git.internal.lan,IP:10.8.0.1"
openssl x509 -req -in git.csr -CA lab-ca.crt -CAkey lab-ca.key \
-CAcreateserial -days 730 -sha256 -copy_extensions copy -out git.crtসমস্যাটি শেষ command-এ: openssl x509 -req ডিফল্টভাবে CSR থেকে সব extension বাদ দেয়, এর মধ্যে আপনি সতর্কতার সঙ্গে যোগ করা SAN-ও থাকে। -copy_extensions copy, যা OpenSSL 3.x-এর একটি option এবং তাই 24.04-এ কাজ করে, এই extension-গুলো বহাল রাখে। এটি বাদ দিলে signed certificate-এ SAN থাকে না, এবং Chrome আবার NET::ERR_CERT_COMMON_NAME_INVALID দেখায়। আগের মতো একই openssl x509 -noout -ext subjectAltName check ব্যবহার করে যাচাই করুন।
উপরের trust-store ধাপ অনুসরণ করে প্রতি machine-এ একবার করে lab-ca.crt distribute করুন। lab-ca.key-কে এখন অত্যন্ত গুরুত্বপূর্ণ credential হিসেবে সুরক্ষিত রাখুন: mode 600 ব্যবহার করুন। সম্ভব হলে এটি এমন একটি box-এ রাখুন, যেটি এটি যেসব server-এর জন্য certificate sign করে তাদের কোনোটি নয়। কারণ যার কাছে এটি থাকবে, সে আপনার client-গুলোর বিশ্বাসযোগ্য যেকোনো নামের জন্য certificate তৈরি করতে পারবে।
মেয়াদ শেষ হওয়া এবং রোটেশন
Public CA certificate-এর lifetime কমে যাচ্ছে। CA/Browser Forum March 2026-এ নতুনভাবে জারি করা publicly trusted certificate-এর সর্বোচ্চ মেয়াদ 200 দিন নির্ধারণ করেছে, যা আগে 398 দিন ছিল। এই সীমা 2027 সালে 100 দিন এবং March 2029-এর মধ্যে 47 দিনে নামবে। তবে এই নিয়ম শুধু publicly trusted CA-এর ক্ষেত্রে প্রযোজ্য। আপনার private CA এই নিয়মের অধীন নয়, এবং manually installed root-এর ক্ষেত্রে browser এই সীমা কার্যকর করে না। একটি বাস্তব সীমা অবশ্যই প্রযোজ্য: certificate যে সংস্থাই issue করুক, Apple platform 825 দিনের বেশি বৈধ TLS server certificate প্রত্যাখ্যান করে। তাই iPhone বা Mac থেকে সংযোগ করা হলে leaf certificate-এর মেয়াদ দুই বছর বা তার কম রাখুন। -days 730 সব জায়গায় এই সীমার মধ্যে থাকে। দুই বছরের leaf certificate সহ দশ বছরের root একটি উপযুক্ত internal কাঠামো।
দীর্ঘমেয়াদি certificate কেবল একটি উপায়ে ব্যর্থ হয়: এমন একটি তারিখে একসঙ্গে এবং নীরবে, যে তারিখ বেছে নেওয়ার কথা কারও মনে থাকে না। আপনার কাছে কী আছে তা পরীক্ষা করুন:
openssl x509 -in /etc/ssl/certs/git.internal.crt -noout -enddateRenewal-এর জন্য একটি বাস্তব calendar schedule তৈরি করুন। অথবা cron-কে 30 দিন আগে সতর্ক করতে দিন। মেয়াদ শেষ হতে যত সেকেন্ড বাকি আছে তা নির্ধারিত সীমার মধ্যে এলে openssl x509 -checkend 2592000 -in cert.crt non-zero status দিয়ে শেষ হয়। আপনি যদি ইতিমধ্যে status monitoring-এর জন্য Uptime Kuma চালান, তাহলে এর HTTPS monitor বিনা খরচে certificate-এর মেয়াদ শেষ হওয়ার কাছাকাছি এলে তা জানায়।
Private CA দিয়ে rotation সাধারণত সরল: CSR তৈরি এবং sign করার command আবার চালান, file বদলান, তারপর web server reload করুন। root পরিবর্তিত হয়নি, তাই কোনো client এই পরিবর্তন লক্ষ্য করে না।
ব্যর্থতার ধরন এবং যে বার্তাগুলো আপনি দেখবেন
NET::ERR_CERT_AUTHORITY_INVALID হলো trust ইনস্টল করার আগের প্রত্যাশিত অবস্থা; এটি certificate-এর ত্রুটি নয়। root ইনস্টল করার পরেও এটি থাকলে: Linux-এ Chrome system store-এর বদলে NSS পড়ে (certutil ধাপ দেখুন); অথবা কপি করা ফাইলটি .crt দিয়ে শেষ হয়নি এবং update-ca-certificates-এ 0 added দেখিয়েছে; অথবা server আপনার trusted certificate-এর বদলে অন্য certificate পাঠাচ্ছে। openssl s_client -connect git.internal.lan:443 </dev/null 2>/dev/null | openssl x509 -noout -fingerprint -sha256 দিয়ে fingerprint তুলনা করুন।
NET::ERR_CERT_COMMON_NAME_INVALID দেখালে certificate-এ SAN নেই, অথবা SAN address bar-এ থাকা নামটি অন্তর্ভুক্ত করে না। প্রচলিত উদাহরণ হলো: SAN-এ DNS:git.internal.lan আছে, কিন্তু user https://10.8.0.1-এ গিয়েছেন। trust-store পরিবর্তন করে এটি ঠিক করা যায় না; অনুপস্থিত entry যুক্ত করে certificate পুনরায় issue করুন।
curl: (60) SSL certificate problem: self-signed certificate দেখালে curl certificate-টিকে trust করে না। Private CA দ্বারা signed certificate-এর ক্ষেত্রে self-signed certificate in certificate chain variant-এর অর্থও একই। একবারের সমাধান: curl --cacert lab-ca.crt https://...; স্থায়ী সমাধান: trust store। -k নয়।
unable to load certificate ... Expecting: TRUSTED CERTIFICATE (অথবা Expecting: CERTIFICATE REQUEST, অথবা no start line) দেখালে PEM নিয়ে বিভ্রান্তি হয়েছে। আপনি OpenSSL-কে ভুল ধরনের ফাইল দিয়েছেন: certificate প্রত্যাশিত স্থানে key বা CSR, অথবা PEM প্রত্যাশিত স্থানে DER binary। head -1 filename-এ আপনার কাছে আসলে কী আছে তা জানায়; certificate -----BEGIN CERTIFICATE----- দিয়ে শুরু হয়। DER-এর ক্ষেত্রে openssl x509 -inform der -in file.der -out file.crt দিয়ে রূপান্তর করুন।
nginx: [emerg] SSL_CTX_use_PrivateKey_file(...) failed (SSL: error ... key values mismatch) দেখালে certificate এবং key পরস্পরের সঙ্গে মেলে না। সাধারণত generation command দুবার চালানো হলে এবং ফাইলগুলো মিশে গেলে এমন হয়। openssl x509 -in git.internal.crt -noout -pubkey | sha256sum এবং openssl pkey -in git.internal.key -pubout | sha256sum তুলনা করে নিশ্চিত করুন; hash মিলে গেলে জোড়াটিও মিলে যায়। ভিন্ন হলে দুটিই একসঙ্গে পুনরায় তৈরি করুন।
FAQ
Chrome-এ self-signed certificate তৈরি করার পরও কেন "Not secure" দেখায়?
যদি ত্রুটিটি NET::ERR_CERT_AUTHORITY_INVALID হয়, certificate-এ সমস্যা নেই; Chrome এখনো এটিকে বিশ্বাস করার কারণ জানে না। এটি অথবা আপনার private CA root-কে client-এর trust store-এ ইনস্টল করুন। মনে রাখবেন, Linux-এ Chrome system store নয়, certutil-এর মাধ্যমে NSS database ব্যবহার করে। ত্রুটিটি যদি NET::ERR_CERT_COMMON_NAME_INVALID হয়, certificate-এ URL-এর সঙ্গে মেলা Subject Alternative Name নেই। সে ক্ষেত্রে -addext "subjectAltName=..." দিয়ে certificate নতুন করে ইস্যু করতে হবে।
-k ছাড়া curl-কে কীভাবে self-signed certificate বিশ্বাস করাব?
Certificate-টি PEM format-এ, .crt extension-সহ, /usr/local/share/ca-certificates/-এ কপি করুন এবং sudo update-ca-certificates চালান। আউটপুটে অবশ্যই 1 added দেখাতে হবে। এরপর থেকে curl এটিকে যেকোনো public certificate-এর মতো যাচাই করবে। System পরিবর্তন না করে একবারের request-এর জন্য curl --cacert /path/to/cert.crt শুধু ওই file-এর বিরুদ্ধে যাচাই করে। -k সম্পূর্ণ verification বন্ধ করে এবং এটি কোনো script-এ ব্যবহার করা উচিত নয়।
Self-signed certificate কত দিন valid থাকতে পারে?
প্রযুক্তিগতভাবে আপনি ইচ্ছামতো দীর্ঘ সময় নির্ধারণ করতে পারেন। CA/Browser Forum-এর সীমা বর্তমানে 200 দিন এবং 2029 সালের মধ্যে 47 দিনে নামবে; এই সীমা publicly trusted CA-এর ক্ষেত্রে প্রযোজ্য, private trust-এর ক্ষেত্রে নয়। বাস্তবে server certificate-এর মেয়াদ সর্বোচ্চ 825 দিন রাখুন, কারণ issuer যেই হোক, Apple device 825 দিনের বেশি মেয়াদের certificate প্রত্যাখ্যান করে। দশ বছরের private root এবং দুই বছরের (-days 730) leaf certificate একটি যুক্তিসংগত default। তবে renewal-এর তারিখ calendar-এ রাখুন, কারণ মেয়াদ শেষ হওয়া internal certificate এমন সময়ে সবকিছু বন্ধ করে দিতে পারে, যে তারিখ কারও মনে থাকে না।
Self-signed certificate ব্যবহার করব, নাকি Let's Encrypt?
Service-এর public DNS name থাকলে এবং এটি Internet থেকে reachable হলে সবসময় Let's Encrypt ব্যবহার করুন। এটি বিনামূল্যে, স্বয়ংক্রিয় এবং প্রতিটি client ইতিমধ্যে বিশ্বাস করে। Let's Encrypt যে certificate ইস্যু করতে পারে না, সেসব ক্ষেত্রে self-signed certificate বা private CA ব্যবহার করুন। এর মধ্যে রয়েছে private IP, .lan-এর মতো internal-only hostname, air-gapped network এবং VPN-এর আড়ালে ইচ্ছাকৃতভাবে গোপন রাখা service। সিদ্ধান্তটি security strength-এর ওপর নয়, reachability ও naming-এর ওপর নির্ভর করে। Cryptography একই।
/usr/local/share/ca-certificates-এ যোগ করার পরও certificate কেন প্রত্যাখ্যাত হচ্ছে?
তিনটি বিষয় পরীক্ষা করুন। File-এর শেষে .crt থাকতে হবে। .pem extension নীরবে বাদ পড়ে এবং update-ca-certificates 0 added রিপোর্ট করে। Content অবশ্যই -----BEGIN CERTIFICATE----- দিয়ে শুরু হওয়া PEM text হতে হবে, DER binary নয়। এছাড়া application-টি সত্যিই system store ব্যবহার করছে কি না যাচাই করুন। Linux-এর Chrome, Firefox, Python requests, Node.js এবং Java প্রত্যেকেই আলাদা private trust store ব্যবহার করে। তাই প্রতিটির ক্ষেত্রে certificate আলাদাভাবে যোগ করতে হবে।