nginx配置支持wss,https网页连接mqtt

本文介绍在HTTPS环境下如何使用WSS连接MQTT服务器,包括服务器端的配置(如nginx反向代理设置)、前端使用Eclipse Paho JavaScript Client库进行WSS连接的方法,以及连接成功后的消息订阅和发送。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前在前端网页上写一个小网站,用于开发时在线订阅、发送mqtt数据包。
当部署在线上服务器时,因为域名网页有加载Https证书,所以连接mqtt时只能选用wss方式,却没有成功连接上mqtt。而mqtt的ws连接方式是可以的。

一、服务端配置

1.mqtt的配置文件

先来看线上服务器中mqtt配置文件

port 1883

listener 61613
protocol websockets

配置中,1883是tcp连接, 61613是ws连接方式

2.nginx配置方案

采用的方案是,在nginx中配置wss支持,再反向代理转至mqtt的ws连接端口,实测这样配置后mqtt是可以在https网页中通过wss正常连接、收发数据等。

# 先定义一个upstream分发到ws,此处反向代理或做负载均衡
upstream mqttServer {
    server localhost:61613;
}

server {
	listen      80 ;
	listen 443 ssl ;
    server_name  mqtt.example.cn;
    ssl_certificate /etc/letsencrypt/live/mqtt.example.cn/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mqtt.example.cn/privkey.pem;
    
    # 配置wss支持
	location /mqttwss {
		proxy_set_header Host $http_host;
		proxy_pass http://mqttServer;
	    proxy_http_version 1.1;
		proxy_set_header X-Client-IP $remote_addr;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
		proxy_read_timeout 300s; # 默认是60秒,可设置
	}
}

二、前端wss连接

选择 Eclipse Paho JavaScript Client 连接库
utility.js

/*
Eclipse Paho MQTT-JS Utility
This utility can be used to test the Eclipse Paho MQTT Javascript client.
*/

// Create a client instance
client = null;
connected = false;

// called when the client connects
function onConnect(context) {
  // Once a connection has been made, make a subscription and send a message.
  alert("连接成功: \nHost: " + context.invocationContext.host + ':' + context.invocationContext.port + context.invocationContext.path + ' \nClientID: ' + context.invocationContext.clientId);
  connected = true;
}

function onFail(context) {
  alert("连接失败: " + context.errorMessage);
  connected = false;
}

// called when the client loses its connection
function onConnectionLost(responseObject) {
  if (responseObject.errorCode !== 0) {
    alert("连接已断开,请重新连接: " + responseObject.errorMessage);
  }
  connected = false;
}

// called when a message arrives
/*called when a message arrives
* @message: 收到消息
*/
function onMessageArrived(message) {
  alert('Message Recieved: \nTopic: '+message.destinationName+'\nPayload: '+message.payloadString+'\nQoS: '+message.qos);
  // alert(message);
  var messageTime = new Date().toISOString();
  // pare message
  // alert('Topic:' + message.destinationName);
  // alert('Payload:' + safe_tags_regex(message.payloadString));
  // alert('messageTime:' + messageTime);
  // alert('QoS:' + message.qos);
}

/*连接*/
function connect(clientId){
    var hostname = 'mqtt.example.cn';
    var port = 443;
    // var clientId = 'msg_publisher_1';

    var path = '/mqttwss';
    var user = 'username';
    var pass = 'password';
    var keepAlive = 90;
    var timeout = 3;
    var tls = true;
    var cleanSession = false;
    var lastWillTopic = '/test/will/' + clientId;
    var lastWillQos = 1;
    var lastWillRetain = false;
    var lastWillMessage = 'net offline';


    if(path.length > 0){
      client = new Paho.MQTT.Client(hostname, port, path, clientId);
    } else {
      client = new Paho.MQTT.Client(hostname, port, clientId);
    }

    // set callback handlers
    client.onConnectionLost = onConnectionLost;
    client.onMessageArrived = onMessageArrived;


    var options = {
      invocationContext: {host : hostname, port: port, path: client.path, clientId: clientId},
      timeout: timeout,
      keepAliveInterval:keepAlive,
      cleanSession: cleanSession,
      useSSL: tls,
      onSuccess: onConnect,
      onFailure: onFail
    };



    if(user.length > 0){
      options.userName = user;
    }

    if(pass.length > 0){
      options.password = pass;
    }

    if(lastWillTopic.length > 0){
      var lastWillMessage = new Paho.MQTT.Message(lastWillMessage);
      lastWillMessage.destinationName = lastWillTopic;
      lastWillMessage.qos = lastWillQos;
      lastWillMessage.retained = lastWillRetain;
      options.willMessage = lastWillMessage;
    }

    // connect the client
    client.connect(options);
}

/*连接断开*/
function disconnect(){
    client.disconnect();
    alert('Connection - Disconnected.');
    connected = false;
}

/*发送mqtt消息包
* @topic: 订阅主题 string
* @qos: 消息质量 int
* @message: 消息体
* @retain: 是否保留 bool
*/
function publish(topic, qos, message, retain){
    if (!connected) {
        alert('mqtt未连接,请稍后再试');
        return;
    }
    alert('Publishing Message: \nTopic: '+topic+'\nQoS: ' + qos + '\nMessage: '+message);
    message = new Paho.MQTT.Message(message);
    message.destinationName = topic;
    message.qos = qos;
    message.retained = retain;
    client.send(message);
}

