Ubuntu-তে নিজস্ব CA সার্টিফিকেট যোগ করার নিয়ম
Ubuntu-এর trust store-এ নিজস্ব CA সার্টিফিকেট যোগ করতে root certificate-টি /usr/local/share/ca-certificates ডিরেক্টরিতে রাখুন এবং update-ca-certificates কমান্ডটি চালান।
Ubuntu-এর trust store-এ আপনার নিজস্ব CA যোগ করা
Ubuntu-এর trust store-এ আপনার নিজস্ব CA যোগ করতে, root certificate-টিকে /usr/local/share/ca-certificates/ ডিরেক্টরিতে .crt দিয়ে শেষ হওয়া একটি নামে কপি করুন, তারপর sudo update-ca-certificates কমান্ডটি চালান। একটি CA (certificate authority) হলো এমন এক জোড়া কী (key pair), যার certificate অন্য certificate-কে স্বাক্ষর করার অনুমতি রাখে। একবার আপনার মেশিন root-টিকে বিশ্বাস করলে, সেই root দ্বারা স্বাক্ষরিত প্রতিটি certificate গৃহীত হবে, ফলে আপনার নিজস্ব সার্ভিসগুলোর মধ্যে HTTPS ভেরিফিকেশন ব্যর্থ হওয়া বন্ধ হবে।
এই নির্দেশিকাটি openssl ব্যবহার করে সম্পূর্ণ চেইনটি অফলাইনে তৈরি করে। আপনি একটি root key এবং একটি root certificate তৈরি করবেন, একটি সার্ভারের জন্য একটি leaf certificate ইস্যু করবেন, তারপর root-টিকে ইনস্টল করবেন এবং দেখবেন কীভাবে একই ভেরিফিকেশন কমান্ডের ফলাফল পরিবর্তিত হয়। এই ক্রমটিই গুরুত্বপূর্ণ: ইনস্টল করার আগে এবং পরে ভেরিফাই করার মাধ্যমেই আপনি বুঝতে পারবেন যে ইনস্টলেশনটিই ফলাফল পরিবর্তনের কারণ।
Ubuntu 24.04-এর ডিফল্ট ইমেজে OpenSSL 3 এবং ca-certificates প্যাকেজ থাকে, তাই প্রথমে নতুন কিছু ইনস্টল করার প্রয়োজন নেই (আগস্ট 2026 অনুযায়ী যাচাইকৃত)।
কখন আপনার নিজের CA চালানো উচিত?
Let's Encrypt-এর মতো পাবলিক CA-এর জন্য পাবলিক DNS-এ একটি নাম এবং এমন একটি সার্ভার প্রয়োজন যেখানে তারা পৌঁছাতে পারে। অভ্যন্তরীণ নামগুলো এর জন্য উপযুক্ত নয়। প্রাইভেট নেটওয়ার্কে থাকা কোনো ডেটাবেস বা টানেলের সাথে যুক্ত কোনো অ্যাডমিন প্যানেল পাবলিক সার্টিফিকেট পেতে পারে না, এবং শুধুমাত্র সার্টিফিকেট পাওয়ার জন্য সেগুলোকে ইন্টারনেটে উন্মুক্ত করাও উচিত নয়।
একটি Ubuntu-তে self-signed certificate শুধুমাত্র একটি হোস্টের সমস্যার সমাধান করে। প্রতিটি ক্লায়েন্টকে সেই একটি সার্টিফিকেট বিশ্বাস করতে হয় এবং পরবর্তী হোস্টের ক্ষেত্রে একই কাজ আবার করতে হয়। একটি প্রাইভেট CA এই সিদ্ধান্তকে এক ধাপ উপরে নিয়ে যায়। ক্লায়েন্টরা একবার রুট সার্টিফিকেটকে বিশ্বাস করলেই হয়, এরপর সেই রুট দ্বারা স্বাক্ষরিত প্রতিটি সার্টিফিকেট স্বয়ংক্রিয়ভাবে বিশ্বস্ত হয়ে যায়, এমনকি এমন হোস্টের সার্টিফিকেটও যা এখনো তৈরি হয়নি।
এর ঝুঁকি বাস্তব। রুট কি (root key) সীমাবদ্ধতার মধ্যে যেকোনো কিছু স্বাক্ষর করতে পারে, তাই যার কাছে ca.key থাকবে, সে এমন সার্টিফিকেট ইস্যু করতে পারবে যা আপনার মেশিনগুলো গ্রহণ করবে। একে ঠিক সেভাবেই সুরক্ষিত রাখুন যেভাবে আপনি SSH key management-এ একটি প্রাইভেট কি সুরক্ষিত রাখেন। যদি কোনো সার্ভিসের পাবলিক DNS নাম থাকে, তবে এই ঝামেলায় না গিয়ে পাবলিক CA ব্যবহার করুন: Certbot with nginx and Let's Encrypt ব্যবহার করা অনেক সহজ এবং এতে ক্লায়েন্ট সাইডে বাড়তি কিছু ইনস্টল করার প্রয়োজন হয় না।
CA key এবং root certificate তৈরি করা
এমন একটি ডিরেক্টরিতে কাজ করুন যা শুধুমাত্র আপনি খুলতে পারেন। root key কখনোই সেই ডিরেক্টরি থেকে বাইরে বের করবেন না।
install -d -m 700 ~/ca
cd ~/ca
openssl genrsa -aes256 -out ca.key 4096
chmod 600 ca.key-aes256 আপনার বেছে নেওয়া একটি passphrase দিয়ে key-টিকে encrypt করে, এবং পরবর্তীতে এই key দিয়ে স্বাক্ষর করার প্রতিটি কমান্ড সেই passphrase চাইবে। -aes256 ব্যবহার না করলে key-টি ডিস্কে plain text হিসেবে থাকবে, ফলে একটি ব্যাকআপ বা অন্য কোনো অ্যাডমিন অ্যাকাউন্টের মাধ্যমে যে কেউ আপনার মেশিনের বিশ্বাসযোগ্য সার্টিফিকেট ইস্যু করার ক্ষমতা পেয়ে যেতে পারে।
এখন root certificate তৈরি করুন, যা CA key নিজের জন্য স্বাক্ষর করে।
openssl req -x509 -new -key ca.key -sha256 -days 3650 \
-subj "/O=Example Internal/CN=Example Internal Root CA" \
-addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
-addext "keyUsage=critical,keyCertSign,cRLSign" \
-addext "subjectKeyIdentifier=hash" \
-addext "nameConstraints=critical,permitted;DNS:internal.example" \
-out ca.crtinternal.example-কে আপনার ব্যবহৃত নামের suffix দিয়ে প্রতিস্থাপন করুন এবং পরবর্তী extension-টি রাখার আগে পরের সেকশনটি পড়ুন।
প্রতিটি extension একটি নির্দিষ্ট কাজ করে।
basicConstraintsএবংCA:TRUE-এর সমন্বয় এটিকে একটি CA certificate হিসেবে তৈরি করে। এটি ছাড়া, এই key দিয়ে স্বাক্ষরিত যেকোনো সার্টিফিকেট ক্লায়েন্ট প্রত্যাখ্যান করবে, এমনকি স্বাক্ষরটি সঠিক হলেও।pathlen:0নির্দেশ করে যে CA-টি leaf certificate স্বাক্ষর করতে পারবে, কিন্তু এর নিচে অন্য কোনো CA তৈরি করতে পারবে না।keyUsagekey-টিকে শুধুমাত্র সার্টিফিকেট এবং revocation list স্বাক্ষরের মধ্যে সীমাবদ্ধ রাখে, যাতে ভুলবশত একই key-কে TLS server key হিসেবে ব্যবহার করা না যায়।subjectKeyIdentifierroot-কে একটি শনাক্তকারী (identifier) দেয় যার দিকে leaf certificate-গুলো নির্দেশ করে; শত শত সার্টিফিকেট থাকা স্টোর থেকে ক্লায়েন্ট কীভাবে সঠিক issuer খুঁজে পাবে, এটি তার উপায়।nameConstraintsএই CA কোন কোন নামের নিশ্চয়তা দিতে পারবে তা সীমাবদ্ধ করে।
কমান্ডটি আপনার প্রত্যাশা অনুযায়ী কাজ করেছে কি না তা অনুমান না করে, যা তৈরি করেছেন তা যাচাই করে দেখুন।
openssl x509 -noout -subject -issuer -serial -dates -in ca.crt
openssl x509 -noout -text -in ca.crtSubject এবং issuer একই স্ট্রিং প্রদর্শন করবে, কারণ একটি root certificate নিজেকেই স্বাক্ষর করে। Serial এবং তারিখ দুটি আপনার তৈরি করা ফাইল থেকে আসবে, তাই অন্য কারো গাইডের ওপর নির্ভর না করে সেই আউটপুট থেকেই তথ্যগুলো নিন।
আপনার CA কী স্বাক্ষর করতে পারবে তা সীমাবদ্ধ করুন
সিস্টেম স্টোরে থাকা একটি রুট সার্টিফিকেট ইন্টারনেটের প্রতিটি নামের জন্য বিশ্বস্ত হিসেবে গণ্য হয়, যদি না আপনি অন্য কিছু নির্ধারণ করেন। একটি সার্ভারের একটি ফাইলে এত বিশাল ক্ষমতা রাখা ঝুঁকিপূর্ণ। nameConstraints এই ঝুঁকি কমায়। রুট সার্টিফিকেটে permitted;DNS:internal.example থাকলে, internal.example-এর বাইরের কোনো নামের জন্য এই CA থেকে আসা চেইনটি প্রত্যাখ্যাত হবে, এমনকি স্বাক্ষর সঠিক হলেও।
এটি বিশ্বাস করার পরিবর্তে পরীক্ষা করে দেখুন।
openssl req -new -newkey rsa:2048 -nodes -keyout /tmp/outside.key -out /tmp/outside.csr \
-subj "/CN=www.example.com"
openssl x509 -req -in /tmp/outside.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-days 30 -sha256 \
-extfile <(printf 'subjectAltName=DNS:www.example.com\n') -out /tmp/outside.crt
openssl verify -CAfile ca.crt /tmp/outside.crt
echo $?সার্টিফিকেটটি ইস্যু করা হয়েছে, কারণ আপনার CA যা কিছু স্বাক্ষর করতে বলা হয় তা-ই স্বাক্ষর করে। যাচাইকরণের সময় এটি ব্যর্থ হয়: এক্সিট স্ট্যাটাস নন-জিরো হয় এবং OpenSSL সেই সীমাবদ্ধতার নাম উল্লেখ করে যা লঙ্ঘিত হয়েছে। এটিই এই এক্সটেনশনের মূল উপযোগিতা। একটি চুরি হওয়া CA কি (key) দিয়েও সাবট্রির বাইরের কোনো নামের জন্য কার্যকর সার্টিফিকেট তৈরি করা সম্ভব নয়। কাজ শেষ হলে rm /tmp/outside.* দিয়ে অবশিষ্ট ফাইলগুলো মুছে ফেলুন।
সীমাবদ্ধতা কার্যকর করার আগে চারটি বিষয় জেনে রাখা প্রয়োজন। এটি critical হিসেবে চিহ্নিত, তাই যে ক্লায়েন্ট এই এক্সটেনশনটি বোঝে না, সে চেইনটিকে উপেক্ষা করার পরিবর্তে প্রত্যাখ্যান করবে। এটি নিরাপদ পদ্ধতি হলেও পুরনো TLS লাইব্রেরির ক্ষেত্রে সমস্যা হতে পারে। DNS নামের জন্য একটি অনুমোদিত সাবট্রি IP অ্যাড্রেস SAN-কে সীমাবদ্ধ করে না, কারণ যে নামের ধরনের কোনো সাবট্রি তালিকাভুক্ত নেই তা অনিয়ন্ত্রিত থাকে। তাই আপনার সার্টিফিকেটে যদি IP অ্যাড্রেস থাকে, তবে একই এক্সটেনশনে permitted;IP:10.0.0.0/255.255.0.0 যোগ করুন। সাবট্রিটিকে আপনার ইস্যু করা প্রতিটি নাম কভার করতে হবে, যার মধ্যে ছোট হোস্টনামও অন্তর্ভুক্ত। তাই উপরের উদাহরণের বিপরীতে app-এর মতো সাধারণ নামের জন্য একটি সার্টিফিকেট ব্যর্থ হবে। এই সীমাবদ্ধতা রুটের সাথে যুক্ত থাকে, তাই মত পরিবর্তন করলে নতুন রুট সার্টিফিকেট তৈরি করতে হবে এবং প্রতিটি ক্লায়েন্টে তা নতুন করে ইনস্টল করতে হবে।
আপনার CA দ্বারা স্বাক্ষরিত একটি leaf certificate ইস্যু করুন
একটি leaf certificate হলো সেই সার্টিফিকেট যা একটি সার্ভার ক্লায়েন্টদের কাছে উপস্থাপন করে। এর নিজস্ব key এবং একটি CSR (certificate signing request) দিয়ে শুরু করুন। CSR-এ public key এবং অনুরোধকৃত নাম থাকে এবং এটি leaf key দ্বারা স্বাক্ষরিত হয়, যা প্রমাণ করে যে অনুরোধকারী ব্যক্তি private key-টির অধিকারী।
openssl req -new -newkey rsa:2048 -nodes \
-keyout app.key -out app.csr \
-subj "/CN=app.internal.example"
chmod 600 app.keyযে নামগুলো গুরুত্বপূর্ণ সেগুলো CSR-এ নয়, বরং একটি extension file-এ রাখতে হয়। ক্লায়েন্টরা hostname-এর সাথে subjectAltName (SAN) মিলিয়ে দেখে এবং common name-কে পুরোপুরি উপেক্ষা করে। তাই কোনো সার্টিফিকেটে যদি CN থাকে কিন্তু SAN না থাকে, তবে বর্তমানের যেকোনো ক্লায়েন্টে hostname verification ব্যর্থ হবে, CN-এ যাই লেখা থাকুক না কেন।
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:app.internal.example, DNS:api.internal.example
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:alwaysসেটিকে app.ext হিসেবে সেভ করুন, তারপর CA ব্যবহার করে অনুরোধটি স্বাক্ষর করুন।
openssl x509 -req -in app.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-days 397 -sha256 -extfile app.ext -out app.crt-CAcreateserial ফাইলটি CA-এর পাশে ca.srl তৈরি করে, যেখানে পরবর্তী serial number থাকে যাতে এই CA থেকে ইস্যু করা দুটি সার্টিফিকেটের serial number একই না হয়। এই ফাইলটি CA ডিরেক্টরিতে রাখুন। -days 397 একটি পছন্দ, টুলটির কোনো সীমাবদ্ধতা নয়। পাবলিক CA-এর তুলনায় এখানে সার্টিফিকেটের মেয়াদ কম রাখা বেশি গুরুত্বপূর্ণ, কারণ একটি প্রাইভেট CA-এর কোনো revocation infrastructure থাকে না। আপনি নিজে তৈরি না করলে এখানে কোনো CRL বা OCSP responder থাকে না, তাই কোনো leaf key ফাঁস হয়ে গেলে সার্টিফিকেটটির মেয়াদ শেষ না হওয়া পর্যন্ত সেটি ব্যবহারযোগ্য থেকে যায়।
trust store-এ যাওয়ার আগে ফলাফলটি যাচাই করে নিন।
openssl x509 -noout -subject -issuer -serial -dates -in app.crt
openssl x509 -noout -ext subjectAltName -in app.crtissuer লাইনে এখন leaf-এর পরিবর্তে CA-এর নাম দেখা যাবে। SAN লাইনে সেই নামগুলো তালিকাভুক্ত থাকে যেগুলোর জন্য এই সার্টিফিকেটটি বৈধ, এবং ক্লায়েন্ট শুধুমাত্র সেই তালিকার সাথেই নাম মিলিয়ে দেখে।
কোনো কিছু ইনস্টল করার আগে একটি explicit -CAfile দিয়ে যাচাই করুন
openssl verify -CAfile ca.crt app.crt
echo $?এটি একটি সুনির্দিষ্ট প্রশ্ন করে: app.crt কি ca.crt-এ থাকা সার্টিফিকেটের সাথে চেইন তৈরি করে? এটি এই মেশিনটি কী বিশ্বাস করে সে সম্পর্কে কিছু বলে না, কারণ আপনি কমান্ড লাইনে OpenSSL-কে রুট সার্টিফিকেটটি দিয়েছেন। এখানে ব্যর্থতা মানে হলো সার্টিফিকেটগুলোর নিজস্ব কোনো সমস্যা আছে, তাই এগিয়ে যাওয়ার আগে এটি সমাধান করুন।
এখন মেশিনকে জিজ্ঞাসা করুন।
openssl verify app.crt
echo $?কোনো -CAfile না থাকলে, OpenSSL তার বিল্ট-ইন সার্টিফিকেট ডিরেক্টরিতে ফিরে যায়। openssl version -d আপনার বিল্ড যে বেস ডিরেক্টরি ব্যবহার করে তা প্রিন্ট করে, এবং Ubuntu-তে এর অধীনে থাকা certs ডিরেক্টরিটি /etc/ssl/certs-এ সমাধান হয়। আপনার রুট সার্টিফিকেটটি এখনো সেখানে নেই, তাই যাচাইকরণ ব্যর্থ হয়: চেইনটি এমন একটি ইস্যুয়ারে পৌঁছায় যা স্টোরে নেই এবং খোঁজার জন্য আর কোনো জায়গা অবশিষ্ট থাকে না। প্রস্থান স্ট্যাটাস (exit status) লক্ষ্য করুন। এটিই সেই জিনিস যা দুই ধাপ পরে পরিবর্তিত হবে।
একটি প্রকৃত ক্লায়েন্ট openssl verify-এর চেয়ে ভালো পরীক্ষা করে, কারণ এটি চেইনের পাশাপাশি হোস্টনামও যাচাই করে। সার্টিফিকেটটি সার্ভ করুন এবং তা ফেচ (fetch) করুন।
openssl s_server -accept 8443 -cert app.crt -key app.key -www &
curl --resolve app.internal.example:8443:127.0.0.1 https://app.internal.example:8443/--resolve সংযোগটিকে 127.0.0.1-এ পাঠায় কিন্তু এখনো app.internal.example অনুরোধ করে, তাই SAN মিলে যায় এবং একমাত্র খোলা প্রশ্নটি হলো বিশ্বাসযোগ্যতা। curl ব্যর্থ হয় এবং চেইনটি কেন যাচাই করতে পারেনি তার কারণ প্রিন্ট করে। আরও বিস্তারিত জানার জন্য -v যোগ করুন। টেস্ট সার্ভারটি চালু রাখুন।
/usr/local/share/ca-certificates ডিরেক্টরিতে রুট সার্টিফিকেট ইনস্টল করা
sudo cp ca.crt /usr/local/share/ca-certificates/example-internal-root.crt
sudo chmod 644 /usr/local/share/ca-certificates/example-internal-root.crt
sudo update-ca-certificatesযেসব খুঁটিনাটি বিষয় নিশ্চিত করে যে এটি সঠিকভাবে কাজ করবে:
- ফাইলের নাম অবশ্যই
.crtদিয়ে শেষ হতে হবে।update-ca-certificatesম্যানুয়াল পেজ অনুযায়ী,/usr/local/share/ca-certificatesডিরেক্টরির নিচে থাকা.crtএক্সটেনশনযুক্ত সার্টিফিকেটগুলো অন্তর্ভুক্ত করা হয় এবং সেগুলোকে পরোক্ষভাবে বিশ্বাসযোগ্য (implicitly trusted) হিসেবে গণ্য করা হয়।root.pemবাroot.cerনামে কোনো ফাইল থাকলে তা কোনো সতর্কতা ছাড়াই এড়িয়ে যাওয়া হয়। - ফাইলের বিষয়বস্তু অবশ্যই PEM ফরম্যাটে হতে হবে, যা
BEGIN CERTIFICATEএবংEND CERTIFICATEলাইন দিয়ে ঘেরা একটি base64 ব্লক। একটি DER ফাইলকে শুধু নাম পরিবর্তন করে.crtকরলে তা বাইনারিই থেকে যায় এবং পড়া যায় না। সেক্ষেত্রেopenssl x509 -inform DER -in ca.der -out ca.crtব্যবহার করে সেটিকে রূপান্তর করুন। - এখানে শুধুমাত্র রুট সার্টিফিকেট রাখা উচিত। CA প্রাইভেট কি এবং লিফ সার্টিফিকেট ট্রাস্ট স্টোরে রাখার প্রয়োজন নেই।
update-ca-certificates কমান্ডটি কতগুলো সার্টিফিকেট যোগ বা অপসারণ করা হয়েছে তা প্রদর্শন করে। যদি কোনোটি যোগ না হয়, তবে বুঝতে হবে ফাইলের এক্সটেনশন বা ফরম্যাটে সমস্যা রয়েছে।
সিস্টেমের দিক থেকে এই পরিবর্তনটি নিশ্চিত করুন, শুধুমাত্র ওই মেসেজের ওপর নির্ভর করবেন না।
ls -l /etc/ssl/certs/$(openssl x509 -noout -subject_hash -in /usr/local/share/ca-certificates/example-internal-root.crt).0
grep -c 'BEGIN CERTIFICATE' /etc/ssl/certs/ca-certificates.crtপ্রথম কমান্ডটি আপনার সার্টিফিকেটের সাবজেক্ট হ্যাশ থেকে একটি ফাইলের নাম তৈরি করে এবং তা তালিকাভুক্ত করে। update-ca-certificates সেই সিম্বলিক লিঙ্কটি তৈরি করেছে, যা আপনার ইনস্টল করা ফাইলের দিকে নির্দেশ করে। দ্বিতীয় কমান্ডটি একক-ফাইল বান্ডিলে থাকা সার্টিফিকেটের সংখ্যা গণনা করে। ইনস্টল করার আগেও এটি চালিয়ে দেখুন, তাহলে সংখ্যাটি এক বৃদ্ধি পেতে দেখবেন।
যখন আপনি এই রুট সার্টিফিকেটটি অন্য মেশিনে কপি করবেন, তখন ইনস্টল করার আগে নিশ্চিত হয়ে নিন যে কপিটি অক্ষত আছে। একটি রুট সার্টিফিকেট ভুল হওয়া সিস্টেমের জন্য অত্যন্ত ঝুঁকিপূর্ণ, তাই ব্যবহারের আগে অন্য যেকোনো ডাউনলোডের মতো এটিকে চেকসাম দিয়ে যাচাই করে নিন।
সিস্টেম স্টোরের বিপরীতে পুনরায় যাচাই করুন
openssl verify app.crt
echo $?
curl --resolve app.internal.example:8443:127.0.0.1 https://app.internal.example:8443/একই কমান্ড, একই সার্টিফিকেট ফাইল, কিন্তু ফলাফল ভিন্ন। app.crt সম্পর্কে কিছুই পরিবর্তন করা হয়নি এবং সার্ভারটি সেই একই সার্ভার যা আপনি আগে চালু করেছিলেন। একমাত্র পার্থক্য হলো, রুট সার্টিফিকেটটি এখন সেই স্টোরে রয়েছে যা ক্লায়েন্টরা রিড করে, তাই চেইনটি সম্পন্ন হয়েছে। এটিই সেই মেকানিজম যা মনে রাখা জরুরি: যাচাইকরণ হলো এমন একজন ইস্যুয়্যার খোঁজা যাকে ক্লায়েন্ট ইতিমধ্যে বিশ্বাস করে, এবং একটি CA ইনস্টল করার মাধ্যমেই ইস্যুয়্যার সেই স্থানে পৌঁছায় যেখানে ক্লায়েন্ট অনুসন্ধান চালায়।
kill %1 ব্যবহার করে টেস্ট সার্ভারটি বন্ধ করুন।
কেন /etc/ssl/certs ডিরেক্টরিতে আপনার ফাইল রাখা উচিত নয়
/etc/ssl/certs হলো জেনারেট করা আউটপুট। update-ca-certificates এটিকে আসল সার্টিফিকেট ফাইলগুলোর সিম্বলিক লিঙ্ক (symlinks) দিয়ে পূর্ণ করে এবং সেগুলোর পাশে /etc/ssl/certs/ca-certificates.crt নামে একটি কনক্যাটেনেটেড বান্ডেল ফাইল তৈরি করে।
আপনি নিজে থেকে এই ডিরেক্টরিতে কোনো সার্টিফিকেট কপি করলে তা কোনো কিছুতেই খুঁজে পাবে না। OpenSSL-এর ডিরেক্টরি লুকআপ শুধুমাত্র সার্টিফিকেটের সাবজেক্ট হ্যাশ (subject hash) অনুযায়ী নাম রাখা ফাইলগুলোই ওপেন করে, তাই myca.crt নামের কোনো ফাইল এর কাছে অদৃশ্য। Ubuntu-তে curl এই বান্ডেল ফাইলটি পড়ে এবং বান্ডেলটি নিবন্ধিত উৎসগুলো থেকে পুনরায় তৈরি করা হয়, তাই আপনার কপি করা ফাইলটি সেই পাথেও থাকে না। আপনি যদি update-ca-certificates --fresh চালান, তবে ডিরেক্টরির সিম্বলিক লিঙ্কগুলো মুছে ফেলে পুনরায় তৈরি করা হয়, যার ফলে আপনার হাতে তৈরি করা লিঙ্কগুলোও মুছে যায়।
এই বিভাজনের অন্য অংশটি হলো /usr/share/ca-certificates, যা ca-certificates প্যাকেজের অন্তর্ভুক্ত এবং /etc/ca-certificates.conf ফাইলে তালিকাভুক্ত থাকে। প্যাকেজ আপডেট হলে এটি পুনরায় লেখা হয়। /usr/local/share/ca-certificates হলো লোকাল অ্যাডমিনিস্ট্রেটরের জন্য সংরক্ষিত ডিরেক্টরি, তাই আপনার CA সার্টিফিকেটটি প্যাকেজ ম্যানেজমেন্টের যেকোনো আপগ্রেড থেকে সুরক্ষিত থাকে।
কোন প্রোগ্রামগুলো সিস্টেম ট্রাস্ট স্টোর উপেক্ষা করে
রুট সার্টিফিকেট ইনস্টল করলে OpenSSL ব্যবহারকারী বা /etc/ssl/certs ফাইলটি পড়ে এমন প্রতিটি প্রোগ্রাম ঠিক হয়ে যায়। এর মধ্যে রয়েছে curl, wget, git, পাইথনের স্ট্যান্ডার্ড ssl মডিউল এবং Go প্রোগ্রামগুলো, যা লিনাক্সে সিস্টেম ফাইলগুলো পড়ে। যেসব রানটাইম নিজস্ব সার্টিফিকেট তালিকা ব্যবহার করে, সেগুলো এতে প্রভাবিত হয় না; আর সফলভাবে ইনস্টল করার পরেও বেশিরভাগ বিভ্রান্তি এখান থেকেই তৈরি হয়।
- Node.js একটি কম্পাইল-ইন তালিকা ব্যবহার করে। আপনার রুট সার্টিফিকেটটিকে
NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/example-internal-root.crtএনভায়রনমেন্ট ভেরিয়েবলের মাধ্যমে নির্দেশ করুন, যা প্রসেস শুরুর আগেই সেট করতে হবে, কারণ Node স্টার্টআপের সময় একবারই এই ভেরিয়েবলটি পড়ে। বর্তমান Node রিলিজগুলোতে সিস্টেম স্টোর পড়ার একটি অপশনও আছে; আপনার ভার্সনে এটি আছে কি না তা দেখতেnode --help | grep -i system-caচালান। - পাইথনের
requestsলাইব্রেরিcertifiবান্ডেল ব্যবহার করে। সেই প্রসেসের জন্যREQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crtসেট করুন অথবা কলেverify="/etc/ssl/certs/ca-certificates.crt"পাস করুন। একই কারণেpip-এর জন্য--certপ্রয়োজন হয়। - Java একটি কি-স্টোর (keystore) পড়ে। উবুন্টুতে
ca-certificates-javaপ্যাকেজটি/etc/ca-certificates/update.d/-এর অধীনে একটি হুক ইনস্টল করে, তাই সেই প্যাকেজটি থাকলেupdate-ca-certificatesজাভা কি-স্টোরকেও রিফ্রেশ করে। এটি না থাকলে,keytool -importcertব্যবহার করে রুট সার্টিফিকেট ইমপোর্ট করুন। - Firefox নিজস্ব স্টোর ব্যবহার করে এবং কখনোই
/etc/ssl/certs-এর দিকে তাকায় না। এর সার্টিফিকেট সেটিংসের মাধ্যমে ইমপোর্ট করুন। লিনাক্সে Chromium একটি প্রতি-ব্যবহারকারী NSS ডেটাবেস পড়ে, যা আপনিlibnss3-toolsপ্যাকেজেরcertutilব্যবহার করে এডিট করতে পারেন। - কন্টেইনারগুলোর নিজস্ব ফাইলসিস্টেম থাকে, তাই হোস্টের স্টোর সেগুলোর ভেতরে কোনো কাজে আসে না। ইমেজ তৈরির সময় রুট সার্টিফিকেটটি কপি করুন এবং
update-ca-certificatesচালান। আপনার সার্ভিসগুলো যদি Docker Compose on a VPS-এ চলে, তবে সে অনুযায়ী পরিকল্পনা করুন।
পরিষ্কারভাবে ইনস্টল করার পরেও কোনো প্রোগ্রাম যদি সার্টিফিকেট গ্রহণ না করে, তবে অন্য কিছু পরিবর্তন করার আগে দেখুন সেটি কোন ফাইলগুলো ওপেন করছে। strace -f -e trace=openat <command> 2>&1 | grep -i cert একটি সরাসরি টুল, যা একবারে আপনার প্রশ্নের উত্তর দিয়ে দেবে।
সময়ের সাথে CA-কে ব্যবহারযোগ্য রাখা
একটি leaf certificate পুনরায় ইস্যু করার অর্থ হলো CSR ধাপ এবং signing ধাপটি পুনরায় সম্পন্ন করা, যেখানে একই app.ext ফাইল ব্যবহার করা হয়। ক্লায়েন্টদের কোনো পদক্ষেপ নিতে হয় না, কারণ তারা যে root-কে বিশ্বাস করে তা পরিবর্তিত হয়নি। CA ডিরেক্টরিতে ca.srl এবং প্রতিটি .ext ফাইল সংরক্ষণ করুন, যাতে পরবর্তী ইস্যু করার সময় নতুন করে কিছু মনে করার প্রয়োজন না হয়, বরং আগে কাজ করা কমান্ডটিই পুনরায় চালানো যায়।
ca.key এবং ca.crt-এর ব্যাকআপ মেশিনের বাইরে কোথাও রাখুন এবং অবশ্যই তা এনক্রিপ্ট করা অবস্থায় রাখুন। key হারিয়ে ফেললে আপনি নতুন কিছু ইস্যু করতে পারবেন না: সেক্ষেত্রে আপনাকে একটি দ্বিতীয় CA তৈরি করতে হবে এবং প্রথমটি যেখানে যেখানে ইনস্টল করেছিলেন, সেখানে নতুন root ইনস্টল করতে হবে। কোন কোন মেশিন এবং কোন কোন অ্যাপ্লিকেশন স্টোরে root ইনস্টল করা হয়েছে তার একটি লিখিত তালিকা রাখুন, কারণ এই তালিকাটিই rotation এবং removal-এর জন্য অপরিহার্য।
যখন root-এর মেয়াদ শেষ হওয়ার সময় ঘনিয়ে আসে, তখন আগেই নতুন root তৈরি করুন এবং দুটি root-ই পাশাপাশি ইনস্টল করুন। স্টোরে দুটি root থাকা কোনো সমস্যা নয় এবং ক্লায়েন্ট যেকোনো একটি গ্রহণ করবে। নতুন root-এর বিপরীতে leaf certificate-গুলো পুনরায় ইস্যু করুন এবং কোনো কিছুর ওপর পুরনো root-এর নির্ভরতা না থাকলে সেটি সরিয়ে ফেলুন।
ট্রাস্ট স্টোর থেকে একটি CA অপসারণ করা
sudo rm /usr/local/share/ca-certificates/example-internal-root.crt
sudo update-ca-certificates --fresh--fresh কমান্ডটি /etc/ssl/certs ডিরেক্টরি থেকে সিমলিঙ্কগুলো মুছে ফেলে এবং অবশিষ্ট সোর্সগুলো থেকে সেগুলোকে পুনরায় তৈরি করে, ফলে মুছে ফেলা রুট সার্টিফিকেটটি ডিরেক্টরি এবং বান্ডেল উভয় জায়গা থেকেই সরে যায়। যেভাবে ইনস্টলেশন যাচাই করেছিলেন, একইভাবে অপসারণটিও যাচাই করুন।
openssl verify app.crt
echo $?
grep -c 'BEGIN CERTIFICATE' /etc/ssl/certs/ca-certificates.crt
ls -l /etc/ssl/certs/$(openssl x509 -noout -subject_hash -in ~/ca/ca.crt).0যাচাইকরণ প্রক্রিয়াটি পুনরায় ব্যর্থ হবে, সার্টিফিকেটের সংখ্যা আগের অবস্থায় ফিরে আসবে এবং হ্যাশ সিমলিঙ্কটি আর থাকবে না।
এই কমান্ডটি শুধুমাত্র সিস্টেম স্টোরে পরিবর্তন আনে, অন্য কোথাও নয়। অন্যান্য প্রতিটি জায়গা থেকে ইনস্টলেশনটি ম্যানুয়ালি বাতিল করুন: NODE_EXTRA_CA_CERTS পরিষ্কার করুন, যেকোনো Java keystore থেকে অ্যালিয়াসটি মুছে ফেলুন, প্রতিটি ব্রাউজার প্রোফাইল থেকে রুট সার্টিফিকেটটি সরিয়ে ফেলুন এবং যে কন্টেইনার ইমেজে এটি অন্তর্ভুক্ত ছিল তা পুনরায় বিল্ড করুন। রুট সার্টিফিকেট অপসারণ করলেই এর মাধ্যমে স্বাক্ষরিত সার্টিফিকেটগুলো অবৈধ হয়ে যায় না। যে মেশিনগুলো এখনও এটিকে বিশ্বাস করে, সেগুলোতে সেগুলো বৈধই থাকবে। এই কারণেই একটি প্রাইভেট CA-এর ক্ষেত্রে রুট সার্টিফিকেটটি কোথায় কোথায় ব্যবহার করা হয়েছে তার একটি লিখিত তালিকা রাখা জরুরি। যে CA-কে আপনি পুরোপুরি প্রত্যাহার করতে পারেন না, তা একটি স্থায়ী নিরাপত্তা ঝুঁকি। তাই সেটআপ করার দিনই একটি মেশিনে অপসারণ প্রক্রিয়াটি পরীক্ষা করে দেখুন, যখন আপনার তালিকার দৈর্ঘ্য ছোট থাকে।
FAQ
Ubuntu-তে আমি কোথায় CA certificate রাখব?
/usr/local/share/ca-certificates/ ডিরেক্টরিতে, যেখানে ফাইলের নাম .crt দিয়ে শেষ হবে এবং তাতে PEM কন্টেন্ট থাকবে, এরপর sudo update-ca-certificates কমান্ডটি চালান। এই ডিরেক্টরিটি লোকাল অ্যাডমিনিস্ট্রেটরের জন্য সংরক্ষিত, তাই প্যাকেজ আপগ্রেড করার সময় এটি অপরিবর্তিত থাকে। /usr/share/ca-certificates ডিরেক্টরিটি ca-certificates প্যাকেজের অন্তর্ভুক্ত এবং /etc/ssl/certs ফাইলটি উভয় জায়গা থেকেই তৈরি হয়, তাই এগুলোর কোনোটিতে ফাইল রাখলে তা ওভাররাইট হতে পারে অথবা উপেক্ষা করা হতে পারে।
update-ca-certificates চালানোর পরেও কেন curl সার্টিফিকেট প্রত্যাখ্যান করে?
কারণগুলো ক্রমানুসারে যাচাই করুন। ফাইলের নাম .crt দিয়ে শেষ না হলে অথবা সেটি PEM-এর পরিবর্তে DER ফরম্যাটে থাকলে update-ca-certificates সেটিকে এড়িয়ে যাবে এবং কিছুই যোগ করবে না। সার্টিফিকেটে হোস্টনেমের সাথে মিল আছে এমন কোনো subjectAltName না থাকলে এটি ট্রাস্ট ফেইলিয়র নয়, বরং হোস্টনেম ফেইলিয়র; এটি openssl x509 -noout -ext subjectAltName -in app.crt দিয়ে পরীক্ষা করুন। সার্ভার হয়তো শুধু লিফ সার্টিফিকেট পাঠাচ্ছে, যেখানে একটি ইন্টারমিডিয়েট সার্টিফিকেটও প্রয়োজন। CURL_CA_BUNDLE বা --cacert এনভায়রনমেন্ট ভেরিয়েবলের মাধ্যমে curl-কে অন্য কোনো বান্ডেলের দিকে নির্দেশ করা থাকতে পারে। এছাড়া দীর্ঘ সময় ধরে চলা সার্ভিসগুলো রিস্টার্ট করতে হয়, কারণ অধিকাংশ প্রোগ্রাম একবার চালু হওয়ার সময় ট্রাস্ট স্টোরটি পড়ে নেয়।
সিস্টেম ট্রাস্ট স্টোর কি Firefox, Chrome, Node এবং Java-এর ক্ষেত্রে কাজ করে?
না। curl, wget, git, Python-এর স্ট্যান্ডার্ড ssl মডিউল এবং Go প্রোগ্রামগুলো সিস্টেম ফাইলগুলো পড়ে, তাই update-ca-certificates চালানোর সাথে সাথেই সেগুলো কাজ করে। Firefox নিজস্ব স্টোর ব্যবহার করে। Linux-এ Chromium প্রতিটি ইউজারের জন্য আলাদা NSS ডাটাবেস ব্যবহার করে, যা libnss3-tools প্যাকেজের certutil দিয়ে এডিট করতে হয়। Node.js-এর জন্য NODE_EXTRA_CA_CERTS এনভায়রনমেন্ট ভেরিয়েবলটি আপনার রুট ফাইলের দিকে নির্দেশ করতে হয়। Java একটি কি-স্টোর (keystore) পড়ে, যা ca-certificates-java প্যাকেজ ইনস্টল করা থাকলে update-ca-certificates রিফ্রেশ করে। Python-এর requests লাইব্রেরি certifi ব্যবহার করে এবং এর জন্য REQUESTS_CA_BUNDLE প্রয়োজন।
Ubuntu-এর ট্রাস্ট স্টোর থেকে আমি কীভাবে একটি CA মুছে ফেলব?
/usr/local/share/ca-certificates/ থেকে ফাইলটি মুছে ফেলুন এবং sudo update-ca-certificates --fresh চালান। --fresh অপশনটি /etc/ssl/certs ডিরেক্টরির সিমলিংকগুলো মুছে ফেলে নতুন করে তৈরি করে, ফলে সার্টিফিকেটটি হ্যাশ সিমলিংক এবং ca-certificates.crt বান্ডেল থেকে একই সাথে মুছে যায়। সেই CA দ্বারা স্বাক্ষরিত কোনো সার্টিফিকেটের বিপরীতে openssl verify চালিয়ে এবং এক্সিট স্ট্যাটাস দেখে নিশ্চিত হোন। এরপর অন্য যেসব স্টোরে এটি যোগ করেছিলেন, সেখান থেকেও একইভাবে মুছে ফেলুন, কারণ ওই কমান্ডটি অন্য কোনো স্টোরকে প্রভাবিত করে না।
পাবলিক সাইটের জন্য কি আমি Let's Encrypt-এর পরিবর্তে প্রাইভেট CA ব্যবহার করতে পারি?
না। ভিজিটরের ব্রাউজার আপনার রুট সার্টিফিকেটটি আগে কখনো দেখেনি, তাই এটি একটি ফুল-পেজ ওয়ার্নিং দেখাবে এবং আপনি আপনার নিয়ন্ত্রণাধীন নয় এমন ডিভাইসে রুট সার্টিফিকেট ইনস্টল করতে পারবেন না। প্রাইভেট CA শুধুমাত্র সেই সব নামের জন্য যা আপনার নিজস্ব মেশিনগুলো রিজলভ করে এবং যেসব ক্লায়েন্ট আপনি পরিচালনা করেন। অপরিচিত কেউ ভিজিট করবে এমন যেকোনো সাইটের জন্য পাবলিক CA থেকে সার্টিফিকেট নিন।