家宽封了 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;
...
}
1
rekulas 2023-05-24 22:45:51 +08:00
我都没理解到你的回路,http 访问报错判断下端口 301 不就行了?是不是想复杂了
|
2
eudemonwind 2023-05-24 22:54:03 +08:00 via Android
扫到你开了 http 直接封宽带
|
3
kingpo OP @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 ,只记一个端口就行
|
4
kingpo OP @eudemonwind #2 没那么严重吧,翻了之前的帖子好多老哥都开端口访问的
|
5
kingpo OP 这里实现的是 1 个端口直接访问 http 和 https 的效果,正常是要两个端口
|
7
kaedeair 2023-05-24 23:26:48 +08:00
这个用 traefik 写两条路由,一条 http ,一条 https ,用相同的 entrypoint ,然后在 http 的路由加个 RedirectSchema 的中间件很容易实现,不必死死抱着 nginx
|
11
rekulas 2023-05-24 23:47:14 +08:00 1
@kingpo 其实可以把你的描述精简下,一句话:我是如何实现 http 协议访问 https 端口的时候自动重定向的 🤣
|
12
olaloong 2023-05-24 23:57:18 +08:00 via Android
这样也行啊
我是套了层 haproxy 来端口复用,rdp ssh http https 全在一个端口上 |
13
ochatokori 2023-05-25 00:27:41 +08:00 via Android
@rekulas #11 看完你这条我终于看懂楼主想说什么了
|
14
Tink 2023-05-25 08:44:26 +08:00
我理解,就算是没封 80 和 443 ,你 nginx 也得开两个端口呀,只监听 443 不是也不能跳吗
|
15
chronos 2023-05-25 09:12:11 +08:00
@Tink 他这个方案就是只开放一个 https 的端口,当 http 协议访问 https 的端口进来时返回 497 状态码告诉浏览器要使用 https 协议来访问。
|
16
netnr 2023-05-25 09:13:11 +08:00 via Android
我来当大聪明,以下都能正常访问
http://your.site.tld:2222 https://your.site.tld:2222 https 的 2222 端口是正常配置的,http 也能访问是因为触发了 https 的 497 错误码,利用这个错误码来访问 以上有个前提是 80 443 都被封了 |
17
Imr 2023-05-25 09:20:36 +08:00 1
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; } } |
19
yunyuyuan 2023-05-25 10:16:26 +08:00
贴一下我的,直连 /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.com 。foo-zto.example.com 解析地址是 vpn 组网的地址 |
20
caiqichang 2023-05-25 11:04:49 +08:00
说的好,我选择用 stream_ssl_preread 模块,同 #17
|
21
kkocdko 2023-05-25 23:23:42 +08:00
我理解你的意思。HTTP 到 HTTPS 重定向这个问题我研究过,并没有标准答案。
最常见的方法是 80 端口和 443 端口同时监听,重定向用 302 或者 497 都有,对于监听单个非默认端口,Nginx 有使用 stream_ssl_preread 的,楼主的方法我也看到别人用过,并不是首创。 顺便讲一些更深入一点的东西。要区分 HTTP 和 HTTPS ,观察 TCP 连接进来的第一个字节即可。如果第一个字节是 0x16 那就说明对方希望进行 TLS 握手,是 HTTPS ,正常服务。如果不是,那就要当作 HTTP 来解析,并进行重定向。 参考实现如下。这里我还使用了一个偷懒技巧,不解析 HTTP 直接给客户端灌一段 JS 来实现重定向。 https://github.com/kkocdko/ksite/blob/76f8f15b02412fc1bf765517518dd10f8c44fbba/src/tls.rs#L109 |