Configuring and Testing Mosquitto MQTT Topic Restrictions

mosquitto-broker-topic-restrictionsNot only can you restrict access to the Mosquitto MQTT broker using a username and password you can also restrict access to topics.

Unless you are running an open broker you will want to restrict access to topics so that only authorized users/clients can publish or subscribe to them.



Topic restrictions are configured on the Broker, and there is nothing to configure on the client.

Topic restriction is done in an access control list ( ACL ) file.

To enable topic restrictions you need to edit the mosquitto.conf file to use it.

Note: You should create a copy of the default file as a backup before you edit it.

You will find the setting in the Default authentication and topic access control section:

You need to add the following line (windows install example)

acl_file c:\mosquitto\aclfile.example

A default file ( aclfile.example ) is provided with the installation.

The contents of this file are shown below:

mosquitto-default-acl-file

The default ACL file is very restrictive, and if implemented as is, would deny access to almost every topic to every user and client.

The general rule is that, by default, you are denied access unless explicitly allowed.

The file has effectively three sections:

  • General section
  • User specific section
  • Client or user ID section

General Section

Entries here start with the keyword topic and apply to all clients except if the client provides a user name.

If the client provides a username then entries in this section are ignored for that user.

The entry in the default file is

topic read $SYS/#

This gives read (subscribe) access to any client that doesn’t supply a username to the topic $SYS/#.

Any client trying to subscribe or publish to any other topics e.g. house/sensor1 would be denied.

User Section

This section uses the keyword user.

Each user can have topic entries that define access rights. The default file contains the following entry

user roger
topic foo/bar

This entry only apples if the client supplies a username otherwise it is ignored.

The entry means that a user named roger can publish and subscribe on the topic foo/bar.

No other user can publish or subscribe on any other topics.

Note: topic foo/bar is the same as topic readwrite foo/bar

Client or User ID Section

Every client will provide a client ID.

Entries in this section will only apply to the client with that Client ID.

The entry in the default file is

pattern write $SYS/broker/connection/%c/state

This means that a client with client name or ID of P1 can publish to the topic:

$SYS/broker/connection/P1/state

and a client with client ID of P2 can publish to the topic

$SYS/broker/connection/P2/state

Client P! cannot publish to :

$SYS/broker/connection/P2/state

However entries in the General section and User section will also need to be taken into consideration and could allow more access.

The user id is used in a similar fashion.

pattern readwrite phone/inbox/%u/#

Would give user roger publish and subscribe access to:

phone/inbox/roger/#

Detecting Access Control Restrictions

Unfortunately it is not easy to detect ACL restrictions as they aren’t notified to the client.

This means that if a client subscribes to a topic and is denied by the ACL then the client doesn’t know it has been denied as it receives a positive acknowledgement.

In addition if a client publishes to a topic and is denied, again the client doesn’t know it has been denied as it receives a positive acknowledgement. (This you will see in the examples below)

The only way you can really detect a problem is by subscribing and publishing to a topic and detecting or not detecting the published message.

Access Control Examples -General Settings

In the detailed examples below we look at topic restrictions using the general settings.

Later we look at User and client settings and how they are used to control topic access.

In the examples below we will use a simple python script to subscribe and publish and examine the results on the python client and on the broker console.

In the examples below we will do the following:

  1. Subscribe and Publish to a topic with no ACL configured.
  2. Subscribe and Publish to a topic using the default ACL file.
  3. Edit the default ACL file to allow subscriptions and then Subscribe and Publish to a topic.
  4. Edit the default ACL file to allow subscriptions and publishing and then Subscribe and Publish to a topic.

In each case we look at the various return and error codes shown by the client script and on the Mosquitto broker console.

For the examples I have enabled logging of all error messages on the broker.

Example 1-Subscribe and Publish to a topic with no ACL configured.

With no ACL being used then we are free to subscribe and publish to any topic.

The screen shots below show that the messages we publish are received.

acl_restrictions_no_acl

Example 2- Subscribe and Publish to a topic with the default ACL configured.

With the default ACL being used then we are restricted to reading the #SYS topic.

In the example we subscribe to house/# and publish to house/sensor1

The screen shots below show that the messages we publish are not received which is as expected.

However notice that the subscribe return code and publish return code indicate success.

However the Mosquitto server console logs a published denied message.

