I’m setting up a tap config on a Darwin client (Tunnelblick on OSX) to a
Linux server (Fedora). The config has the following (only relevant
portions):
== server
dev tap0
server-bridge
push "redirect-gateway def1 ipv6"
push "ifconfig-ipv6 {local-ipv6-address} {linklocal-addr}”
…etc
== client
client
dev tap
remote {host} {port} udp4
…etc
The ipv4 vpn works fine, but the routes created for ipv6 are on the
wrong interface — they're on the network transport interface, not the
tap interface. This causes ipv6 to not function (since the
{linklocal-addr} cannot be reached on that network interface)
I tracked the problem to route.c around line 1880 (in v2.4.6 at least).
(a) There is Darwin/BSD specific code that modifies the gateway string
variable to include the interface name (to “<gatewayip>%<iface>”) if
gateway_needed is true, but it only works if r6->iface is non-NULL.
(b) the gateway_needed flag is set for tap devices, but only after it’s
checked in (a).
I’ve included a patch below that moves (b) above (a), and uses the local
“device" variable (which is either the tt->actual_name, or r6->iface if
set) when creating the modified gateway string. With this change, the
routes are created on the correct interface — the logs show:
== before
add_route_ipv6(::/3 -> {linklocal-addr} metric -1) dev tap0
/sbin/route add -inet6 :: -prefixlen 3 {linklocal-addr}
add net ::: gateway {linklocal-addr}
== after
add_route_ipv6(::/3 -> {linklocal-addr}%tap0 metric -1) dev tap0
/sbin/route add -inet6 :: -prefixlen 3 {linklocal-addr}%tap0
add net ::: gateway {linklocal-addr}%tap0
NOTE1: In the process of setting this up, I noticed a warning message to
gives the wrong advice (route.c:453):
msg(M_WARN, PACKAGE_NAME " ROUTE6: " PACKAGE_NAME " needs a
gateway par\
ameter for a --route-ipv6 option and no default was specified by either
--route\
-ipv6-gateway or --ifconfig-ipv6 options");
... There is no "route-ipv6-gateway" option (although it'd be nice to
have one, since for tap at least the {local-ipv6-address} on the
ifconfig-ipv6 option (in my config above) appears to be ignored.
NOTE2: Since ipv6 does automatic address configuration anyway... it'd be
nice to add a ipv6 equivalent to the dhcp_extract_router_msg() function
(called in forward.c to get the DHCP gateway) that extracts the default
gateway so that ifconfig-ipv6 isn't needed at all. I'd be happy to make
an attempt at that if it'd be useful :)
Thanks,
Scott
diff --git a/src/openvpn/route.c b/src/openvpn/route.c
index 2d6428b2..35ae8d09 100644
--- a/src/openvpn/route.c
+++ b/src/openvpn/route.c
@@ -1879,6 +1879,18 @@ add_route_ipv6(struct route_ipv6 *r6, const
struct tuntap *tt, unsigned int flag
network = print_in6_addr( r6->network, 0, &gc);
gateway = print_in6_addr( r6->gateway, 0, &gc);
+ /* On "tun" interface, we never set a gateway if the operating
system
+ * can do "route to interface" - it does not add value, as the
target
+ * dev already fully qualifies the route destination on
point-to-point
+ * interfaces. OTOH, on "tap" interface, we must always set the
+ * gateway unless the route is to be an on-link network
+ */
+ if (tt->type == DEV_TYPE_TAP
+ && !( (r6->flags & RT_METRIC_DEFINED) && r6->metric == 0 ) )
+ {
+ gateway_needed = true;
+ }
+
#if defined(TARGET_DARWIN) \
|| defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \
|| defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
@@ -1887,12 +1899,12 @@ add_route_ipv6(struct route_ipv6 *r6, const
struct tuntap *tt, unsigned int flag
* but for link-local destinations, we MUST specify the interface,
so
* we build a combined "$gateway%$interface" gateway string
*/
- if (r6->iface != NULL && gateway_needed
+ if (gateway_needed
&& IN6_IS_ADDR_LINKLOCAL(&r6->gateway) ) /*
fe80::...%intf */
{
- int len = strlen(gateway) + 1 + strlen(r6->iface)+1;
+ int len = strlen(gateway) + 1 + strlen(device)+1;
char *tmp = gc_malloc( len, true, &gc );
- snprintf( tmp, len, "%s%%%s", gateway, r6->iface );
+ snprintf( tmp, len, "%s%%%s", gateway, device );
gateway = tmp;
}
#endif
@@ -1905,18 +1917,6 @@ add_route_ipv6(struct route_ipv6 *r6, const
struct tuntap *tt, unsigned int flag
* (not currently done for IPv6)
*/
- /* On "tun" interface, we never set a gateway if the operating
system
- * can do "route to interface" - it does not add value, as the
target
- * dev already fully qualifies the route destination on
point-to-point
- * interfaces. OTOH, on "tap" interface, we must always set the
- * gateway unless the route is to be an on-link network
- */
- if (tt->type == DEV_TYPE_TAP
- && !( (r6->flags & RT_METRIC_DEFINED) && r6->metric == 0 ) )
- {
- gateway_needed = true;
- }
-
#if defined(TARGET_LINUX)
#ifdef ENABLE_IPROUTE
argv_printf(&argv, "%s -6 route add %s/%d dev %s",
------------------------------------------------------------------------------
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