SSL & Ngnix: no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking

63,982

Solution 1

My guess is that you have another server listening on port 443. This server has no ssl_certificate defined, and it's automatically selected (SNI). Try to delete all symbolic links from /etc/nginx/sites-enabled except this one server you want to make work (if that's possible, otherwise check all of your servers for listening to 443 without being configured correctly).

Solution 2

I fixed this same problem earlier this morning, so I'm here to clarify C.A's point (which, now that I understand the problem, was well made), you most likely have two server blocks:

# default
server {
    listen 443 default_server; # Note the lack of `ssl`
    server_name _;
    #...
}

#real site
server {
    listen 443 ssl;
    server_name ;
    #...
}

SNI will only match on those that are labelled with an ssl listener. However, the default server will grab all incoming traffic on 443, regardless of SSL or not. Hence, it's actually preveting SNI from actually working at all, right off the bat, by hoarding all of the traffic for itself.

Symptoms:

  • It will seem like nginx isn't loading your config (even with an nginx -t and a service reload)
  • Errors stating "no ssl_certificate found in server block"
  • nginx is just applying your host to the default 443 listener.

Solutions:

I fixed the problem this morning by removing the default server block, hence allowing SNI to match on SSL listeners.

Alternative solution would be to add the ssl listener and the ssl_certificate lines to the server block so that SNI is essentially enabled on your default host. You'll still get SSL errors, so it's not the best solution, but it'll let your SNI work :)

Solution 3

You need to define a single default_server parameter in the nginx config.

Apply default_server on either example.com or www.example.com. Not both.

Hence this will work:

server {
    listen 443 ssl;
    listen 80;

    server_name example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 80 default_server;

    server_name www.example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl default_server;

    server_name www.example.com;
    root /var/www/example.com/public;
    index index.php index.html index.nginx-debian.html;

    ssl on;
    ssl_certificate /etc/ssl/chain.crt;
    ssl_certificate_key /etc/ssl/examplecom.key;

    (rest of your nginx config goes here....)
}

Note on virtual hosts: Make sure the default_server parameter is not defined anywhere else - if you have multiple hosts on the server.

Solution 4

Late to the game as usual, but since it helped me... Check if the certificate is malformed. When building the "unified" crt (crt + intermediate), doing

$cat server.crt provider.intermediate > unified.crt

I somehow lost a LF and got a line like this:

-----END CERTIFICATE----------BEGIN CERTIFICATE-----

instead of

-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----

and nginx would not take the cert and fail with the error mentioned above.

Doing

# openssl x509 -in unified.cert -text -out

gave me the clue for openssl would error out.

Share:
63,982

Related videos on Youtube

0xtuytuy
Author by

0xtuytuy

Updated on September 18, 2022

Comments

  • 0xtuytuy
    0xtuytuy over 1 year

    I have managed to create my certificates with LE with not errors, I have also managed to redirect my traffic from port 80 to port 443. But when i reload my nginx server I am unable to access my website. The Ngnix error logs show this line:

    4 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: 192.168.0.104, server: 0.0.0.0:443
    

    I think this means that it can't find the certificates I then navigated to the path of the certificates and they are both there, what could be the problem ? Here is how my Ngnix configuration looks like:

    server {
           listen         80;
           server_name    pumaportal.com www.pumaportal.com;
           return         301 https://$server_name$request_uri;
    }
    
    server {
        listen 443 ssl;
    
        server_name pumaportal.com www.pumaportal.com;
    
        add_header Strict-Transport-Security "max-age=31536000";
    
        ssl_certificate /etc/letsencrypt/live/pumaportal.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/pumaportal.com/privkey.pem;
    
        ssl_stapling on;
        ssl_stapling_verify on;
    
        access_log /var/log/nginx/sub.log combined;
    
        location /.well-known {
           alias /[MY PATH]/.well-known;
        }
    
        location / {
            proxy_pass http://localhost:2000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
    
    }
    

    It all seems pretty straight forward I don't understand where could the problem be.

    After running nginx -t it all seems ok:

    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
    • Admin
      Admin about 7 years
      Do you have any other server blocks? What exactly did you do when you got that error?
    • Admin
      Admin about 7 years
      Does the nginx user have access to the certificate file and key file? It's not enough to have read access to the files, the user also needs to have read and execute permissions for all directories in the chain to the file.
    • Admin
      Admin over 4 years
  • Marcos Regis
    Marcos Regis about 5 years
    BINGO! In my case, I create config file for vhost mail.mydomain, so I can build a LE certificate for my dovecot installation and forgot to add on config file.
  • Josua Marcel C
    Josua Marcel C about 5 years
    very nice ssl on is working for me
  • padawanTony
    padawanTony about 4 years
    Or just define an ssl_certificate for all your servers that use ssl.
  • C.A. Vuyk
    C.A. Vuyk about 4 years
    quite so, at the time of the question this was not yet common practice
  • Alex
    Alex over 3 years
    This is a pretty good guess. I wasn't sure of what was wrong in my configuration (which somebody else did originally) but once I saw this answer it was pretty obvious. Thanks for the tip.
  • ingo
    ingo over 3 years
    The ssl directive is deprecated Nginx 1.15.0 release note
  • Ayyappa
    Ayyappa almost 3 years
    Awesome guess! I missed deleting conf files which are no more used. And it started working!