一个骚操作, nginx 只监听 1 个非标端口就实现 http 重定向 https

340 天前
 kingpo

家宽封了 80,443 ,服务只能带端口访问
设置 nginx 监听一个高位端口如 2222 指向 443 ,另一个 3333 指向 80
因为非标准端口,没法同时监听 80 和 443
访问带指向 443 的端口 2222 时,如果开了强制 ssl ,只能 https 访问,http 访问时就会报 400 错,因为 http 是 3333 端口监听的,这样在访问时输入就很麻烦了。

怎么才能实现在一个端口访问,http 也能重定向呢,找了几天发现方法
有点骚,但能实现 nginx 只监听 1 个非标端口 http 重定向 https
本质是修改利用 497 错误码重定向指向 https 的地址

客户端请求未使用 HTTPS 协议,但如果您已启用强制 SSL ,并且客户端尝试使用 HTTP 协议访问您的网站,则会收到 HTTP 497 错误。我们这时候就修改 497 的页面指向我们 https 即可

server {
  listen      2222 ssl;
  server_name your.site.tld;
  ssl         on;
  ...
  error_page  497 https://$host:2222$request_uri;
  ...
}
2488 次点击
所在节点    分享发现
22 条回复
rekulas
340 天前
我都没理解到你的回路,http 访问报错判断下端口 301 不就行了?是不是想复杂了
eudemonwind
340 天前
扫到你开了 http 直接封宽带
kingpo
340 天前
@rekulas #1 非标准端口你 xxx.com:2222 只能监听 443 ,这时候不能同时监听 80 ,你这时候 http://xxx.com:2222 访问是报 400 ,301 也还是报 400 ;你 80 是通过 3333 ,http://xxx.com:3333 这个才可以 301 过去 https//:xxx.com:2222 ,我默认要访问的是 xxx.com:2222 ,只记一个端口就行
kingpo
340 天前
@eudemonwind #2 没那么严重吧,翻了之前的帖子好多老哥都开端口访问的
kingpo
340 天前
这里实现的是 1 个端口直接访问 http 和 https 的效果,正常是要两个端口
kingpo
340 天前
@rekulas #1 这里实现的是 1 个端口直接访问 http 和 https 的效果,正常是要两个端口
kaedeair
340 天前
这个用 traefik 写两条路由,一条 http ,一条 https ,用相同的 entrypoint ,然后在 http 的路由加个 RedirectSchema 的中间件很容易实现,不必死死抱着 nginx
kingpo
340 天前
@kaedeair #7 主要是为了方便申请 let's encrypt 证书
kaedeair
340 天前
@kingpo #8 traefik 同样支持 acme 自动签发
rekulas
340 天前
@kingpo 明白你意思了 这种模式我之前也用过
rekulas
340 天前
@kingpo 其实可以把你的描述精简下,一句话:我是如何实现 http 协议访问 https 端口的时候自动重定向的 🤣
olaloong
340 天前
这样也行啊
我是套了层 haproxy 来端口复用,rdp ssh http https 全在一个端口上
ochatokori
340 天前
@rekulas #11 看完你这条我终于看懂楼主想说什么了
Tink
340 天前
我理解,就算是没封 80 和 443 ,你 nginx 也得开两个端口呀,只监听 443 不是也不能跳吗
chronos
340 天前
@Tink 他这个方案就是只开放一个 https 的端口,当 http 协议访问 https 的端口进来时返回 497 状态码告诉浏览器要使用 https 协议来访问。
netnr
340 天前
我来当大聪明,以下都能正常访问
http://your.site.tld:2222
https://your.site.tld:2222

https 的 2222 端口是正常配置的,http 也能访问是因为触发了 https 的 497 错误码,利用这个错误码来访问

以上有个前提是 80 443 都被封了
Imr
340 天前
nginx 自己就有更优雅的解决办法
用 stream 里的 ssl_preread ,类似下面配置(没有验证)

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 2222;
listen [::]:2222;
proxy_pass $upstream;
ssl_preread on;
}
}
kingpo
340 天前
@netnr #16 对的
yunyuyuan
340 天前
贴一下我的,直连 /zerotier 通用配置,好处是打洞的服务也可以用域名+https 访问:
server {
listen [::]:5678 ssl;
listen 443 ssl;
listen 80;
server_name foo.example.com foo-zto.example.com;
error_page 497 https://$host:5678$request_uri;

set $whole_url "$scheme://$host";
if ($whole_url ~ ^http://[^.]*-zto) {
return https://$host$request_uri;
}
}

* 直连用 http://foo.example.com:5678 ,重定向到 https://foo.example.com:5678

* zerotier 用 http://foo-zto.example.com ,可以重定向到 https://foo-zto.example.comfoo-zto.example.com 解析地址是 vpn 组网的地址
caiqichang
340 天前
说的好,我选择用 stream_ssl_preread 模块,同 #17

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/942682

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX