如何实现同一端口代理不同的后端服务

公众号关注 「奇妙的 Linux 世界」

设为「星标」,每天带你玩转 Linux !

2224573d8f20d73ff2191802c31757cf.jpeg


在网络通信中,端口是用于区分不同服务的重要资源。通常,每个服务会绑定到一个特定端口上,但有时我们需要通过同一个端口来代理不同的服务。这种技术被称为端口复用。本文将介绍端口复用的场景、用途、协议特性,并分别使用 Nginx 和 HAProxy 进行端口复用配置。

端口复用的场景与用途

端口复用在以下场景中非常有用:

  1. 资源限制:在IP地址和端口资源有限的环境中,通过同一端口提供多个服务可以最大化利用现有资源。

  2. 简化配置:简化客户端配置,使其无需关心不同服务使用不同端口的问题。

  3. 负载均衡与高可用性:在负载均衡器或反向代理服务器上,通过同一端口代理不同的后端服务,提高服务的可用性和可靠性。

协议特性

端口复用的实现依赖于协议特性。通过分析协议的特定字段或数据包的前几个字节,可以判断请求的类型并将其转发到相应的后端服务。

通过 Wireshark 抓包来分析协议特性,下面是分析 MySQL 协议特性的例子:

25dfd02bcf4593c3d1f72d6b2c7add9f.png

从抓包中,可以发现 MySQL 握手包前面 5 个字节是相对固定的 0x490000000a,特别需要注意的是,MySQL 握手包的第一个字节表示包长度,在不同的版本中,长度可能是不一样的,比如说在 8.0.38 版本中,前一个字节是0x4a,需要你抓包确认。

5f00b463899f86746fb0aee7a4e44c93.png

特别说明一下,MySQL 不能做端口复用,你抓包看MySQL的协议交互会发现,TCP 三次握手之后,第一个包是服务端向客户端发的,这种交互方式在代理层是无法做数据判断的。

以下是一些常见协议的特性示例:

在 http 协议中,数据包的前几个字节是GET, POST,PUT,DELETE等,因为长度不一样,通常分析前3字节即可。

协议协议特性
HTTP(GET)payload(0,3) = 474554
HTTP(POS)payload(0,3) = 504f53
HTTP(PUT)payload(0,3) = 505554
HTTP(DEL)payload(0,3) = 44454c
HTTP(OPT)payload(0,3) = 4f5054
HTTP(HEA)payload(0,3) = 484541
HTTP(CON)payload(0,3) = 434f4e
HTTP(TRA)payload(0,3) = 545241
SSHpayload(0,3) = 535348
FTPpayload(0,3) = 535348
Redispayload(0,4) = 2a320d0a

使用 Nginx 实现端口复用

Nginx 是一款高性能的 HTTP 和反向代理服务器。通过结合 Nginx 的 Stream 模块和 Lua 脚本,我们可以根据 payload 的前几个字节实现端口复用。

安装必要的软件

首先,确保你安装了带有 Lua 支持的 Nginx,推荐使用 OpenResty,它集成了 Nginx 和 LuaJIT。

配置 OpenResty

以下是一个 OpenResty 的配置示例:

stream {
    lua_shared_dict protocol_cache 10m;
    upstream redis_backend {
        server localhost:6379;
    }
    
    upstream http_backend {
        server localhost:80;
    }
 
    upstream ssh_backend {
        server localhost:22;
    }
    lua_add_variable $backend;
    server {
        listen 3000;
        preread_by_lua_block {
            local sock = ngx.req.socket()
            local data, err = sock:peek(3)  -- 读取数据包前3个字节
            if not data then
                ngx.log(ngx.ERR, "接收数据失败: ", err)
                return ngx.exit(ngx.ERROR)
            end
            -- 判断payload内容
            if data == "\x47\x45\x54" or data == "\x50\x4f\x53" or data == "\x50\x55\x54" or data == "\x44\x45\x4c" or data == "\x4f\x50\x54" or data == "\x48\x45\x41" or data == "\x43\x4f\x4e" or data == "\x54\x52\x41" then  -- http
                ngx.var.backend = "http_backend"
            elseif data == "\x2a\x32\x0d" then -- redis
                ngx.var.backend = "redis_backend"
            elseif data == "\x53\x53\x48" then -- ssh
                ngx.var.backend = "ssh_backend"
            end
        }
        proxy_pass $backend;
    }
}

使用 HAProxy 实现端口复用

HAProxy 是一款高性能的 TCP/HTTP 负载均衡器。通过配置 HAProxy,我们也可以根据 payload 内容实现端口复用。

安装 HAProxy

确保你已经安装了 HAProxy,可以使用包管理器进行安装,如 apt-get install haproxy

配置 HAProxy

以下是一个基于TCP协议的示例配置:

frontend main_front
    bind *:3000
    mode tcp
    tcp-request inspect-delay 5s
    
    acl is_http req.payload(0,3) ‐m bin 474554 504f53 505554 44454c 4f5054 484541 434f4e 545241
    acl is_redis req.payload(0,3) ‐m bin 535348
    acl is_ssh req.payload(0,3) ‐m bin 535348
    use_backend http_backend if is_http
    use_backend redis_backend if is_redis
    use_backend ssh_backend if is_ssh
    default_backend another_backend
backend http_backend
    mode tcp
    server server1 localhost:80
backend redis_backend
    mode tcp
    server server1 localhost:6379
backend ssh_backend
    mode tcp
    server server1 localhost:22
backend another_backend
    mode tcp
    server server1 localhost:9000

小结

端口复用能够在资源受限的环境中提高服务的灵活性和可用性。通过分析协议特性,我们可以在同一端口上代理不同的服务。Nginx 和 HAProxy 都提供了强大的功能来实现这一需求,HAProxy 配置更简单明朗。

本文转载自:「 哈希 」,原文:https://url.hi-linux.com/l3u8n ,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-linux.com。

b403b214d3a6f0aeb256641aef8a809c.gif

🚀 最近,我们建立了一个技术交流微信群。目前群里已加入了不少行业内的大神,有兴趣的同学可以加入和我们一起交流技术,在 「奇妙的 Linux 世界」 公众号直接回复 「加群」 邀请你入群。

🌟『极客视界』科技达人必备综合资讯指南,等你来探索!访问网址 https://bestgeek.org 即可打开新世界。

📕 关注『奇妙的 Linux 世界』公众号,带你开启有趣新生活!更多好用好玩的软件资源,可访问 https://666666.dev 免费获取。

3ab17b715cd97fdccdbe977e1cbf2091.png

你可能还喜欢

点击下方图片即可阅读

2b3bb2d12d49ef292fef9e21b2609720.png

无需 Dockerfile,打造你的专属即时容器镜像 : 自建 Nixery 私有服务器

55753fd8fc2a5d496fb1c58d61535c8f.png

点击上方图片,『美团|饿了么』大额外卖红包天天免费领

e4de3a4557f04d3a8726e687da66bf1e.png

更多有趣的互联网新鲜事,关注「奇妙的互联网」视频号全了解!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值