V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
edis0n0
V2EX  ›  程序员

Nginx 如何把 HTTP 和 HTTPS 开在同一个端口?(客户提的奇葩需求)

  •  
  •   edis0n0 · 2022-11-12 23:35:20 +08:00 · 5559 次点击
    这是一个创建于 734 天前的主题,其中的信息可能已经有所发展或是发生改变。
    http://example.com:8888https://example.com:8888 都能访问。Nginx 开同一个端口会报错,客户说之前别的程序员都能做到。我想了想应该确实可以,用 HTTP 访问 HTTPS 端口都能返回一个错误页,返回一个正常网页应该没问题,但不知道具体怎么弄。

    **已经确认了不是 301 跳转这类做法,客户不支持 HTTPS 的上古软件里写死了地址。**
    25 条回复    2022-11-14 14:41:27 +08:00
    icoming
        1
    icoming  
       2022-11-12 23:38:20 +08:00
    啥意思?都能访问,但是内容不一样?
    olaloong
        2
    olaloong  
       2022-11-12 23:38:24 +08:00 via Android   ❤️ 1
    nginx 原生倒是不知道,不过前面套个 haproxy 端口复用确实可以实现
    edis0n0
        3
    edis0n0  
    OP
       2022-11-12 23:39:20 +08:00
    @icoming #1 要求是都能访问,内容一样。客户不支持 HTTPS 的上古软件里写死了地址,但希望同时支持其它设备通过同端口 HTTPS 访问。
    0ZXYDDu796nVCFxq
        4
    0ZXYDDu796nVCFxq  
       2022-11-12 23:41:47 +08:00 via Android   ❤️ 17
    四层代理到不同的端口
    https://serverfault.com/a/930789
    lhx2008
        5
    lhx2008  
       2022-11-12 23:42:39 +08:00
    https://www.rutschle.net/tech/sslh/README.html
    找了一下还真的有人实现这些奇技淫巧
    edis0n0
        6
    edis0n0  
    OP
       2022-11-12 23:44:44 +08:00
    按 4 楼的方案已经实现了,感谢。
    olaloong
        7
    olaloong  
       2022-11-12 23:45:37 +08:00   ❤️ 1
    @olaloong 补充一下 haproxy 的配置,我是把 SSH HTTP HTTPS 监听在了同一个端口上

    frontend main
    mode tcp
    bind *:12482
    # acl 规则
    tcp-request inspect-delay 3s
    acl is_ssh req.payload(0,3) -m bin 535348
    acl is_http req.proto_http
    acl is_ssl req.ssl_hello_type 1
    # 设置四层允许通过
    tcp-request content accept if is_ssh
    tcp-request content accept if is_http
    tcp-request content accept if is_ssl
    tcp-request content reject
    # 分发到对应的 backend
    use_backend ssh if is_ssh
    use_backend http if is_http
    use_backend https if is_ssl

    backend http
    mode tcp
    server http 127.0.0.1:80

    backend https
    mode tcp
    server https 127.0.0.1:443

    backend ssh
    mode tcp
    server ssh 127.0.0.1:22
    zzh0410
        8
    zzh0410  
       2022-11-13 00:00:37 +08:00 via Android
    你甚至可以在一个端口实现 http https mysql oracle 等等,可以直接识别协议头进行转发
    zzh0410
        9
    zzh0410  
       2022-11-13 00:01:25 +08:00 via Android
    当然也是使用 haproxy
    aladdinding
        10
    aladdinding  
       2022-11-13 00:12:26 +08:00
    没有什么是加一层不能解决的
    jousca
        11
    jousca  
       2022-11-13 01:00:09 +08:00
    又学到新花样了……
    edis0n0
        12
    edis0n0  
    OP
       2022-11-13 01:07:29 +08:00
    @olaloong #7 你这样后端就拿不到用户 IP 了
    ysc3839
        13
    ysc3839  
       2022-11-13 01:30:51 +08:00 via Android
    仅用 nginx 可能实现不了,nginx 是可以检测到错误,但不能按照正常流程处理,应该得配合其他工具来实现。
    kwh
        14
    kwh  
       2022-11-13 02:21:19 +08:00
    写一个反向代理监听 8888 端口,如果是 http 请求会是明文,可以转发到 http 端口,如果是 https ,报文应该有所不同可以转发到 https 端口。
    rrfeng
        15
    rrfeng  
       2022-11-13 07:29:33 +08:00 via Android
    准确的说 nginx 的 http 模块无法实现
    bjzhush
        16
    bjzhush  
       2022-11-13 08:18:10 +08:00 via iPhone
    NGINX 非常强大,我之前还用 NGINX 玩过破解。
    就是有一套 PHP 源码加密了,只能运行在 xxx.com 域名下,但是我们肯定是没有 xxx.com 的,通过 NGINX 修改数据,可以实现任意域名过来之后,PHP 拿到的域名都是 xxx.com ,从而实现破解
    neilp
        17
    neilp  
       2022-11-13 08:43:11 +08:00
    @lhx2008 sslh 有性能瓶颈, connect 延迟也有问题.

    后来, 我自己用 nginx 配置实现了. http, tls, ssh 等多协议共存.

    https://github.com/Neilpang/nginx-multiplexer
    iX8NEGGn
        18
    iX8NEGGn  
       2022-11-13 10:40:21 +08:00 via iPhone
    哈哈哈,一年前我一同学的客户就提出过这奇葩要求,我有幸帮他解决过,记得是用了 nginx 的一个不是默认自带的模块,需要自己编译安装。
    ThirdFlame
        19
    ThirdFlame  
       2022-11-13 11:22:09 +08:00
    @edis0n0 #12 外边套一层 haproxy (启用 Proxy protocol ),里面用 nginx (也启用) 就能正常获取到用户 ip 了
    edis0n0
        20
    edis0n0  
    OP
       2022-11-13 21:20:01 +08:00
    @ThirdFlame #19 试了下没成功,有参考配置吗
    julyclyde
        21
    julyclyde  
       2022-11-14 09:27:40 +08:00
    @aladdinding 请问“加一层”怎么解决 http 和 smtp 在同一个端口的需求?
    xqk111
        22
    xqk111  
       2022-11-14 10:59:10 +08:00
    @aladdinding 哈哈哈哈,确实
    aladdinding
        23
    aladdinding  
       2022-11-14 11:34:37 +08:00
    @julyclyde http 数据报文都是从 method 开始,比如 get post 等,可以先读一小段数据,如果发现是 http 就转发到处理 http 的程序,smtp 同理
    aladdinding
        24
    aladdinding  
       2022-11-14 11:35:24 +08:00
    @julyclyde 也就是在传输层和应用层之间加一层
    julyclyde
        25
    julyclyde  
       2022-11-14 14:41:27 +08:00
    @aladdinding smtp 是服务器先说话,和 http 不一样,咋就同理了?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1306 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 661ms · UTC 23:56 · PVG 07:56 · LAX 15:56 · JFK 18:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.