/*订阅主题
* @topic: 订阅主题 string
* @qos: 消息质量 int
*/
function subscribe(topic, qos){
    if (!connected) {
        alert('mqtt未连接,请稍后再试');
        return;
    }
    alert('Subscribing to: \nTopic: ' + topic +'\nQoS: '+qos);
    client.subscribe(topic, {qos: qos});
}
/*取消主题订阅
* @topic: 订阅主题 string
* @qos: 消息质量 int
*/
function unsubscribe(topic){
    client.unsubscribe(topic, {
         onSuccess: unsubscribeSuccess,
         onFailure: unsubscribeFailure,
         invocationContext: {topic : topic}
     });
}
function unsubscribeSuccess(context){
    alert('Successfully unsubscribed from ', context.invocationContext.topic);
}
function unsubscribeFailure(context){
    alert('Failed to  unsubscribe from ', context.invocationContext.topic);
}


// Just in case someone sends html
function safe_tags_regex(str) {
   return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

function makeid()
{
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for( var i=0; i < 5; i++ )
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

<think>嗯,用户问的是如何用Nginx配置MQTT代理。首先,我需要回忆一下NginxMQTT的相关知识。MQTT是基于TCP的协议,通常使用1883端口,而WebSocket则可能用8083或者443(如果是WSS)。Nginx作为反向代理,可以处理这些连接。 记得用户提供的引用中有几个配置示例,比如引用2里的mqtt_ws.conf配置了HTTP升级头部,这对WebSocket支持很重要。因为WebSocket连接需要Upgrade和Connection头,所以Nginx必须正确设置这些。还有引用5提到了TLS配置,用SSL证书加密MQTT流量,这样更安全。 然后,用户可能需要不同的场景配置,比如普通TCP代理、WebSocket或者加密的WSS。我需要分别说明这些情况。比如,TCP代理需要Nginx的stream模块,而HTTP层面的代理需要http模块。同时,配置SSL的话,需要指定证书路径和协议版本。 另外,要注意的是Nginx默认可能没有启用stream模块,需要编译时加上--with-stream参数。这点用户可能不知道,所以需要提醒。还有,配置完成后要检查语法并重启服务,这部分操作步骤也要写清楚。 可能用户会遇到的问题包括配置错误导致连接不上,或者证书路径不正确。所以需要强调路径的正确性和权限问题。此外,性能调优参数如proxy_timeout和buffer大小也很重要,特别是处理大量连接时。 最后,生成的相关问题要围绕用户可能进一步的需求,比如内外网通信、性能优化、TLS配置细节等。这些可以帮助用户深入了解更多相关内容。</think>### 如何配置Nginx代理MQTT流量 #### 一、基础配置原理 MQTT协议支持TCP和WebSocket两种传输方式,Nginx可通过以下两种模式实现代理: 1. **TCP层代理**:使用`stream`模块直接代理MQTT的TCP端口(默认1883) 2. **应用层代理**:通过WebSocket协议代理MQTT over WebSocket(常用端口8083/8084) #### 二、具体配置步骤 ##### 1. TCP层代理配置(普通MQTT) ```nginx # 在nginx.conf的stream块中添加 stream { upstream mqtt_backend { server 192.168.1.100:1883; # 目标MQTT服务器地址 } server { listen 1883; proxy_pass mqtt_backend; proxy_connect_timeout 150s; proxy_timeout 2h; # 保持长连接 proxy_buffer_size 3M; # 调整缓冲区大小[^5] } } ``` *适用场景*:物联网设备直连代理 ##### 2. WebSocket代理配置 ```nginx http { map $http_upgrade $connection_upgrade { default upgrade; '' close; } upstream mqtt_ws { server 10.0.0.2:8083; # MQTT over WebSocket服务地址 } server { listen 80; server_name mqtt.example.com; location / { proxy_pass http://mqtt_ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; # 必须的WebSocket升级头[^2] proxy_read_timeout 1d; # 保持持久连接 } } } ``` *典型应用*:浏览器通过JavaScript连接MQTT ##### 3. TLS加密配置 ```nginx server { listen 8883 ssl; # SSL加密端口 ssl_certificate /etc/nginx/certs/server.crt; ssl_certificate_key /etc/nginx/certs/server.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; proxy_pass mqtt_backend; proxy_connect_timeout 150s; proxy_buffer_size 3M; # 建议根据消息大小调整 } ``` *注意*:证书路径需要与实际部署位置一致 #### 三、关键配置说明 1. **连接保持**:MQTT需要长连接,需设置`proxy_timeout 2h` 2. **WebSocket支持**:必须配置`Upgrade`和`Connection`头实现协议升级[^3] 3. **性能优化**: - `proxy_buffer_size`根据消息负载调整 - 使用`least_conn`负载均衡策略应对高并发 #### 四、验证与调试 1. 检查配置语法: ```bash nginx -t ``` 2. 查看连接状态: ```bash netstat -ant | grep 1883 ``` 3. 抓包验证: ```bash tcpdump -i eth0 port 1883 -w mqtt.pcap ```
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值