8

Nginx实现http和https复用1个端口的2种解决方式

 1 year ago
source link: https://hugo.111520.xyz/posts/2023-05-26-nginx-http-redirect-https/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

http 和 https 背景知识

http 和 https 是两种常见的网络传输协议,它们的区别在于其安全性。

http 是明文传输,数据在传输时没有加密,存在被读取和修改数据的风险,http 传输敏感信息如密码等不够安全。

https 使用 SSL 或 TLS 协议来加密传输过程中的数据,数据在传输过程不会被窃取和篡改。

http 默认端口是 80,https 默认端口是 443。

当你浏览器输入访问 http:example.com 时,实际访问的是 http:example.com:80

当你浏览器输入访问 https:example.com 时,实际访问的是 https:example.com:443

浏览器输入网址一般我们会简单只输入:example.com,此时默认是指向 http:example.com,如果要通过 https 协议访问,需要完整输入前缀 https:https:example.com

为了安全,所以我们网站要设置只通过 https 模式访问,那么访问 example.comhttp:example.com 时怎么办呢?答案就是设置重定向,http 自动重定向到 https。

example.com / http:example.com -> https:example.com

此时你访问网站,带不带 http,都最终会指向 https。

常规 http 重定向

当你的 80 和 443 端口都可用时,通过 Nginx 可以很方便的设置 http 重定向到 https,只需在配置文件 nginx.conf 中进行以下配置即可。

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}
  1. listen 80; - 监听 HTTP 请求的默认端口 80。
  2. server_name example.com; - 将请求的主机名设为 example.com。
  3. return 301 https://$server_name$request_uri; - 将请求重定向到 HTTPS 的 443 端口,并将请求 URI 保持不变。
  4. return 301 - 返回 301 状态码,表示永久性重定向。这将通知浏览器将 HTTP 请求重定向到 HTTPS 请求。

监听一个非标端口实现访问 http 和 https

如果 80 和 443 端口不可用,比如在家庭宽带的公共 ip 这两端口是被封的,那么只能分配其他端口。

此时需要给 http 和 https 各自设置一个端口,这里以 http:2222 和 https:3333 为例。

此时我们访问网站时需要加上端口号,http:example.com:2222https:example.com:3333

因为指定了端口,每次输入访问地址时就会比较麻烦,主要是因为你要记住两个端口并区分,如果你只允许 https,那对应访问会有下面的这些情况:

  • 端口 2222 http:example.com:2222 只 http 访问,此时会报错,因为网站只允许 https,需要设置重定向到 https:example.com:3333,我们先设置它。https:example.com:2222 会报错,因为 2222 是 http 的端口,不能用 https 访问。

  • 端口 3333 http:example.com:3333 http 访问的 https,也会报错,提示需要用 https 访问。你得输入 https:example.com:3333

#2222和3333

http:example.com:2222  -> https:example.com:3333 (重定向后)
https:example.com:2222    无法访问

http:example.com:3333     无法访问
https:example.com:3333 -> https:example.com:3333 


#对比原来的标准端口

http:example.com  -> https:example.com (重定向后)
https:example.com    https:example.com

总之,繁琐的地方是要 2 个端口不好记,并且对应需要区分每个端口对应 http 和 https。

那么能不能实现这种呢?

#只用一个非标准端口实现
http:example.com:3333  -> https:example.com:3333 
https:example.com:3333    https:example.com:3333

答案是可以的,这里提供两种方法。

方法 1:利用 497

利用错误码 497 进行重定向。

Nginx 配置文件添加

server { 
	listen 3333 ssl; 
	server_name your.site.tld; 
	ssl on; 
	error_page 497 https://$host:3333$request_uri; 
	 }

这里实现的原理是利用了 497 错误码页面,我们设置 https 监听端口为 3333 后,如果用 http 访问 http:example.com:3333,Nginx 会返回错误码 497 页面,告诉你错误请求,纯 HTTP 请求已发送到 HTTPS 端口,我们直接修改 497 页面为我们 https 地址即可。此时 http 也能访问,因为触发了 497 错误码,重定向到了 https 地址。

#497错误码页面

400 Bad Request
The plain HTTP request was sent to HTTPS port

Nginx Proxy Manager 里配置方式,在 host 代理 advanced 自定义填写以下代码即可。 `error_page 497 https://host:3333host:3333host:3333request_uri;

https://s3.bmp.ovh/imgs/2023/06/15/6fddd0ec8fe27835.png

方法 2:stream_ssl_preread 实现

Nginx 里 stream_ssl_preread 可以直接实现 http 访问 https,配置如下:

stream {  
upstream http {  
server 127.0.0.1:80;  
}  
upstream https {  
server 127.0.0.1:443;  
}  
  
map $ssl_preread_protocol $upstream {  
default https;  
"" http;  
}  
  
server {  
listen 3333;  
listen [::]:3333;  
proxy_pass $upstream;  
ssl_preread on;  
}  
}
关注一下有惊喜
wxqr.png 公众号
赞赏支持
wechatpay.png 微信打赏 alipay.png 支付宝打赏

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK