This guide implements defense-in-depth security for INN2 servers using iptables firewall rules. The architecture restricts public access while maintaining Tor hidden service connectivity and whitelisted peer access.
# Ensure iptables is installed sudo apt install iptables iptables-persistent -y # Verify INN is running sudo systemctl status innd # Verify Tor is configured (if using hidden service) sudo systemctl status tor
# Clear all existing rules (CAREFUL: may disconnect SSH) sudo iptables -F sudo iptables -X sudo iptables -Z
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Default DROP for incoming, ACCEPT for outgoing sudo iptables -P INPUT DROP sudo iptables -P FORWARD DROP sudo iptables -P OUTPUT ACCEPT
# Allow all localhost traffic (required for Tor) sudo iptables -A INPUT -i lo -j ACCEPT sudo iptables -A OUTPUT -o lo -j ACCEPT
# Allow established and related connections sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Add your trusted peer IPs (replace with actual IPs) sudo iptables -A INPUT -p tcp -s 203.0.113.10 --dport 119 -j ACCEPT sudo iptables -A INPUT -p tcp -s 198.51.100.20 --dport 119 -j ACCEPT sudo iptables -A INPUT -p tcp -s 192.0.2.30 --dport 119 -j ACCEPT # Allow entire subnet (if needed) sudo iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 119 -j ACCEPT
# Allow SSH (if managing remotely) sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT # Allow HTTP/HTTPS (if running web server) sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Log dropped NNTP attempts (before final DROP) sudo iptables -A INPUT -p tcp --dport 119 -m limit --limit 5/min -j LOG --log-prefix "NNTP-DROP: " --log-level 4 # Final DROP (implicit due to default policy, but explicit for clarity) sudo iptables -A INPUT -j DROP
Create a persistent firewall configuration:
sudo nano /etc/iptables/rules.v4
*filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] # Localhost (CRITICAL for Tor) -A INPUT -i lo -j ACCEPT # Established connections -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # SSH (adjust port if non-standard) -A INPUT -p tcp --dport 22 -j ACCEPT # HTTP/HTTPS (if web server) -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # Whitelisted NNTP peers -A INPUT -p tcp -s 203.0.113.10 --dport 119 -j ACCEPT -A INPUT -p tcp -s 198.51.100.20 --dport 119 -j ACCEPT -A INPUT -p tcp -s 192.0.2.30 --dport 119 -j ACCEPT # Log dropped NNTP attempts -A INPUT -p tcp --dport 119 -m limit --limit 5/min -j LOG --log-prefix "NNTP-DROP: " --log-level 4 COMMIT
# Load rules sudo iptables-restore < /etc/iptables/rules.v4 # Make persistent across reboots sudo netfilter-persistent save
# Should succeed (Tor uses localhost) telnet 127.0.0.1 119
# From external machine, should timeout/refuse telnet YOUR_PUBLIC_IP 119
# From whitelisted IP, should succeed telnet YOUR_SERVER_IP 119
# List all rules sudo iptables -L -n -v # Check specific chain sudo iptables -L INPUT -n -v --line-numbers
# View firewall logs sudo tail -f /var/log/syslog | grep NNTP-DROP # Count dropped attempts sudo grep "NNTP-DROP" /var/log/syslog | wc -l
Ensure INN readers.conf matches firewall policy:
sudo nano /etc/news/readers.conf
# Localhost (for Tor)
auth "localhost" {
hosts: "localhost, 127.0.0.1, ::1"
default: "<localhost>"
}
access "localhost" {
users: "<localhost>"
newsgroups: "*"
access: RPA
}
# Whitelisted peers only
auth "peers" {
hosts: "203.0.113.10, 198.51.100.20, 192.0.2.30"
default: "<peer>"
}
access "peers" {
users: "<peer>"
newsgroups: "*"
access: RPA
}
# Add iptables rule sudo iptables -I INPUT 6 -p tcp -s NEW_PEER_IP --dport 119 -j ACCEPT # Save changes sudo netfilter-persistent save # Add to readers.conf sudo nano /etc/news/readers.conf # Add NEW_PEER_IP to hosts: line # Reload INN sudo systemctl reload innd
# Find rule number sudo iptables -L INPUT -n -v --line-numbers # Delete rule (replace X with line number) sudo iptables -D INPUT X # Save changes sudo netfilter-persistent save
Apply same rules for IPv6:
sudo nano /etc/iptables/rules.v6
*filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] # Localhost -A INPUT -i lo -j ACCEPT # Established -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # SSH -A INPUT -p tcp --dport 22 -j ACCEPT # Whitelisted peers (IPv6) -A INPUT -p tcp -s 2001:db8::10 --dport 119 -j ACCEPT COMMIT
sudo ip6tables-restore < /etc/iptables/rules.v6 sudo netfilter-persistent save
# Verify localhost rule exists sudo iptables -L INPUT -n -v | grep "127.0.0.1" # Test directly telnet 127.0.0.1 119 # Check Tor logs sudo journalctl -u tor -f
# Verify peer IP is whitelisted sudo iptables -L INPUT -n -v | grep PEER_IP # Check if IP changed (dynamic IP issue) dig +short peer.example.net # Temporarily allow for testing sudo iptables -I INPUT 1 -p tcp -s PEER_IP --dport 119 -j ACCEPT
# ACCEPT all (removes restrictions) sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT sudo iptables -P OUTPUT ACCEPT sudo iptables -F
sudo nano /usr/local/bin/inn-peer-manager.sh
#!/bin/bash
# INN Peer Whitelist Manager
ACTION=$1
PEER_IP=$2
case "$ACTION" in
add)
echo "Adding peer: $PEER_IP"
iptables -I INPUT 6 -p tcp -s $PEER_IP --dport 119 -j ACCEPT
netfilter-persistent save
echo "Peer $PEER_IP added. Update readers.conf manually."
;;
remove)
echo "Removing peer: $PEER_IP"
RULE_NUM=$(iptables -L INPUT -n --line-numbers | grep "$PEER_IP" | grep "dpt:119" | awk '{print $1}')
if [ -n "$RULE_NUM" ]; then
iptables -D INPUT $RULE_NUM
netfilter-persistent save
echo "Peer $PEER_IP removed."
else
echo "Peer $PEER_IP not found."
fi
;;
list)
echo "Current NNTP peers:"
iptables -L INPUT -n -v | grep "dpt:119"
;;
*)
echo "Usage: $0 {add|remove|list} [PEER_IP]"
exit 1
;;
esac
sudo chmod +x /usr/local/bin/inn-peer-manager.sh # Usage sudo /usr/local/bin/inn-peer-manager.sh add 203.0.113.50 sudo /usr/local/bin/inn-peer-manager.sh list sudo /usr/local/bin/inn-peer-manager.sh remove 203.0.113.50