Configure Nginx reverse proxy for MQTT
Asked Answered
P

4

6

I'm trying to setting up a reverse proxy that resolve localhost:8081 to a broker installed on an other machine. My Nginx config file is:

worker_processes  1;

events {
    worker_connections 1024;
}

server {
    listen 8081;
    server_name localhost;

    location / {
        proxy_pass tcp://192.168.1.177:1883;
    }
}

But when I try to connect to the broker (from the machine where I'm configuring Nginx) with the command

 mosquitto_sub -h localhost -p 8081 -t "stat/tasmota_8231A8/POWER1"

I get the error Connection refused.

Edit: Mosquitto broker config:

persistence true
persistence_location /var/lib/mosquitto/

include_dir /etc/mosquitto/conf.d

listener 1883
allow_anonymous true

Edit I try with this config file for nginx worker_processes 1;

events {
    worker_connections 1024;
}
stream {
   listen 8081;
   proxy_pass 192.168.1.77:1883;
} 
Protochordate answered 7/3, 2022 at 10:51 Comment(0)
S
6

This won't work for native MQTT.

What you have configured is a HTTP proxy, but MQTT != HTTP.

You need to configure nginx as a stream proxy. e.g.

stream {
  server {
      listen 8081;
      proxy_pass 192.168.1.77:1883;
  }
}

https://docs.nginx.com/nginx/admin-guide/tcp-udp-load-balancer/

Or configure mosquitto to support MQTT over WebSockets (Assuming the client supports this as well). Then you can use HTTP based proxying as WebSockets bootstrap via HTTP.

Schreiber answered 7/3, 2022 at 11:38 Comment(5)
I changed the conf file with your advice but it sill doesn't work. It always print Connection refusedProtochordate
Edit the question to show exactly what you've done and the error message. (Also have you enabled external connections in the mosquitto.conf?)Schreiber
I edite the question. The error showman from mosquitto is exactly “Connection refused”. If I type a wrong address the mosquitto_sub doesn’t return the control to the terminal, so I think I can reach the broker on the other machine (nginx resolve the local host to the correct ip) but the broker is bad configuredProtochordate
You need to show how you tried my changes to the nginx configSchreiber
You should also be looking at the logs for both nginx and mosquitto (also check the edit to the answer)Schreiber
A
0

I got your scenario fully working with the following config (firewall turned off, SELinux set to permissive):

nginx config (on loadbalancer1):

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
   worker_connections 1024;
}


stream {

   server {
      listen              1883;
      proxy_pass          stream_backend;
      proxy_buffer_size   16k;
   }


   upstream stream_backend {
      server mqtt-node-1:1883;
      server mqtt-node-2:1883;
  }

}

mosquitto config on mqtt-node-1 and mqtt-node-2:

max_queued_bytes 10000

max_queued_messages 100

listener 1883

log_type error
log_type information
log_type debug
log_type warning
Angelicaangelico answered 23/4, 2023 at 15:19 Comment(0)
R
0

Instead of using MQTT protocol (TCP in NGINX), try to use HTTP reverse proxy with connection upgrade to WebSocket.

It worked for me:

  1. Add configuration to mosquitto (file /etc/mosquitto/conf.d/ws.conf in Ubuntu 22.04 LTS):
listener 8080 ::1
bind_address localhost
protocol websockets
allow_anonymous true

which opens a local IPv6 port using WebSocket protocol. You can choose IPv4, if you prefer.

  1. Add location in NGINX (file /etc/nginx/sites-enabled/default) inside server scope:
server {
  listen [::]:443 http2 ssl ipv6only=on;
  listen 443 http2 ssl;
  ...
  location /ws {
    proxy_pass http://ip6-localhost:8080/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
  }
}

The proxy_pass points to localhost port, and proxy_set_header allows to switch from HTTP (http://) to WS (ws://) - or HTTPS (https://) to WSS (wss://).

To test MQTT over WebSocket, there's a good Web tool: https://www.hivemq.com/demos/websocket-client/.

Ravenous answered 11/5, 2023 at 2:25 Comment(0)
A
-1

Connection refused is indicative of trying to connect to a port on which no service is listening. Please verify that nginx service is running and that a listener indeed exists. You can do this by

sudo netstat -nlt 

This command will show you ports that are taken. The configured port of the nginx listener should appear in the list

Angelicaangelico answered 23/4, 2023 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.