3

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;
} 
Luca Lotifi
  • 39
  • 1
  • 1
  • 6

4 Answers4

4

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.

hardillb
  • 54,545
  • 11
  • 67
  • 105
  • I changed the conf file with your advice but it sill doesn't work. It always print Connection refused – Luca Lotifi Mar 07 '22 at 12:14
  • Edit the question to show exactly what you've done and the error message. (Also have you enabled external connections in the mosquitto.conf?) – hardillb Mar 07 '22 at 12:34
  • 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 configured – Luca Lotifi Mar 07 '22 at 13:15
  • You need to show how you tried my changes to the nginx config – hardillb Mar 07 '22 at 13:17
  • You should also be looking at the logs for both nginx and mosquitto (also check the edit to the answer) – hardillb Mar 07 '22 at 14:14
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
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/.

-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