When testing my Nginx 1.11.9 server running on Ubuntu 16.04.1 LTS with OpenSSL 1.0.2g, I encountered the frustrating "No ALPN negotiated" message despite all documentation indicating these versions should support ALPN (Application-Layer Protocol Negotiation). Here's how I dug into the issue:
# Verification command
echo | openssl s_client -alpn h2 -connect example.com:443 | grep ALPN
The key revelation came when examining the Nginx build configuration. Notice this critical line from nginx -V
output:
built with OpenSSL 1.0.1f 6 Jan 2014 (running with OpenSSL 1.0.2g 1 Mar 2016)
This indicates that while the system has OpenSSL 1.0.2g installed, Nginx was actually compiled against OpenSSL 1.0.1f - which doesn't support ALPN.
Here's the step-by-step process I followed to resolve this:
# 1. Reinstall Nginx with proper OpenSSL linking
sudo apt-get remove --purge nginx nginx-common nginx-full
sudo apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev
wget https://nginx.org/download/nginx-1.11.9.tar.gz
tar -xzvf nginx-1.11.9.tar.gz
cd nginx-1.11.9
Configure with explicit OpenSSL path:
./configure --with-openssl=/usr/local/ssl \
--with-http_ssl_module \
--with-http_v2_module \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
[other original configure parameters]
After compiling and installing, verify with:
nginx -V | grep "built with OpenSSL"
Ensure your server block includes these directives:
server {
listen 443 ssl http2;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers on;
[other SSL configuration]
}
After implementation, test with these methods:
1. OpenSSL command-line test:
openssl s_client -alpn h2 -connect yourdomain.com:443 | grep ALPN
2. Curl verification:
curl -v --http2 https://yourdomain.com
- Mixed OpenSSL versions in build vs runtime environments
- Missing
http2
in listen directive - Outdated cipher suites that don't support modern protocols
- Firewall interference with ALPN handshake
Remember that some CDNs or reverse proxies might interfere with ALPN negotiation. Always test directly against your origin server when debugging.
Recently, while configuring HTTP/2 on my Ubuntu 16.04 server running NGINX 1.11.9 with OpenSSL 1.0.2g, I encountered an unexpected roadblock. Despite documentation suggesting these versions should support ALPN (Application-Layer Protocol Negotiation), tests consistently showed "ALPN is not supported".
First, let's confirm the components:
nginx -V
openssl version -a
In my case, the output revealed:
nginx version: nginx/1.11.9
built with OpenSSL 1.0.1f 6 Jan 2014 (running with OpenSSL 1.0.2g 1 Mar 2016)
OpenSSL 1.0.2h 3 May 2016
built on: linux-x86_64
The key discovery was that while OpenSSL 1.0.2 was installed, NGINX was compiled against OpenSSL 1.0.1. This version mismatch explains why ALPN wasn't working despite having OpenSSL 1.0.2 installed system-wide.
Here's how I fixed it:
- First, ensure you have the latest OpenSSL development headers:
- Download NGINX source matching your installed version:
- Configure with the correct OpenSSL path:
- Compile and install:
sudo apt-get install libssl-dev
wget http://nginx.org/download/nginx-1.11.9.tar.gz
tar -xzf nginx-1.11.9.tar.gz
cd nginx-1.11.9
./configure --with-http_ssl_module --with-http_v2_module \
--with-openssl=/usr/include/openssl \
[your existing configure options from nginx -V output]
make
sudo make install
After recompiling, verify with:
echo | openssl s_client -alpn h2 -connect yourdomain.com:443 | grep ALPN
You should now see ALPN protocol negotiation in the output.
Ensure your server block includes these directives:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# Modern SSL configuration
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384...';
# Enable ALPN
ssl_alpn http/1.1 h2;
}
If recompiling seems daunting, consider using dynamic modules:
sudo apt-get install nginx-extras
sudo apt-get install libnginx-mod-http-headers-more-filter
Then load the HTTP/2 module dynamically in nginx.conf:
load_module modules/ngx_http_v2_module.so;
After implementing these changes:
- Restart NGINX:
sudo systemctl restart nginx
- Test with:
curl -v --http2 https://yourdomain.com
- Verify with online tools like KeyCDN's HTTP/2 test
The key takeaway is ensuring NGINX is compiled against the same OpenSSL version that supports ALPN. This often requires recompiling NGINX with the correct OpenSSL headers, even when newer OpenSSL versions are installed system-wide.