Skip to content

Commit

Permalink
Breaking: Bind to loopback if no listeners are configured.
Browse files Browse the repository at this point in the history
  • Loading branch information
ralight committed Sep 17, 2020
1 parent 1b26927 commit d7d3087
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 32 deletions.
20 changes: 20 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
Breaking changes:
- When the Mosquitto broker is run without configuring any listeners it will
now bind to the loopback interfaces 127.0.0.1 and/or ::1. This means that
only connections from the local host will be possible.

Running the broker as `mosquitto` or `mosquitto -p 1883` will bind to the
loopback interface.

Running the broker with a configuration file with no listeners configured
will bind to the loopback interface with port 1883.

Running the broker with a listener defined will bind by default to `0.0.0.0`
/ `::` and so will be accessible from any interface. It is still possible to
bind to a specific address/interface.

If the broker is run as `mosquitto -c mosquitto.conf -p 1884`, and a
listener is defined in the configuration file, then the port defined on the
command line will be IGNORED, and no listener configured for it.


Broker:
- When running as root, if dropping privileges to the "mosquitto" user fails,
then try "nobody" instead. This reduces the burden on users installing
Expand Down
16 changes: 13 additions & 3 deletions man/mosquitto.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

<refsect1>
<title>Description</title>
<para><command>mosquitto</command> is a broker for the MQTT protocol version 3.1.1/3.1.</para>
<para><command>mosquitto</command> is a broker for the MQTT protocol version 5.0/3.1.1/3.1.</para>
</refsect1>

<refsect1>
Expand All @@ -39,7 +39,12 @@
<term><option>-c</option></term>
<term><option>--config-file</option></term>
<listitem>
<para>Load configuration from a file. If not given, the default values as described in <citerefentry><refentrytitle>mosquitto.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> are used.</para>
<para>
Load configuration from a file. If not given, then the broker will listen on port 1883 bound to the loopback interface,
and the default values as described in <citerefentry><refentrytitle>mosquitto.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
are used.
</para>
<important><para>See the <option>-p</option> option for a description of changes in behaviour from 1.6.x to 2.0.</para></important>
</listitem>
</varlistentry>
<varlistentry>
Expand All @@ -53,7 +58,12 @@
<term><option>-p</option></term>
<term><option>--port</option></term>
<listitem>
<para>Listen on the port specified instead of the default 1883. This acts in addition to the port setting in the config file. May be specified multiple times to open multiple sockets listening on different ports. This socket will be bound to all network interfaces.</para>
<para>Listen on the port specified. May be specified up to 10 times to open multiple sockets listening on different ports.</para>
<important><para>In version 1.6.x and earlier, the listener defined by <option>-p</option> (or the default port of 1883) would be
bound to all interfaces and so be accessible from any network. It could also be used in combination with <option>-c</option>.</para>
<para>From version 2.0 onwards, the listeners defined with <option>-p</option> are bound to the loopback interface only, and so can
only be connected to from the local machine. If both <option>-p</option> is used and a listener is defined in a configuration
file, then the <option>-p</option> options are IGNORED.</para></important>
</listitem>
</varlistentry>
<varlistentry>
Expand Down
11 changes: 6 additions & 5 deletions src/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,10 +401,12 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid port specified (%d).", port_tmp);
return MOSQ_ERR_INVAL;
}else{
if(config->default_listener.port){
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Default listener port specified multiple times. Only the latest will be used.");
if(config->cmd_port_count == CMD_PORT_LIMIT){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Only %d ports can be specified on the command line.", CMD_PORT_LIMIT);
return MOSQ_ERR_INVAL;
}
config->default_listener.port = port_tmp;
config->cmd_port[config->cmd_port_count] = port_tmp;
config->cmd_port_count++;
}
}else{
log__printf(NULL, MOSQ_LOG_ERR, "Error: -p argument given, but no port specified.");
Expand All @@ -420,8 +422,7 @@ int config__parse_args(struct mosquitto_db *db, struct mosquitto__config *config
}
}

