security nginx-proxy-manager ufw hostinger vps linux hardening iptables ssh best-practices
NPM handles only HTTP/HTTPS proxying, SSL termination, basic rate limiting, and app-level access control. It does not provide port-level control, non-HTTP protection, network filtering, scan defense, direct-IP protection, or SSH/admin brute-force protection.
- High risk: Brute force and direct service access
- Medium risk: Container escape and reconnaissance
- Low risk: DDoS amplification
I highly recommend using your home/office ISP block to enable primary ssh as we'd rarely have a dedicated static IP address to ourself to SSH from. To allow a subnet of IP addresses, you can do so using CIDR notation to specify a netmask. For example, if you want to allow all of the IP addresses ranging from 203.0.113.1 to 203.0.113.254 you would append 203.0.113.0/24 to the "Source" field in above code.
First, get your public ip address
dig +short myip.opendns.com @resolver1.opendns.com
Then running the below will output the routed CIDR which is under the BGP Prefix section “AS | BGP Prefix | CC | Registry | Allocated”. The BGP Prefix is outputted and can be pasted into your firewall rule.
dig +short <your IP address>.origin.asn.cymru.com TXT
Prioritize essential controls first, then add service-specific allows, and end with a default deny. Keep the rule order correct and verify after each change.
Rule Name: SSH-Primary
Port: 22
Protocol: TCP
Source: <your ISP's whole routed block/BGP Prefix>
Action: ALLOW
Priority: 1
Rule Name: SSH-Backup
Port: 2222
Protocol: TCP
Source: 0.0.0.0/0
Action: ALLOW (with heavy rate limiting)
Priority: 2
Rule Name: HTTP-Web
Port: 80
Protocol: TCP
Source: 0.0.0.0/0
Action: ALLOW
Priority: 2
Notes: Required for NPM to serve websites
Rule Name: HTTPS-Web
Port: 443
Protocol: TCP
Source: 0.0.0.0/0
Action: ALLOW
Priority: 3
Notes: Required for NPM SSL termination
Rule Name: NPM-Admin
Port: 81
Protocol: TCP
Source: YOUR_ADMIN_IP/32
Action: ALLOW
Priority: 4
Notes: Restrict to admin IPs only
Rule Name: RustDesk-TCP
Ports: 21115, 21116, 21117, 21118, 21119
Protocol: TCP
Source: YOUR_TRUSTED_IPS/32
Action: ALLOW
Priority: 5-9
Notes: Only allow from trusted management IPs
Rule Name: App-Services
Ports: 3002, 3003, 3010, 4000, 5000, 5678, 8080, 8081
Protocol: TCP
Source: SPECIFIC_IP_RANGES (not 0.0.0.0/0)
Action: ALLOW
Priority: 10+
Notes: Only open if direct internet access is required
Rule Name: Default-Deny
All other traffic
Action: DENY/DROP
Priority: 999
Notes: Block all other incoming traffic
Run on the VPS for host-level protection as a safety net.
# Reset and configure UFW
sudo ufw --force reset
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH from your IP only (REPLACE YOUR_IP)
sudo ufw allow from YOUR_IP to any port 22 comment 'SSH access'
# Allow web traffic
sudo ufw allow 80/tcp comment 'HTTP web traffic'
sudo ufw allow 443/tcp comment 'HTTPS web traffic'
# Allow NPM admin from trusted IPs only (REPLACE YOUR_ADMIN_IP)
sudo ufw allow from YOUR_ADMIN_IP to any port 81 comment 'NPM admin'
# Enable firewall
sudo ufw --force enable
# Check status
sudo ufw status verbose# Rate limit SSH to prevent brute force
sudo ufw limit ssh/tcp comment 'Rate limit SSH'
# Allow RustDesk from specific IPs (REPLACE TRUSTED_IP)
sudo ufw allow from TRUSTED_IP to any port 21115:21119 proto tcp comment 'RustDesk'
# Block common attack ports
sudo ufw deny 23/tcp comment 'Block Telnet'
sudo ufw deny 135/tcp comment 'Block RPC'
sudo ufw deny 445/tcp comment 'Block SMB'- Access lists: Create access lists in NPM, add IP restrictions for sensitive routes, enable authentication where possible, and use strong unique passwords.
- Security settings: Enable block common exploits, configure rate limiting, force SSL redirects, disable unnecessary features, and apply regular updates.
# Monitor UFW logs
sudo tail -f /var/log/ufw.log
# Check failed SSH attempts
sudo grep "Failed password" /var/log/auth.log | tail -10
# Monitor NPM logs
docker logs nginx-proxy-manager | tail -20
# Check listening ports
netstat -tlnp | grep LISTENStatus: Implementation required immediately
Risk level: Critical without firewall
Estimated setup time: 30–45 minutes