TL;DR
Server của bạn đang dùng TLS 1.0 hoặc TLS 1.1. Các trình duyệt hiện đại đã ngừng hỗ trợ cả hai từ đầu năm 2020 — Chrome 84 và Firefox 74 đều đã loại bỏ chúng. Hãy bật TLS 1.2/1.3, tắt các phiên bản cũ, và vấn đề sẽ được giải quyết.
# Nginx — thêm vào server block hoặc http block của bạn
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
Reload Nginx sau khi thay đổi: sudo systemctl reload nginx
Lỗi Này Có Nghĩa Gì
ERR_SSL_VERSION_OR_CIPHER_MISMATCH xuất hiện khi quá trình bắt tay TLS thất bại trước khi một byte nào của trang được truyền đi. Có ba nguyên nhân có thể gây ra lỗi này:
- Server chỉ hỗ trợ TLS 1.0 hoặc TLS 1.1. Chrome 84 (tháng 8/2020) và Firefox 74 (tháng 3/2020) đều đã loại bỏ hỗ trợ cho các phiên bản này.
- Tất cả cipher suite trên server bị coi là không an toàn và đã bị loại khỏi các client hiện đại.
- Common Name của chứng chỉ SSL không khớp với tên miền — ít phổ biến hơn, nhưng vẫn gây ra cùng một mã lỗi.
Chín trong mười trường hợp là do server được cấu hình từ năm 2014 và chưa bao giờ được cập nhật lại. Config cũ, trình duyệt mới, bắt tay thất bại.
Kiểm Tra Cấu Hình TLS Hiện Tại
Trước khi chỉnh sửa bất cứ thứ gì, hãy xem server của bạn đang quảng bá giao thức nào:
# Từ bất kỳ máy Linux nào có cài openssl
openssl s_client -connect yourdomain.com:443 -tls1
openssl s_client -connect yourdomain.com:443 -tls1_1
openssl s_client -connect yourdomain.com:443 -tls1_2
openssl s_client -connect yourdomain.com:443 -tls1_3
Nếu -tls1 hoặc -tls1_1 kết nối thành công nhưng -tls1_2 thất bại — đó chính là vấn đề của bạn. Để xem chi tiết ở mức cipher, nmap nhanh hơn:
nmap --script ssl-enum-ciphers -p 443 yourdomain.com
Muốn xem báo cáo đầy đủ có chấm điểm? Chạy SSL Labs Server Test (tìm kiếm "ssllabs server test"). Công cụ này liệt kê mọi giao thức được hỗ trợ và đánh dấu những giao thức lỗi thời bằng chữ F màu đỏ nổi bật.
Sửa Trên Nginx
Mở file config Nginx — thường là /etc/nginx/nginx.conf hoặc file site trong thư mục /etc/nginx/sites-available/. Tìm SSL block và thay thế bằng:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# Thay thế dòng ssl_protocols hiện có bằng dòng này:
ssl_protocols TLSv1.2 TLSv1.3;
# Danh sách cipher hiện đại — loại bỏ cipher yếu
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
}
# Kiểm tra config, sau đó reload
nginx -t
sudo systemctl reload nginx
Sửa Trên Apache
Chỉnh sửa file virtual host hoặc /etc/apache2/mods-enabled/ssl.conf. Chỉ thị quan trọng là SSLProtocol — dấu trừ trước tên giao thức sẽ tắt rõ ràng các phiên bản cũ:
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
# Tắt các giao thức cũ
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# Chỉ dùng cipher suite hiện đại
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
</VirtualHost>
# Kiểm tra và khởi động lại
apache2ctl configtest
sudo systemctl restart apache2
Sửa Trên Node.js (HTTPS server)
Đang chạy HTTPS server tùy chỉnh bằng Node.js? Truyền các tùy chọn TLS trực tiếp vào lệnh gọi createServer:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
minVersion: 'TLSv1.2', // từ chối mọi kết nối dưới TLS 1.2
ciphers: [
'ECDHE-RSA-AES128-GCM-SHA256',
'ECDHE-RSA-AES256-GCM-SHA384',
'ECDHE-RSA-CHACHA20-POLY1305',
].join(':'),
};
https.createServer(options, app).listen(443);
Khi Bạn Là Client, Không Phải Server
Đang gọi API của bên thứ ba và gặp lỗi này? Server từ xa đang có vấn đề — server của bạn hoàn toàn bình thường. Các lựa chọn của bạn:
- Liên hệ nhà cung cấp API. Yêu cầu họ bật TLS 1.2. Đó mới là cách sửa thực sự.
- Nếu bạn cần giải pháp tạm thời cho các hệ thống nội bộ trong khi chờ đợi, bạn có thể giới hạn HTTP client của mình chỉ dùng TLS 1.2 một cách tường minh:
# Python requests — ép dùng TLS 1.2 tối thiểu qua custom adapter
import ssl
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.ssl_ import create_urllib3_context
class TLS12Adapter(HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
ctx = create_urllib3_context()
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
kwargs['ssl_context'] = ctx
super().init_poolmanager(*args, **kwargs)
session = requests.Session()
session.mount('https://', TLS12Adapter())
response = session.get('https://old-api.example.com/endpoint')
Không hạ cấp client của bạn để chấp nhận TLS 1.0/1.1 trong môi trường production. Làm vậy sẽ phá vỡ hoàn toàn mục đích bảo mật.
Kiểm Tra Phiên Bản OpenSSL
TLS 1.3 yêu cầu OpenSSL 1.1.1 trở lên. Phiên bản cũ hơn thì TLS 1.3 đơn giản là không khả dụng, bất kể bạn cấu hình gì trong nginx.conf.
openssl version
# Cần ít nhất OpenSSL 1.1.1 để hỗ trợ TLS 1.3
Đang dùng OpenSSL 1.0.x? Nâng cấp thư viện trước, sau đó mới cập nhật config server:
# Trên Debian/Ubuntu
sudo apt update && sudo apt install openssl libssl-dev
# Trên CentOS/RHEL 8+
sudo dnf install openssl
Xác Minh Kết Quả Sửa Lỗi
# Xác nhận TLS 1.2 hoạt động
openssl s_client -connect yourdomain.com:443 -tls1_2
# Kết quả mong đợi: SSL handshake has read ... bytes
# Tìm dòng: Protocol: TLSv1.2
# Xác nhận TLS cũ bị từ chối
openssl s_client -connect yourdomain.com:443 -tls1_1
# Kết quả mong đợi: lỗi alert handshake failure hoặc tương tự
# Xác nhận TLS 1.3 hoạt động (nếu được hỗ trợ)
openssl s_client -connect yourdomain.com:443 -tls1_3
Mở trang web trên Chrome. Lỗi sẽ biến mất và biểu tượng ổ khóa sẽ xuất hiện. Nhấp vào đó → Kết nối an toàn → Chứng chỉ hợp lệ để xác nhận phiên bản giao thức đang được sử dụng.
CN Chứng Chỉ Không Khớp (Cùng Lỗi, Nguyên Nhân Khác)
Tên miền không khớp cũng kích hoạt lỗi ERR_SSL_VERSION_OR_CIPHER_MISMATCH trên một số trình duyệt — khó hiểu ở chỗ đây là cùng một mã lỗi. Kiểm tra bằng lệnh:
openssl s_client -connect yourdomain.com:443 | openssl x509 -noout -subject -subj_hash
# subject= CN=yourdomain.com
# Hoặc kiểm tra SAN
openssl s_client -connect yourdomain.com:443 | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
CN hoặc ít nhất một mục SAN phải khớp với tên miền bạn đang kết nối. Nếu không có mục nào khớp, hãy cấp lại chứng chỉ cho đúng tên miền.

