今天遇到两个nginx问题nginx: [emerg] bind() to 0.0.0.0:4433 failed (98: Address already in use)no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking 都让我情绪崩溃了。

  • nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)

netstat -anp|grep 443没有找到占用端口的程序,可以断定是nginx启动时重复监听导致的,仔细查看配置文件后,发现stream块中与http块的443重复导致,删掉stream块(之前做正向代理测试,忘了删除)即可。

stream{
 listen 443;
}

http{
	server {
	 listen 443 ssl;
	}
}
  • no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking

可以确定肯定配置了ssl_certificate、ssl_certificate_key 。

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ...
}

经检查发现,除了上述配置,另有一个server块的SSL 添加default_server导致,删除default_server即可,使用的nginx版本是openresty1.13.6.2

server {
   listen 443 ssl  default_server ;
  }

修改后

server {
   listen 443 ssl ;
   //没有配置ssl_certificate     
  }

官方文档listen指令,default_server作用如下

The default_server parameter, if present, will cause the server to
become the default server for the specified address:port pair. If none
of the directives have the default_server parameter then the first
server with the address:port pair will be the default server for this
pair.

似乎还是不能解释为什么删掉default_server就好了。在SSL & Ngnix: no “ssl_certificate” is defined in server listening on SSL port while SSL handshaking中提到

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.

翻译过来就是,SNI(server name indication)会匹配有ssl标记的listen;default_server会将访问443端口的所有访问都拦截过来,也就是说default_server会阻止SNI的工作;
顺便,加深下default_server的理解,参考How nginx processes a request,default_server是对端口而言的,也就是说可以为不同端口可以指定default_server,

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}

server {
    listen      192.168.1.1:80 default_server;
    server_name example.net www.example.net;
    ...
}

server {
    listen      192.168.1.2:80 default_server;
    server_name example.com www.example.com;
    ...
}

如果没有指定default_server,那么nginx.conf中第一个server会作为default server。