The error MULTI: bad source address from client [192.168.x.x], packet dropped
occurs when OpenVPN receives traffic from a client with a source IP that doesn't match its expected routing topology. This commonly happens with NATed clients where the private IP range conflicts with the VPN's subnet.
The typical client-config-dir
approach requires maintaining IP-specific rules:
# ccd/DEFAULT
ifconfig-push 10.78.96.100 255.255.255.0
iroute 192.168.1.0 255.255.255.0
This becomes unmanageable as clients connect from diverse networks (192.168.x.y, 10.x.y.z, etc.).
1. Dynamic IP Handling
# Server config addition
client-to-client
duplicate-cn
topology subnet
2. Route Isolation Method
# Add to server.conf
route 192.168.0.0 255.255.0.0 net_gateway
route 10.0.0.0 255.0.0.0 net_gateway
Modify both client and server configurations to handle NAT properly:
# Server
push "route 0.0.0.0 128.0.0.0"
push "route 128.0.0.0 128.0.0.0"
# Client
route-nopull
route 0.0.0.0 0.0.0.0 vpn_gateway 1
For dynamic environments, implement a client-connect script:
#!/bin/bash
# /etc/openvpn/scripts/client-connect.sh
CLIENT_IP=$(echo $trusted_ip | cut -d' ' -f1)
iptables -t nat -A POSTROUTING -s $CLIENT_IP -j MASQUERADE
exit 0
Add to server config:
script-security 2
client-connect /etc/openvpn/scripts/client-connect.sh
After implementing changes:
# Check routes
ip route show table all
# Verify NAT
sudo conntrack -L | grep openvpn
# Test connectivity
traceroute -n 8.8.8.8
When running an OpenVPN server with clients behind NAT, you might encounter the frustrating error:
MULTI: bad source address from client [192.168.x.x], packet dropped
This occurs when the server receives traffic from a client's private IP address (like 192.168.x.x) that doesn't match the expected VPN subnet (10.78.96.0/24 in our example).
The core issue stems from OpenVPN's security model. The server expects all client traffic to originate from within the VPN subnet (10.78.96.0/24). However, when clients are behind NAT:
- Their original private IP gets preserved in packets
- The server sees this "real" IP instead of the VPN-assigned one
- OpenVPN's default behavior is to drop such packets
Most forums suggest creating client-specific configuration files in the client-config-dir
:
# In ccd/DEFAULT
ifconfig-push 10.78.96.100 10.78.96.101
iroute 192.168.1.0 255.255.255.0
The problem? This requires knowing client networks in advance and doesn't scale well.
Here's a better solution that works for any client network:
# Add to server.conf
client-to-client
duplicate-cn
topology subnet
script-security 2
learn-address /etc/openvpn/learn-address.sh
Then create /etc/openvpn/learn-address.sh
:
#!/bin/bash
ACTION=$1
IP=$2
CN=$3
if [ "$ACTION" == "add" ]; then
# Allow traffic from this client's real network
iptables -A INPUT -s $IP -j ACCEPT
fi
if [ "$ACTION" == "delete" ]; then
# Clean up when client disconnects
iptables -D INPUT -s $IP -j ACCEPT
fi
exit 0
For less strict environments, you can modify OpenVPN's source verification:
# In server.conf
disable-occ
# Or completely disable source checking (use with caution)
disable-source-check
After implementing changes, verify with:
sudo openvpn --config server.conf --verb 6
tail -f /var/log/syslog | grep openvpn
You should no longer see the "bad source address" messages, while maintaining security.
While the client-config-dir approach works for static deployments, the learn-address method provides a more dynamic solution that adapts to clients connecting from any network. The iptables integration ensures proper traffic flow while maintaining security boundaries.
Remember to:
- Make learn-address.sh executable (
chmod +x
) - Adjust iptables rules to match your security requirements
- Monitor logs after implementation