tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
sysctl to disable protocol stack
What follows is (just for your info and discussion for now)
a patch that adds sysctls that disable network protocol stacks.
This includes both IPv4 and IPv6 (though just as you cannot successfully
compile a kernel with no IPv4, it turns out to really be a pretty bad
idea, though not instantly fatal, to disable IPv4 currently...)
The sysctls are net.inet.ip.disabled and net.inet6.ip6.disabled
Set those to 1 to disable the relevant protocol (or other values
as described in the patch to sysctl.7).
Normally, you'd set (one) of those at most in /etc/sysctl.conf,
of that happens, for most purposes, the protocol should (amost)
not exist (some of the sysctl tree needs to remain, and in this
patch, all of it remains, fixing that is still to be added here)
much the same as if you compiled without INET6 (or if it were
possible, without INET, setting net.inet.ip.disabled=1 is a good
way to start discovering some of the problems that remain to be fixed
for when we do want IPv4 to be (optionally) removed).
First question to answer - why the sysctl names? Surely
net.inet.disabled (and net.inet6.disabled) would be better?
Yes - they would, but the next sysctl name field under inet,
or inet6, is a protocol name (number, really), from a number
space that isn't under our control, and I didn't want to usurp
anyone's protocol number (I guess, using 256 or something outside
the possible range of protocol numbers would have worked).
This is trivial to change to whatever people like...
Next, why just inet and inet6 ... the original code I'm taking
this from had sysctl trees added for netiso and netatalk as well,
to allow them to be disabled - I'm not sure that was ever tested
(even compile tested...) so I decided to omit that for now - NetBSD
currently has no net.atalk or net.iso sysctl trees that I'm aware
of, so aything in this area would be total invention. The kernel
support for disabling (at least sockets) in those protocols is there,
and adding support for dropping packets for them is trivial, so
we can add that later once the general mechanism is in place.
The original version of this was done to NetBSD 3-beta I think
(all I can see is that __NetBSD_Version__ is 3.0 - but some of
the files are older than in my 3.0 release source tree (so I
am guessing that 3.0 beta was probably the currently available
"recent" version fr the students who did the work initially.
(You can get some idea how long I've had this sitting in a cupboard...)
Lots of NetBSD has changed since then, so this isn't yet well tested
(I ran a current kernel for 20 minutes to play with it, and the
basics look OK, but there is more than needs doing). I can't run
current for long periods yet, so I need to go stick this same code
into NetBSD 5, so I can test it properly - but I thought that some
of you mightlike to take a look and see just how simple this really
all is.
The shar file appended has two patches, one to sysctl.7 (the only
file outside src/sys that's touched by this .. of course, that didn't
exist in NetBSD 3, so it's content is all just recently invented...)
and the other a patch to the kernel (a half dozen or so files have
minor changes).
Opinions, testing, enhancements, all gratefully received...
kre
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# kernel.patch
# sysctl.patch
#
echo x - kernel.patch
sed 's/^X//' >kernel.patch << 'END-of-kernel.patch'
Xdiff -ur sys/kern/uipc_domain.c tsys/kern/uipc_domain.c
X--- sys/kern/uipc_domain.c 2009-10-04 06:02:52.000000000 +0700
X+++ tsys/kern/uipc_domain.c 2009-12-07 20:48:04.000000000 +0700
X@@ -159,6 +159,9 @@
X if (dp == NULL)
X return NULL;
X
X+ if (dom_disabled(dp, DOMAIN_NO_SOCKETS))
X+ return NULL;
X+
X for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
X if (pr->pr_type && pr->pr_type == type)
X return pr;
X@@ -180,6 +183,9 @@
X if (dp == NULL)
X return NULL;
X
X+ if (dom_disabled(dp, DOMAIN_NO_SOCKETS))
X+ return NULL;
X+
X for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
X if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
X return pr;
Xdiff -ur sys/kern/uipc_socket.c tsys/kern/uipc_socket.c
X--- sys/kern/uipc_socket.c 2009-11-07 23:05:37.000000000 +0700
X+++ tsys/kern/uipc_socket.c 2009-12-07 20:47:01.000000000 +0700
X@@ -538,9 +538,14 @@
X else
X prp = pffindtype(dom, type);
X if (prp == NULL) {
X+ struct domain *dp;
X+
X /* no support for domain */
X- if (pffinddomain(dom) == 0)
X+ if ((dp = pffinddomain(dom)) == 0)
X+ return EAFNOSUPPORT;
X+ if (dom_disabled(dp, DOMAIN_NO_SOCKETS))
X return EAFNOSUPPORT;
X+
X /* no support for socket type */
X if (proto == 0 && type != 0)
X return EPROTOTYPE;
Xdiff -ur sys/net/rtsock.c tsys/net/rtsock.c
X--- sys/net/rtsock.c 2009-09-17 00:48:19.000000000 +0700
X+++ tsys/net/rtsock.c 2009-12-07 20:45:59.000000000 +0700
X@@ -1063,8 +1063,16 @@
X }
X }
X IFADDR_FOREACH(ifa, ifp) {
X+ struct domain *dp;
X+
X if (af && af != ifa->ifa_addr->sa_family)
X continue;
X+
X+ dp = pffinddomain(ifa->ifa_addr->sa_family);
X+ if (dp == NULL /* panic! */ ||
X+ dom_disabled(dp, DOMAIN_NO_ADDRESSES))
X+ continue;
X+
X info.rti_info[RTAX_IFA] = ifa->ifa_addr;
X info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
X info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr;
Xdiff -ur sys/netinet/if_arp.c tsys/netinet/if_arp.c
X--- sys/netinet/if_arp.c 2009-11-20 16:03:50.000000000 +0700
X+++ tsys/netinet/if_arp.c 2009-12-09 12:25:03.000000000 +0700
X@@ -927,6 +927,10 @@
X void *tha;
X int s;
X uint64_t *arps;
X+ extern struct domain inetdomain;
X+
X+ if (__predict_false(dom_disabled(&inetdomain, DOMAIN_NO_INPUT)))
X+ goto out;
X
X if (__predict_false(m_makewritable(&m, 0, m->m_pkthdr.len, M_DONTWAIT)))
X goto out;
Xdiff -ur sys/netinet/in.h tsys/netinet/in.h
X--- sys/netinet/in.h 2009-09-14 17:36:50.000000000 +0700
X+++ tsys/netinet/in.h 2009-12-07 20:55:20.000000000 +0700
X@@ -454,7 +454,8 @@
X #define IPCTL_RANDOMID 22 /* use random IP ids (if
configured) */
X #define IPCTL_LOOPBACKCKSUM 23 /* do IP checksum on loopback */
X #define IPCTL_STATS 24 /* IP statistics */
X-#define IPCTL_MAXID 25
X+#define IPCTL_DISABLE 25 /* IPv4 disabled! */
X+#define IPCTL_MAXID 26
X
X #define IPCTL_NAMES { \
X { 0, 0 }, \
X@@ -482,6 +483,7 @@
X { "random_id", CTLTYPE_INT }, \
X { "do_loopback_cksum", CTLTYPE_INT }, \
X { "stats", CTLTYPE_STRUCT }, \
X+ { "disabled", CTLTYPE_INT }, \
X }
X #endif /* _NETBSD_SOURCE */
X
Xdiff -ur sys/netinet/ip_input.c tsys/netinet/ip_input.c
X--- sys/netinet/ip_input.c 2009-09-17 06:09:00.000000000 +0700
X+++ tsys/netinet/ip_input.c 2009-12-07 22:17:40.000000000 +0700
X@@ -521,6 +521,13 @@
X #endif
X
X /*
X+ * If IPv4 has been disabled, then anything that arrives
X+ * is simply dropped.
X+ */
X+ if (__predict_false(dom_disabled(&inetdomain, DOMAIN_NO_INPUT)))
X+ goto bad;
X+
X+ /*
X * If no IP addresses have been set yet but the interfaces
X * are receiving, can't do anything with incoming packets yet.
X */
X@@ -2277,6 +2284,13 @@
X
X sysctl_createv(clog, 0, NULL, NULL,
X CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
X+ CTLTYPE_INT, "disabled",
X+ SYSCTL_DESCR("Remove support for INET (IPv4)"),
X+ NULL, 0, &inetdomain.dom_disable, 0,
X+ CTL_NET, PF_INET, IPPROTO_IP,
X+ IPCTL_DISABLE, CTL_EOL);
X+ sysctl_createv(clog, 0, NULL, NULL,
X+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
X CTLTYPE_INT, "forwarding",
X SYSCTL_DESCR("Enable forwarding of INET datagrams"),
X NULL, 0, &ipforwarding, 0,
Xdiff -ur sys/netinet/tcp_input.c tsys/netinet/tcp_input.c
X--- sys/netinet/tcp_input.c 2009-09-10 05:41:28.000000000 +0700
X+++ tsys/netinet/tcp_input.c 2009-12-07 21:18:39.000000000 +0700
X@@ -1490,6 +1490,8 @@
X goto badsyn;
X }
X } else {
X+ struct domain *dp;
X+
X /*
X * Received a SYN.
X *
X@@ -1512,6 +1514,21 @@
X break;
X }
X
X+ /*
X+ * if the network protocol has been disabled,
X+ * then refuse incoming connection attempts
X+ * (with a RST for politeness, unless we're
X+ * really pretending to be an ignorant oaf)
X+ */
X+ dp = pffinddomain(af);
X+ if (dp == NULL)
X+ goto drop; /* or panic() */
X+ if (dom_disabled(dp, DOMAIN_NO_CONNECT)) {
X+ if (dp->dom_disable & DOMAIN_IGNORE)
X+ goto drop;
X+ goto dropwithreset;
X+ }
X+
X #ifdef INET6
X /*
X * If deprecated address is forbidden, we do
Xdiff -ur sys/netinet6/in6.h tsys/netinet6/in6.h
X--- sys/netinet6/in6.h 2009-09-12 05:06:29.000000000 +0700
X+++ tsys/netinet6/in6.h 2009-12-07 21:57:56.000000000 +0700
X@@ -577,7 +577,8 @@
X #define IPV6CTL_IFQ 42 /* ip6intrq node */
X /* New entries should be added here from current IPV6CTL_MAXID value. */
X /* to define items, should talk with KAME guys first, for *BSD compatibility
*/
X-#define IPV6CTL_MAXID 43
X+#define IPV6CTL_DISABLED 43 /* remove support for INET6 */
X+#define IPV6CTL_MAXID 44
X
X #define IPV6CTL_NAMES { \
X { 0, 0 }, \
X@@ -623,6 +624,7 @@
X { 0, 0 }, \
X { "maxfrags", CTLTYPE_INT }, \
X { "ifq", CTLTYPE_NODE }, \
X+ { "disabled", CTLTYPE_INT }, \
X }
X
X #endif /* _NETBSD_SOURCE */
Xdiff -ur sys/netinet6/ip6_input.c tsys/netinet6/ip6_input.c
X--- sys/netinet6/ip6_input.c 2009-09-17 06:09:01.000000000 +0700
X+++ tsys/netinet6/ip6_input.c 2009-12-07 22:18:54.000000000 +0700
X@@ -287,6 +287,13 @@
X #endif
X
X /*
X+ * If support for IPv6 has been removed,
X+ * IPv6 packets that arrive are always trash
X+ */
X+ if (__predict_false(dom_disabled(&inet6domain, DOMAIN_NO_INPUT)))
X+ goto bad;
X+
X+ /*
X * make sure we don't have onion peering information into m_tag.
X */
X ip6_delaux(m);
X@@ -1714,6 +1721,13 @@
X
X sysctl_createv(clog, 0, NULL, NULL,
X CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
X+ CTLTYPE_INT, "disabled",
X+ SYSCTL_DESCR("Remove support for INET6 (IPv6)"),
X+ NULL, 0, &inet6domain.dom_disable, 0,
X+ CTL_NET, PF_INET6, IPPROTO_IPV6,
X+ IPV6CTL_DISABLED, CTL_EOL);
X+ sysctl_createv(clog, 0, NULL, NULL,
X+ CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
X CTLTYPE_INT, "forwarding",
X SYSCTL_DESCR("Enable forwarding of INET6 datagrams"),
X NULL, 0, &ip6_forwarding, 0,
Xdiff -ur sys/sys/domain.h tsys/sys/domain.h
X--- sys/sys/domain.h 2009-09-12 05:06:29.000000000 +0700
X+++ tsys/sys/domain.h 2009-12-07 21:06:20.000000000 +0700
X@@ -85,6 +85,7 @@
X uint_fast8_t dom_sa_cmpofs;
X uint_fast8_t dom_sa_cmplen;
X struct dom_rtlist dom_rtcache;
X+ int dom_disable;
X };
X
X STAILQ_HEAD(domainhead,domain);
X@@ -98,6 +99,15 @@
X extern struct domainhead domains;
X void domain_attach(struct domain *);
X void domaininit(bool);
X+
X+#define DOMAIN_DISABLED 0x00000001 /* disable everything */
X+#define DOMAIN_IGNORE 0x00000002 /* act as if unknown */
X+#define DOMAIN_NO_SOCKETS 0x00000010 /* no new sockets */
X+#define DOMAIN_NO_ADDRESSES 0x00000020 /* no addresses visible
*/
X+#define DOMAIN_NO_CONNECT 0x00000040 /* no new conections */
X+#define DOMAIN_NO_INPUT 0x00000080 /* input rejected */
X+
X+#define dom_disabled(dp, flag) ((dp)->dom_disable & (DOMAIN_DISABLED |
(flag)))
X #endif
X
X #endif /* !_SYS_DOMAIN_H_ */
END-of-kernel.patch
echo x - sysctl.patch
sed 's/^X//' >sysctl.patch << 'END-of-sysctl.patch'
X--- /release/current/usr/src/share/man/man7/sysctl.7 2009-12-08
15:57:32.000000000 +0700
X+++ sysctl.7 2009-12-09 12:59:19.000000000 +0700
X@@ -989,6 +989,7 @@
X .It ip anonportmin integer yes
X .It ip checkinterface integer yes
X .It ip directed-broadcast integer yes
X+.It ip disabled integer yes
X .It ip do_loopback_cksum integer yes
X .It ip forwarding integer yes
X .It ip forwsrcrt integer yes
X@@ -1104,6 +1105,17 @@
X the packets for those packets are received.
X .It Li ip.directed-broadcast
X If set to 1, enables directed broadcast behavior for the host.
X+.It Li ip.disabled
X+If set to 1, or any odd number, support for IPv4 is (approximately)
X+removed from the system.
X+Even non-zero values remove support for selected parts of the protocol.
X+The value set should be the sum of those the following constants to
X+achieve the desired effect.
X+To prevent new PF_INET sockets being created: 16.
X+To prevent configuring addresses, and hide any already configured: 32.
X+To refuse incoming TCP connections: 64, and to not send a reset
X+while doing so: 2.
X+To drop all incoming IPv4 datagrams: 128.
X .It Li ip.do_loopback_cksum
X Perform IP checksum on loopback.
X .It Li ip.forwarding
X@@ -1358,6 +1370,7 @@
X .It ip6 auto_flowlabel integer yes
X .It ip6 dad_count integer yes
X .It ip6 defmcasthlim integer yes
X+.It ip6 disabled integer yes
X .It ip6 forwarding integer yes
X .It ip6 gifhlim integer yes
X .It ip6 hashsize integer yes
X@@ -1409,6 +1422,12 @@
X This value applies to all the transport protocols on top of IPv6.
X There are APIs to override the value, as documented in
X .Xr ip6 4 .
X+.It Li ip6.disabled
X+If set to 1, or any odd number, support for IPv6 is (approximately)
X+removed from the system.
X+See the description of
X+.Li ip.disabled
X+for a description of the various even values possible.
X .It Li ip6.forwarding
X If set to 1, enables IPv6 forwarding for the node,
X meaning that the node is acting as a router.
END-of-sysctl.patch
exit
Home |
Main Index |
Thread Index |
Old Index