Netty搭建的MQTT協議服務Nginx代理轉發後無法獲取用戶真實IP

確保您的 MQTT 客戶端、MQTT 服務(Netty MQTT 服務)和 Nginx 都支持代理協議。不是所有的軟件都支持這種協議。

以下是Ngin與MQTT服務端修改,客戶端針對每個平臺自行搜索修改

Nginx配置修改

stream {
    upstream mqtt_backend {
        server mqtt_server_ip:mqtt_server_port;
    }

    server {
        listen mqtt_proxy_port proxy_protocol;
        proxy_pass mqtt_backend;
        proxy_protocol on;
    }
}

示例

stream {
    upstream mqtt_backend {
        server 192.168.1.10:1883; # MQTT 後端服務器的 IP 地址和端口
    }

    server {
        listen 8888 proxy_protocol; # 使用代理協議監聽的端口,客戶端將連接到此端口
        proxy_pass mqtt_backend;
        proxy_protocol on;
    }
}

在這個示例中:

  1. 192.168.1.10:1883 是您的 MQTT 服務(Netty MQTT 服務)的 IP 地址和端口。
  2. 8888 是 Nginx 代理將監聽的端口,客戶端將連接到此端口。這個端口可以是任何可用的端口號,但請確保它與您的實際需求相符。
  3. proxy_protocol 是一個指令,用於告訴 Nginx 使用代理協議。在 listen 8888 proxy_protocol; 中,proxy_protocol 指示 Nginx 使用代理協議處理傳入的連接。

客戶端將連接到 Nginx 代理的 8888 端口,Nginx 會將連接轉發到 MQTT 後端服務器(IP 地址爲 192.168.1.10,端口爲 1883)。通過使用代理協議,Nginx 將把客戶端的連接信息(如原始 IP 地址和端口)傳遞給 MQTT 服務。

 

Netty服務端

  1. 首先,將以下 HAProxy 代理協議庫添加到您的項目中:

Maven 依賴:

<dependency>
  <groupId>io.netty</groupId>
  <artifactId>netty-codec-haproxy</artifactId>
  <version>4.1.72.Final</version>
</dependency>

 

  1. ChannelInitializer 類中將 HAProxyMessageDecoder 添加到管道中:

 

import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.haproxy.HAProxyMessageDecoder;

public class MyMqttServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        // 將 HAProxyMessageDecoder 添加到管道中
        pipeline.addLast(new HAProxyMessageDecoder());

        // ... 添加其他處理器,例如 MQTT 編解碼器和業務處理器 ...
    }
}

 

 

  1. 在您的自定義 ChannelInboundHandler 中,獲取代理協議頭中的客戶端真實 IP 和端口:
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.haproxy.HAProxyMessage;

public class ProxyProtocolHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HAProxyMessage) {
            HAProxyMessage haProxyMessage = (HAProxyMessage) msg;
            String clientIp = haProxyMessage.sourceAddress();
            int clientPort = haProxyMessage.sourcePort();

            // 在這裏,您可以將客戶端的真實 IP 和端口傳遞給後續處理器
            // 例如,將它們設置爲 ChannelHandlerContext 的屬性
            ctx.channel().attr(AttributeKey.valueOf("clientIp")).set(clientIp);
            ctx.channel().attr(AttributeKey.valueOf("clientPort")).set(clientPort);

            // 繼續處理其他消息
            ctx.fireChannelRead(msg);
        } else {
            super.channelRead(ctx, msg);
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章