How to Fix Firewall Rules for PostgreSQL Remote Access on CentOS (iptables Configuration Guide)


27 views

When setting up remote PostgreSQL access on CentOS, the difference between these two error messages reveals crucial firewall configuration insights:

# Timeout error indicates blocked traffic
Ncat: connection timed out

# Connection refused suggests PostgreSQL isn't listening
Ncat: Connection refused

First verify PostgreSQL is actually configured to listen:

# Check postgresql.conf
grep listen_addresses /var/lib/pgsql/data/postgresql.conf
# Should show:
listen_addresses = '*'

# Verify pg_hba.conf has appropriate host entries
host    all             all             0.0.0.0/0               md5

The guide's recommended rules need refinement. Here's what actually works:

# Inbound rule (NEW connections)
-A INPUT -p tcp -m tcp --dport 5432 -m state --state NEW,ESTABLISHED -j ACCEPT

# Outbound rule (responses)
-A OUTPUT -p tcp -m tcp --sport 5432 -m state --state ESTABLISHED -j ACCEPT

# Alternative for specific IP access
-A INPUT -p tcp -s 192.168.1.100 --dport 5432 -m state --state NEW,ESTABLISHED -j ACCEPT

When troubleshooting:

# Check current iptables rules
iptables -L -n -v

# Test basic connectivity
telnet your_server_ip 5432

# Verify PostgreSQL is running
systemctl status postgresql

# Check listening ports
netstat -tulnp | grep 5432
  • SELinux blocking connections (check with getenforce)
  • Network Address Translation (NAT) issues when connecting through VPN
  • Multiple firewall systems running simultaneously (firewalld vs iptables)

For a server allowing connections from 192.168.1.0/24:

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

# PostgreSQL Rules
-A INPUT -s 192.168.1.0/24 -p tcp -m tcp --dport 5432 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -d 192.168.1.0/24 -p tcp -m tcp --sport 5432 -m state --state ESTABLISHED -j ACCEPT

# Default deny
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

Save to /etc/sysconfig/iptables and restart with systemctl restart iptables


When configuring remote PostgreSQL access on CentOS 7 with iptables, you're likely encountering two distinct network-level errors:

  • Connection timed out - Indicates packets aren't reaching the PostgreSQL service (firewall blocking)
  • Connection refused - Means packets reach the host but PostgreSQL isn't listening (service configuration issue)

Here's the proper ruleset that handles both inbound and outbound traffic for PostgreSQL:

# Allow new and established inbound connections
-A INPUT -p tcp -s 192.168.1.0/24 --dport 5432 -m state --state NEW,ESTABLISHED -j ACCEPT

# Allow established outbound connections
-A OUTPUT -p tcp --sport 5432 -m state --state ESTABLISHED -j ACCEPT

# For specific IP access (replace 1.2.3.4 with client IP)
-A INPUT -p tcp -s 1.2.3.4 --dport 5432 -m state --state NEW,ESTABLISHED -j ACCEPT

Before firewall adjustments, ensure PostgreSQL is properly configured:

# In postgresql.conf (usually /var/lib/pgsql/data/postgresql.conf)
listen_addresses = '*'

# In pg_hba.conf
host    all             all             192.168.1.0/24          md5
host    all             all             1.2.3.4/32              md5

After implementing changes:

  1. Restart services:
    systemctl restart postgresql
    service iptables restart
  2. Test connectivity from client:
    psql -h postgres-server-ip -U username -d database_name
    telnet postgres-server-ip 5432
  3. Check service status:
    ss -tulnp | grep postgres
    journalctl -xe

For CentOS 7 with iptables (firewalld disabled):

# Save current rules
iptables-save > /etc/sysconfig/iptables

# Make rules persistent
systemctl enable iptables
systemctl start iptables

Consider using a dedicated chain for PostgreSQL rules for better management:

# Create chain
iptables -N POSTGRESQL

# Add rules to chain
iptables -A POSTGRESQL -p tcp --dport 5432 -j ACCEPT

# Reference chain in INPUT
iptables -A INPUT -j POSTGRESQL