On Mon, Oct 19, 2020 at 07:16:46PM +1000, David Gwynne wrote:
> On Mon, Oct 19, 2020 at 10:03:29AM +0100, Stuart Henderson wrote:
> > On 2020/10/19 11:47, David Gwynne wrote:
> > > On Sun, Oct 18, 2020 at 08:57:34PM +0100, Stuart Henderson wrote:
> > > > On 2020/10/18 14:04, David Gwynne wrote:
> > > > > the problem i'm hitting is that i have a multihomed box where the
> > > > > service it provides listens on an IP address that's assigned to lo1.
> > > > > it's a host running a service, it's not a router, so the
> > > > > net.inet.ip.forwarding sysctl is not set to 1.
> > > >
> > > > I ran into this, I just turned on the forwarding sysctl to avoid the
> > > > problem.
> > > >
> > > > > i came up with this diff, which adds even more special casing for
> > > > > loopback interfaces. it says addreesses on loopbacks are globally
> > > > > reachable, even if ip forwarding is disabled.
> > > >
> > > > I don't see why loopbacks should be special. Another place this
> > > > might show up is services running on carp addresses (I haven't updated
> > > > those machines yet but there's a fair chance they'll be affected too).
> > > > I would prefer an explicit sysctl to disable "strong host model".
> > >
> > > loopback is already special. if a packet comes from an loopback
> > > interface, we allow it to talk to any IP on the local machine. i think
> > > this is mostly to cope with the semantic we've had where local traffic
> > > get's tied to a loopback interface instead of going anywhere near the
> > > physical ones.
> > >
> > > carp is also special.
> > >
> > > let me paste the ip_laddr function instead of the diff to it, it's a bit
> > > more obvious what's going on:
> >
> > Thanks, that will already work for the machines I was thinking of then.
> >
> > > back to loopback and receiving packets. loopback is special because it
> > > is not connected to the outside world. it is impossible to send a packet
> > > via a loopback interface from another host, so configuring a globally
> > > (externally) routable IP on it is currently pointless unless you enable
> > > forwarding. i think making loopback more special and allowing it
> > > to be globally reachable makes sense. i can't think of any downsides to
> > > this at the moment, except that the behaviour would be subtle/not
> > > obvious
> >
> > ok, so it makes sense for this to be independent of any possible
> > separate lever.
> >
> > > is there a need to configure a globally reachable IP on a non-loopback
> > > interface on a host (not router)? if so, then i'd be more convinced that
> > > we need a separate lever to pull.
> >
> > I'm not using it this way, but here's a scenario.
> >
> > Say there are a couple of webservers with addresses from a carp on
> > ethernet/vlan, with a link to their upstream router on some separate
> > interface. They announce the carp prefix into ospf.
>
> so carp is just being used to elect a webserver as a master, and then
> the result of that election is fed upstream.
>
> > They aren't routing themselves so the only reason to have forwarding=1
> > is to have them use "weak host model".
> >
> > With forwarding=0 I think they'll have to use "stub router no" otherwise
> > everything will be announced high metric (rather than being dependent on
> > carp state), but ospfd explicitly handles this; it's marked in parse.y
> > with "/* allow to force non stub mode */".
>
> so is a Big Global Lever what you want here? if you enable weak host
> mode, all IPs on the host will be addressible from all legs of the
> host. would it make more sense to configure specific interfaces as
> holding globally addressible IPs?
>
> if my understanding of your scenario is right, you could configure
> the carp interface with the weak or globally accessible flag. in
> my situation i could configure that on lo1.
such a diff looks like this. it adds a "global" flag that you can set on
interfaces.
Index: sbin/ifconfig/ifconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.429
diff -u -p -r1.429 ifconfig.c
--- sbin/ifconfig/ifconfig.c 7 Oct 2020 14:38:54 -0000 1.429
+++ sbin/ifconfig/ifconfig.c 20 Oct 2020 00:12:06 -0000
@@ -468,6 +468,8 @@ const struct cmd {
{ "-autoconfprivacy", IFXF_INET6_NOPRIVACY, 0, setifxflags },
{ "soii", -IFXF_INET6_NOSOII, 0, setifxflags },
{ "-soii", IFXF_INET6_NOSOII, 0, setifxflags },
+ { "global", IFXF_GLOBAL, 0, setifxflags },
+ { "-global", -IFXF_GLOBAL, 0, setifxflags },
#ifndef SMALL
{ "hwfeatures", NEXTARG0, 0, printifhwfeatures },
{ "metric", NEXTARG, 0, setifmetric },
@@ -675,7 +677,7 @@ const struct cmd {
"\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX" \
"\15LINK0\16LINK1\17LINK2\20MULTICAST" \
"\23INET6_NOPRIVACY\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII" \
- "\30AUTOCONF4"
+ "\30AUTOCONF4" "\031GLOBAL"
int getinfo(struct ifreq *, int);
void getsock(int);
Index: sys/netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.351
diff -u -p -r1.351 ip_input.c
--- sys/netinet/ip_input.c 22 Aug 2020 17:55:30 -0000 1.351
+++ sys/netinet/ip_input.c 20 Oct 2020 00:12:06 -0000
@@ -753,29 +753,42 @@ in_ouraddr(struct mbuf *m, struct ifnet
break;
}
}
- } else if (ipforwarding == 0 && rt->rt_ifidx != ifp->if_index &&
- !((ifp->if_flags & IFF_LOOPBACK) || (ifp->if_type == IFT_ENC) ||
- (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST))) {
- /* received on wrong interface. */
-#if NCARP > 0
- struct ifnet *out_if;
+ } else if (ipforwarding == 0 && !ip_laddr(ifp, m, rt)) {
+ ipstat_inc(ips_wrongif);
+ match = 2;
+ }
+
+ return (match);
+}
+int
+ip_laddr(struct ifnet *ifp, struct mbuf *m, struct rtentry *rt)
+{
+ struct ifnet *rtifp;
+ int match = 0;
+
+ if (rt->rt_ifidx == ifp->if_index ||
+ ifp->if_type == IFT_ENC ||
+ ISSET(ifp->if_flags, IFF_LOOPBACK) ||
+ ISSET(m->m_pkthdr.pf.flags, PF_TAG_TRANSLATE_LOCALHOST))
+ return (1);
+
+ /* received on a different interface. */
+ rtifp = if_get(rt->rt_ifidx);
+ if (rtifp != NULL) {
+ if (ISSET(rtifp->if_xflags, IFXF_GLOBAL))
+ match = 1;
+#if NCARP > 0
/*
* Virtual IPs on carp interfaces need to be checked also
* against the parent interface and other carp interfaces
* sharing the same parent.
*/
- out_if = if_get(rt->rt_ifidx);
- if (!(out_if && carp_strict_addr_chk(out_if, ifp))) {
- ipstat_inc(ips_wrongif);
- match = 2;
- }
- if_put(out_if);
-#else
- ipstat_inc(ips_wrongif);
- match = 2;
+ else if (carp_strict_addr_chk(rtifp, ifp))
+ match = 1;
#endif
}
+ if_put(rtifp);
return (match);
}
Index: sys/netinet/ip_var.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.86
diff -u -p -r1.86 ip_var.h
--- sys/netinet/ip_var.h 8 Dec 2019 11:08:22 -0000 1.86
+++ sys/netinet/ip_var.h 20 Oct 2020 00:12:06 -0000
@@ -244,6 +244,7 @@ void ip_savecontrol(struct inpcb *, str
void ipintr(void);
int ip_input_if(struct mbuf **, int *, int, int, struct ifnet *);
int ip_deliver(struct mbuf **, int *, int, int);
+int ip_laddr(struct ifnet *, struct mbuf *, struct rtentry *);
void ip_forward(struct mbuf *, struct ifnet *, struct rtentry *, int);
int rip_ctloutput(int, struct socket *, int, int, struct mbuf *);
void rip_init(void);
Index: sys/netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.229
diff -u -p -r1.229 ip6_input.c
--- sys/netinet6/ip6_input.c 24 Aug 2020 16:40:07 -0000 1.229
+++ sys/netinet6/ip6_input.c 20 Oct 2020 00:12:06 -0000
@@ -425,30 +425,9 @@ ip6_input_if(struct mbuf **mp, int *offp
if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL)) {
struct in6_ifaddr *ia6 = ifatoia6(rt->rt_ifa);
- if (ip6_forwarding == 0 && rt->rt_ifidx != ifp->if_index &&
- !((ifp->if_flags & IFF_LOOPBACK) ||
- (ifp->if_type == IFT_ENC) ||
- (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST))) {
- /* received on wrong interface */
-#if NCARP > 0
- struct ifnet *out_if;
-
- /*
- * Virtual IPs on carp interfaces need to be checked
- * also against the parent interface and other carp
- * interfaces sharing the same parent.
- */
- out_if = if_get(rt->rt_ifidx);
- if (!(out_if && carp_strict_addr_chk(out_if, ifp))) {
- ip6stat_inc(ip6s_wrongif);
- if_put(out_if);
- goto bad;
- }
- if_put(out_if);
-#else
+ if (ip6_forwarding == 0 && !ip_laddr(ifp, m, rt)) {
ip6stat_inc(ip6s_wrongif);
goto bad;
-#endif
}
/*
* packets to a tentative, duplicated, or somehow invalid