Permissions for the listener in the database

Junior Silva2 days ago

Hello everyone.
Thinking about security and reducing the attack surface, as well as separation of responsibilities, I separated the listening server from the database.
It turns out that I tried to give minimal permissions to the Postgres user "listener," but almost all the columns are "related" to each other, resulting in a lot of permissions being needed. However, my idea, if possible, was to grant write permissions only to positions and some others, preventing this listening user from accessing tc_users and more sensitive tables. If an attacker were to gain access to the database's listener user, they would only be able to write to a very few columns and read only what's necessary.
Would this be possible somehow?

Thank you in advance.

Track-tracea day ago

Why would you think someone can gain acces as a database user and not your whole server?

I would think a bigger risk would be your devices sending data Unencrypted to your server. Once they know the device id they can just send modified device data to the server which will end up in your database.

Junior Silvaa day ago

I always think about security as much as possible. And the idea is exactly that: a potential attacker can gain access to my entire server, but in this case, the listener, since it's the gateway to traccar, is the most targeted. My database server has all its ports closed, with only one port open to a third server, my reverse proxy.

So, if an attacker were to gain access to my listener server, they would certainly have access to traccar.xml with the database password. I specifically wanted this PostgreSQL listener user to have limited permissions. For this reason, the attacker couldn't do much except insert false positions into the devices.

The user password, the list of all clients, all of this would be safe.

How are you planning to separate Traccar into listening part and everything else?

Junior Silvaa day ago

In practice, I have already implemented the separation:

  1. On the listener server, I installed Traccar and left only port 5023 open to listen to the trackers. Nothing else works on this server.

  2. In the listener's Traccar.xml, I configured PostgreSQL by pointing to the IP of the second server (backend/bank).

  3. On the second server, I installed Traccar + PostgreSQL, closed all the ports, leaving open only:

    • 8082 for the reverse proxy (frontend/API)
    • 5432 only for the listener IP (to insert positions).
  4. I created a specific user for the listener, with the intention of giving minimum permissions: consult only the tc_devices table and insert it in tc_positions.

  5. However, when testing, Traccar always requests more permissions in new columns (including tc_users), making the extreme limitation I wanted impossible.

My goal was to reduce the risk if the listener was compromised, ensuring that he could only write positions and read what was necessary. This fine limitation of permissions did not work as expected, but the concept of separating listener and backend continues.

What exactly do you mean by "Traccar always requests more permissions in new columns".

Junior Silva21 hours ago

Hi Anton, thanks for the quick reply.
I want to point out that the Traccar service on the listening server fails to start, and the logs show unexpected errors even when the permissions appear to be correct.
Here's my step-by-step experience:

  • Initial Idea: My goal was to create a database user (listener_user) with the absolute minimum necessary permissions. I started by granting only SELECT permissions on tc_devices (to validate the device ID) and INSERT permissions on tc_positions.
  • The Problem with DatabaseChangeLogLock: The first major hurdle wasn't the lack of permissions on data tables, but rather a persistent "Database is in a locked state" error. After extensive debugging, I discovered that the listener instance requires SELECT permissions on the DATABASECHANGELOG and DATABASECHANGELOGLOCK tables. Apparently, it needs to read the database schema version before proceeding, even though the migration itself is the backend server's responsibility. * The Final Discovery: Even after granting SELECT permissions on these control tables, the service continued to fail with various unclear permission denied errors. After numerous attempts to add granular permissions, the only way I found to get the listener service to start successfully was by granting full privileges, with the following commands:
    GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO traccar_listener_user;
    GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO traccar_listener_user;

This seems to completely defeat the purpose of having a separate, limited user for the listener, as it now has the power to DELETE or UPDATE any table, including tc_users.
So, to be precise, my question is:
Is there any way to run a "listener-only" instance without granting it full privileges on all tables? Preferably only tc_devices (query) and tc_positions (write).
Thanks for your help.

Anton Tananaev17 hours ago

Have you tried disabling database.changelog? Set the value to empty.