How to Fix “No ALPN Negotiated” Error in Nginx with OpenSSL 1.0.2g


2 views

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:

  1. First, ensure you have the latest OpenSSL development headers:
  2. sudo apt-get install libssl-dev
  3. Download NGINX source matching your installed version:
  4. wget http://nginx.org/download/nginx-1.11.9.tar.gz
    tar -xzf nginx-1.11.9.tar.gz
    cd nginx-1.11.9
  5. Configure with the correct OpenSSL path:
  6. ./configure --with-http_ssl_module --with-http_v2_module \
    --with-openssl=/usr/include/openssl \
    [your existing configure options from nginx -V output]
  7. Compile and install:
  8. 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:

  1. Restart NGINX: sudo systemctl restart nginx
  2. Test with: curl -v --http2 https://yourdomain.com
  3. 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.