acl_restrictions_default_acl

Example 3- Subscribe and Publish to a topic with an Edited ACL .

This time we edit the default ACL to allow subscribing to topic house/#

The setting is

topic read house/#

Again,In the example we subscribe to house/# and publish to house/sensor1

The screen shots below show that the messages we publish are not received which is as expected.

However notice that the subscribe return and publish return codes indicate success.

However the Mosquitto server console logs a published denied message.

acl_restrictions_edited_read_acl

Example 4- Subscribe and Publish to a topic with an Edited ACL.

This time we edit the default ACL to allow anyone to subscribe and publish to topic house/# .

the setting is

topic readwrite house/#

Again,In the example we subscribe to house/# and publish to house/sensor1

The screen shots below show that the messages we publish are received, which is as expected.

This time the Mosquitto server console logs the message being sent back to the client.

acl_restrictions_edited_readwrite_acl

User Restrictions

User restrictions are triggered when the client provides a username.

If a username is provided by the client then the ACL list is checked for that user.

Username restrictions will override General restrictions.

This means that if the General settings allow access to that topic, if the client provides a username, and that username doesn’t have an entry in the ACL explicitly giving access to that topic, then they are denied.

Client Settings

Client settings usually use the client ID as part of a pattern match.

You normally see entries like:

pattern readwrite house/%C/#

This setting will allow a client with client id python1 to publish and subscribe to topic house/python1/#.

Client python1 will not be able to publish and subscribe to topic house/lights/#.

Client Settings and General Settings are additive. This means that if the client settings don’t allow, but the General settings do then, it is allowed.

Client Settings will override User Settings. This means that if clients settings allow a client to publish/subscribe to a topic then they are allowed regardless of the user settings.

The Following table tries to summarize the General,User and Client Settings

General Settings

User Settings

Client sends Username

Client

Settings

Result

Blank Blank No Blank Denied
Configured Blank or configured No Blank Depends on General settings
Blank or configured Blank Yes Blank Denied
Blank or configured Configured Yes Blank Depends on User settings. General settings don’t apply
Blank or configured Blank or configured No Configured Combination of General and Client settings
Blank or configured Blank or configured Yes Configured Client Settings will override user settings and user settings make General settings irrelevant

Examples Settings

Here are some example settings to illustrate the above

Example 1 -User Settings

#General settings

readwrite topic #

#User settings

user Roger
topic readwrite house/#

#Client settings

#Blank

Result

Only user roger can publish and subscribe to topic house/#.

If the client doesn’t send a username then the client can publish and subscribe to all topics -entry readwrite topic # in General settings.


Example 2 -User and Client Settings

#General settings

#Blank

#User settings

user Roger
topic readwrite house/P1/#

#Client settings

pattern readwrite house/%C/#

Result

If the client name is Python 1 then that client can publish and subscribe to topic house/Python1/# regardless of the username sent.

However only user roger can publish and subscribe to topic house/P1/#..

Important Notes:

Topic names and usernames are case sensitive. User roger isn’t the same as user Roger.

Topic house/Python1/# isn’t the same as house/python1/#.

Common Questions and Answers

Q- How do I know if my published message has been denied by the broker or just lost?

A- You cannot tell from the client.

Q-Does the user in the ACL user section need to be added to the passwords file?

A- No, not for the ACL to work, but it does if you are also using username and password authentication.

Summary

You can restrict access to a broker by configuring Access control.

Access control can be applied to users,client ids and topics.

From a client perspective is isn’t easy to know if access control is being applied as restrictions aren’t notified to the client.



Mosquitto Configuration Tutorials

Related Tutorials and Resources

Please rate? And use Comments to let me know more
[Total: 12    Average: 4.6/5]

