Nginx手动配置证书并设置http跳转https

黄师傅 2,206 2023-04-12

同一个端口实现http跳转https

默认的,http和https需要使用不同的端口,做http到https的跳转,也需要从http的端口(默认为80)跳转到https的端口(443),那么,如何实现在一个端口的情况下,使用http访问转向到https呢?一个简单的方法是利用nginx的497错误码

原理:http和https是tcp的上层协议,当nginx服务器建立tcp连接后,根据收到的第一份数据来确定客户端是希望建立tls还是http。nginx会判断tcp请求的首写节内容以进行区分,如果是0x80或者0x16就可能是ssl或者tls,然后尝试https握手。如果端口开启了https,但请求过来的并不是,会抛出一个http级别的错误,这个错误的状态码是NGX_HTTP_TO_HTTPS,错误代码497,然后在返回response中会抛出一个400错误(因为497不是标准状态码,丢给浏览器也没有用),这时浏览器会显示"400 Bad Request,The plain HTTP request wes sent to HTTPS port"

这样,可以对497进行路由处理,做302重定向,核心代码如下:

error_page 497 https://$host:8080$request_uri;

示例配置如下:

server {
    charset utf-8;
    client_max_body_size 128M;
 
    listen 8080 ssl;
 
    ssl_certificate      cert/test.com.pem;
    ssl_certificate_key  cert/test.com.pem;
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;
    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;
 
    server_name test;
    root        /var/www;
    index       index.php;
 
    access_log  /var/log/nginx/access.log;
    error_log   /var/log/nginx/error.log;
 
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
 
    location /check.html {
        return 200;
        access_log off;
    }
 
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
        #fastcgi_pass unix:/var/run/php5-fpm.sock;
        try_files $uri =404;
    }
 
    location ~* /\. {
        deny all;
    }
    error_page 497 https://$host:8080$request_uri;
}

在线配置文件生成

在线生成nginx配置文件
https://nginxconfig.io
20220424183337

图片防盗链

通过检测header字段里的referer字段判断,若referer来自规定的域名或空时,认为是正常的访问,否则为盗链
#https访问http的图片,因为安全性规定,所带referer为空

location ~* .(gif|jpg|png|bmp)$ {    
    valid_referers none blocked *.xxx.com server_names ~.google. ~.baidu.;    
    if ($invalid_referer) {        
        return 403;        
    }
}