OpenVPN server fails to respond to clients after outgoing interface is removed and re-created
Description
While operating OpenVPN client and server over UDP, the outgoing interface in server was restarted. It was a tunnel device that was removed and re-created. Consequently, when the client sent packets to the server, these were received. However the server was unable to send packets to client, reporting an error to its log:
Beta/10.10.1.22:33192 write UDPv4 []: No such device (fd=6,code=19)
The tunnel was inoperable until the client initiated reconnection (via keepalive).
If the restart of interface happened in the client, it had no ill effects.
Reproduction
- Create OpenVPN tunnel between 2 devices over some dynamically created interface in the server. For example WiFi.
- Test the connection over the tunnel. It should work.
- Destroy and re-create the interface (turn-off WiFi, then turn it on). The interface must be destroyed, not just closed (DOWN).
- Test the connection to client and the connection over the tunnel. The connection to the client will be working but the connection over the tunnel will not.
Expected behavior
- The server should be able to send packets when there is a valid route to a client.
Version information OS: Linux-6.1.18 (embedded) OpenVPN: 2.6.5
Snippet from config.log (cross-compilation)
$ /usr/src/racom/ra2_fwbuild/build/openvpn/src/configure --host=mips64-linux-gnuabi64 --prefix= --sysconfdir=/etc --with-sysroot=/usr/src/racom/ra2_fwbuild/staging --disable-dependency-tracking --disable-selinux --disable-systemd --disable-plugins --disable-debug --disable-pkcs11 --enable-small IFCONFIG= ROUTE= IPROUTE=/sbin/ip NETSTAT=/bin/netstat
hostname = lapka-Latitude-5520
uname -m = x86_64
uname -r = 6.2.0-33-generic
uname -s = Linux
uname -v = #33-Ubuntu SMP PREEMPT_DYNAMIC Tue Sep 5 14:49:19 UTC 2023
Analysis
When using UDP and compiled with flag ENABLE_IP_PKTINFO, the server stores information about the target address the client used to connect and the index of the interface it used (in_pktinfo::ipi_ifindex in structure link_socket_actual). These are then used to set source address of UDP packets sent to the client (src/openvpn/socket.c: link_socket_write_udp_posix_sendmsg()). However if the interface was removed and re-created, its original index is no longer valid and an attempt to use it leads to the error ("write UDPv4 []: No such device").
Proposed solution
Do not use possibly obsolete ipi_ifindex as a hint for source address resolution. In function src/openvpn/socket.c: link_socket_write_udp_posix_sendmsg() use special value 0 when filling in_pktinfo::ipi_ifindex in CMSG structure for sendmsg().
Tested patch is in attachment.
Alternative solution: Update interface index and stored address with each packet received from client. It may still lead to the error if no new packet from client arrives after the restart of interface.