Skip to main content

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.