Restrict SSH Port Forwarding with IPTables
When running SSH services inside a container or virtual machine, you may want to restrict access to specific IP addresses. This blog post walks you through creating an IPTables script to forward and secure SSH access on your server.
The Use Case
Imagine you have:
- A Proxmox server with an LXC container running SSH.
- The external port 2222 on the host forwarding to the container’s SSH port 22.
- A need to allow access only from a specific IP address (e.g.,
2.3.4.5
).
Below is a script to manage the IPTables rules dynamically.
The Script
Save the following script as manage_ssh_forwarding.sh
:
#!/bin/bash
# Parameters
ACTION=$1
CHAIN_NAME="SSH_FORWARD"
PERMITTED_IP="2.3.4.5"
CONTAINER_IP="192.168.1.2"
EXTERNAL_PORT="2222"
CONTAINER_SSH_PORT="22"
if [[ "$ACTION" == "add" ]]; then
# Create a custom chain in the nat table
iptables -t nat -N $CHAIN_NAME
# Allow traffic from the permitted IP address and perform DNAT
iptables -t nat -A $CHAIN_NAME -p tcp -s $PERMITTED_IP --dport $EXTERNAL_PORT -j DNAT --to-destination $CONTAINER_IP:$CONTAINER_SSH_PORT
# Drop other traffic to port 2222
iptables -A INPUT -p tcp --dport $EXTERNAL_PORT ! -s $PERMITTED_IP -j DROP
# Add the chain to the PREROUTING chain in the nat table
iptables -t nat -A PREROUTING -j $CHAIN_NAME
# Allow forwarding for traffic from the permitted IP address
iptables -A FORWARD -p tcp -s $PERMITTED_IP -d $CONTAINER_IP --dport $CONTAINER_SSH_PORT -j ACCEPT
# Drop other forwarded traffic to the container
iptables -A FORWARD -p tcp -d $CONTAINER_IP --dport $CONTAINER_SSH_PORT -j DROP
# Add POSTROUTING rule for container responses
iptables -t nat -A POSTROUTING -s $CONTAINER_IP -j MASQUERADE
echo "SSH forwarding chain added."
elif [[ "$ACTION" == "delete" ]]; then
# Remove rules added by the chain
iptables -t nat -D PREROUTING -j $CHAIN_NAME
iptables -D INPUT -p tcp --dport $EXTERNAL_PORT ! -s $PERMITTED_IP -j DROP
iptables -D FORWARD -p tcp -s $PERMITTED_IP -d $CONTAINER_IP --dport $CONTAINER_SSH_PORT -j ACCEPT
iptables -D FORWARD -p tcp -d $CONTAINER_IP --dport $CONTAINER_SSH_PORT -j DROP
iptables -t nat -D POSTROUTING -s $CONTAINER_IP -j MASQUERADE
# Flush and delete the custom chain
iptables -t nat -F $CHAIN_NAME
iptables -t nat -X $CHAIN_NAME
echo "SSH forwarding chain deleted."
else
echo "Usage: $0 {add|delete}"
exit 1
fi
How to Use
1. Save the Script
Save the script to your server, for example:
nano manage_ssh_forwarding.sh
Paste the script and save the file.
2. Make It Executable
chmod +x manage_ssh_forwarding.sh
3. Add Rules
To apply the rules, run:
./manage_ssh_forwarding.sh add
4. Delete Rules
To remove the rules, run:
./manage_ssh_forwarding.sh delete
Explanation of the Rules
PREROUTING: Redirects incoming traffic on port 2222 from the allowed IP (2.3.4.5) to the container’s SSH port 22.
INPUT: Drops any traffic to port 2222 that is not from the permitted IP.
FORWARD: Ensures only permitted traffic reaches the container and drops all other forwarded traffic.
POSTROUTING: Handles NAT to ensure replies from the container are correctly routed.
Verify Your Configuration
To confirm the rules are in place:
iptables -t nat -L -n -v
iptables -L -n -v
Test Connectivity
Try connecting from the allowed IP address:
ssh -p 2222 <your-server-ip>
Attempts from other IPs should be blocked.
Conclusion
This IPTables script helps secure SSH access to your container by limiting connections to a specific IP. Feel free to customise it further based on your environment.
Happy networking! 🚀