Date: Mon, 15 Jun 2020 13:46:40 +0000 (UTC) From: Ed Maste <emaste@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r362198 - in vendor/blocklist/20200615: . bin diff etc etc/rc.d include lib libexec port test Message-ID: <202006151346.05FDket7067145@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: emaste Date: Mon Jun 15 13:46:40 2020 New Revision: 362198 URL: https://svnweb.freebsd.org/changeset/base/362198 Log: Tag 2020-06-15 blocklist snapshot Upstream git hash 7093cd90cc9eae6bf9fa6b66f679ea6b15451c1e Obtained from: https://github.com/zoulasc/blocklist Sponsored by: The FreeBSD Foundation Added: vendor/blocklist/20200615/ - copied from r362196, vendor/blocklist/dist/ vendor/blocklist/20200615/diff/postfix.diff - copied unchanged from r362197, vendor/blocklist/dist/diff/postfix.diff Replaced: vendor/blocklist/20200615/Makefile - copied unchanged from r362197, vendor/blocklist/dist/Makefile vendor/blocklist/20200615/Makefile.inc - copied unchanged from r362197, vendor/blocklist/dist/Makefile.inc vendor/blocklist/20200615/README - copied unchanged from r362197, vendor/blocklist/dist/README vendor/blocklist/20200615/TODO - copied unchanged from r362197, vendor/blocklist/dist/TODO vendor/blocklist/20200615/bin/Makefile - copied unchanged from r362197, vendor/blocklist/dist/bin/Makefile vendor/blocklist/20200615/bin/blocklistctl.8 - copied unchanged from r362197, vendor/blocklist/dist/bin/blocklistctl.8 vendor/blocklist/20200615/bin/blocklistctl.c - copied unchanged from r362197, vendor/blocklist/dist/bin/blocklistctl.c vendor/blocklist/20200615/bin/blocklistd.8 - copied unchanged from r362197, vendor/blocklist/dist/bin/blocklistd.8 vendor/blocklist/20200615/bin/blocklistd.c - copied unchanged from r362197, vendor/blocklist/dist/bin/blocklistd.c vendor/blocklist/20200615/bin/blocklistd.conf.5 - copied unchanged from r362197, vendor/blocklist/dist/bin/blocklistd.conf.5 vendor/blocklist/20200615/bin/conf.c - copied unchanged from r362197, vendor/blocklist/dist/bin/conf.c vendor/blocklist/20200615/bin/conf.h - copied unchanged from r362197, vendor/blocklist/dist/bin/conf.h vendor/blocklist/20200615/bin/internal.c - copied unchanged from r362197, vendor/blocklist/dist/bin/internal.c vendor/blocklist/20200615/bin/internal.h - copied unchanged from r362197, vendor/blocklist/dist/bin/internal.h vendor/blocklist/20200615/bin/run.c - copied unchanged from r362197, vendor/blocklist/dist/bin/run.c vendor/blocklist/20200615/bin/run.h - copied unchanged from r362197, vendor/blocklist/dist/bin/run.h vendor/blocklist/20200615/bin/state.c - copied unchanged from r362197, vendor/blocklist/dist/bin/state.c vendor/blocklist/20200615/bin/state.h - copied unchanged from r362197, vendor/blocklist/dist/bin/state.h vendor/blocklist/20200615/bin/support.c - copied unchanged from r362197, vendor/blocklist/dist/bin/support.c vendor/blocklist/20200615/bin/support.h - copied unchanged from r362197, vendor/blocklist/dist/bin/support.h vendor/blocklist/20200615/diff/ftpd.diff - copied unchanged from r362197, vendor/blocklist/dist/diff/ftpd.diff vendor/blocklist/20200615/diff/named.diff - copied unchanged from r362197, vendor/blocklist/dist/diff/named.diff vendor/blocklist/20200615/diff/proftpd.diff - copied unchanged from r362197, vendor/blocklist/dist/diff/proftpd.diff vendor/blocklist/20200615/diff/ssh.diff - copied unchanged from r362197, vendor/blocklist/dist/diff/ssh.diff vendor/blocklist/20200615/etc/Makefile - copied unchanged from r362197, vendor/blocklist/dist/etc/Makefile vendor/blocklist/20200615/etc/npf.conf - copied unchanged from r362197, vendor/blocklist/dist/etc/npf.conf vendor/blocklist/20200615/etc/rc.d/Makefile - copied unchanged from r362197, vendor/blocklist/dist/etc/rc.d/Makefile vendor/blocklist/20200615/etc/rc.d/blocklistd - copied unchanged from r362197, vendor/blocklist/dist/etc/rc.d/blocklistd vendor/blocklist/20200615/include/Makefile - copied unchanged from r362197, vendor/blocklist/dist/include/Makefile vendor/blocklist/20200615/include/bl.h - copied unchanged from r362197, vendor/blocklist/dist/include/bl.h vendor/blocklist/20200615/include/blocklist.h - copied unchanged from r362197, vendor/blocklist/dist/include/blocklist.h vendor/blocklist/20200615/lib/Makefile - copied unchanged from r362197, vendor/blocklist/dist/lib/Makefile vendor/blocklist/20200615/lib/bl.c - copied unchanged from r362197, vendor/blocklist/dist/lib/bl.c vendor/blocklist/20200615/lib/blocklist.c - copied unchanged from r362197, vendor/blocklist/dist/lib/blocklist.c vendor/blocklist/20200615/lib/libblocklist.3 - copied unchanged from r362197, vendor/blocklist/dist/lib/libblocklist.3 vendor/blocklist/20200615/libexec/Makefile - copied unchanged from r362197, vendor/blocklist/dist/libexec/Makefile vendor/blocklist/20200615/libexec/blocklistd-helper - copied unchanged from r362197, vendor/blocklist/dist/libexec/blocklistd-helper vendor/blocklist/20200615/port/Makefile.am - copied unchanged from r362197, vendor/blocklist/dist/port/Makefile.am vendor/blocklist/20200615/port/_strtoi.h - copied unchanged from r362197, vendor/blocklist/dist/port/_strtoi.h vendor/blocklist/20200615/port/configure.ac - copied unchanged from r362197, vendor/blocklist/dist/port/configure.ac vendor/blocklist/20200615/port/fgetln.c - copied unchanged from r362197, vendor/blocklist/dist/port/fgetln.c vendor/blocklist/20200615/port/fparseln.c - copied unchanged from r362197, vendor/blocklist/dist/port/fparseln.c vendor/blocklist/20200615/port/pidfile.c - copied unchanged from r362197, vendor/blocklist/dist/port/pidfile.c vendor/blocklist/20200615/port/popenve.c - copied unchanged from r362197, vendor/blocklist/dist/port/popenve.c vendor/blocklist/20200615/port/port.h - copied unchanged from r362197, vendor/blocklist/dist/port/port.h vendor/blocklist/20200615/port/sockaddr_snprintf.c - copied unchanged from r362197, vendor/blocklist/dist/port/sockaddr_snprintf.c vendor/blocklist/20200615/port/strlcat.c - copied unchanged from r362197, vendor/blocklist/dist/port/strlcat.c vendor/blocklist/20200615/port/strlcpy.c - copied unchanged from r362197, vendor/blocklist/dist/port/strlcpy.c vendor/blocklist/20200615/port/strtoi.c - copied unchanged from r362197, vendor/blocklist/dist/port/strtoi.c vendor/blocklist/20200615/test/Makefile - copied unchanged from r362197, vendor/blocklist/dist/test/Makefile vendor/blocklist/20200615/test/cltest.c - copied unchanged from r362197, vendor/blocklist/dist/test/cltest.c vendor/blocklist/20200615/test/srvtest.c - copied unchanged from r362197, vendor/blocklist/dist/test/srvtest.c Copied: vendor/blocklist/20200615/Makefile (from r362197, vendor/blocklist/dist/Makefile) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/blocklist/20200615/Makefile Mon Jun 15 13:46:40 2020 (r362198, copy of r362197, vendor/blocklist/dist/Makefile) @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2015/01/21 16:16:00 christos Exp $ + +SUBDIR = lib .WAIT include bin etc libexec + +.include <bsd.subdir.mk> Copied: vendor/blocklist/20200615/Makefile.inc (from r362197, vendor/blocklist/dist/Makefile.inc) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/blocklist/20200615/Makefile.inc Mon Jun 15 13:46:40 2020 (r362198, copy of r362197, vendor/blocklist/dist/Makefile.inc) @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.2 2015/01/22 04:20:50 christos Exp $ + +WARNS=6 +.if !defined(LIB) +LDADD+= -lblocklist +DPADD+= ${LIBBLOCKLIST} +.endif +CPPFLAGS+= -I${.CURDIR}/../include +CPPFLAGS+=-DHAVE_STRUCT_SOCKADDR_SA_LEN -DHAVE_UTIL_H -DHAVE_DB_H + Copied: vendor/blocklist/20200615/README (from r362197, vendor/blocklist/dist/README) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/blocklist/20200615/README Mon Jun 15 13:46:40 2020 (r362198, copy of r362197, vendor/blocklist/dist/README) @@ -0,0 +1,113 @@ +# $NetBSD: README,v 1.7 2015/01/26 00:34:50 christos Exp $ + +This package contains library that can be used by network daemons to +communicate with a packet filter via a daemon to enforce opening and +closing ports dynamically based on policy. + +The interface to the packet filter is in libexec/blocklistd-helper +(this is currently designed for npf) and the configuration file +(inspired from inetd.conf) is in etc/blocklistd.conf. + +On NetBSD you can find an example npf.conf and blocklistd.conf in +/usr/share/examples/blocklistd; you need to adjust the interface +in npf.conf and copy both files to /etc; then you just enable +blocklistd=YES in /etc/rc.conf, start it up, and you are all set. + +There is also a startup file in etc/rc.d/blocklistd + +Patches to various daemons to add blocklisting capabilitiers are in the +"diff" directory: + - OpenSSH: diff/ssh.diff [tcp socket example] + - Bind: diff/named.diff [both tcp and udp] + - ftpd: diff/ftpd.diff [tcp] + +These patches have been applied to NetBSD-current. + +The network daemon (for example sshd) communicates to blocklistd, via +a unix socket like syslog. The library calls are simple and everything +is handled by the library. In the simplest form the only thing the +daemon needs to do is to call: + + blocklist(action, acceptedfd, message); + +Where: + action = 0 -> successful login clear blocklist state + 1 -> failed login, add to the failed count + acceptedfd -> the file descriptor where the server is + connected to the remote client. It is used + to determine the listening socket, and the + remote address. This allows any program to + contact the blocklist daemon, since the verification + if the program has access to the listening + socket is done by virtue that the port + number is retrieved from the kernel. + message -> an optional string that is used in debugging logs. + +Unfortunately there is no way to get information about the "peer" +from a udp socket, because there is no connection and that information +is kept with the server. In that case the daemon can provide the +peer information to blocklistd via: + + blocklist_sa(action, acceptedfd, sockaddr, sockaddr_len, message); + +The configuration file contains entries of the form: + +# Blacklist rule +# host/Port type protocol owner name nfail disable +192.168.1.1:ssh stream tcp * -int 10 1m +8.8.8.8:ssh stream tcp * -ext 6 60m +ssh stream tcp6 * * 6 60m +http stream tcp * * 6 60m + +Here note that owner is * because the connection is done from the +child ssh socket which runs with user privs. We treat ipv4 connections +differently by maintaining two different rules one for the external +interface and one from the internal We also register for both tcp +and tcp6 since those are different listening sockets and addresses; +we don't bother with ipv6 and separate rules. We use nfail = 6, +because ssh allows 3 password attempts per connection, and this +will let us have 2 connections before blocking. Finally we block +for an hour; we could block forever too by specifying * in the +duration column. + +blocklistd and the library use syslog(3) to report errors. The +blocklist filter state is persisted automatically in /var/db/blocklistd.db +so that if the daemon is restarted, it remembers what connections +is currently handling. To start from a fresh state (if you restart +npf too for example), you can use -f. To watch the daemon at work, +you can use -d. + +The current control file is designed for npf, and it uses the +dynamic rule feature. You need to create a dynamic rule in your +/etc/npf.conf on the group referring to the interface you want to block +called blocklistd as follows: + +ext_if=bge0 +int_if=sk0 + +group "external" on $ext_if { + ... + ruleset "blocklistd-ext" + ruleset "blocklistd" + ... +} + +group "internal" on $int_if { + ... + ruleset "blocklistd-int" + ... +} + +You can use 'blocklistctl dump -a' to list all the current entries +in the database; the ones that have nfail <c>/<t> where <c>urrent +>= <t>otal, should have an id assosiated with them; this means that +there is a packet filter rule added for that entry. For npf, you +can examine the packet filter dynamic rule entries using 'npfctl +rule <rulename> list'. The number of current entries can exceed +the total. This happens because entering packet filter rules is +asynchronous; there could be other connection before the rule +becomes activated. + +Enjoy, + +christos Copied: vendor/blocklist/20200615/TODO (from r362197, vendor/blocklist/dist/TODO) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/blocklist/20200615/TODO Mon Jun 15 13:46:40 2020 (r362198, copy of r362197, vendor/blocklist/dist/TODO) @@ -0,0 +1,21 @@ +# $NetBSD: TODO,v 1.6 2015/01/22 18:15:56 christos Exp $ + +- don't poll periodically, find the next timeout +- use the socket also for commands? Or separate socket? +- add functionality to the control program. Should it change the database + directly, or talk to the daemon to have it do it? +- perhaps handle interfaces too instead of addresses for dynamic ip? + <bge0/4>? What to do with multiple addresses? +- perhaps rate limit against DoS +- perhaps instead of scanning the list have a sparse map by port? +- do we want to use libnpf directly for efficiency? +- add more daemons ftpd? +- do we care about the db state becoming too large? +- instead of a yes = bump one, no = return to 0 interface, do we want + to have something more flexible like? + +n + -n + block + unblock +- do we need an api in blocklistctl to perform maintenance +- fix the blocklistctl output to be more user friendly Copied: vendor/blocklist/20200615/bin/Makefile (from r362197, vendor/blocklist/dist/bin/Makefile) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/blocklist/20200615/bin/Makefile Mon Jun 15 13:46:40 2020 (r362198, copy of r362197, vendor/blocklist/dist/bin/Makefile) @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.10 2015/01/22 17:49:41 christos Exp $ + +BINDIR=/sbin + +PROGS=blocklistd blocklistctl +MAN.blocklistd=blocklistd.8 blocklistd.conf.5 +MAN.blocklistctl=blocklistctl.8 +SRCS.blocklistd = blocklistd.c conf.c run.c state.c support.c internal.c +SRCS.blocklistctl = blocklistctl.c conf.c state.c support.c internal.c +DBG=-g + +LDADD+=-lutil +DPADD+=${LIBUTIL} + +.include <bsd.prog.mk> Copied: vendor/blocklist/20200615/bin/blocklistctl.8 (from r362197, vendor/blocklist/dist/bin/blocklistctl.8) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/blocklist/20200615/bin/blocklistctl.8 Mon Jun 15 13:46:40 2020 (r362198, copy of r362197, vendor/blocklist/dist/bin/blocklistctl.8) @@ -0,0 +1,86 @@ +.\" $NetBSD: blocklistctl.8,v 1.8 2016/06/07 17:31:02 christos Exp $ +.\" +.\" Copyright (c) 2015 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Christos Zoulas. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd June 7, 2016 +.Dt BLOCKLISTCTL 8 +.Os +.Sh NAME +.Nm blocklistctl +.Nd display and change the state of blocklistd +.Sh SYNOPSIS +.Nm +.Cm dump +.Op Fl abdnrw +.Sh DESCRIPTION +.Nm +is a program used to display the state of +.Xr blocklistd 8 +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl a +Show all database entries, by default it shows only the embryonic ones. +.It Fl b +Show only the blocked entries. +.It Fl d +Increase debugging level. +.It Fl n +Don't display a header. +.It Fl r +Show the remaining blocked time instead of the last activity time. +.It Fl w +Normally the width of addresses is good for IPv4, the +.Fl w +flag, makes the display wide enough for IPv6 addresses. +.El +.Sh SEE ALSO +.Xr blocklistd 8 +.Sh NOTES +Sometimes the reported number of failed attempts can exceed the number +of attempts that +.Xr blocklistd 8 +is configured to block. +This can happen either because the rule has been removed manually, or +because there were more attempts in flight while the rule block was being +added. +This condition is normal; in that case +.Xr blocklistd 8 +will first attempt to remove the existing rule, and then it will re-add +it to make sure that there is only one rule active. +.Sh HISTORY +.Nm +first appeared in +.Nx 7 . +.Fx +support for +.Nm +was implemented in +.Fx 11 . +.Sh AUTHORS +.An Christos Zoulas Copied: vendor/blocklist/20200615/bin/blocklistctl.c (from r362197, vendor/blocklist/dist/bin/blocklistctl.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/blocklist/20200615/bin/blocklistctl.c Mon Jun 15 13:46:40 2020 (r362198, copy of r362197, vendor/blocklist/dist/bin/blocklistctl.c) @@ -0,0 +1,168 @@ +/* $NetBSD: blocklistctl.c,v 1.22 2018/05/24 19:19:37 christos Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/cdefs.h> +__RCSID("$NetBSD: blocklistctl.c,v 1.22 2018/05/24 19:19:37 christos Exp $"); + +#include <stdio.h> +#include <time.h> +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif +#ifdef HAVE_UTIL_H +#include <util.h> +#endif +#include <fcntl.h> +#include <string.h> +#include <syslog.h> +#include <err.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/socket.h> + +#include "conf.h" +#include "state.h" +#include "internal.h" +#include "support.h" + +static __dead void +usage(int c) +{ + if (c == 0) + warnx("Missing/unknown command"); + else + warnx("Unknown option `%c'", (char)c); + fprintf(stderr, "Usage: %s dump [-abdnrw]\n", getprogname()); + exit(EXIT_FAILURE); +} + +static const char * +star(char *buf, size_t len, int val) +{ + if (val == -1) + return "*"; + snprintf(buf, len, "%d", val); + return buf; +} + +int +main(int argc, char *argv[]) +{ + const char *dbname = _PATH_BLSTATE; + DB *db; + struct conf c; + struct dbinfo dbi; + unsigned int i; + struct timespec ts; + int all, blocked, remain, wide, noheader; + int o; + + noheader = wide = blocked = all = remain = 0; + lfun = dlog; + + if (argc == 1 || strcmp(argv[1], "dump") != 0) + usage(0); + + argc--; + argv++; + + while ((o = getopt(argc, argv, "abD:dnrw")) != -1) + switch (o) { + case 'a': + all = 1; + blocked = 0; + break; + case 'b': + blocked = 1; + break; + case 'D': + dbname = optarg; + break; + case 'd': + debug++; + break; + case 'n': + noheader = 1; + break; + case 'r': + remain = 1; + break; + case 'w': + wide = 1; + break; + default: + usage(o); + break; + } + + db = state_open(dbname, O_RDONLY, 0); + if (db == NULL) + err(EXIT_FAILURE, "Can't open `%s'", dbname); + + clock_gettime(CLOCK_REALTIME, &ts); + wide = wide ? 8 * 4 + 7 : 4 * 3 + 3; + if (!noheader) + printf("%*.*s/ma:port\tid\tnfail\t%s\n", wide, wide, + "address", remain ? "remaining time" : "last access"); + for (i = 1; state_iterate(db, &c, &dbi, i) != 0; i = 0) { + char buf[BUFSIZ]; + char mbuf[64], pbuf[64]; + if (!all) { + if (blocked) { + if (c.c_nfail == -1 || dbi.count < c.c_nfail) + continue; + } else { + if (dbi.count >= c.c_nfail) + continue; + } + } + sockaddr_snprintf(buf, sizeof(buf), "%a", (void *)&c.c_ss); + printf("%*.*s/%s:%s\t", wide, wide, buf, + star(mbuf, sizeof(mbuf), c.c_lmask), + star(pbuf, sizeof(pbuf), c.c_port)); + if (c.c_duration == -1) { + strlcpy(buf, "never", sizeof(buf)); + } else { + if (remain) + fmtydhms(buf, sizeof(buf), + c.c_duration - (ts.tv_sec - dbi.last)); + else + fmttime(buf, sizeof(buf), dbi.last); + } + printf("%s\t%d/%s\t%-s\n", dbi.id, dbi.count, + star(mbuf, sizeof(mbuf), c.c_nfail), buf); + } + state_close(db); + return EXIT_SUCCESS; +} Copied: vendor/blocklist/20200615/bin/blocklistd.8 (from r362197, vendor/blocklist/dist/bin/blocklistd.8) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/blocklist/20200615/bin/blocklistd.8 Mon Jun 15 13:46:40 2020 (r362198, copy of r362197, vendor/blocklist/dist/bin/blocklistd.8) @@ -0,0 +1,284 @@ +.\" $NetBSD: blocklistd.8,v 1.23 2020/04/21 13:57:12 christos Exp $ +.\" +.\" Copyright (c) 2015 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Christos Zoulas. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd April 21, 2020 +.Dt BLOCKLISTD 8 +.Os +.Sh NAME +.Nm blocklistd +.Nd block and release ports on demand to avoid DoS abuse +.Sh SYNOPSIS +.Nm +.Op Fl dfrv +.Op Fl C Ar controlprog +.Op Fl c Ar configfile +.Op Fl D Ar dbfile +.Op Fl P Ar sockpathsfile +.Op Fl R Ar rulename +.Op Fl s Ar sockpath +.Op Fl t Ar timeout +.Sh DESCRIPTION +.Nm +is a daemon similar to +.Xr syslogd 8 +that listens to sockets at paths specified in the +.Ar sockpathsfile +for notifications from other daemons about successful or failed connection +attempts. +If no such file is specified, then it only listens to the socket path +specified by +.Ar sockspath +or if that is not specified to +.Pa /var/run/blocklistd.sock . +Each notification contains an (action, port, protocol, address, owner) tuple +that identifies the remote connection and the action. +This tuple is consulted against entries in +.Ar configfile +with syntax specified in +.Xr blocklistd.conf 5 . +If an entry is matched, a state entry is created for that tuple. +Each entry contains a number of tries limit and a duration. +.Pp +The way +.Nm +does configuration entry matching is by having the client side pass the +file descriptor associated with the connection the client wants to blocklist +as well as passing socket credentials. +.Pp +The file descriptor is used to retrieve information (address and port) +about the remote side with +.Xr getpeername 2 +and the local side with +.Xr getsockname 2 . +.Pp +By examining the port of the local side, +.Nm +can determine if the client program +.Dq owns +the port. +By examining the optional address portion on the local side, it can match +interfaces. +By examining the remote address, it can match specific allow or deny rules. +.Pp +Finally +.Nm +can examine the socket credentials to match the user in the configuration file. +.Pp +While this works well for TCP sockets, it cannot be relied on for unbound +UDP sockets. +It is also less meaningful when it comes to connections using non-privileged +ports. +On the other hand, if we receive a request that has a local endpoint indicating +a UDP privileged port, we can presume that the client was privileged to be +able to acquire that port. +.Pp +Once an entry is matched +.Nm +can perform various actions. +If the action is +.Dq add +and the number of tries limit is reached, then a +control script +.Ar controlprog +is invoked with arguments: +.Bd -literal -offset indent +control add <rulename> <proto> <address> <mask> <port> +.Ed +.Pp +and should invoke a packet filter command to block the connection +specified by the arguments. +The +.Ar rulename +argument can be set from the command line (default +.Dv blocklistd ) . +The script could print a numerical id to stdout as a handle for +the rule that can be used later to remove that connection, but +that is not required as all information to remove the rule is +kept. +.Pp +If the action is +.Dq rem +Then the same control script is invoked as: +.Bd -literal -offset indent +control rem <rulename> <proto> <address> <mask> <port> <id> +.Ed +.Pp +where +.Ar id +is the number returned from the +.Dq add +action. +.Pp +.Nm +maintains a database of known connections in +.Ar dbfile . +On startup it reads entries from that file, and updates its internal state. +.Pp +.Nm +checks the list of active entries every +.Ar timeout +seconds (default +.Dv 15 ) +and removes entries and block rules using the control program as necessary. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl C Ar controlprog +Use +.Ar controlprog +to communicate with the packet filter, usually +.Pa /libexec/blocklistd-helper . +The following arguments are passed to the control program: +.Bl -tag -width protocol +.It action +The action to perform: +.Dv add , +.Dv rem , +or +.Dv flush +to add, remove or flush a firewall rule. +.It name +The rule name. +.It protocol +The optional protocol name (can be empty): +.Dv tcp , +.Dv tcp6 , +.Dv udp , +.Dv udp6 . +.It address +The IPv4 or IPv6 numeric address to be blocked or released. +.It mask +The numeric mask to be applied to the blocked or released address +.It port +The optional numeric port to be blocked (can be empty). +.It id +For packet filters that support removal of rules by rule identifier, the +identifier of the rule to be removed. +The add command is expected to return the rule identifier string to stdout. +.El +.It Fl c Ar configuration +The name of the configuration file to read, usually +.Pa /etc/blocklistd.conf . +.It Fl D Ar dbfile +The Berkeley DB file where +.Nm +stores its state, usually +.Pa /var/db/blocklistd.db . +.It Fl d +Normally, +.Nm +disassociates itself from the terminal unless the +.Fl d +flag is specified, in which case it stays in the foreground. +.It Fl f +Truncate the state database and flush all the rules named +.Ar rulename +are deleted by invoking the control script as: +.Bd -literal -offset indent +control flush <rulename> +.Ed +.It Fl P Ar sockspathsfile +A file containing a list of pathnames, one per line that +.Nm +will create sockets to listen to. +This is useful for chrooted environments. +.It Fl R Ar rulename +Specify the default rule name for the packet filter rules, usually +.Dv blocklistd . +.It Fl r +Re-read the firewall rules from the internal database, then +remove and re-add them. +This helps for packet filters that do not retain state across reboots. +.It Fl s Ar sockpath +Add +.Ar sockpath +to the list of Unix sockets +.Nm +listens to. +.It Fl t Ar timeout +The interval in seconds +.Nm +polls the state file to update the rules. +.It Fl v +Cause +.Nm +to print +diagnostic messages to +.Dv stdout +instead of +.Xr syslogd 8 . +.El +.Sh SIGNAL HANDLING +.Nm +deals with the following signals: +.Bl -tag -width "USR2" +.It Dv HUP +Receipt of this signal causes +.Nm +to re-read the configuration file. +.It Dv INT , Dv TERM & Dv QUIT +These signals tell +.Nm +to exit in an orderly fashion. +.It Dv USR1 +This signal tells +.Nm +to increase the internal debugging level by 1. +.It Dv USR2 +This signal tells +.Nm +to decrease the internal debugging level by 1. +.El +.Sh FILES +.Bl -tag -width /libexec/blocklistd-helper -compact +.It Pa /libexec/blocklistd-helper +Shell script invoked to interface with the packet filter. +.It Pa /etc/blocklistd.conf +Configuration file. +.It Pa /var/db/blocklistd.db +Database of current connection entries. +.It Pa /var/run/blocklistd.sock +Socket to receive connection notifications. +.El +.Sh SEE ALSO +.Xr blocklistd.conf 5 , +.Xr blocklistctl 8 , +.Xr npfctl 8 , +.Xr syslogd 8 +.Sh HISTORY +.Nm +first appeared in +.Nx 7 . +.Fx +support for +.Nm +was implemented in +.Fx 11 . +.Sh AUTHORS +.An Christos Zoulas Copied: vendor/blocklist/20200615/bin/blocklistd.c (from r362197, vendor/blocklist/dist/bin/blocklistd.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/blocklist/20200615/bin/blocklistd.c Mon Jun 15 13:46:40 2020 (r362198, copy of r362197, vendor/blocklist/dist/bin/blocklistd.c) @@ -0,0 +1,576 @@ +/* $NetBSD: blocklistd.c,v 1.42 2020/03/11 02:33:18 roy Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <sys/cdefs.h> +__RCSID("$NetBSD: blocklistd.c,v 1.42 2020/03/11 02:33:18 roy Exp $"); + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/queue.h> + +#ifdef HAVE_LIBUTIL_H +#include <libutil.h> +#endif +#ifdef HAVE_UTIL_H +#include <util.h> +#endif +#include <string.h> +#include <signal.h> +#include <netdb.h> +#include <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <inttypes.h> +#include <syslog.h> +#include <ctype.h> +#include <limits.h> +#include <errno.h> +#include <poll.h> +#include <fcntl.h> +#include <err.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <ifaddrs.h> +#include <netinet/in.h> + +#include "bl.h" +#include "internal.h" +#include "conf.h" +#include "run.h" +#include "state.h" +#include "support.h" + +static const char *configfile = _PATH_BLCONF; +static DB *state; +static const char *dbfile = _PATH_BLSTATE; +static sig_atomic_t readconf; +static sig_atomic_t done; +static int vflag; + +static void +sigusr1(int n __unused) +{ + debug++; +} + +static void +sigusr2(int n __unused) +{ + debug--; +} + +static void +sighup(int n __unused) +{ + readconf++; +} + +static void +sigdone(int n __unused) +{ + done++; +} + +static __dead void +usage(int c) +{ + if (c) + warnx("Unknown option `%c'", (char)c); + fprintf(stderr, "Usage: %s [-vdfr] [-c <config>] [-R <rulename>] " + "[-P <sockpathsfile>] [-C <controlprog>] [-D <dbfile>] " + "[-s <sockpath>] [-t <timeout>]\n", getprogname()); + exit(EXIT_FAILURE); +} + +static int +getremoteaddress(bl_info_t *bi, struct sockaddr_storage *rss, socklen_t *rsl) +{ + *rsl = sizeof(*rss); + memset(rss, 0, *rsl); + + if (getpeername(bi->bi_fd, (void *)rss, rsl) != -1) + return 0; + + if (errno != ENOTCONN) { + (*lfun)(LOG_ERR, "getpeername failed (%m)"); + return -1; + } + + if (bi->bi_slen == 0) { + (*lfun)(LOG_ERR, "unconnected socket with no peer in message"); + return -1; + } + + switch (bi->bi_ss.ss_family) { + case AF_INET: + *rsl = sizeof(struct sockaddr_in); + break; + case AF_INET6: + *rsl = sizeof(struct sockaddr_in6); + break; + default: + (*lfun)(LOG_ERR, "bad client passed socket family %u", + (unsigned)bi->bi_ss.ss_family); + return -1; + } + + if (*rsl != bi->bi_slen) { + (*lfun)(LOG_ERR, "bad client passed socket length %u != %u", + (unsigned)*rsl, (unsigned)bi->bi_slen); + return -1; + } + + memcpy(rss, &bi->bi_ss, *rsl); + +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + if (*rsl != rss->ss_len) { + (*lfun)(LOG_ERR, + "bad client passed socket internal length %u != %u", + (unsigned)*rsl, (unsigned)rss->ss_len); + return -1; + } +#endif + return 0; +} + +static void +process(bl_t bl) +{ + struct sockaddr_storage rss; + socklen_t rsl; + char rbuf[BUFSIZ]; + bl_info_t *bi; + struct conf c; + struct dbinfo dbi; + struct timespec ts; + + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + (*lfun)(LOG_ERR, "clock_gettime failed (%m)"); + return; + } + + if ((bi = bl_recv(bl)) == NULL) { + (*lfun)(LOG_ERR, "no message (%m)"); + return; + } + + if (getremoteaddress(bi, &rss, &rsl) == -1) + goto out; + + if (debug) { + sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss); + (*lfun)(LOG_DEBUG, "processing type=%d fd=%d remote=%s msg=%s" + " uid=%lu gid=%lu", bi->bi_type, bi->bi_fd, rbuf, + bi->bi_msg, (unsigned long)bi->bi_uid, + (unsigned long)bi->bi_gid); + } + + if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) { + (*lfun)(LOG_DEBUG, "no rule matched"); + goto out; + } + + + if (state_get(state, &c, &dbi) == -1) + goto out; + + if (debug) { + char b1[128], b2[128]; + (*lfun)(LOG_DEBUG, "%s: initial db state for %s: count=%d/%d " + "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail, + fmttime(b1, sizeof(b1), dbi.last), + fmttime(b2, sizeof(b2), ts.tv_sec)); + } + + switch (bi->bi_type) { + case BL_ABUSE: + /* + * If the application has signaled abusive behavior, + * set the number of fails to be one less than the + * configured limit. Fallthrough to the normal BL_ADD + * processing, which will increment the failure count + * to the threshhold, and block the abusive address. + */ + if (c.c_nfail != -1) + dbi.count = c.c_nfail - 1; + /*FALLTHROUGH*/ + case BL_ADD: + dbi.count++; + dbi.last = ts.tv_sec; + if (c.c_nfail != -1 && dbi.count >= c.c_nfail) { + /* + * No point in re-adding the rule. + * It might exist already due to latency in processing + * and removing the rule is the wrong thing to do as + * it allows a window to attack again. + */ + if (dbi.id[0] == '\0') { + int res = run_change("add", &c, + dbi.id, sizeof(dbi.id)); + if (res == -1) + goto out; + } + sockaddr_snprintf(rbuf, sizeof(rbuf), "%a", + (void *)&rss); + (*lfun)(LOG_INFO, + "blocked %s/%d:%d for %d seconds", + rbuf, c.c_lmask, c.c_port, c.c_duration); + } + break; + case BL_DELETE: + if (dbi.last == 0) + goto out; + dbi.count = 0; + dbi.last = 0; + break; + case BL_BADUSER: + /* ignore for now */ + break; + default: + (*lfun)(LOG_ERR, "unknown message %d", bi->bi_type); + } + state_put(state, &c, &dbi); + +out: + close(bi->bi_fd); + + if (debug) { + char b1[128], b2[128]; + (*lfun)(LOG_DEBUG, "%s: final db state for %s: count=%d/%d " + "last=%s now=%s", __func__, rbuf, dbi.count, c.c_nfail, *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202006151346.05FDket7067145>