Connectivity failures between an Azure virtual machine and an OpenVPN client typically stem from missing static routes or asymmetric routing rather than VPN configuration errors. Ensure the Azure Network Security Group allows UDP traffic on port 1194 and that both the host operating system and the OpenVPN server have explicit routes directing return traffic through the correct network interface.
Verifying Network Security Group Rules
The first layer of troubleshooting involves checking the Azure Network Security Group (NSG) associated with your virtual machine hosting the OpenVPN service. Even if the OpenVPN daemon is running correctly, inbound traffic will be dropped if the NSG does not permit it. You must verify that an inbound security rule exists for UDP port 1194, which is the default port for OpenVPN connections. If you are using a custom port, ensure the rule matches that specific value. It is crucial to check the priority of these rules. Lower priority numbers take precedence over higher ones. If there is a deny-all rule with a lower number than your allow rule, the connection will fail silently. Additionally, confirm that the source address in the NSG rule is set to either the specific IP address of the client attempting to connect or to the Internet wildcard, depending on your security requirements. Do not rely on implicit allow rules; explicitly define the permitted traffic flow.Configuring Static Routes on the Host
A common cause for inability to reach another computer via the VPN is that the host machine does not know how to route packets destined for the OpenVPN subnet back to the client. In this scenario, your Azure IP is 10.5.0.4, and the OpenVPN private address is 10.6.0.4. The host operating system likely has a direct route to its own Azure subnet but lacks a route for the 10.6.0.0/24 network. You need to add a static route that tells the Linux kernel to send traffic for the VPN subnet through the tun interface created by OpenVPN. Use theip route command to achieve this. For example, if the tun interface is named tun0, you would execute:
sudo ip route add 10.6.0.0/24 dev tun0
This command ensures that when the host tries to communicate with any device in the 10.6.0.0/24 range, it sends the packet out through the VPN tunnel. Without this route, the host may attempt to send the response out through its primary Ethernet interface, resulting in asymmetric routing and dropped packets. To make this persistent across reboots, you should add this route to your network configuration files, such as /etc/sysconfig/network-scripts/route-eth0 or use systemd-networkd configurations appropriate for your current CentOS version.
Checking Forwarding and NAT Settings
If the goal is to allow the OpenVPN client to access resources behind the Azure VM, you must enable IP forwarding on the host. Check the status of thenet.ipv4.ip_forward sysctl parameter. It should be set to 1. If it is 0, the kernel will drop forwarded packets. Enable it temporarily with:
sudo sysctl -w net.ipv4.ip_forward=1
For permanent changes, edit /etc/sysctl.conf and uncomment or add net.ipv4.ip_forward = 1. Furthermore, if the OpenVPN client needs to access the internet through the Azure VM, you must configure Network Address Translation (NAT). This is often handled by iptables or nftables. Ensure that a MASQUERADE rule exists for the outgoing interface. However, note that if you are only trying to reach another specific computer on the same local network, NAT might not be necessary, and proper routing is sufficient. Refer to Port Forwarding VM via OpenVPN: A Comprehensive Guide for detailed NAT configurations if broader internet access is required.
Validating Interface Status and Firewall
Useip addr show to confirm that the tun0 interface is up and has the correct IP address assigned. If the interface is down, the OpenVPN service may have failed to establish the tunnel. Check the OpenVPN logs for errors related to peer authentication or certificate validation. Additionally, inspect the host’s firewall settings. While NSGs handle external filtering, the internal Linux firewall (firewalld or iptables) might block inter-interface communication. Ensure that the zone for the tun0 interface is trusted or that specific rules allow traffic between the public interface and the tunnel interface.
Why is my ping successful but other ports blocked?
This usually indicates that ICMP is allowed while TCP/UDP traffic is restricted by a firewall rule or NSG. Verify that your security groups explicitly allow the specific application ports you are trying to reach, not just ICMP echo requests.How do I make the route persistent on modern CentOS?
Instead of editing legacy scripts, use systemd-networkd or NetworkManager dispatcher scripts. Create a dedicated route file in the appropriate network configuration directory to ensure the route survives network service restarts and reboots.What if the OpenVPN server is behind a double NAT?
Double NAT scenarios complicate routing significantly. You may need to configure port forwarding on the upstream router to point to your Azure VM. Ensure that the OpenVPN server is configured to listen on the correct public IP and that the client connects to that public endpoint.Frequently Asked Questions
How do I verify if the OpenVPN tunnel is actually established?
Check the status of the OpenVPN service usingsystemctl status [email protected]. Look for the line indicating that the TUN/TAP interface was successfully opened and that the peer has been authenticated. If the service is active but the tunnel is down, check the log files for handshake failures.
Can I use iptables instead of firewalld for managing traffic?
Yes, you can useiptables directly, especially if you are migrating from older systems. However, on modern CentOS versions, firewalld is the default management tool. If you switch to iptables, ensure you disable firewalld to prevent conflicts between the two firewall managers.
What is the impact of disabling SELinux during troubleshooting?
SELinux can sometimes block OpenVPN from binding to specific ports or accessing network interfaces. Temporarily setting SELinux to permissive mode withsetenforce 0 helps determine if it is the cause of the issue. Remember to restore it to enforcing mode after testing to maintain security.