Hi, On 30/10/2018 13:53, Lev Stipakov wrote: > From: Lev Stipakov <l...@openvpn.net> > > This patch provides additional information, such as > source address/port and destination address/port, to a > "recursive routing" warning message. It also mentiones > possible workaround. > > Trac #843 > > Signed-off-by: Lev Stipakov <l...@openvpn.net> > --- > v4: > - remove unneeded format specifier for const string > > v3: > - factor out ports extraction code into own function > to avoid code duplication > - better commit message > > v2: > - print protocol, source/dest addresses and ports > - mention "--allow-recursive-routing" > - add possible usecase to manpage > > doc/openvpn.8 | 4 ++- > src/openvpn/forward.c | 98 > ++++++++++++++++++++++++++++++++++++++++++++++----- > 2 files changed, 93 insertions(+), 9 deletions(-) > > diff --git a/doc/openvpn.8 b/doc/openvpn.8 > index 94b5cc4..fb9eb84 100644 > --- a/doc/openvpn.8 > +++ b/doc/openvpn.8 > @@ -4090,7 +4090,9 @@ notifications unless this option is enabled. > .TP > .B \-\-allow\-recursive\-routing > When this option is set, OpenVPN will not drop incoming tun packets > -with same destination as host. > +with same destination as host. Could be useful when packets sent by openvpn > +itself are not subject to the routing tables that would move packets > +into the tunnel. > .\"********************************************************* > .SS Data Channel Encryption Options: > These options are meaningful for both Static & TLS\-negotiated key modes > diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c > index f8faa81..e96c546 100644 > --- a/src/openvpn/forward.c > +++ b/src/openvpn/forward.c > @@ -1291,10 +1291,42 @@ read_incoming_tun(struct context *c) > perf_pop(); > } > > +/* > + * Extracts sport and dport from packet, used > + * in recursive routing warning. > + */ > +static void > +extract_sport_dport(const struct buffer *buf, uint8_t protocol, int > offset_to_payload, int packet_len, uint16_t *sport, uint16_t *dport) > +{ > + /* whole packet? */ > + if (BLEN(buf) == packet_len) > + { > + const uint8_t *payload = BPTR(buf) + offset_to_payload; > + > + if (protocol == OPENVPN_IPPROTO_UDP) > + { > + const struct openvpn_udphdr *udp = (const struct openvpn_udphdr > *)payload; > + *sport = ntohs(udp->source); > + *dport = ntohs(udp->dest); > + } > + else if (protocol == OPENVPN_IPPROTO_TCP) > + { > + const struct openvpn_tcphdr *tcp = (const struct openvpn_tcphdr > *)payload; > + *sport = ntohs(tcp->source); > + *dport = ntohs(tcp->dest); > + } > + } > + else > + { > + *sport = 0; > + *dport = 0; > + } > +} > + > /** > * Drops UDP packets which OS decided to route via tun. > * > - * On Windows and OS X when netwotk adapter is disabled or > + * On Windows and OS X when network adapter is disabled or > * disconnected, platform starts to use tun as external interface. > * When packet is sent to tun, it comes to openvpn, encapsulated > * and sent to routing table, which sends it again to tun. > @@ -1306,6 +1338,11 @@ drop_if_recursive_routing(struct context *c, struct > buffer *buf) > struct openvpn_sockaddr tun_sa; > int ip_hdr_offset = 0; > > + uint32_t saddr, daddr; > + struct in6_addr saddr6, daddr6; > + uint16_t sport, dport; > + uint8_t protocol; > + > if (c->c2.to_link_addr == NULL) /* no remote addr known */ > { > return; > @@ -1320,7 +1357,7 @@ drop_if_recursive_routing(struct context *c, struct > buffer *buf) > const struct openvpn_iphdr *pip; > > /* make sure we got whole IP header */ > - if (BLEN(buf) < ((int) sizeof(struct openvpn_iphdr) + ip_hdr_offset)) > + if (BLEN(buf) < ((int)sizeof(struct openvpn_iphdr) + ip_hdr_offset)) > { > return; > } > @@ -1331,12 +1368,21 @@ drop_if_recursive_routing(struct context *c, struct > buffer *buf) > return; > } > > - pip = (struct openvpn_iphdr *) (BPTR(buf) + ip_hdr_offset); > + pip = (const struct openvpn_iphdr *)(BPTR(buf) + ip_hdr_offset); > > - /* drop packets with same dest addr as gateway */ > + /* drop packets with the same dest addr as gateway */ > if (tun_sa.addr.in4.sin_addr.s_addr == pip->daddr) > { > drop = true; > + > + /* collect information for warning message */ > + > + saddr = ntohl(pip->saddr); > + daddr = ntohl(pip->daddr); > + protocol = pip->protocol; > + > + extract_sport_dport(buf, protocol, ip_hdr_offset + sizeof(struct > openvpn_iphdr), > + ip_hdr_offset + (int)(ntohs(pip->tot_len)), > &sport, &dport);
In the 3rd don-t we need to also add sizeof(struct openvpn_iphdr)? Or is it included in pip->tot_len? > } > } > else if (proto_ver == 6) > @@ -1344,7 +1390,7 @@ drop_if_recursive_routing(struct context *c, struct > buffer *buf) > const struct openvpn_ipv6hdr *pip6; > > /* make sure we got whole IPv6 header */ > - if (BLEN(buf) < ((int) sizeof(struct openvpn_ipv6hdr) + > ip_hdr_offset)) > + if (BLEN(buf) < ((int)sizeof(struct openvpn_ipv6hdr) + > ip_hdr_offset)) > { > return; > } > @@ -1355,22 +1401,58 @@ drop_if_recursive_routing(struct context *c, struct > buffer *buf) > return; > } > > - /* drop packets with same dest addr as gateway */ > + /* drop packets with the same dest addr as gateway */ > pip6 = (struct openvpn_ipv6hdr *) (BPTR(buf) + ip_hdr_offset); > if (IN6_ARE_ADDR_EQUAL(&tun_sa.addr.in6.sin6_addr, &pip6->daddr)) > { > drop = true; > + > + /* collect information for warning message */ > + > + saddr6 = pip6->saddr; > + daddr6 = pip6->daddr; > + protocol = pip6->nexthdr; > + > + extract_sport_dport(buf, protocol, ip_hdr_offset + sizeof(struct > openvpn_ipv6hdr), > + (int)sizeof(struct openvpn_ipv6hdr) + > ip_hdr_offset + (int)ntohs(pip6->payload_len), > + &sport, &dport); > } > } > > if (drop) > { > struct gc_arena gc = gc_new(); > + struct buffer addrs_buf = alloc_buf_gc(128, &gc); > > + /* drop packet */ > c->c2.buf.len = 0; > > - msg(D_LOW, "Recursive routing detected, drop tun packet to %s", > - print_link_socket_actual(c->c2.to_link_addr, &gc)); > + if (protocol == OPENVPN_IPPROTO_UDP) > + { > + buf_printf(&addrs_buf, "UDP"); > + } > + else if (protocol == OPENVPN_IPPROTO_TCP) > + { > + buf_printf(&addrs_buf, "TCP"); > + } > + else > + { > + buf_printf(&addrs_buf, "%d", protocol); > + } > + > + if (proto_ver == 4) > + { > + buf_printf(&addrs_buf, " %s:%d -> %s:%d", > + print_in_addr_t(saddr, 0, &gc), sport, > + print_in_addr_t(daddr, 0, &gc), dport); > + } else if (proto_ver == 6) > + { > + buf_printf(&addrs_buf, " %s:%d -> %s:%d", > + print_in6_addr(saddr6, 0, &gc), sport, > + print_in6_addr(daddr6, 0, &gc), dport); > + } > + > + msg(D_LOW, "Recursive routing detected, drop packet %s. Fix your > routing or consider using --allow-recursive-routing option.", > BSTR(&addrs_buf)); I would add "if you know what you are doing", otherwisethe average Joe will think that he can just add "--allow-recursive-routing" to his config and the problem is fixed. Regards, > gc_free(&gc); > } > } > -- Antonio Quartulli _______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel