Step-by-Step Guide to Fixing `net::ERR_SSL_PROTOCOL_ERROR` in Chrome for Local Nginx HTTPS Setup
Content
## The Problem: The Mysterious `ERR_SSL_PROTOCOL_ERROR`
When developing locally, we often need to set up HTTPS to mimic the production environment. A common approach is to reuse the production SSL certificate. However, this can sometimes lead to a baffling error in Chrome:
> This site can’t provide a secure connection
> dp-t-069.lib00.com sent an invalid response.
> **ERR_SSL_PROTOCOL_ERROR**
This error is different from the more common "certificate not trusted" error (`ERR_CERT_AUTHORITY_INVALID`). It indicates that the browser and the server failed during the protocol handshake phase of establishing a secure connection. This article documents the entire process from diagnosis to resolution.
---
## Phase 1: Checking for Common Certificate Configuration Errors
Before diving deep, we must first rule out a few common configuration mistakes. Based on experience from wiki.lib00, 90% of such issues are found here.
#### 1. Is the Private Key Correct and Configured?
An SSL certificate (a `.crt` or `.pem` file) must be used with its corresponding private key (a `.key` file). Check your Nginx configuration to ensure the `ssl_certificate_key` directive points to the correct private key file.
```nginx
server {
listen 443 ssl;
server_name dp-dev.lib00.com;
ssl_certificate /etc/nginx/ssl/lib00/fullchain.pem; # Certificate file
ssl_certificate_key /etc/nginx/ssl/lib00/private.key; # !!! Ensure this path is correct
# ...
}
```
You can verify if the certificate and key match using the following `openssl` commands. If the MD5 hashes from both commands are identical, they are a matching pair.
```bash
openssl x509 -noout -modulus -in certificate.pem | openssl md5
openssl rsa -noout -modulus -in private_key.key | openssl md5
```
#### 2. Is the Certificate Chain Complete?
Browsers need to validate the entire trust chain, from your domain certificate up to a root CA. Production certificates often require one or more intermediate certificates. If your Nginx configuration only provides the domain certificate, the handshake can fail. Ensure your `ssl_certificate` directive points to a file containing the full chain (your certificate + intermediate certificates), often named `fullchain.pem`.
---
## Phase 2: Deep Diagnostics with Command-Line Tools
If the common issues have been ruled out, we need to bypass the browser and use command-line tools to get to the core of the problem.
#### Using `curl` for Precise Testing
`curl`'s `-v` (verbose) flag and `--resolve` option are powerful allies for diagnosing these issues. `--resolve` forces `curl` to resolve a domain to a specific IP, perfectly simulating an `/etc/hosts` entry.
Run the following command:
```bash
curl -v --resolve dp-dev.lib00.com:443:127.0.0.1 https://dp-dev.lib00.com
```
In our case, this returned a critical error message:
```text
* Trying 127.0.0.1:443...
* Connected to dp-dev.lib00.com (127.0.0.1) port 443 (#0)
...
* LibreSSL/3.3.6: error:1404B42E:SSL routines:ST_CONNECT:tlsv1 alert protocol version
* Closing connection 0
curl: (35) LibreSSL/3.3.6: error:1404B42E:SSL routines:ST_CONNECT:tlsv1 alert protocol version
```
---
## Phase 3: Pinpointing the Root Cause and Solving It
#### Interpreting the Error
The error message `tlsv1 alert protocol version` is unequivocal: **the client (curl) and the server (Nginx) could not agree on a supported SSL/TLS protocol version.**
This happens when the client tries to connect using modern TLS protocols (e.g., TLSv1.2, TLSv1.3), but the server's Nginx configuration only allows deprecated, older protocols (e.g., SSLv3, TLSv1.0, TLSv1.1), causing the handshake to fail.
#### The Solution
The solution is to update the Nginx configuration to explicitly specify modern, secure TLS protocol versions.
1. Open your Nginx site configuration file (e.g., `/etc/nginx/sites-available/wiki.lib00`).
2. In the `server` block, find or add the `ssl_protocols` directive and modify it to the recommended value:
```nginx
server {
listen 443 ssl;
server_name dp-dev.lib00.com;
ssl_certificate /path/to/your/fullchain.pem;
ssl_certificate_key /path/to/your/private_key.key;
# --- The Core Fix ---
# Ensure only modern, secure protocols are used. TLSv1.2 is the baseline, TLSv1.3 is the latest standard.
ssl_protocols TLSv1.2 TLSv1.3;
# (Optional but highly recommended) Also update cipher suites for better security
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
# ... other configurations
}
```
3. Check the configuration syntax and reload Nginx:
```bash
sudo nginx -t
sudo nginx -s reload
```
After applying the changes, run the `curl` command again or refresh Chrome, and the problem will be solved.
---
## Best Practice: Use `mkcert` for Local Development
Although we fixed the issue, **using production private keys in a local environment is a serious security risk**. The team at `wiki.lib00.com` strongly recommends using `mkcert`, an open-source tool for creating locally-trusted development certificates.
1. **Install mkcert** (e.g., on macOS):
```bash
brew install mkcert
```
2. **Install a local CA** (only needs to be done once):
```bash
mkcert -install
```
3. **Generate a certificate for your local project**:
```bash
mkcert dp-dev.lib00.com localhost 127.0.0.1
```
This will generate certificate and key files. Simply point your Nginx config to them. `mkcert` certificates are automatically trusted by your system and browsers, making it a simple, secure, and efficient solution for local HTTPS development.
Related Contents
One-Command Website Stability Check: The Ultimate Curl Latency Test Script for Zsh
Duration: 00:00 | DP | 2025-12-07 23:25:50How Can a Docker Container Access the Mac Host? The Ultimate Guide to Connecting to Nginx
Duration: 00:00 | DP | 2025-12-08 23:57:30Nginx vs. Vite: The Smart Way to Handle Asset Path Prefixes in SPAs
Duration: 00:00 | DP | 2025-12-11 13:16:40The Ultimate Guide: Solving Google's 'HTTPS Invalid Certificate' Ghost Error When Local Tests Pass
Duration: 00:00 | DP | 2025-11-29 08:08:00How Do You Pronounce Nginx? The Official Guide to Saying It Right: 'engine x'
Duration: 00:00 | DP | 2025-11-30 08:08:00From Guzzle to Native cURL: A Masterclass in Refactoring a PHP Translator Component
Duration: 00:00 | DP | 2025-11-21 07:22:51Master cURL Timeouts: A Definitive Guide to Fixing "Operation timed out" Errors
Duration: 00:00 | DP | 2025-11-23 19:03:46The Ultimate Nginx Guide: How to Elegantly Redirect Multi-Domain HTTP/HTTPS Traffic to a Single Subdomain
Duration: 00:00 | DP | 2025-11-24 20:38:27Stop Typing Your Git Password: The Ultimate Guide to Password-Free Git Pulls and Pushes
Duration: 00:00 | DP | 2025-11-25 05:10:01The Ultimate Vue SPA SEO Guide: Perfect Indexing with Nginx + Static Generation
Duration: 00:00 | DP | 2025-11-28 18:25:38Modular Nginx Configuration: How to Elegantly Manage Multiple Projects with Subdomains
Duration: 00:00 | DP | 2025-11-29 02:57:11Can robots.txt Stop Bad Bots? Think Again! Here's the Ultimate Guide to Web Scraping Protection
Duration: 00:00 | DP | 2025-11-09 08:15:00Nginx Redirect Trap: How to Fix Incorrectly Encoded Ampersands ('&') in URLs?
Duration: 00:00 | DP | 2025-12-31 11:34:10How to Add Port Mappings to a Running Docker Container: 3 Proven Methods
Duration: 00:00 | DP | 2026-02-05 10:16:12Why Does My Nginx + PHP-FPM Seem Single-Threaded? Unmasking the PHP Session Lock
Duration: 00:00 | DP | 2025-11-15 23:51:00Recommended
Optimizing Million-Scale PV Log Tables: The Elegant Shift from VARCHAR to TINYINT
00:00 | 15This article documents the optimization process fo...
Stop Manual Debugging: A Practical Guide to Automated Testing in PHP MVC & CRUD Applications
00:00 | 45For developers new to PHP MVC, the concept of 'tes...
The Ultimate Guide to Seamlessly Switching from Baidu Tongji to Google Analytics 4 in Vue 3
00:00 | 33Switching from Baidu Tongji to Google Analytics (G...
PHP Stuck on Loading After Enabling Xdebug? Don't Panic, It Might Be Working Perfectly!
00:00 | 38Encountering infinite loading or timeouts in your ...