Thêm CA riêng vào trust store của Ubuntu
Tạo CA riêng bằng openssl, ký leaf certificate và cài root vào /usr/local/share/ca-certificates để Ubuntu tin cậy HTTPS nội bộ, không còn lỗi xác minh.
Thêm CA riêng vào trust store của Ubuntu
Để thêm CA riêng vào trust store của Ubuntu, hãy sao chép chứng chỉ root vào /usr/local/share/ca-certificates/ với tên kết thúc bằng .crt, sau đó chạy sudo update-ca-certificates. CA (certificate authority) là một cặp key có chứng chỉ được phép ký các chứng chỉ khác. Khi máy đã tin cậy root của bạn, mọi chứng chỉ do root đó ký đều được chấp nhận. Vì vậy, HTTPS giữa các service của bạn sẽ không còn fail khi xác minh.
Hướng dẫn này tạo toàn bộ chain offline bằng openssl. Bạn tạo root key và root certificate, cấp một leaf certificate cho server, sau đó cài root và theo dõi cùng một lệnh xác minh thay đổi kết quả. Thứ tự này rất quan trọng: xác minh trước và sau khi cài đặt cho thấy chính việc cài đặt đã thay đổi kết quả.
Ubuntu 24.04 có sẵn OpenSSL 3 và package ca-certificates trên image mặc định, nên trước tiên không cần cài thêm gì (đã kiểm tra vào August 2026).
Khi nào nên tự vận hành CA?
Một CA công khai như Let's Encrypt cần một tên trong DNS công khai và một máy chủ mà CA có thể truy cập. Tên nội bộ không đáp ứng điều kiện này. Database trên mạng riêng hoặc admin panel chỉ bind vào một tunnel không thể nhận certificate công khai. Bạn cũng không nên expose chúng ra Internet chỉ để lấy certificate.
Certificate tự ký trên Ubuntu chỉ giải quyết được một host. Mọi client phải trust certificate đó. Khi thêm host tiếp theo, bạn lại phải thực hiện lại các bước tương tự. Private CA đưa quyết định trust lên một cấp. Client chỉ cần trust root một lần. Sau đó, mọi certificate do root ký đều được trust, kể cả certificate dành cho những host chưa tồn tại.
Chi phí là có thật. Root key có thể ký mọi thứ mà các constraint cho phép. Vì vậy, bất kỳ ai đọc được ca.key đều có thể issue certificate mà các máy của bạn sẽ accept. Hãy bảo vệ nó giống như cách bạn bảo vệ private key trong quản lý SSH key. Nếu một service có tên DNS công khai, hãy bỏ qua toàn bộ quy trình này và dùng public CA: Certbot với nginx và Let's Encrypt ít tốn công hơn và không cần cài đặt gì ở phía client.
Tạo khóa CA và chứng chỉ root
Làm việc trong một thư mục chỉ tài khoản của bạn có thể mở. Khóa root không bao giờ được rời khỏi thư mục đó.
install -d -m 700 ~/ca
cd ~/ca
openssl genrsa -aes256 -out ca.key 4096
chmod 600 ca.key-aes256 mã hóa khóa bằng passphrase bạn chọn. Mọi lệnh sau này dùng khóa này để ký đều sẽ yêu cầu passphrase đó. Nếu bỏ -aes256, khóa được lưu rõ trên đĩa. Khi đó, chỉ cần có bản sao lưu hoặc tài khoản của một quản trị viên khác là người đó có thể cấp chứng chỉ được các máy của bạn tin cậy.
Bây giờ tạo chứng chỉ root, tức chứng chỉ mà khóa CA dùng để tự ký cho chính nó.
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.crtThay internal.example bằng hậu tố tên bạn thực sự sử dụng. Đọc phần tiếp theo trước khi giữ lại extension cuối cùng đó.
Mỗi extension có một nhiệm vụ.
basicConstraintscùng vớiCA:TRUEbiến chứng chỉ này thành chứng chỉ CA. Nếu thiếu chúng, client sẽ từ chối mọi chứng chỉ do khóa này ký, ngay cả khi chữ ký hợp lệ.pathlen:0cho biết CA được phép ký chứng chỉ leaf, nhưng không được phép ký thêm CA nào bên dưới nó.keyUsagegiới hạn khóa vào việc ký chứng chỉ và danh sách thu hồi, để không thể vô tình dùng cùng khóa này làm khóa TLS server.subjectKeyIdentifiercung cấp cho root một định danh mà các chứng chỉ leaf trỏ ngược về đó. Nhờ vậy, client tìm được issuer phù hợp trong store chứa vài trăm chứng chỉ.nameConstraintsgiới hạn các tên mà CA này được phép xác nhận.
Hãy đọc lại những gì bạn đã tạo, thay vì mặc định rằng lệnh đã thực hiện đúng ý bạn.
openssl x509 -noout -subject -issuer -serial -dates -in ca.crt
openssl x509 -noout -text -in ca.crtSubject và issuer hiển thị cùng một chuỗi, vì chứng chỉ root tự ký. Serial và hai mốc thời gian lấy từ file bạn vừa tạo. Hãy lấy chúng từ kết quả đó, không lấy từ hướng dẫn của người khác.
Giới hạn những tên mà CA được phép ký
Một root trong system store được tin cậy cho mọi tên trên Internet, trừ khi bạn chỉ định khác. Đó là mức quyền rất lớn được lưu trong một file trên một server. nameConstraints giảm phạm vi quyền này. Khi có permitted;DNS:internal.example trong root, chain từ CA này cho một tên nằm ngoài internal.example sẽ bị từ chối dù chữ ký hợp lệ.
Hãy kiểm tra trường hợp đó thay vì tin cậy nó.
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 $?Certificate vẫn được cấp, vì CA của bạn sẽ ký mọi thứ bạn yêu cầu nó ký. Lỗi xảy ra ở bước verification: exit status khác 0 và OpenSSL nêu rõ constraint đã bị vi phạm. Đó là tác dụng của extension này. Ngay cả khi CA key bị đánh cắp, kẻ tấn công vẫn không thể tạo một certificate hoạt động cho tên nằm ngoài subtree. Khi xong việc, hãy xóa các file còn lại bằng rm /tmp/outside.*.
Có 4 điều cần biết trước khi áp dụng constraint. Constraint được đánh dấu critical, nên client không hiểu extension này phải từ chối chain thay vì bỏ qua nó. Đây là hướng an toàn, nhưng có thể gây lỗi với TLS library cũ. Permitted subtree cho DNS name không giới hạn các IP address SAN, vì name type không có subtree tương ứng vẫn không bị giới hạn. Do đó, hãy thêm permitted;IP:10.0.0.0/255.255.0.0 trong cùng extension nếu certificate của bạn chứa IP address. Subtree phải bao phủ mọi tên mà bạn có thể cấp certificate trong tương lai, bao gồm cả short hostname. Vì vậy, certificate cho tên trần app sẽ không vượt qua kiểm tra với ví dụ trên. Constraint được ghi cố định vào root, nên nếu đổi ý, bạn phải tạo root certificate mới và cài lại trên mọi client.
Phát hành leaf certificate do CA ký
Leaf certificate là certificate mà server cung cấp cho client. Trước tiên, tạo private key và CSR (certificate signing request) riêng cho certificate này. CSR chứa public key và tên được yêu cầu, đồng thời được ký bằng leaf key để chứng minh bên yêu cầu đang giữ phần private key.
openssl req -new -newkey rsa:2048 -nodes \
-keyout app.key -out app.csr \
-subj "/CN=app.internal.example"
chmod 600 app.keyCác tên cần dùng phải nằm trong file extension, không nằm trong CSR. Client đối chiếu hostname với subjectAltName (SAN) và hoàn toàn bỏ qua common name. Vì vậy, certificate có CN nhưng không có SAN sẽ không vượt qua bước xác minh hostname trên mọi client hiện nay, bất kể CN chứa gì.
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:app.internal.example, DNS:api.internal.example
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:alwaysLưu nội dung đó vào app.ext, sau đó dùng CA để ký request.
openssl x509 -req -in app.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-days 397 -sha256 -extfile app.ext -out app.crt-CAcreateserial tạo ca.srl bên cạnh CA. File này lưu serial number tiếp theo để không có hai certificate nào do CA này phát hành dùng chung một serial number. Giữ file đó trong thư mục CA. -days 397 là lựa chọn cấu hình, không phải giới hạn của công cụ. Ở đây, thời hạn ngắn quan trọng hơn so với khi dùng public CA, vì private CA không có hạ tầng thu hồi certificate. Sẽ không có CRL hoặc OCSP responder nếu bạn không tự xây dựng, nên leaf key bị lộ vẫn có thể được sử dụng cho đến khi certificate hết hạn.
Kiểm tra kết quả trước khi đưa certificate vào trust store.
openssl x509 -noout -subject -issuer -serial -dates -in app.crt
openssl x509 -noout -ext subjectAltName -in app.crtDòng issuer hiện ghi tên CA thay vì chính leaf certificate. Dòng SAN liệt kê các tên mà certificate này hợp lệ cho, và client chỉ đối chiếu với danh sách đó, không đối chiếu với thông tin nào khác.
Xác minh bằng -CAfile tường minh trước khi cài đặt bất kỳ thứ gì
openssl verify -CAfile ca.crt app.crt
echo $?Lệnh này chỉ trả lời một câu hỏi cụ thể: app.crt có nối được đến chứng chỉ trong ca.crt không? Kết quả không cho biết máy này tin cậy những gì, vì bạn đã truyền root cho OpenSSL ngay trên command line. Nếu bước này thất bại, vấn đề nằm ở chính các chứng chỉ. Hãy sửa lỗi trước khi tiếp tục.
Bây giờ hãy kiểm tra bằng trust store của máy.
openssl verify app.crt
echo $?Khi không có -CAfile, OpenSSL sử dụng thư mục chứng chỉ tích hợp sẵn. openssl version -d in ra thư mục cơ sở mà bản build của bạn sử dụng. Trên Ubuntu, thư mục certs bên dưới đó trỏ đến /etc/ssl/certs. Root của bạn chưa nằm trong thư mục này, nên bước xác minh thất bại: chain đi đến một issuer không có trong store và không còn nơi nào khác để tìm. Hãy ghi lại exit status. Đây là giá trị sẽ thay đổi sau 2 bước nữa.
Một client thực sẽ là phép kiểm tra tốt hơn openssl verify, vì nó kiểm tra cả hostname và chain. Hãy cung cấp chứng chỉ rồi tải nó xuống.
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 kết nối đến 127.0.0.1 nhưng vẫn yêu cầu app.internal.example, nên SAN khớp và vấn đề duy nhất còn lại là trust. curl thất bại và in ra lý do nó không thể xác minh chain. Thêm -v để xem chi tiết hơn. Giữ test server tiếp tục chạy.
Cài root vào /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-certificatesCác chi tiết quyết định việc này có hoạt động hay không:
- Tên file phải kết thúc bằng
.crt. Trang hướng dẫn sử dụngupdate-ca-certificatesnêu rằng các certificate có phần mở rộng.crtnằm bên dưới/usr/local/share/ca-certificatessẽ được đưa vào và mặc định được tin cậy. File có tênroot.pemhoặcroot.cersẽ bị bỏ qua mà không có thông báo. - Nội dung phải ở định dạng PEM, tức là block base64 nằm giữa các dòng
BEGIN CERTIFICATEvàEND CERTIFICATE. File DER được đổi tên thành.crtvẫn là dữ liệu nhị phân và sẽ không được đọc. Hãy chuyển đổi bằngopenssl x509 -inform DER -in ca.der -out ca.crt. - Chỉ root được đặt ở đây. CA private key và leaf certificate không thuộc trust store.
update-ca-certificates in ra số certificate đã thêm và đã xóa. Nếu không thêm certificate nào thì nguyên nhân là phần mở rộng hoặc định dạng file.
Hãy xác nhận thay đổi từ phía system thay vì chỉ dựa vào thông báo đó.
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.crtLệnh đầu tiên tạo tên file từ subject hash của chính certificate rồi liệt kê file đó. update-ca-certificates đã tạo symlink này và symlink trỏ ngược về file bạn đã cài đặt. Lệnh thứ hai đếm số certificate trong bundle một file. Hãy chạy lệnh này trước khi cài đặt để theo dõi số lượng tăng thêm một.
Khi sao chép root này sang các máy khác, hãy kiểm tra bản sao đã được truyền nguyên vẹn trước khi cài đặt. Root certificate là loại file mà việc sai nội dung gây hậu quả nghiêm trọng nhất trên system, vì vậy hãy xử lý nó như mọi file tải xuống khác mà bạn sẽ xác minh bằng checksum trước khi sử dụng.
Xác minh lại bằng kho chứng chỉ của hệ thống
openssl verify app.crt
echo $?
curl --resolve app.internal.example:8443:127.0.0.1 https://app.internal.example:8443/Cùng lệnh, cùng file chứng chỉ, nhưng kết quả khác. Không có gì trong app.crt thay đổi, và server vẫn là server bạn đã khởi động trước đó. Điểm khác biệt duy nhất là root CA hiện đã nằm trong kho chứng chỉ mà các client đó đọc, nên chain có thể hoàn tất. Đây là cơ chế cần ghi nhớ: quá trình xác minh tìm một issuer mà client đã tin cậy, còn cài đặt CA là cách đưa issuer đó vào nơi client tìm kiếm.
Dừng test server bằng kill %1.
Vì sao /etc/ssl/certs không phải nơi bạn đặt file
/etc/ssl/certs là output được tạo tự động. update-ca-certificates tạo các symlink trong đó, trỏ về các file certificate thực tế, rồi ghi bundle đã nối /etc/ssl/certs/ca-certificates.crt ngay bên cạnh.
Một certificate bạn tự copy vào directory đó sẽ không được thành phần nào tìm thấy. Cơ chế tìm kiếm theo directory của OpenSSL chỉ mở các file có tên dựa trên subject hash của certificate, nên file tên myca.crt sẽ bị bỏ qua. curl trên Ubuntu đọc file bundle, còn bundle được tạo lại từ các nguồn đã đăng ký, nên bản copy của bạn cũng không nằm trong đường dẫn đó. Chạy update-ca-certificates --fresh sẽ xóa và tạo lại các symlink trong directory, nên mọi link bạn tự tạo cũng bị xóa theo.
Phần còn lại của cách phân chia này là /usr/share/ca-certificates. Nó thuộc package ca-certificates và được liệt kê trong /etc/ca-certificates.conf. Các bản cập nhật package sẽ ghi lại file này. /usr/local/share/ca-certificates là directory dành riêng cho quản trị viên hệ thống, nên CA của bạn vẫn còn sau mỗi lần nâng cấp package quản lý phần còn lại.
Chương trình nào bỏ qua trust store của hệ thống
Việc cài root certificate sẽ sửa lỗi cho mọi chương trình gọi OpenSSL hoặc đọc /etc/ssl/certs. Các chương trình này gồm curl, wget, git, module ssl chuẩn của Python và các chương trình Go, vì chúng đọc các file hệ thống trên Linux. Các runtime có danh sách certificate riêng sẽ không bị ảnh hưởng. Đây là nguyên nhân chính gây nhầm lẫn sau khi cài đặt thành công.
- Node.js sử dụng danh sách được tích hợp sẵn. Trỏ Node.js đến root certificate bằng
NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/example-internal-root.crtvà đặt biến này trong môi trường trước khi process khởi động, vì Node chỉ đọc biến một lần khi startup. Các bản phát hành Node hiện tại cũng có tùy chọn đọc system store. Chạynode --help | grep -i system-cađể kiểm tra phiên bản của bạn có tùy chọn này hay không. - Thư viện
requestscủa Python sử dụng bundlecertifi. ĐặtREQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crtcho process đó hoặc truyềnverify="/etc/ssl/certs/ca-certificates.crt"vào lời gọi.pipcũng nhận--certvì cùng lý do. - Java đọc keystore. Trên Ubuntu, package
ca-certificates-javacài một hook tại/etc/ca-certificates/update.d/, nênupdate-ca-certificatescũng refresh Java keystore khi package đó có mặt. Nếu không có package này, hãy import root certificate bằngkeytool -importcert. - Firefox giữ store riêng và không bao giờ đọc
/etc/ssl/certs. Hãy import certificate thông qua phần cài đặt certificate của Firefox. Chromium trên Linux đọc NSS database riêng của từng user. Bạn chỉnh database này bằngcertutiltừ packagelibnss3-tools. - Container có filesystem riêng, nên store của host không có tác dụng bên trong container. Copy root certificate vào image và chạy
update-ca-certificatestrong quá trình build. Hãy tính đến điều này nếu các service của bạn chạy bằng Docker Compose trên VPS.
Khi chương trình vẫn từ chối certificate sau khi cài đặt đúng, hãy xác định trước nó mở những file nào rồi mới thay đổi thêm. strace -f -e trace=openat <command> 2>&1 | grep -i cert khá trực tiếp và trả lời câu hỏi này chỉ sau một lần chạy.
Duy trì CA có thể sử dụng theo thời gian
Cấp lại chứng chỉ leaf là thực hiện lại bước CSR và bước ký, với cùng tệp app.ext. Client không cần thực hiện thao tác nào, vì root mà chúng tin cậy không thay đổi. Giữ ca.srl và mọi tệp .ext trong thư mục CA để lần cấp tiếp theo chỉ cần chạy lại một command đã hoạt động, thay vì phải dựng lại từ trí nhớ.
Sao lưu ca.key và ca.crt ở một nơi ngoài máy, đồng thời vẫn mã hóa chúng. Nếu mất key, bạn không thể cấp chứng chỉ mới: bạn phải tạo một CA thứ hai và cài root của CA đó trên mọi nơi mà root đầu tiên đã được cài. Lập danh sách bằng văn bản về mọi máy và mọi application store đã nhận root, vì chỉ danh sách đó mới giúp thực hiện việc rotation và gỡ bỏ.
Khi root sắp hết hạn, hãy tạo root thay thế sớm và cài cả hai root song song. Có hai root trong store là bình thường và client chấp nhận một trong hai. Cấp lại các chứng chỉ leaf với root mới, rồi gỡ root cũ sau khi không còn thành phần nào phụ thuộc vào nó.
Xóa CA khỏi kho tin cậy
sudo rm /usr/local/share/ca-certificates/example-internal-root.crt
sudo update-ca-certificates --fresh--fresh xóa các symlink trong /etc/ssl/certs rồi tạo lại chúng từ những nguồn vẫn còn. Vì vậy, root đã xóa sẽ biến mất khỏi cả thư mục và bundle. Xác nhận việc xóa theo cách tương tự như khi xác nhận cài đặt.
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).0Xác minh lại thất bại, số lượng certificate trở về mức ban đầu và symlink hash không còn.
Lệnh đó chỉ tác động đến kho của hệ thống, không tác động đến nơi nào khác. Hãy tự hoàn tác việc cài đặt ở từng nơi còn lại: xóa nội dung của NODE_EXTRA_CA_CERTS, xóa alias khỏi mọi Java keystore, xóa root khỏi từng browser profile và build lại mọi container image đã tích hợp root đó. Việc xóa root cũng không làm các certificate do root ký mất hiệu lực. Chúng vẫn hợp lệ trên mọi máy còn tin cậy root đó. Đây là lý do thực tế khiến private CA cần có danh sách ghi rõ root đã được cài ở đâu. Một CA không thể thu hồi hoàn toàn là một lỗ hổng tồn tại vĩnh viễn. Vì vậy, hãy kiểm tra việc xóa trên một máy ngay trong ngày thiết lập CA, khi danh sách này vẫn còn ngắn.
FAQ
Tôi đặt chứng chỉ CA ở đâu trên Ubuntu?
Đặt trong /usr/local/share/ca-certificates/, dùng tên tệp kết thúc bằng .crt và nội dung PEM, sau đó chạy sudo update-ca-certificates. Thư mục này dành riêng cho quản trị viên local, nên các lần nâng cấp package sẽ không thay đổi nội dung trong đó. /usr/share/ca-certificates thuộc package ca-certificates, còn /etc/ssl/certs được tạo từ cả hai thư mục, nên tệp đặt trong một trong hai thư mục đó sẽ bị ghi đè hoặc bị bỏ qua.
Vì sao curl vẫn từ chối chứng chỉ sau khi chạy update-ca-certificates?
Hãy kiểm tra lần lượt các nguyên nhân. Tệp có thể không kết thúc bằng .crt hoặc có thể ở định dạng DER thay vì PEM. Khi đó update-ca-certificates sẽ bỏ qua tệp và không thêm gì. Chứng chỉ có thể không có subjectAltName khớp với hostname. Đây là lỗi hostname, không phải lỗi tin cậy; hãy kiểm tra bằng openssl x509 -noout -ext subjectAltName -in app.crt. Server có thể chỉ gửi certificate leaf trong khi cần gửi thêm intermediate. curl có thể đang dùng bundle khác được chỉ định bởi CURL_CA_BUNDLE hoặc --cacert. Service chạy lâu cũng cần restart, vì hầu hết chương trình chỉ đọc trust store một lần khi khởi động.
System trust store có áp dụng cho Firefox, Chrome, Node và Java không?
Không. curl, wget, git, module ssl chuẩn của Python và các chương trình Go đọc các tệp hệ thống, nên chúng hoạt động ngay sau khi chạy update-ca-certificates. Firefox dùng store riêng. Chromium trên Linux dùng NSS database theo từng user, được chỉnh sửa bằng certutil thuộc package libnss3-tools. Node.js cần NODE_EXTRA_CA_CERTS trỏ đến tệp root của bạn. Java đọc một keystore; update-ca-certificates chỉ refresh keystore này khi package ca-certificates-java được cài đặt. requests của Python dùng certifi và cần REQUESTS_CA_BUNDLE.
Làm thế nào để xóa CA khỏi trust store của Ubuntu?
Xóa tệp khỏi /usr/local/share/ca-certificates/ rồi chạy sudo update-ca-certificates --fresh. Tùy chọn --fresh xóa các symlink trong /etc/ssl/certs và tạo lại chúng, nên chứng chỉ sẽ đồng thời bị xóa khỏi các hash symlink và bundle ca-certificates.crt. Xác nhận bằng cách chạy openssl verify với một chứng chỉ được CA đó ký, rồi kiểm tra exit status. Sau đó lặp lại việc xóa trong mọi store khác mà bạn đã thêm chứng chỉ, vì lệnh này không tác động đến các store đó.
Tôi có thể dùng CA private thay cho Let's Encrypt cho một public site không?
Không. Trình duyệt của khách truy cập chưa từng biết root của bạn, nên sẽ hiển thị cảnh báo toàn trang. Bạn cũng không thể cài root đó trên những máy mình không kiểm soát. CA private phù hợp với các name chỉ những máy của bạn phân giải được và với các client do bạn quản trị. Với mọi site mà người lạ truy cập, hãy lấy chứng chỉ từ một public CA.