45 comments

  1. Hi Steve,
    I’m trying to set the ACL with an admin user with access to all topics, and a pattern for normal users.
    I’ve tried the following in the acl_file:
    user admin
    topic readwrite house/#
    pattern readwrite house/%u/#

    In my password file, I have 2 users: admin and user1. I can connect fine using admin. However, as soon as I try to connect using user1, I get a socket error from the broker, and both admin and user1 gets disconnected.

    Help appreciated. Thanks

      1. Hi Steve,
        I checked, and sure enough the client_ids were the same. I generated a new client_id for user1, but user1 still can’t connect. The admin stays connected this time.

  2. Hello.
    Could you help me, please, to solve mqtt access problem?

    I have client’s authorization with certificates.
    And it works fine.

    But i also need to add one client’s authorization, as admin, to read all client’s topics.

    My ACL:
    pattern readwrite %u/#
    user admin
    topic readwrite #

    But in this way nobody has access to write/read topics.
    If i did in ACL only – pattern readwrite %u/# – work fine.

    How can i use certificates and user authorization in one ACL?

    1. Hi
      Can you try again I just tested it with:
      user admin
      topic readwrite house/#

      pattern readwrite houde/%u/#

      and it worked as expected.
      admin could access all topics under house/
      rgds
      steve

      1. Hello, Steve.
        Thank you for your answer.
        But if i use the same contruction, nobody can connect (even with certificate).

        Could you show me your config, please?

        My config:

        allow_anonymous true
        password_file /etc/mosquitto/passwd

        listener 1883 localhost
        listener 8883
        cafile /etc/mosquitto/mqtt_ca.crt
        certfile /etc/mosquitto/cert.crt
        keyfile /etc/mosquitto/cert.key
        require_certificate true
        use_identity_as_username true
        acl_file /etc/mosquitto/mqtt.acl
        tls_version tlsv1.2

        1. My config doesn’t use certificates
          # Place your local configuration in /etc/mosquitto/conf.d/
          #
          # A full description of the configuration file is at
          # /usr/share/doc/mosquitto/examples/mosquitto.conf.example

          pid_file /var/run/mosquitto.pid

          persistence true
          persistence_location /var/lib/mosquitto/

          #log_dest file /var/log/mosquitto/mosquitto.log

          include_dir /etc/mosquitto/conf.d
          port 1883
          log_type error
          log_type notice
          log_type information
          log_type debug
          log_type websockets

          connection_messages true

          log_type all
          log_dest stdout
          acl_file aclfile.example

          The acl_file is
          # This affects access control for clients with no username.
          #topic read $SYS/#
          #topic read +/r2
          #topic readwrite #

          # This only affects clients with username “roger”.

          user steve
          #topic read +/r1
          topic readwrite house/#

          # This affects all clients.
          #pattern write $SYS/broker/connection/%c/state
          #pattern write house/%C/#
          pattern readwrite house/%u/#

          I used steve not admin. With the above file all users will need a username.
          Rgds
          Steve

  3. Hi,

    I am facing an issue while configuring the acl so that the client can subscribe to a specific subtopic. Actually I want that the client should subscribe to +/r1 and publish at +/r2.

    Following is my acl file content:
    user xyz
    topic read +/r1
    topic write +/r2

    But the issue is the client can read all the topics even r2, r3 or anything else.

    1. Hi
      The problem with your current acl is that only usere xyz can publish on +/r2 which works OK. However user xyz can subscribe to +/r1 which no one can publish on.
      When I test it I see the publish being denied on all topics except +/r2.
      To see what is being published use:

      user steve
      topic read +/r1
      topic readwrite +/r2

      or to the general section add
      topic read +/r2
      or
      topic read #
      depending on how restrictive you want it.
      Rgds
      Steve

  4. Hello!
    1) Can more than one user share the same topics in the ACL? Like:
    user Roger
    user Paul
    topic readwrite house/temperaturesettings
    topic readwrite house/doorlocks

    2) “Client Settings will override User Settings”. This sounds strange to me. It seems to me that any malicious user with a valid password can get access to any topic by just changing it’s client id to one with nice privilegies? Or did I miss something?

    1. Hi
      Its seems like the structure is
      user
      topics
      e.g
      user superuser
      topic readwrite #
      user steve
      topic readwrite #

      I tried putting users on one line with commas and it didn’t work
      You are correct that the client could use a client_id that had access but it would need to know these as they are not sent by the broker.
      Rgds
      Steve

  5. Hi, i’ve been spelling and testing but I’m stuck… 🙁

    I’ve got an x-number registered mqtt users. I use the pattern:
    pattern readwrite %u/#

    This does exactely what I want. The problem arrises if I want to add a ‘superuser’ who may see everything. If I add
    user superuser
    topic #

    All the other users are not allowed anymore. The only way i’m able to allow them is by adding them to the acl file.

    Do you have a generic way / pattern to add this superuser without having to specify the others?

    Regards

    1. Hi
      I tried it and it worked as expected. Here is the file I used
      # This affects access control for clients with no username.
      topic read $SYS/#
      #topic read house/#
      #topic readwrite #

      # This only affects clients with username “roger”.
      user superuser
      topic readwrite #

      # This affects all clients.
      #pattern write $SYS/broker/connection/%c/state
      #pattern write house/%C/#
      pattern readwrite house/%u/#

      1. Hi Steve, turned out that the acl is only red at mosquitto start and not at user-connect. I wanted to implement a dynamic authorization via the acl-file . This would have been an easy solution. Now I must checkout how to use the auth_plugin. The problem is that from html direct to mosquitto you must provide user and password. This is unacceptable in my situation so I must find a way to do the checking on the server. For a moment I was thinking javascript websockets to php and bridge php to mqtt but this looks less performant than to use a plugin.

  6. Hello Steve,

    I get following when i try to implement clientID pattern ‘Unknown configuration variable “pattern”‘, any help would be appreciated.

    1. I assume this is when you try to start mosquitto. Can you use the ask steve page and send me you conf file or paste the relevant lines in the comment box
      rgds
      steve

  7. dear steve,

    when I should edit mosquitto.conf or /etc/conf.d/default.conf?

    I’m really in doubt bc I tought that default.conf is a substitute for mosquitto.conf…

    1. Hi
      You should edit the mosquitto.conf file. When testing I create a new conf file and use that as it is easier than editing the mosquitto.connf file as you need su permission.

  8. Hello Steve! When I put the acl_file entry on conf.d/default.conf, it stops all authentication: nothing can even connect to the broker. Why?

  9. Hi Steve,

    Great article, very informative. Is it possible to deny access by IP Addresses? Or to only allow access to specific IP Address?

    Thanks.

    1. Glad you found the article useful. You cannot restrict access by IP address using the mosquitto.conf file. In a way it is not surprising as client IP addresses can change.
      If you needed to do that then you could use IPtables on Linux.

  10. Hello Steve,

    Thank you for the article. It is very imformative. I was wondering is there any way to use external service as acl data provider. I mean in this example broker loads file. But you have to reload it every time acl change a happens. Would it be possible to use database to check acl?

    1. Not as far as I know but the broker is being upgraded to support mqtt vs 5 and things might change then.
      Last time I checked it was supposed to be released in august but I haven’t heard anything. Here is a link to the blog https://mosquitto.org/blog/
      rgds
      steve

  11. Hi
    My users are more than 1 million
    And I am needing user only subscribe in self userid
    So I have to add all user self topic in acl
    If acl contain 1 million user in file so mosquitto cannot load it
    Do you have idea for prevent sinscribe user in other topic for many users?

  12. Hi, Steve. For the example 4, I’ve commented all other setting in ACL file and add in “topic readwrite house/#” but when I publish, the broker still denied the publish. Do you have any idea about this?

    1. BTW, i’m using the windows command prompt console to do the testing and my ACL file only have the setting I mentioned above, if this could be the cause.

  13. @Steve. A very good explanation.
    You have mentioned that :
    “The general rule is that, by default, you are denied access unless explicitly allowed.”

    Is there as way in which we could deny a user from publishing to a particular topics only while he/she has access to other topics. What I want is explicit deny instead of explicit allow.

    1. Of my head I would try to allow all using the # wildcard and then deny on a user name basis. I haven’t tried it yet but I will and let you know. Just to be sure I get what you want . you want all users to have access but deny individual users access to certain topics? Is that correct

  14. Also you said that :
    ” Entries here start with the keyword topic and apply to all clients except if the client provides a user name.
    If the client provides a username then entries in this section are ignored for that user. ”

    the above sentences are not clear. what do you mean from “username” ? username in the CONNECT message or in the GENERAL section of the “acl_file” ?
    can you provide an example?

    thank you very much for your help
    Best regard…

    1. Jack
      username in the connect message. If you look back to the password tutorial you can supply a username and password from the client but if the broker is set for anonymous access, and has no passwords file set the the broker ignores it.
      However that username can be used for access control.
      Does that make sense?

  15. dear steve
    what do you mean from “outline” and “ouline” in this expression?
    {outline]topic read house/# [/ouline]

Leave a Reply

Your email address will not be published. Required fields are marked *