Files
nym/scripts/wireguard-exit-policy/exit-policy-tests.sh
T
import this 314a37cabe WG exit policy scripts update (#5921)
* add NIP-3 ports to WG manager script

* add monero ports to local testing script

* console output snippet update
2025-07-30 09:43:39 +00:00

241 lines
7.6 KiB
Bash

#!/bin/bash
# Nym Exit Policy Verification Unit Tests
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
NC='\033[0m'
NYM_CHAIN="NYM-EXIT"
WG_INTERFACE="nymwg"
check_port_range_rules() {
local port_range="$1"
local protocol="${2:-tcp}"
local chain="${3:-$NYM_CHAIN}"
# Extract start and end ports
local start_port=$(echo "$port_range" | cut -d'-' -f1)
local end_port=$(echo "$port_range" | cut -d'-' -f2)
if iptables -t filter -C "$chain" -p "$protocol" --dport "$start_port:$end_port" -j ACCEPT 2>/dev/null; then
echo -e "${GREEN}✓ Rule exists: $chain $protocol port range $start_port:$end_port${NC}"
return 0
else
echo -e "${RED}✗ Rule missing: $chain $protocol port range $start_port:$end_port${NC}"
echo -e "${YELLOW}Dumping all rules in $chain:${NC}"
iptables -L "$chain" -n | grep "$protocol"
return 1
fi
}
# Test port range rules
test_port_range_rules() {
echo -e "${YELLOW}Testing Port Range Rules...${NC}"
# Select the essential port ranges for testing
local port_ranges=(
"20-21:tcp:FTP"
"80-81:tcp:HTTP"
"2082-2083:tcp:CPanel"
"5222-5223:tcp:XMPP"
"27000-27050:tcp:Steam (sampling)"
"989-990:tcp:FTP over TLS"
"5000-5005:tcp:RTP/VoIP"
"8087-8088:tcp:Simplify Media"
"8232-8233:tcp:Zcash"
"8332-8333:tcp:Bitcoin"
"18080-18081:tcp:Monero"
)
local total_failures=0
for range in "${port_ranges[@]}"; do
IFS=':' read -r port_range protocol service <<< "$range"
# Extract start and end ports
local start_port=$(echo "$port_range" | cut -d'-' -f1)
local end_port=$(echo "$port_range" | cut -d'-' -f2)
echo -e "${YELLOW}Testing $service $protocol port range $port_range${NC}"
if iptables -t filter -C "$NYM_CHAIN" -p "$protocol" --dport "$start_port:$end_port" -j ACCEPT 2>/dev/null; then
echo -e "${GREEN}✓ Rule exists: $NYM_CHAIN $protocol port range $start_port:$end_port${NC}"
else
echo -e "${RED}✗ Rule missing: $NYM_CHAIN $protocol port range $start_port:$end_port${NC}"
((total_failures++))
echo -e "${YELLOW}Existing rules for protocol $protocol:${NC}"
iptables -L "$NYM_CHAIN" -n | grep "$protocol"
fi
done
if [ $total_failures -eq 0 ]; then
return 0
else
return 1
fi
}
test_critical_services() {
echo -e "${YELLOW}Testing Critical Service Rules...${NC}"
local tcp_services=(
22 # SSH
53 # DNS
443 # HTTPS
853 # DNS over TLS
1194 # OpenVPN
)
local udp_services=(
53 # DNS
123 # NTP
1194 # OpenVPN
)
local failures=0
# Test TCP services
for port in "${tcp_services[@]}"; do
local rule_found=false
# First check for exact match
if iptables -t filter -C "$NYM_CHAIN" -p tcp --dport "$port" -j ACCEPT 2>/dev/null; then
echo -e "${GREEN}✓ Rule exists: NYM-EXIT tcp port $port${NC}"
rule_found=true
else
# If not found as exact port, search for it in port ranges
# This checks if the port is covered by any range rule
if iptables-save | grep -E "^-A $NYM_CHAIN.*tcp.*dpts:" | grep -qP "dpts:(\d+:)?$port(:|\d+)" || \
iptables-save | grep -E "^-A $NYM_CHAIN.*tcp.*dpts:" | grep -qP "dpts:$port:"; then
echo -e "${GREEN}✓ Rule exists: NYM-EXIT tcp port $port (covered by a range rule)${NC}"
rule_found=true
else
echo -e "${RED}✗ Rule missing: NYM-EXIT tcp port $port${NC}"
((failures++))
fi
fi
done
# Test UDP services - similar approach
for port in "${udp_services[@]}"; do
local rule_found=false
if iptables -t filter -C "$NYM_CHAIN" -p udp --dport "$port" -j ACCEPT 2>/dev/null; then
echo -e "${GREEN}✓ Rule exists: NYM-EXIT udp port $port${NC}"
rule_found=true
else
# If not found as exact port, search for it in port ranges
if iptables-save | grep -E "^-A $NYM_CHAIN.*udp.*dpts:" | grep -qP "dpts:(\d+:)?$port(:|\d+)" || \
iptables-save | grep -E "^-A $NYM_CHAIN.*udp.*dpts:" | grep -qP "dpts:$port:"; then
echo -e "${GREEN}✓ Rule exists: NYM-EXIT udp port $port (covered by a range rule)${NC}"
rule_found=true
else
echo -e "${RED}✗ Rule missing: NYM-EXIT udp port $port${NC}"
((failures++))
fi
fi
done
echo -e "${YELLOW}Relevant existing rules for HTTP (port 80):${NC}"
iptables-save | grep -E "$NYM_CHAIN.*tcp" | grep -E "(dpt|dpts):.*80"
return $failures
}
# Verify default reject rule exists
test_default_reject_rule() {
echo -e "${YELLOW}This test takes some time, do not quit the process${NC}"
echo
echo -e "${YELLOW}Testing Default Reject Rule...${NC}"
# Try different patterns to detect the reject rule
if iptables -L "$NYM_CHAIN" | grep -q "REJECT.*all.*anywhere.*anywhere.*reject-with"; then
echo -e "${GREEN}✓ Default REJECT rule exists${NC}"
return 0
elif iptables -L "$NYM_CHAIN" | grep -q "REJECT.*all -- .*everywhere.*everywhere"; then
echo -e "${GREEN}✓ Default REJECT rule exists${NC}"
return 0
elif iptables -L "$NYM_CHAIN" | grep -q "REJECT.*all.*0.0.0.0/0.*0.0.0.0/0"; then
echo -e "${GREEN}✓ Default REJECT rule exists${NC}"
return 0
elif iptables -n -L "$NYM_CHAIN" | grep -qE "REJECT.*all.*0.0.0.0/0.*0.0.0.0/0"; then
echo -e "${GREEN}✓ Default REJECT rule exists${NC}"
return 0
elif iptables -L "$NYM_CHAIN" | tail -1 | grep -q "REJECT"; then
echo -e "${GREEN}✓ Default REJECT rule exists at the end of chain${NC}"
return 0
else
echo -e "${RED}✗ Default REJECT rule missing${NC}"
# Display the last 3 rules in the chain for debugging
echo -e "${YELLOW}Last 3 rules in the chain:${NC}"
iptables -L "$NYM_CHAIN" | tail -3
return 1
fi
}
run_all_tests() {
local total_failures=0
local total_tests=0
local skip_default_reject=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--skip-default-reject)
skip_default_reject=true
shift
;;
*)
echo -e "${RED}Unknown argument: $1${NC}"
exit 1
;;
esac
done
local test_functions=(
"test_port_range_rules"
"test_critical_services"
)
if [ "$skip_default_reject" = false ]; then
test_functions+=("test_default_reject_rule")
fi
echo -e "${YELLOW}Running Nym Exit Policy Verification Tests...${NC}"
for test_func in "${test_functions[@]}"; do
((total_tests++))
$test_func
if [ $? -ne 0 ]; then
((total_failures++))
echo -e "${RED}Test $test_func FAILED${NC}"
else
echo -e "${GREEN}Test $test_func PASSED${NC}"
fi
done
echo -e "\n${YELLOW}Test Summary:${NC}"
echo -e "Total Tests: $total_tests"
echo -e "Failures: $total_failures"
if [ $total_failures -eq 0 ]; then
echo -e "${GREEN}All Tests Passed Successfully!${NC}"
exit 0
else
echo -e "${RED}Some Tests Failed. Please review the iptables configuration.${NC}"
exit 1
fi
}
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
# Run the tests
run_all_tests "$@"