Post

Fixing 3CX IP Blacklist From SSH

I have a 3CX system at home as a fallback phone in the event our wireless provider has issues. It is hosted locally in a Proxmox VE on an old MacBook Pro.

I recently made some changes to my home network that resulted in me being locked out of the interface. This is despite me having a rule permitting the entire /20 I use at home. Not sure how it happened, but it did. A quick Google search says pay 3CX $75 for a support ticket. This is a super simple problem, and I’d rather rebuild from backup before I spend $75 on something like this.

Let’s fix it.

Find the SQL

I knew from the install 3CX is a modified version of Debian. I recall it also has a database from various updates I’ve done in the past.

1
2
root@3cx:~# ps aux | grep sql
postgres     536  0.0  1.4 219748 29076 ?        Ss    2024   1:19 /usr/lib/postgresql/15/bin/postgres -D /var/lib/postgresql/15/main -c config_file=/etc/postgresql/15/main/postgresql.conf

PostgreSQL is running. Let’s login.

1
2
3
4
root@3cx:~# sudo -i -u postgres
postgres@3cx:~$ psql
psql (15.10 (Debian 15.10-0+deb12u1))
Type "help" for help.

Find the Blacklist

Let’s list out the tables.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
postgres=# \l

                                                      List of databases
      Name       |    Owner    | Encoding |   Collate   |    Ctype    | ICU Locale | Locale Provider |   Access privileges   
-----------------+-------------+----------+-------------+-------------+------------+-----------------+-----------------------
 database_single | phonesystem | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | 
 masterprofiles  | phonesystem | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | 
 postgres        | postgres    | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | 
 template0       | postgres    | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/postgres          +
                 |             |          |             |             |            |                 | postgres=CTc/postgres
 template1       | postgres    | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/postgres          +
                 |             |          |             |             |            |                 | postgres=CTc/postgres
(5 rows)

Guessing here but let’s see what database_single is since it is owned by phonesystem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
postgres=# \c database_single
You are now connected to database "database_single" as user "postgres".
database_single=# \dt
                    List of relations
 Schema |           Name            | Type  |    Owner    
--------+---------------------------+-------+-------------
 public | announcement              | table | phonesystem
 public | audiofeed                 | table | phonesystem
 public | audiofeedcontent          | table | phonesystem
 public | audit_log                 | table | phonesystem
 public | blacklist                 | table | phonesystem
 public | calendar                  | table | phonesystem
~~~~ Truncated ~~~~
 public | holiday                   | table | phonesystem
 public | inboundcalleridblock      | table | phonesystem
 public | inboundrule               | table | phonesystem

I feel blacklist might be related to my issues.

Let’s see what we have for a structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
database_single=# \d blacklist
                                    Table "public.blacklist"
   Column    |          Type          | Collation | Nullable |             Default              
-------------+------------------------+-----------+----------+----------------------------------
 idblacklist | integer                |           | not null | nextval('sqblacklist'::regclass)
 ipaddr      | character varying(255) |           | not null | 
 ipmask      | character varying(255) |           | not null | ''::character varying
 description | character varying(512) |           |          | 
 expiresat   | character varying(255) |           | not null | 
 blocktype   | integer                |           |          | 0
 pv_addedby  | character varying      |           |          | 
Indexes:
    "blacklist_pkey" PRIMARY KEY, btree (idblacklist)

I’m sure they have a perfectly good reason to use the character varying data type over cidr or inet. Let’s see what we have in the table.

1
2
3
4
5
6
database_single=# SELECT * FROM blacklist WHERE ipaddr LIKE '192.168%';
 idblacklist |    ipaddr    |     ipmask      |                                description                                |  expiresat  | blocktype | pv_addedby 
-------------+--------------+-----------------+---------------------------------------------------------------------------+-------------+-----------+------------
       15423 | 192.168.0.1 | 255.255.255.255 | PBX: blocked for too many failed authentications; User-Agent: FreePBX 1.8 | 13695524072 |         0 | 
(1 row)

Remove the Blacklist

That would be my issue. Delete!

1
database_single=# DELETE FROM blacklist WHERE idblacklist = 15423;

Cool, but still can’t login. I reboot the server and clear my browser cache and cookies, then open a new browser tab.

1
2
3
4
database_single=# exit;
postgres@3cx:~$ exit;
logout
root@3cx:~# reboot now

Server comes up, I can login. Everything is happy. I add a /32 for my PC to the allow list.

Sources / Linkage

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.

© Kevin Schwickrath. Some rights reserved.

Using the Chirpy theme for Jekyll.