Hello,

I have the following multihomed setup:


           BGP1                        BGP2
            ^                           ^
            |                           |
+-----------+-----------+    +----------+-----------+
| IP1.1   IP1.2   IP1.3 |    | IP2.1  IP2.2   IP3.1 |
|                       |    |                      |
|                       |    |                      |
|          RTR1         |    |         RTR2         |
|                       |    |                      |
|                       |    |                      |
|          vIP          |    |         vIP          |
+-----------+-----------+    +----------+-----------+
            |                           |
            |                           |
            |                           |
            |            VRRP           |
            +---------------------------+


I.e. two routers with BGP to multiple ISPs. VRRP running at inner side keeping one virtual IP (vIP) up at the master router.

Someday I hope I'll be able to use the vIP only for openvpn server bind IP ("local" config option). Untill then, for legacy reasons, I have to use the "multihome" config option, so that clients could connect to each of the 7 IPs (IP1.1, IP1.2, IP1.3, IP2.1, IP2.2, IP2.3, vIP).

Unfortunately, Linux would not respond to /some/ clients over UDP. It seems like this is due to the way "multihome" forces the output interface using IP_PKTINFO when we have asymetric path to/from vpn clients.

To provide single-socket UDP multihoming, openvpn uses the IP_PKTINFO data from recvmsg() and passes it as-is to sendmsg(). Apparently ipi_ifindex behaves in an interesting way under Linux. man 7 ip states:

    If  IP_PKTINFO  is  passed  to  sendmsg(2)  and ipi_spec_dst  is  not
    zero, then it is used as the local source address for the routing table
    lookup and for setting up IP source route options.  When ipi_ifindex is
    not zero, the primary local address of the interface  specified  by
    the  index overwrites ipi_spec_dst for the routing table lookup.


In my tests it's like /ipi_ifindex/ will override any routing table decision. But then if there is no routing table entry for the destination via that interface, the destination will be assumed to be on-link and will not be routed via a gateway. No error is returned to userspace, but if the destination does not respond to an ARP request on that link, the packet will be silently dropped. That's what I see with tcpdump on the openvpn server: arp requests for the dst address of the openvpn client. For example if a.b.c.100 is an openvpn client and x.y.z.1 is the virtual IP on the openvpn server to which the client tries to connect:

11:52:40.695830 ARP, Request who-has a.b.c.100 tell x.y.z.1, length 28

I got it working by patching socket.c in the following manner:

--- openvpn-2.4.0/src/openvpn/socket.c  2016-12-26 13:51:00.000000000 +0200
+++ openvpn-2.4.0/src/openvpn/socket.c  2018-03-09 15:37:10.015832657 +0200
@@ -3379,7 +3379,7 @@
             {
                 struct in_pktinfo *pkti;
                 pkti = (struct in_pktinfo *) CMSG_DATA(cmsg);
-                pkti->ipi_ifindex = to->pi.in4.ipi_ifindex;
+                pkti->ipi_ifindex = 0;
                 pkti->ipi_spec_dst = to->pi.in4.ipi_spec_dst;
                 pkti->ipi_addr.s_addr = 0;
             }


I guess this should be confirmed by someone else too, and I haven't looked into IPv6 side at all, but the above patch works for me ™.

Best regards,
Teodor Milkov
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to