How to Fix Nginx Permission Denied Error When Binding Ports and Implement Domain-Based Routing with Port Preservation


3 views

When encountering the "Permission denied" error (13) while Nginx tries to connect to upstream servers on non-standard ports (like 41002), this typically stems from Linux security mechanisms. Here's what's happening under the hood:

2015/01/28 16:04:49 [crit] 30571#0: *1 connect() to 123.123.123.1:41002 failed (13: Permission denied)

For RHEL/CentOS systems, you'll need to adjust SELinux policies:

# Temporary solution (not recommended for production)
setenforce 0

# Permanent solution (allows Nginx to connect to non-standard ports)
semanage port -a -t http_port_t -p tcp 41001
semanage port -a -t http_port_t -p tcp 41002

Here's the proper server block configuration that preserves both the port and URI:

server {
    server_name uat.company.com;
    listen 41001;
    listen 41002;
    listen 8080;

    location / {
        proxy_pass http://123.123.123.1:$server_port;
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # Handle redirects properly
        proxy_redirect http://123.123.123.1:$server_port/ http://$host:$server_port/;
    }
}

server {
    server_name qa.company.com;
    listen 41001;
    listen 41002;
    listen 8080;

    location / {
        proxy_pass http://123.123.123.2:$server_port;
        proxy_set_header Host $host:$server_port;
        # ... same headers as above
    }
}

Key points to ensure port preservation works:

  • Always include $server_port in both proxy_pass and Host header
  • Configure proper proxy_redirect rules to handle backend redirects
  • Verify DNS records point to your Nginx server

Ensure your firewall allows traffic on these ports:

# For UFW (Ubuntu)
ufw allow 41001/tcp
ufw allow 41002/tcp

# For firewalld (RHEL/CentOS)
firewall-cmd --permanent --add-port=41001/tcp
firewall-cmd --permanent --add-port=41002/tcp
firewall-cmd --reload

When troubleshooting, check these logs:

# Nginx error log
tail -f /var/log/nginx/error.log

# SELinux audit logs
ausearch -m avc -ts recent

# Network connectivity
nc -zv 123.123.123.1 41002
tcpdump -i any port 41002

When implementing a reverse proxy solution for multiple environments (DEV/QA/UAT) with port preservation requirements, we often encounter permission and routing issues. The key requirements are:

  1. Maintaining original port numbers in proxied requests
  2. Preserving URI paths during redirection
  3. Handling multiple ports (41001, 41002, 8080)
  4. SELinux context considerations

Here's the proper server block configuration that handles both port preservation and URI routing:


# /etc/nginx/conf.d/multi_env_proxy.conf
server {
    server_name uat.company.com;
    listen 41001;
    listen 41002;
    listen 8080;

    location / {
        proxy_pass http://123.123.123.1:$server_port;
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    server_name qa.company.com;
    listen 41001;
    listen 41002;
    listen 8080;

    location / {
        proxy_pass http://123.123.123.2:$server_port;
        proxy_set_header Host $host:$server_port;
        # Additional headers same as above
    }
}

For systems with SELinux enabled, you must configure proper context for network connections:


# Check current SELinux boolean for HTTPD
getsebool -a | grep httpd

# Allow nginx to make network connections
setsebool -P httpd_can_network_connect 1

# Alternative: Temporarily set permissive mode for testing
setenforce 0

The magic happens through these key components:

  • $server_port captures the original request port
  • Host header modification maintains the original host:port combination
  • X-Forwarded headers ensure backends receive correct client information

Use curl to verify the proxy behavior:


curl -v http://uat.company.com:41002/webapp/
curl -v http://qa.company.com:8080/static/home.html

Check nginx logs for troubleshooting:


tail -f /var/log/nginx/error.log
journalctl -u nginx -f

For complex routing scenarios, consider these additional parameters:


proxy_redirect off;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_read_timeout 300;
proxy_connect_timeout 300;