if(config->listener_count == 0
|| config->default_listener.bind_interface
if(config->default_listener.bind_interface
#ifdef WITH_TLS
|| config->default_listener.cafile
|| config->default_listener.capath
Expand Down
122 changes: 100 additions & 22 deletions src/mosquitto.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,42 +206,120 @@ void mosquitto__daemonise(void)
}


int listeners__start_single_mqtt(struct mosquitto_db *db, mosq_sock_t **listensock, int *listensock_count, int *listensock_index, struct mosquitto__listener *listener)
{
int i;
mosq_sock_t *listensock_new;

if(net__socket_listen(listener)){
return 1;
}
(*listensock_count) += listener->sock_count;
listensock_new = mosquitto__realloc(*listensock, sizeof(mosq_sock_t)*(*listensock_count));
if(!listensock_new){
return 1;
}
*listensock = listensock_new;

for(i=0; i<listener->sock_count; i++){
if(listener->socks[i] == INVALID_SOCKET){
return 1;
}
(*listensock)[*listensock_index] = listener->socks[i];
(*listensock_index)++;
}
return MOSQ_ERR_SUCCESS;
}


int listeners__add_local(struct mosquitto_db *db, mosq_sock_t **listensock, int *listensock_count, int *listensock_index, const char *host, uint16_t port)
{
struct mosquitto__listener *listeners;

listeners = mosquitto__realloc(db->config->listeners, (db->config->listener_count+1)*sizeof(struct mosquitto__listener));
if(listeners == NULL){
return MOSQ_ERR_NOMEM;
}
db->config->listener_count++;
db->config->listeners = listeners;
memset(&listeners[db->config->listener_count-1], 0, sizeof(struct mosquitto__listener));

listeners[db->config->listener_count-1].security_options.allow_anonymous = -1;
listeners[db->config->listener_count-1].security_options.allow_zero_length_clientid = true;
listeners[db->config->listener_count-1].protocol = mp_mqtt;
listeners[db->config->listener_count-1].port = port;
listeners[db->config->listener_count-1].maximum_qos = 2;
listeners[db->config->listener_count-1].max_topic_alias = 10;
listeners[db->config->listener_count-1].host = mosquitto__strdup(host);
if(listeners[db->config->listener_count-1].host == NULL){
return MOSQ_ERR_NOMEM;
}
if(listeners__start_single_mqtt(db, listensock, listensock_count, listensock_index, &listeners[db->config->listener_count-1])){
mosquitto__free(listeners[db->config->listener_count-1].host);
listeners[db->config->listener_count-1].host = NULL;
db->config->listener_count--;
return MOSQ_ERR_UNKNOWN;
}
return MOSQ_ERR_SUCCESS;
}

int listeners__start_local_only(struct mosquitto_db *db, mosq_sock_t **listensock, int *listensock_count)
{
/* Attempt to open listeners bound to 127.0.0.1 and ::1 only */
int i;
int listensock_index = 0;
int rc;

if(db->config->cmd_port_count == 0){
rc = listeners__add_local(db, listensock, listensock_count, &listensock_index, "127.0.0.1", 1883);
if(rc == MOSQ_ERR_NOMEM) return MOSQ_ERR_NOMEM;
rc = listeners__add_local(db, listensock, listensock_count, &listensock_index, "::1", 1883);
if(rc == MOSQ_ERR_NOMEM) return MOSQ_ERR_NOMEM;
}else{
for(i=0; i<db->config->cmd_port_count; i++){
rc = listeners__add_local(db, listensock, listensock_count, &listensock_index, "127.0.0.1", db->config->cmd_port[i]);
if(rc == MOSQ_ERR_NOMEM) return MOSQ_ERR_NOMEM;
rc = listeners__add_local(db, listensock, listensock_count, &listensock_index, "::1", db->config->cmd_port[i]);
if(rc == MOSQ_ERR_NOMEM) return MOSQ_ERR_NOMEM;
}
}

if(db->config->listener_count > 0){
return MOSQ_ERR_SUCCESS;
}else{
return MOSQ_ERR_UNKNOWN;
}
}


int listeners__start(struct mosquitto_db *db, mosq_sock_t **listensock, int *listensock_count)
{
int i, j;
int i;
int listensock_index = 0;

listensock_index = 0;
(*listensock_count) = 0;

if(db->config->listener_count == 0){
if(listeners__start_local_only(db, listensock, listensock_count)){
db__close(db);
if(db->config->pid_file){
remove(db->config->pid_file);
}
return 1;
}
return MOSQ_ERR_SUCCESS;
}

for(i=0; i<db->config->listener_count; i++){
if(db->config->listeners[i].protocol == mp_mqtt){
if(net__socket_listen(&db->config->listeners[i])){
db__close(db);
if(db->config->pid_file){
remove(db->config->pid_file);
}
return 1;
}
(*listensock_count) += db->config->listeners[i].sock_count;
*listensock = mosquitto__realloc(*listensock, sizeof(mosq_sock_t)*(*listensock_count));
if(!(*listensock)){
if(listeners__start_single_mqtt(db, listensock, listensock_count, &listensock_index, &db->config->listeners[i])){
db__close(db);
if(db->config->pid_file){
remove(db->config->pid_file);
}
return 1;
}
for(j=0; j<db->config->listeners[i].sock_count; j++){
if(db->config->listeners[i].socks[j] == INVALID_SOCKET){
db__close(db);
if(db->config->pid_file){
remove(db->config->pid_file);
}
return 1;
}
(*listensock)[listensock_index] = db->config->listeners[i].socks[j];
listensock_index++;
}
}else if(db->config->listeners[i].protocol == mp_websockets){
#ifdef WITH_WEBSOCKETS
db->config->listeners[i].ws_context = mosq_websockets_init(&db->config->listeners[i], db->config);
Expand Down
5 changes: 3 additions & 2 deletions src/mosquitto_broker_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ and the Eclipse Distribution License is available at

#define WEBSOCKET_CLIENT -2


#define CMD_PORT_LIMIT 10
#define TOPIC_HIERARCHY_LIMIT 200

/* ========================================
Expand Down Expand Up @@ -235,7 +235,6 @@ struct mosquitto__security_options {
};

struct mosquitto__listener {
int fd;
uint16_t port;
char *host;
char *bind_interface;
Expand Down Expand Up @@ -285,6 +284,8 @@ struct mosquitto__config {
bool check_retain_source;
char *clientid_prefixes;
bool connection_messages;
uint16_t cmd_port[CMD_PORT_LIMIT];
int cmd_port_count;
bool daemon;
struct mosquitto__listener default_listener;
struct mosquitto__listener *listeners;
Expand Down
4 changes: 4 additions & 0 deletions src/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener)

if(net__socket_nonblock(&sock)){
freeaddrinfo(ainfo);
mosquitto__free(listener->socks);
return 1;
}

Expand All @@ -650,6 +651,7 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener)
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);
freeaddrinfo(ainfo);
mosquitto__free(listener->socks);
return 1;
}
}
Expand All @@ -659,13 +661,15 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener)
net__print_error(MOSQ_LOG_ERR, "Error: %s");
COMPAT_CLOSE(sock);
freeaddrinfo(ainfo);
mosquitto__free(listener->socks);
return 1;
}

if(listen(sock, 100) == -1){
net__print_error(MOSQ_LOG_ERR, "Error: %s");
freeaddrinfo(ainfo);
COMPAT_CLOSE(sock);
mosquitto__free(listener->socks);
return 1;
}
}
Expand Down

0 comments on commit d7d3087

Please sign in to comment.