emqx配置ssl/wss/mqtts并且测试通过

3,529 阅读2分钟

1 实现方法

  1. 安装EMQ
  2. 配置nginx转发
  3. 代码测试

1 安装EMQ

  • 1.1 采用docker安装,传送门
docker pull emqx/emqx:v4.0.0

docker run -d --name emqx -p 1883:1883 -p 8081:8081 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqx/emqx:v4.0.0

  • 1.2 EMQ X SSL/TLS 使用配置指南

如果客户端需要直接与 EMQ X 建立 SSL/TLS 连接,那么需要修改 EMQ X 中 SSL/TLS 相关的配置项,通常包括监听端口、CA 证书文件、服务器证书文件等。

如果图省事,可以直接使用emq自带的证书

官方链接:EMQ X SSL/TLS 使用配置指南 | EMQ

# 监听端口我们使用默认的 8883
listener.ssl.external = 8883
# 配置为我们申请下来的证书
listener.ssl.external.keyfile = etc/certs/zhouzb.club/Apache/3_zhouzb.club.key
listener.ssl.external.certfile = etc/certs/zhouzb.club/Apache/2_zhouzb.club.crt
listener.ssl.external.cacertfile = etc/certs/zhouzb.club/Apache/1_root_bundle.crt
# 不开启对端验证
listener.ssl.external.verify = verify_none

  • 1.3 配置文件说明 官方链接:配置说明 | EMQ Docs (emqx.cn) 配置文件 | 说明 | | ------------------ | ------------------- | | etc/emqx.conf | EMQ X 配置文件 | | etc/acl.conf | EMQ X 默认 ACL 规则配置文件 | | etc/plugins/*.conf | EMQ X 扩展插件配置文件|

2 配置nginx转发

为什么要配置nginx转发,其实这里有两个好处:

  • 一是用nginx可以分流,避免流量高峰
  • 二是nginx的高级用法,可以将非加密连接转发到加密连接中
server {

# 建议 WebSocket 也绑定到 443 端口
#listen 443, 8083;
listen 443 ssl;
server_name your.site.com;

ssl on;

ssl_certificate ssl/your.pem;  # 证书路径
ssl_certificate_key ssl/your.key; # 密钥路径


location /mqtt {
    proxy_pass http://127.0.0.1:8084;
    proxy_set_header Sec-WebSocket-Protocol mqtt;
    # 这行就是去除 Sec-WebSocket-Protocol
    #more_clear_headers Sec-WebSocket-Protocol;

    proxy_http_version 1.1;
    proxy_set_header Upgrade websocket;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-real-ip $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
}


}

3 代码测试

这里直接使用mqttjs库连接, 使用前请自行下载.

const mqtt = require('mqtt')
const fs = require('fs')
const { Command } = require('commander')

const program = new Command()
program
  .option('-p, --protocol <type>', 'connect protocol: mqtt, mqtts, ws, wss. default is mqtt', 'mqtt')
  .parse(process.argv)

const host = 'test.mosquitto.org'
const port = '1883'
const clientId = `mqtt_${Math.random().toString(16).slice(3)}`

// connect options
const OPTIONS = {
  clientId,
  clean: true,
  connectTimeout: 4000,
  username: 'emqx',
  password: 'public',
  reconnectPeriod: 1000,
}
// protocol list
const PROTOCOLS = ['mqtt', 'mqtts', 'ws', 'wss']
program.protocol = "wss"
// default is mqtt, unencrypted tcp connection
let connectUrl = `mqtt://${host}:${port}`
if (program.protocol && PROTOCOLS.indexOf(program.protocol) === -1) {
  console.log('protocol must one of mqtt, mqtts, ws, wss.')
} else if (program.protocol === 'mqtts') {
  // mqtts, encrypted tcp connection
  connectUrl = `mqtts://${host}:8883`
//   OPTIONS['ca'] = fs.readFileSync('./broker.emqx.io-ca.crt')
} else if (program.protocol === 'ws') {
  // ws, unencrypted WebSocket connection
  const mountPath = '/mqtt' // mount path, connect emqx via WebSocket
  // connectUrl = `ws://${host}:8080${mountPath}`
  connectUrl = `ws://${host}:8080`
} else if (program.protocol === 'wss') {
  // wss, encrypted WebSocket connection
  const mountPath = '/mqtt' // mount path, connect emqx via WebSocket   
  connectUrl = `wss://test.mosquitto.org:443/mqtt`  

} else {}
console.log("connectUrl:"+connectUrl);
const topic = '/msg/alarmUser/1397739313621377025'

const client = mqtt.connect(connectUrl, OPTIONS)

client.on('connect', () => {
  console.log(`${program.protocol}: Connected`)
  client.subscribe([topic], () => {
    console.log(`${program.protocol}: Subscribe to topic '${topic}'`)
  })
  client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false }, (error) => {
    if (error) {
      console.error(error)
    }
  })
})

client.on('reconnect', (error) => {
  console.log(`Reconnecting(${program.protocol}):`, error)
})

client.on('error', (error) => {
  console.log(`Cannot connect(${program.protocol}):`, error)
})

client.on('message', (topic, payload) => {
  console.log('Received Message:', topic, payload.toString())
})

测试结果,可以看到,已经成功连接

image.png