Subject: kern/898: enable strict control of ip input
To: None <gnats-admin@NetBSD.ORG>
From: Simon J. Gerraty <sjg@zen.void.oz.au>
List: netbsd-bugs
Date: 03/23/1995 01:35:04
>Number: 898
>Category: kern
>Synopsis: patch to prevent ip packets being delivered to other than receiving interface
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Thu Mar 23 01:35:02 1995
>Originator: Simon J. Gerraty
>Organization:
Zen Programming...
>Release: 1.0
>Environment:
System: NetBSD zen.void.oz.au 1.0 NetBSD 1.0 (ZEN) #6: Tue Dec 13 09:55:20 EST 1994 root@zen.void.oz.au:/usr/src/sys/arch/i386/compile/ZEN i386
>Description:
In the following config:
(bad_guy) 1.1 ------ 1.2 [NetBSD] 2.2 ------ (good_guys)
"bad_guy" can set a route to address 2.2 via 1.1 and reach a service
which NetBSD is trying to only offer to "good_guys".
The simple patch below, makes NetBSD check whether the dest address
2.2 belongs to the interface the packet arrived on (or came from a
loopback interface) and if not, simply drops it.
This then allows NetBSD to offer different service sets on different
interfaces.
The patch below is against --current ip_input.c, I've used
ipforwarding < 0 to control this, but that it probably not a good idea
(folk who really want this will not want anyone to be able to turn it
off), but is useful for experimenting with it. I use
sysctl -w net.inet.ip.forwarding=-1
before starting inetd (modified to bind to specific addrs not *.23
say).
>How-To-Repeat:
<code/input/activities to reproduce the problem (multiple
lines)>
>Fix:
*** ip_input.c.~1~ Wed Jun 29 20:31:01 1994
--- ip_input.c Thu Mar 23 12:54:56 1995
***************
*** 241,248 ****
for (ia = in_ifaddr; ia; ia = ia->ia_next) {
#define satosin(sa) ((struct sockaddr_in *)(sa))
! if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr)
goto ours;
if (
#ifdef DIRECTED_BROADCAST
ia->ia_ifp == m->m_pkthdr.rcvif &&
--- 241,262 ----
for (ia = in_ifaddr; ia; ia = ia->ia_next) {
#define satosin(sa) ((struct sockaddr_in *)(sa))
! if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) {
! /* one of our addresses */
! if (ipforwarding >= 0)
goto ours;
+ /*
+ * ipforwarding < 0 means only accept
+ * packets to addresses belonging to the interface
+ * or it arrived on the loopback interface.
+ */
+ if (ia->ia_ifp == m->m_pkthdr.rcvif ||
+ m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)
+ goto ours;
+ /* nope, someone playing games with us */
+ ipstat.ips_cantforward++;
+ goto bad;
+ }
if (
#ifdef DIRECTED_BROADCAST
ia->ia_ifp == m->m_pkthdr.rcvif &&
***************
*** 330,336 ****
/*
* Not for us; forward if possible and desirable.
*/
! if (ipforwarding == 0) {
ipstat.ips_cantforward++;
m_freem(m);
} else
--- 344,350 ----
/*
* Not for us; forward if possible and desirable.
*/
! if (ipforwarding <= 0) {
ipstat.ips_cantforward++;
m_freem(m);
} else
>Audit-Trail:
>Unformatted: