• home > tools > webServer > nginx >

    nginx配置SNI阻断IP扫描导致的域名泄漏

    Author:zhoulujun Date:

    在Nginx的默认SSL配置下,当客户端尝试建立TLS连接时发送的SNI不包含域名时,Nginx依旧会发送SSL TLS证书给客户端,从而导致ip背后的域名信

    在Nginx的默认SSL配置下,当客户端尝试建立TLS连接时发送的SNI不包含域名时,Nginx依旧会发送SSL/TLS证书给客户端,从而导致ip背后的域名信息泄露。

    SNI

    SNI(Server Name Indication),是为了解决一个服务器使用多个域名和证书的SSL/TLS扩展。在使用TLS的时候,http server希望根据HTTP请求中HOST的不同,来决定使用不同的证书。简单地说这个扩展使得在同一个IP上可以以不同的证书配置不同的域名

    一句话简述它的工作原理就是:在连接到服务器建立SSL链接之前先发送要访问站点的域名(Hostname),这样服务器根据这个域名返回一个合适的证书。

    由于HTTP的HOST字段在HTTP GET中。而TLS的握手以及证书验证都是在HTTP开始之前。这个时候,TLS协议的HELLO字段中增加了一个server name字段,让HTTP的client的可以提前 设置HOST,从而使server在tls的握手阶段可以选择证书。

    然后,这个机制本身可以抛开http不关心,只要TLS client提前设置了server name,便可以实现SNI

    nginx开启SNI

    nginx支持TLS协议的SNI扩展。不过,SNI扩展还必须有客户端的支持,另外本地的OpenSSL必须支持它。

    如果启用了SSL支持,nginx便会自动识别OpenSSL并启用SNI。是否启用SNI支持,是在编译时由当时的 ssl.h 决定的 SSL_CTRL_SET_TLSEXT_HOSTNAME,如果编译时使用的OpenSSL库支持SNI,则目标系统的OpenSSL库只要支持它就可以正常使用SNI了。

    nginx在默认情况下是**TLS SNI support disabled**

    nginx SNI

    当客户端不支持SNI时,请求到服务器,nginx服务器默认会返回第一个server的证书用来和客户端进行校验

    而Nginx如果开启了TLS SNI support,就能支持多个SSL加密站点共同使用一个IP

    查看nginx是否支持SNI

    方法也很简单,首先先看看你现在的Nginx是否enable了这个功能

    /usr/local/nginx/sbin/nginx -V

    nginx: nginx version: nginx/1.1.0

    nginx: TLS SNI support disable

    nginx: configure arguments: –user=www –group=www –prefix=/usr/local/nginx –with-http_stub_status_module –with-http_ssl_module –with-http_gzip_static_module –with-ipv6

    如果是TLS SNI support disable那你需要重新编译下Nginx,如果enable了,你直接修改配置文件就行

    配置nginx支持SNI

    为了阻止Nginx发送证书给不合法的客户端,以下三个模块是必须的。

    --with-stream

    --with-stream_ssl_module

    --with-stream_ssl_preread_module

    修改nginx配置文件

    stream {
        map $ssl_preread_server_name $name { #根据ssl sni name选择策略
        backend.example.com      web; #把backend.example.com 改成你的
        default                  block; #只要sni name 不正确就断开连接
        }
    
        upstream web {
            server 127.0.0.1:444; #正常的Web服务
        }
    
        upstream block {
            server 127.0.0.1:80; #用于阻止不合法请求
        }
        
        server {
            listen      443 reuseport; 
            listen [::]:443 reuseport;
            proxy_pass  $name;
            ssl_preread on; #开启ssl_preread
        }
    }
    # server 配置
    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name _; #不提供正确的域名直接断开连接
        return 444;
    }
    
    server {
        listen 127.0.0.1:444 ssl http2; #端口号和stream中的要一样
        ssl_certificate       /path/to/example.crt;
        ssl_certificate_key   /path/to/example.key;
        ssl_trusted_certificate /path/to/example.ca-bundle;
        ssl_protocols         TLSv1.3 TLSv1.2;
        ssl_prefer_server_ciphers off;
        ssl_early_data on;
        ssl_session_cache   shared:SSL:40m;
        ssl_session_timeout 4h;
        ssl_session_tickets off;
        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.4.4;
        resolver_timeout 10s;
        ssl_dhparam /etc/nginx/nginx.pem;
        server_name example.com;
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    }



    参考文章:

    https://carey.akhack.com/2017/05/03/nginx支持SNI/

    不给SNI,就滚蛋! 防止ip扫描导致的域名泄漏 --Nginx版 https://www.johnrosen1.com/nginx-sni/

    nginx使用SNI功能的方法 https://www.cnblogs.com/hugetong/p/11727275.html



    转载本站文章《nginx配置SNI阻断IP扫描导致的域名泄漏》,
    请注明出处:https://www.zhoulujun.cn/html/tools/webServer/nginx/2020_0407_8365.html