OpenVPN Setup with iptables
Complete OpenVPN server configuration with iptables rules for secure VPN access and client port forwarding.
OpenVPN Server Setup
1. Install OpenVPN
Debian/Ubuntu
# Update package list
apt update
# Install OpenVPN and Easy-RSA
apt install openvpn easy-rsa -y
# Create CA directory
make-cadir /etc/openvpn/easy-rsa
CentOS/RHEL
# Install EPEL repository
yum install epel-release -y
# Install OpenVPN
yum install openvpn -y
# Install Easy-RSA
git clone https://github.com/OpenVPN/easy-rsa.git /etc/openvpn/easy-rsa
2. Generate Certificates
# Navigate to Easy-RSA directory
cd /etc/openvpn/easy-rsa
# Initialize PKI
./easyrsa init-pki
# Build CA
./easyrsa build-ca nopass
# Generate server certificate
./easyrsa gen-req server nopass
./easyrsa sign-req server server
# Generate Diffie-Hellman parameters
./easyrsa gen-dh
# Generate TLS auth key
openvpn --genkey secret ta.key
3. Create Server Configuration
# Create server config directory
mkdir -p /etc/openvpn/server
# Copy certificates
cp pki/ca.crt /etc/openvpn/server/
cp pki/issued/server.crt /etc/openvpn/server/
cp pki/private/server.key /etc/openvpn/server/
cp pki/dh.pem /etc/openvpn/server/
cp ta.key /etc/openvpn/server/
Server Configuration File
# Create server configuration
cat > /etc/openvpn/server/server.conf << 'EOF'
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh.pem
auth SHA256
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
keepalive 10 120
tls-auth ta.key 0
cipher AES-256-CBC
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 3
explicit-exit-notify 1
EOF
iptables Configuration for OpenVPN Server
1. Basic OpenVPN iptables Rules
#!/bin/bash
# OpenVPN Server iptables Configuration
# Clear existing rules
iptables -F
iptables -X
# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback and established connections
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow SSH access
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow OpenVPN port (UDP)
iptables -A INPUT -p udp --dport 1194 -j ACCEPT
# Allow OpenVPN port (TCP) - optional
iptables -A INPUT -p tcp --dport 1194 -j ACCEPT
# Allow forwarding for VPN clients
iptables -A FORWARD -i tun0 -j ACCEPT
iptables -A FORWARD -o tun0 -j ACCEPT
# NAT for VPN clients
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
# Log and drop
iptables -A INPUT -j LOG --log-prefix "DROP: "
iptables -A INPUT -j DROP
2. Advanced OpenVPN iptables Rules
#!/bin/bash
# Advanced OpenVPN Server with Security
# Clear existing rules
iptables -F
iptables -X
# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback and established connections
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Anti-spoofing rules
iptables -A INPUT -s 127.0.0.0/8 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -s 255.255.255.255 -j DROP
# SSH with rate limiting
iptables -A INPUT -p tcp --dport 22 -m limit --limit 5/minute --limit-burst 10 -j ACCEPT
# OpenVPN with rate limiting
iptables -A INPUT -p udp --dport 1194 -m limit --limit 10/minute --limit-burst 20 -j ACCEPT
# Allow forwarding for VPN clients
iptables -A FORWARD -i tun0 -j ACCEPT
iptables -A FORWARD -o tun0 -j ACCEPT
# NAT for VPN clients
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
# Log and drop
iptables -A INPUT -j LOG --log-prefix "DROP: "
iptables -A INPUT -j DROP
Client Port Forwarding Configuration
1. Basic Client Port Forwarding
Forward Specific Ports to VPN Clients
# Forward HTTP to VPN client 10.8.0.10
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 10.8.0.10:80
# Forward HTTPS to VPN client 10.8.0.11
iptables -t nat -A PREROUTING -p tcp --dport 8443 -j DNAT --to-destination 10.8.0.11:443
# Forward SSH to VPN client 10.8.0.12
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to-destination 10.8.0.12:22
# Allow forwarding for these ports
iptables -A FORWARD -p tcp --dport 80 -d 10.8.0.10 -j ACCEPT
iptables -A FORWARD -p tcp --dport 443 -d 10.8.0.11 -j ACCEPT
iptables -A FORWARD -p tcp --dport 22 -d 10.8.0.12 -j ACCEPT
2. Dynamic Client Port Forwarding
Script for Dynamic Port Forwarding
#!/bin/bash
# Dynamic Port Forwarding Script
# Function to add port forwarding for client
add_client_forward() {
local CLIENT_IP=$1
local EXTERNAL_PORT=$2
local INTERNAL_PORT=$3
local PROTOCOL=${4:-tcp}
echo "Adding port forward: $EXTERNAL_PORT -> $CLIENT_IP:$INTERNAL_PORT ($PROTOCOL)"
# Add DNAT rule
iptables -t nat -A PREROUTING -p $PROTOCOL --dport $EXTERNAL_PORT -j DNAT --to-destination $CLIENT_IP:$INTERNAL_PORT
# Add FORWARD rule
iptables -A FORWARD -p $PROTOCOL --dport $INTERNAL_PORT -d $CLIENT_IP -j ACCEPT
echo "Port forward added successfully"
}
# Function to remove port forwarding
remove_client_forward() {
local EXTERNAL_PORT=$1
local PROTOCOL=${2:-tcp}
echo "Removing port forward for port $EXTERNAL_PORT ($PROTOCOL)"
# Remove DNAT rule
iptables -t nat -D PREROUTING -p $PROTOCOL --dport $EXTERNAL_PORT -j DNAT --to-destination $CLIENT_IP:$INTERNAL_PORT 2>/dev/null
# Remove FORWARD rule
iptables -D FORWARD -p $PROTOCOL --dport $INTERNAL_PORT -d $CLIENT_IP -j ACCEPT 2>/dev/null
echo "Port forward removed"
}
# Example usage
# add_client_forward 10.8.0.10 8080 80 tcp
# add_client_forward 10.8.0.11 8443 443 tcp
# add_client_forward 10.8.0.12 2222 22 tcp
3. Client-Specific Port Forwarding
Web Server Client
# Forward web traffic to client 10.8.0.10
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.8.0.10:80
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 10.8.0.10:443
# Allow forwarding
iptables -A FORWARD -p tcp --dport 80 -d 10.8.0.10 -j ACCEPT
iptables -A FORWARD -p tcp --dport 443 -d 10.8.0.10 -j ACCEPT
Database Client
# Forward database traffic to client 10.8.0.11
iptables -t nat -A PREROUTING -p tcp --dport 3306 -j DNAT --to-destination 10.8.0.11:3306
iptables -t nat -A PREROUTING -p tcp --dport 5432 -j DNAT --to-destination 10.8.0.11:5432
# Allow forwarding
iptables -A FORWARD -p tcp --dport 3306 -d 10.8.0.11 -j ACCEPT
iptables -A FORWARD -p tcp --dport 5432 -d 10.8.0.11 -j ACCEPT
SSH Client
# Forward SSH to client 10.8.0.12
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to-destination 10.8.0.12:22
# Allow forwarding
iptables -A FORWARD -p tcp --dport 22 -d 10.8.0.12 -j ACCEPT
Complete OpenVPN Server Configuration
1. Full Server Setup Script
#!/bin/bash
# Complete OpenVPN Server Setup with iptables
# Configuration variables
VPN_PORT=1194
VPN_PROTO=udp
VPN_NETWORK=10.8.0.0/24
EXTERNAL_IF=eth0
INTERNAL_IF=tun0
echo "Setting up OpenVPN server..."
# Install OpenVPN (Debian/Ubuntu)
apt update
apt install openvpn easy-rsa -y
# Setup certificates
cd /etc/openvpn/easy-rsa
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa gen-req server nopass
./easyrsa sign-req server server
./easyrsa gen-dh
openvpn --genkey secret ta.key
# Copy certificates
mkdir -p /etc/openvpn/server
cp pki/ca.crt /etc/openvpn/server/
cp pki/issued/server.crt /etc/openvpn/server/
cp pki/private/server.key /etc/openvpn/server/
cp pki/dh.pem /etc/openvpn/server/
cp ta.key /etc/openvpn/server/
# Create server configuration
cat > /etc/openvpn/server/server.conf << EOF
port $VPN_PORT
proto $VPN_PROTO
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh.pem
auth SHA256
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
keepalive 10 120
tls-auth ta.key 0
cipher AES-256-CBC
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 3
explicit-exit-notify 1
EOF
# Enable IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
# Configure iptables
iptables -F
iptables -X
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback and established
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow OpenVPN
iptables -A INPUT -p $VPN_PROTO --dport $VPN_PORT -j ACCEPT
# Allow forwarding for VPN
iptables -A FORWARD -i $INTERNAL_IF -j ACCEPT
iptables -A FORWARD -o $INTERNAL_IF -j ACCEPT
# NAT for VPN clients
iptables -t nat -A POSTROUTING -s $VPN_NETWORK -o $EXTERNAL_IF -j MASQUERADE
# Save iptables rules
iptables-save > /etc/iptables/rules.v4
# Start and enable OpenVPN
systemctl enable openvpn@server
systemctl start openvpn@server
echo "OpenVPN server setup complete!"
2. Client Certificate Generation
#!/bin/bash
# Generate client certificates
CLIENT_NAME=$1
if [ -z "$CLIENT_NAME" ]; then
echo "Usage: $0 <client_name>"
exit 1
fi
cd /etc/openvpn/easy-rsa
# Generate client certificate
./easyrsa gen-req $CLIENT_NAME nopass
./easyrsa sign-req client $CLIENT_NAME
# Create client configuration
cat > /etc/openvpn/client/$CLIENT_NAME.ovpn << EOF
client
dev tun
proto udp
remote YOUR_SERVER_IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
verb 3
<ca>
$(cat pki/ca.crt)
</ca>
<cert>
$(cat pki/issued/$CLIENT_NAME.crt)
</cert>
<key>
$(cat pki/private/$CLIENT_NAME.key)
</key>
<tls-auth>
$(cat ta.key)
</tls-auth>
EOF
echo "Client certificate generated: /etc/openvpn/client/$CLIENT_NAME.ovpn"
Monitoring and Management
1. OpenVPN Status Monitoring
#!/bin/bash
# OpenVPN Status Monitor
echo "=== OpenVPN Status ==="
systemctl status openvpn@server
echo -e "\n=== Connected Clients ==="
cat /var/log/openvpn-status.log | grep "CLIENT_LIST"
echo -e "\n=== VPN Interface ==="
ip addr show tun0
echo -e "\n=== VPN Routes ==="
ip route show | grep 10.8.0
2. Port Forwarding Status
#!/bin/bash
# Port Forwarding Status
echo "=== Active Port Forwards ==="
iptables -t nat -L PREROUTING -v --line-numbers
echo -e "\n=== Forward Rules ==="
iptables -L FORWARD -v --line-numbers
echo -e "\n=== Connection Tracking ==="
conntrack -L | grep -E "(10.8.0|DNAT)"
3. Client Connection Script
#!/bin/bash
# Client Connection Management
# Function to list connected clients
list_clients() {
echo "Connected VPN clients:"
cat /var/log/openvpn-status.log | grep "CLIENT_LIST" | awk '{print $2}'
}
# Function to disconnect client
disconnect_client() {
local CLIENT_NAME=$1
echo "Disconnecting client: $CLIENT_NAME"
echo "kill $CLIENT_NAME" | nc localhost 7505
}
# Function to add port forward for client
add_client_forward() {
local CLIENT_IP=$1
local EXTERNAL_PORT=$2
local INTERNAL_PORT=$3
echo "Adding port forward: $EXTERNAL_PORT -> $CLIENT_IP:$INTERNAL_PORT"
iptables -t nat -A PREROUTING -p tcp --dport $EXTERNAL_PORT -j DNAT --to-destination $CLIENT_IP:$INTERNAL_PORT
iptables -A FORWARD -p tcp --dport $INTERNAL_PORT -d $CLIENT_IP -j ACCEPT
}
# Usage examples
# list_clients
# disconnect_client client1
# add_client_forward 10.8.0.10 8080 80
Troubleshooting
1. Common OpenVPN Issues
Client can't connect
# Check OpenVPN service
systemctl status openvpn@server
# Check firewall rules
iptables -L INPUT | grep 1194
# Check server logs
tail -f /var/log/openvpn.log
Port forwarding not working
# Check NAT rules
iptables -t nat -L PREROUTING -v
# Check forwarding rules
iptables -L FORWARD -v
# Test connectivity
telnet localhost 8080
2. Debugging Commands
# Check OpenVPN status
systemctl status openvpn@server
# Check VPN interface
ip addr show tun0
# Check routing
ip route show
# Check iptables rules
iptables -L -v
iptables -t nat -L -v
# Check connection tracking
conntrack -L | grep 10.8.0
Security Considerations
1. Additional Security Rules
# Block access to VPN server from VPN network
iptables -A INPUT -s 10.8.0.0/24 -j DROP
# Allow only specific clients
iptables -A INPUT -p udp --dport 1194 -s 192.168.1.0/24 -j ACCEPT
# Rate limit VPN connections
iptables -A INPUT -p udp --dport 1194 -m limit --limit 5/minute --limit-burst 10 -j ACCEPT
2. Client Isolation
# Prevent clients from accessing each other
iptables -A FORWARD -i tun0 -o tun0 -j DROP
# Allow only specific client-to-client communication
iptables -A FORWARD -i tun0 -o tun0 -s 10.8.0.10 -d 10.8.0.11 -j ACCEPT
Note: Always test OpenVPN configurations in a safe environment and ensure you have alternative access methods before applying restrictive rules.