From 6fa63e1816f543db1c68320f442e30f95d8f9f78 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Mon, 15 Jun 2020 13:17:22 +0000 Subject: Following upstream, rename blacklist to blocklist Also move up one level from vendor/NetBSD/blacklist to vendor/blocklist, as this is now has a standalone home at https://github.com/zoulasc/blocklist I also renamed the individual files under dist/ so that the subsequent update from upstream will drop in. Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- bin/blacklistctl.8 | 86 ------- bin/blacklistctl.c | 168 -------------- bin/blacklistd.8 | 227 ------------------ bin/blacklistd.c | 568 ---------------------------------------------- bin/blacklistd.conf.5 | 229 ------------------- bin/blocklistctl.8 | 86 +++++++ bin/blocklistctl.c | 168 ++++++++++++++ bin/blocklistd.8 | 227 ++++++++++++++++++ bin/blocklistd.c | 568 ++++++++++++++++++++++++++++++++++++++++++++++ bin/blocklistd.conf.5 | 229 +++++++++++++++++++ etc/blacklistd.conf | 14 -- etc/blocklistd.conf | 14 ++ etc/rc.d/blacklistd | 57 ----- etc/rc.d/blocklistd | 57 +++++ include/blacklist.h | 46 ---- include/blocklist.h | 46 ++++ lib/blacklist.c | 88 ------- lib/blocklist.c | 88 +++++++ lib/libblacklist.3 | 132 ----------- lib/libblocklist.3 | 132 +++++++++++ libexec/blacklistd-helper | 129 ----------- libexec/blocklistd-helper | 129 +++++++++++ 22 files changed, 1744 insertions(+), 1744 deletions(-) delete mode 100644 bin/blacklistctl.8 delete mode 100644 bin/blacklistctl.c delete mode 100644 bin/blacklistd.8 delete mode 100644 bin/blacklistd.c delete mode 100644 bin/blacklistd.conf.5 create mode 100644 bin/blocklistctl.8 create mode 100644 bin/blocklistctl.c create mode 100644 bin/blocklistd.8 create mode 100644 bin/blocklistd.c create mode 100644 bin/blocklistd.conf.5 delete mode 100644 etc/blacklistd.conf create mode 100644 etc/blocklistd.conf delete mode 100644 etc/rc.d/blacklistd create mode 100644 etc/rc.d/blocklistd delete mode 100644 include/blacklist.h create mode 100644 include/blocklist.h delete mode 100644 lib/blacklist.c create mode 100644 lib/blocklist.c delete mode 100644 lib/libblacklist.3 create mode 100644 lib/libblocklist.3 delete mode 100644 libexec/blacklistd-helper create mode 100644 libexec/blocklistd-helper diff --git a/bin/blacklistctl.8 b/bin/blacklistctl.8 deleted file mode 100644 index 7c6521117745..000000000000 --- a/bin/blacklistctl.8 +++ /dev/null @@ -1,86 +0,0 @@ -.\" $NetBSD: blacklistctl.8,v 1.9 2016/06/08 12:48:37 wiz 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 BLACKLISTCTL 8 -.Os -.Sh NAME -.Nm blacklistctl -.Nd display and change the state of blacklistd -.Sh SYNOPSIS -.Nm -.Cm dump -.Op Fl abdnrw -.Sh DESCRIPTION -.Nm -is a program used to display the state of -.Xr blacklistd 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 blacklistd 8 -.Sh NOTES -Sometimes the reported number of failed attempts can exceed the number -of attempts that -.Xr blacklistd 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 blacklistd 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 diff --git a/bin/blacklistctl.c b/bin/blacklistctl.c deleted file mode 100644 index aebbf72acc5e..000000000000 --- a/bin/blacklistctl.c +++ /dev/null @@ -1,168 +0,0 @@ -/* $NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 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 -__RCSID("$NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 christos Exp $"); - -#include -#include -#ifdef HAVE_LIBUTIL_H -#include -#endif -#ifdef HAVE_UTIL_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/bin/blacklistd.8 b/bin/blacklistd.8 deleted file mode 100644 index 5846047304dc..000000000000 --- a/bin/blacklistd.8 +++ /dev/null @@ -1,227 +0,0 @@ -.\" $NetBSD: blacklistd.8,v 1.18 2016/07/30 06:09:29 dholland 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 BLACKLISTD 8 -.Os -.Sh NAME -.Nm blacklistd -.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/blacklistd.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 blacklistd.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 -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
-.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 blacklistd ) . -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 remove -Then the same control script is invoked as: -.Bd -literal -offset indent -control remove
-.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/blacklistd-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/blacklistd.conf . -.It Fl D Ar dbfile -The Berkeley DB file where -.Nm -stores its state, usually -.Pa /var/run/blacklistd.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 -.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 blacklistd . -.It Fl r -Re-read the firewall rules from the internal database, then -remove and re-add them. -This helps for packet filters that don't 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 FILES -.Bl -tag -width /libexec/blacklistd-helper -compact -.It Pa /libexec/blacklistd-helper -Shell script invoked to interface with the packet filter. -.It Pa /etc/blacklistd.conf -Configuration file. -.It Pa /var/db/blacklistd.db -Database of current connection entries. -.It Pa /var/run/blacklistd.sock -Socket to receive connection notifications. -.El -.Sh SEE ALSO -.Xr blacklistd.conf 5 , -.Xr blacklistctl 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 diff --git a/bin/blacklistd.c b/bin/blacklistd.c deleted file mode 100644 index ac92bbf2ffbf..000000000000 --- a/bin/blacklistd.c +++ /dev/null @@ -1,568 +0,0 @@ -/* $NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 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 -__RCSID("$NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 christos Exp $"); - -#include -#include -#include - -#ifdef HAVE_LIBUTIL_H -#include -#endif -#ifdef HAVE_UTIL_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 ] [-R ] " - "[-P ] [-C ] [-D ] " - "[-s ] [-t ]\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_ADD: - dbi.count++; - dbi.last = ts.tv_sec; - if (dbi.id[0]) { - /* - * We should not be getting this since the rule - * should have blocked the address. A possible - * explanation is that someone removed that rule, - * and another would be that we got another attempt - * before we added the rule. In anycase, we remove - * and re-add the rule because we don't want to add - * it twice, because then we'd lose track of it. - */ - (*lfun)(LOG_DEBUG, "rule exists %s", dbi.id); - (void)run_change("rem", &c, dbi.id, 0); - dbi.id[0] = '\0'; - } - if (c.c_nfail != -1 && dbi.count >= c.c_nfail) { - 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; - 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, - fmttime(b1, sizeof(b1), dbi.last), - fmttime(b2, sizeof(b2), ts.tv_sec)); - } -} - -static void -update_interfaces(void) -{ - struct ifaddrs *oifas, *nifas; - - if (getifaddrs(&nifas) == -1) - return; - - oifas = ifas; - ifas = nifas; - - if (oifas) - freeifaddrs(oifas); -} - -static void -update(void) -{ - struct timespec ts; - struct conf c; - struct dbinfo dbi; - unsigned int f, n; - char buf[128]; - void *ss = &c.c_ss; - - if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { - (*lfun)(LOG_ERR, "clock_gettime failed (%m)"); - return; - } - -again: - for (n = 0, f = 1; state_iterate(state, &c, &dbi, f) == 1; - f = 0, n++) - { - time_t when = c.c_duration + dbi.last; - if (debug > 1) { - char b1[64], b2[64]; - sockaddr_snprintf(buf, sizeof(buf), "%a:%p", ss); - (*lfun)(LOG_DEBUG, "%s:[%u] %s count=%d duration=%d " - "last=%s " "now=%s", __func__, n, buf, dbi.count, - c.c_duration, fmttime(b1, sizeof(b1), dbi.last), - fmttime(b2, sizeof(b2), ts.tv_sec)); - } - if (c.c_duration == -1 || when >= ts.tv_sec) - continue; - if (dbi.id[0]) { - run_change("rem", &c, dbi.id, 0); - sockaddr_snprintf(buf, sizeof(buf), "%a", ss); - syslog(LOG_INFO, "released %s/%d:%d after %d seconds", - buf, c.c_lmask, c.c_port, c.c_duration); - } - state_del(state, &c); - goto again; - } -} - -static void -addfd(struct pollfd **pfdp, bl_t **blp, size_t *nfd, size_t *maxfd, - const char *path) -{ - bl_t bl = bl_create(true, path, vflag ? vdlog : vsyslog); - if (bl == NULL || !bl_isconnected(bl)) - exit(EXIT_FAILURE); - if (*nfd >= *maxfd) { - *maxfd += 10; - *blp = realloc(*blp, sizeof(**blp) * *maxfd); - if (*blp == NULL) - err(EXIT_FAILURE, "malloc"); - *pfdp = realloc(*pfdp, sizeof(**pfdp) * *maxfd); - if (*pfdp == NULL) - err(EXIT_FAILURE, "malloc"); - } - - (*pfdp)[*nfd].fd = bl_getfd(bl); - (*pfdp)[*nfd].events = POLLIN; - (*blp)[*nfd] = bl; - *nfd += 1; -} - -static void -uniqueadd(struct conf ***listp, size_t *nlist, size_t *mlist, struct conf *c) -{ - struct conf **list = *listp; - - if (c->c_name[0] == '\0') - return; - for (size_t i = 0; i < *nlist; i++) { - if (strcmp(list[i]->c_name, c->c_name) == 0) - return; - } - if (*nlist == *mlist) { - *mlist += 10; - void *p = realloc(*listp, *mlist * sizeof(*list)); - if (p == NULL) - err(EXIT_FAILURE, "Can't allocate for rule list"); - list = *listp = p; - } - list[(*nlist)++] = c; -} - -static void -rules_flush(void) -{ - struct conf **list; - size_t nlist, mlist; - - list = NULL; - mlist = nlist = 0; - for (size_t i = 0; i < rconf.cs_n; i++) - uniqueadd(&list, &nlist, &mlist, &rconf.cs_c[i]); - for (size_t i = 0; i < lconf.cs_n; i++) - uniqueadd(&list, &nlist, &mlist, &lconf.cs_c[i]); - - for (size_t i = 0; i < nlist; i++) - run_flush(list[i]); - free(list); -} - -static void -rules_restore(void) -{ - struct conf c; - struct dbinfo dbi; - unsigned int f; - - for (f = 1; state_iterate(state, &c, &dbi, f) == 1; f = 0) { - if (dbi.id[0] == '\0') - continue; - (void)run_change("add", &c, dbi.id, sizeof(dbi.id)); - } -} - -int -main(int argc, char *argv[]) -{ - int c, tout, flags, flush, restore, ret; - const char *spath, **blsock; - size_t nblsock, maxblsock; - - setprogname(argv[0]); - - spath = NULL; - blsock = NULL; - maxblsock = nblsock = 0; - flush = 0; - restore = 0; - tout = 0; - flags = O_RDWR|O_EXCL|O_CLOEXEC; - while ((c = getopt(argc, argv, "C:c:D:dfP:rR:s:t:v")) != -1) { - switch (c) { - case 'C': - controlprog = optarg; - break; - case 'c': - configfile = optarg; - break; - case 'D': - dbfile = optarg; - break; - case 'd': - debug++; - break; - case 'f': - flush++; - break; - case 'P': - spath = optarg; - break; - case 'R': - rulename = optarg; - break; - case 'r': - restore++; - break; - case 's': - if (nblsock >= maxblsock) { - maxblsock += 10; - void *p = realloc(blsock, - sizeof(*blsock) * maxblsock); - if (p == NULL) - err(EXIT_FAILURE, - "Can't allocate memory for %zu sockets", - maxblsock); - blsock = p; - } - blsock[nblsock++] = optarg; - break; - case 't': - tout = atoi(optarg) * 1000; - break; - case 'v': - vflag++; - break; - default: - usage(c); - } - } - - argc -= optind; - if (argc) - usage(0); - - signal(SIGHUP, sighup); - signal(SIGINT, sigdone); - signal(SIGQUIT, sigdone); - signal(SIGTERM, sigdone); - signal(SIGUSR1, sigusr1); - signal(SIGUSR2, sigusr2); - - openlog(getprogname(), LOG_PID, LOG_DAEMON); - - if (debug) { - lfun = dlog; - if (tout == 0) - tout = 5000; - } else { - if (tout == 0) - tout = 15000; - } - - update_interfaces(); - conf_parse(configfile); - if (flush) { - rules_flush(); - if (!restore) - flags |= O_TRUNC; - } - - struct pollfd *pfd = NULL; - bl_t *bl = NULL; - size_t nfd = 0; - size_t maxfd = 0; - - for (size_t i = 0; i < nblsock; i++) - addfd(&pfd, &bl, &nfd, &maxfd, blsock[i]); - free(blsock); - - if (spath) { - FILE *fp = fopen(spath, "r"); - char *line; - if (fp == NULL) - err(EXIT_FAILURE, "Can't open `%s'", spath); - for (; (line = fparseln(fp, NULL, NULL, NULL, 0)) != NULL; - free(line)) - addfd(&pfd, &bl, &nfd, &maxfd, line); - fclose(fp); - } - if (nfd == 0) - addfd(&pfd, &bl, &nfd, &maxfd, _PATH_BLSOCK); - - state = state_open(dbfile, flags, 0600); - if (state == NULL) - state = state_open(dbfile, flags | O_CREAT, 0600); - if (state == NULL) - return EXIT_FAILURE; - - if (restore) { - if (!flush) - rules_flush(); - rules_restore(); - } - - if (!debug) { - if (daemon(0, 0) == -1) - err(EXIT_FAILURE, "daemon failed"); - if (pidfile(NULL) == -1) - err(EXIT_FAILURE, "Can't create pidfile"); - } - - for (size_t t = 0; !done; t++) { - if (readconf) { - readconf = 0; - conf_parse(configfile); - } - ret = poll(pfd, (nfds_t)nfd, tout); - if (debug) - (*lfun)(LOG_DEBUG, "received %d from poll()", ret); - switch (ret) { - case -1: - if (errno == EINTR) - continue; - (*lfun)(LOG_ERR, "poll (%m)"); - return EXIT_FAILURE; - case 0: - state_sync(state); - break; - default: - for (size_t i = 0; i < nfd; i++) - if (pfd[i].revents & POLLIN) - process(bl[i]); - } - if (t % 100 == 0) - state_sync(state); - if (t % 10000 == 0) - update_interfaces(); - update(); - } - state_close(state); - return 0; -} diff --git a/bin/blacklistd.conf.5 b/bin/blacklistd.conf.5 deleted file mode 100644 index 3b85fb889e32..000000000000 --- a/bin/blacklistd.conf.5 +++ /dev/null @@ -1,229 +0,0 @@ -.\" $NetBSD: blacklistd.conf.5,v 1.7 2017/06/07 13:50:57 wiz 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 5, 2017 -.Dt BLACKLISTD.CONF 5 -.Os -.Sh NAME -.Nm blacklistd.conf -.Nd configuration file format for blacklistd -.Sh DESCRIPTION -The -.Nm -files contains configuration entries for -.Xr blacklistd 8 -in a fashion similar to -.Xr inetd.conf 5 . -Only one entry per line is permitted. -Every entry must have all fields populated. -Each field can be separated by a tab or a space. -Comments are denoted by a -.Dq # -at the beginning of a line. -.Pp -There are two kinds of configuration lines, -.Va local -and -.Va remote . -By default, configuration lines are -.Va local , -i.e. the address specified refers to the addresses on the local machine. -To switch to between -.Va local -and -.Va remote -configuration lines you can specify the stanzas: -.Dq [local] -and -.Dq [remote] . -.Pp -On -.Va local -and -.Va remote -lines -.Dq * -means use the default, or wildcard match. -In addition, for -.Va remote -lines -.Dq = -means use the values from the matched -.Va local -configuration line. -.Pp -The first four fields, -.Va location , -.Va type , -.Va proto , -and -.Va owner -are used to match the -.Va local -or -.Va remote -addresses, whereas the last 3 fields -.Va name , -.Va nfail , -and -.Va disable -are used to modify the filtering action. -.Pp -The first field denotes the -.Va location -as an address, mask, and port. -The syntax for the -.Va location -is: -.Bd -literal -offset indent - [
|][/][:] -.Ed -.Pp -The -.Dv address -can be an IPv4 address in numeric format, an IPv6 address -in numeric format and enclosed by square brackets, or an interface name. -Mask modifiers are not allowed on interfaces because interfaces -can have multiple addresses in different protocols where the mask has a different -size. -.Pp -The -.Dv mask -is always numeric, but the -.Dv port -can be either numeric or symbolic. -.Pp -The second field is the socket -.Va type : -.Dv stream , -.Dv dgram , -or numeric. -The third field is the -.Va prococol : -.Dv tcp , -.Dv udp , -.Dv tcp6 , -.Dv udp6 , -or numeric. -The fourth file is the effective user -.Va ( owner ) -of the daemon process reporting the event, -either as a username or a userid. -.Pp -The rest of the fields are controlling the behavior of the filter. -.Pp -The -.Va name -field, is the name of the packet filter rule to be used. -If the -.Va name -starts with a -.Dq - , -then the default rulename is prepended to the given name. -If the -.Dv name -contains a -.Dq / , -the remaining portion of the name is interpreted as the mask to be -applied to the address specified in the rule, causing a single rule violation to -block the entire subnet for the configured prefix. -.Pp -The -.Va nfail -field contains the number of failed attempts before access is blocked, -defaulting to -.Dq * -meaning never, and the last field -.Va disable -specifies the amount of time since the last access that the blocking -rule should be active, defaulting to -.Dq * -meaning forever. -The default unit for -.Va disable -is seconds, but one can specify suffixes for different units, such as -.Dq m -for minutes -.Dq h -for hours and -.Dq d -for days. -.Pp -Matching is done first by checking the -.Va local -rules individually, in the order of the most specific to the least specific. -If a match is found, then the -.Va remote -rules are applied. -The -.Va name , -.Va nfail , -and -.Va disable -fields can be altered by the -.Va remote -rule that matched. -.Pp -The -.Va remote -rules can be used for whitelisting specific addresses, changing the mask -size, the rule that the packet filter uses, the number of failed attempts, -or the block duration. -.Sh FILES -.Bl -tag -width /etc/blacklistd.conf -compact -.It Pa /etc/blacklistd.conf -Configuration file. -.El -.Sh EXAMPLES -.Bd -literal -offset 8n -# Block ssh, after 3 attempts for 6 hours on the bnx0 interface -[local] -# location type proto owner name nfail duration -bnx0:ssh * * * * 3 6h -[remote] -# Never block 1.2.3.4 -1.2.3.4:ssh * * * * * * -# For addresses coming from 8.8.0.0/16 block class C networks instead -# individual hosts, but keep the rest of the blocking parameters the same. -8.8.0.0/16:ssh * * * /24 = = -.Ed -.Sh SEE ALSO -.Xr blacklistctl 8 , -.Xr blacklistd 8 -.Sh HISTORY -.Nm -first appeared in -.Nx 7 . -.Fx -support for -.Nm -was implemented in -.Fx 11 . -.Sh AUTHORS -.An Christos Zoulas diff --git a/bin/blocklistctl.8 b/bin/blocklistctl.8 new file mode 100644 index 000000000000..7c6521117745 --- /dev/null +++ b/bin/blocklistctl.8 @@ -0,0 +1,86 @@ +.\" $NetBSD: blacklistctl.8,v 1.9 2016/06/08 12:48:37 wiz 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 BLACKLISTCTL 8 +.Os +.Sh NAME +.Nm blacklistctl +.Nd display and change the state of blacklistd +.Sh SYNOPSIS +.Nm +.Cm dump +.Op Fl abdnrw +.Sh DESCRIPTION +.Nm +is a program used to display the state of +.Xr blacklistd 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 blacklistd 8 +.Sh NOTES +Sometimes the reported number of failed attempts can exceed the number +of attempts that +.Xr blacklistd 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 blacklistd 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 diff --git a/bin/blocklistctl.c b/bin/blocklistctl.c new file mode 100644 index 000000000000..aebbf72acc5e --- /dev/null +++ b/bin/blocklistctl.c @@ -0,0 +1,168 @@ +/* $NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 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 +__RCSID("$NetBSD: blacklistctl.c,v 1.23 2018/05/24 19:21:01 christos Exp $"); + +#include +#include +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/bin/blocklistd.8 b/bin/blocklistd.8 new file mode 100644 index 000000000000..5846047304dc --- /dev/null +++ b/bin/blocklistd.8 @@ -0,0 +1,227 @@ +.\" $NetBSD: blacklistd.8,v 1.18 2016/07/30 06:09:29 dholland 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 BLACKLISTD 8 +.Os +.Sh NAME +.Nm blacklistd +.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/blacklistd.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 blacklistd.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 +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
+.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 blacklistd ) . +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 remove +Then the same control script is invoked as: +.Bd -literal -offset indent +control remove
+.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/blacklistd-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/blacklistd.conf . +.It Fl D Ar dbfile +The Berkeley DB file where +.Nm +stores its state, usually +.Pa /var/run/blacklistd.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 +.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 blacklistd . +.It Fl r +Re-read the firewall rules from the internal database, then +remove and re-add them. +This helps for packet filters that don't 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 FILES +.Bl -tag -width /libexec/blacklistd-helper -compact +.It Pa /libexec/blacklistd-helper +Shell script invoked to interface with the packet filter. +.It Pa /etc/blacklistd.conf +Configuration file. +.It Pa /var/db/blacklistd.db +Database of current connection entries. +.It Pa /var/run/blacklistd.sock +Socket to receive connection notifications. +.El +.Sh SEE ALSO +.Xr blacklistd.conf 5 , +.Xr blacklistctl 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 diff --git a/bin/blocklistd.c b/bin/blocklistd.c new file mode 100644 index 000000000000..ac92bbf2ffbf --- /dev/null +++ b/bin/blocklistd.c @@ -0,0 +1,568 @@ +/* $NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 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 +__RCSID("$NetBSD: blacklistd.c,v 1.38 2019/02/27 02:20:18 christos Exp $"); + +#include +#include +#include + +#ifdef HAVE_LIBUTIL_H +#include +#endif +#ifdef HAVE_UTIL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ] [-R ] " + "[-P ] [-C ] [-D ] " + "[-s ] [-t ]\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_ADD: + dbi.count++; + dbi.last = ts.tv_sec; + if (dbi.id[0]) { + /* + * We should not be getting this since the rule + * should have blocked the address. A possible + * explanation is that someone removed that rule, + * and another would be that we got another attempt + * before we added the rule. In anycase, we remove + * and re-add the rule because we don't want to add + * it twice, because then we'd lose track of it. + */ + (*lfun)(LOG_DEBUG, "rule exists %s", dbi.id); + (void)run_change("rem", &c, dbi.id, 0); + dbi.id[0] = '\0'; + } + if (c.c_nfail != -1 && dbi.count >= c.c_nfail) { + 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; + 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, + fmttime(b1, sizeof(b1), dbi.last), + fmttime(b2, sizeof(b2), ts.tv_sec)); + } +} + +static void +update_interfaces(void) +{ + struct ifaddrs *oifas, *nifas; + + if (getifaddrs(&nifas) == -1) + return; + + oifas = ifas; + ifas = nifas; + + if (oifas) + freeifaddrs(oifas); +} + +static void +update(void) +{ + struct timespec ts; + struct conf c; + struct dbinfo dbi; + unsigned int f, n; + char buf[128]; + void *ss = &c.c_ss; + + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + (*lfun)(LOG_ERR, "clock_gettime failed (%m)"); + return; + } + +again: + for (n = 0, f = 1; state_iterate(state, &c, &dbi, f) == 1; + f = 0, n++) + { + time_t when = c.c_duration + dbi.last; + if (debug > 1) { + char b1[64], b2[64]; + sockaddr_snprintf(buf, sizeof(buf), "%a:%p", ss); + (*lfun)(LOG_DEBUG, "%s:[%u] %s count=%d duration=%d " + "last=%s " "now=%s", __func__, n, buf, dbi.count, + c.c_duration, fmttime(b1, sizeof(b1), dbi.last), + fmttime(b2, sizeof(b2), ts.tv_sec)); + } + if (c.c_duration == -1 || when >= ts.tv_sec) + continue; + if (dbi.id[0]) { + run_change("rem", &c, dbi.id, 0); + sockaddr_snprintf(buf, sizeof(buf), "%a", ss); + syslog(LOG_INFO, "released %s/%d:%d after %d seconds", + buf, c.c_lmask, c.c_port, c.c_duration); + } + state_del(state, &c); + goto again; + } +} + +static void +addfd(struct pollfd **pfdp, bl_t **blp, size_t *nfd, size_t *maxfd, + const char *path) +{ + bl_t bl = bl_create(true, path, vflag ? vdlog : vsyslog); + if (bl == NULL || !bl_isconnected(bl)) + exit(EXIT_FAILURE); + if (*nfd >= *maxfd) { + *maxfd += 10; + *blp = realloc(*blp, sizeof(**blp) * *maxfd); + if (*blp == NULL) + err(EXIT_FAILURE, "malloc"); + *pfdp = realloc(*pfdp, sizeof(**pfdp) * *maxfd); + if (*pfdp == NULL) + err(EXIT_FAILURE, "malloc"); + } + + (*pfdp)[*nfd].fd = bl_getfd(bl); + (*pfdp)[*nfd].events = POLLIN; + (*blp)[*nfd] = bl; + *nfd += 1; +} + +static void +uniqueadd(struct conf ***listp, size_t *nlist, size_t *mlist, struct conf *c) +{ + struct conf **list = *listp; + + if (c->c_name[0] == '\0') + return; + for (size_t i = 0; i < *nlist; i++) { + if (strcmp(list[i]->c_name, c->c_name) == 0) + return; + } + if (*nlist == *mlist) { + *mlist += 10; + void *p = realloc(*listp, *mlist * sizeof(*list)); + if (p == NULL) + err(EXIT_FAILURE, "Can't allocate for rule list"); + list = *listp = p; + } + list[(*nlist)++] = c; +} + +static void +rules_flush(void) +{ + struct conf **list; + size_t nlist, mlist; + + list = NULL; + mlist = nlist = 0; + for (size_t i = 0; i < rconf.cs_n; i++) + uniqueadd(&list, &nlist, &mlist, &rconf.cs_c[i]); + for (size_t i = 0; i < lconf.cs_n; i++) + uniqueadd(&list, &nlist, &mlist, &lconf.cs_c[i]); + + for (size_t i = 0; i < nlist; i++) + run_flush(list[i]); + free(list); +} + +static void +rules_restore(void) +{ + struct conf c; + struct dbinfo dbi; + unsigned int f; + + for (f = 1; state_iterate(state, &c, &dbi, f) == 1; f = 0) { + if (dbi.id[0] == '\0') + continue; + (void)run_change("add", &c, dbi.id, sizeof(dbi.id)); + } +} + +int +main(int argc, char *argv[]) +{ + int c, tout, flags, flush, restore, ret; + const char *spath, **blsock; + size_t nblsock, maxblsock; + + setprogname(argv[0]); + + spath = NULL; + blsock = NULL; + maxblsock = nblsock = 0; + flush = 0; + restore = 0; + tout = 0; + flags = O_RDWR|O_EXCL|O_CLOEXEC; + while ((c = getopt(argc, argv, "C:c:D:dfP:rR:s:t:v")) != -1) { + switch (c) { + case 'C': + controlprog = optarg; + break; + case 'c': + configfile = optarg; + break; + case 'D': + dbfile = optarg; + break; + case 'd': + debug++; + break; + case 'f': + flush++; + break; + case 'P': + spath = optarg; + break; + case 'R': + rulename = optarg; + break; + case 'r': + restore++; + break; + case 's': + if (nblsock >= maxblsock) { + maxblsock += 10; + void *p = realloc(blsock, + sizeof(*blsock) * maxblsock); + if (p == NULL) + err(EXIT_FAILURE, + "Can't allocate memory for %zu sockets", + maxblsock); + blsock = p; + } + blsock[nblsock++] = optarg; + break; + case 't': + tout = atoi(optarg) * 1000; + break; + case 'v': + vflag++; + break; + default: + usage(c); + } + } + + argc -= optind; + if (argc) + usage(0); + + signal(SIGHUP, sighup); + signal(SIGINT, sigdone); + signal(SIGQUIT, sigdone); + signal(SIGTERM, sigdone); + signal(SIGUSR1, sigusr1); + signal(SIGUSR2, sigusr2); + + openlog(getprogname(), LOG_PID, LOG_DAEMON); + + if (debug) { + lfun = dlog; + if (tout == 0) + tout = 5000; + } else { + if (tout == 0) + tout = 15000; + } + + update_interfaces(); + conf_parse(configfile); + if (flush) { + rules_flush(); + if (!restore) + flags |= O_TRUNC; + } + + struct pollfd *pfd = NULL; + bl_t *bl = NULL; + size_t nfd = 0; + size_t maxfd = 0; + + for (size_t i = 0; i < nblsock; i++) + addfd(&pfd, &bl, &nfd, &maxfd, blsock[i]); + free(blsock); + + if (spath) { + FILE *fp = fopen(spath, "r"); + char *line; + if (fp == NULL) + err(EXIT_FAILURE, "Can't open `%s'", spath); + for (; (line = fparseln(fp, NULL, NULL, NULL, 0)) != NULL; + free(line)) + addfd(&pfd, &bl, &nfd, &maxfd, line); + fclose(fp); + } + if (nfd == 0) + addfd(&pfd, &bl, &nfd, &maxfd, _PATH_BLSOCK); + + state = state_open(dbfile, flags, 0600); + if (state == NULL) + state = state_open(dbfile, flags | O_CREAT, 0600); + if (state == NULL) + return EXIT_FAILURE; + + if (restore) { + if (!flush) + rules_flush(); + rules_restore(); + } + + if (!debug) { + if (daemon(0, 0) == -1) + err(EXIT_FAILURE, "daemon failed"); + if (pidfile(NULL) == -1) + err(EXIT_FAILURE, "Can't create pidfile"); + } + + for (size_t t = 0; !done; t++) { + if (readconf) { + readconf = 0; + conf_parse(configfile); + } + ret = poll(pfd, (nfds_t)nfd, tout); + if (debug) + (*lfun)(LOG_DEBUG, "received %d from poll()", ret); + switch (ret) { + case -1: + if (errno == EINTR) + continue; + (*lfun)(LOG_ERR, "poll (%m)"); + return EXIT_FAILURE; + case 0: + state_sync(state); + break; + default: + for (size_t i = 0; i < nfd; i++) + if (pfd[i].revents & POLLIN) + process(bl[i]); + } + if (t % 100 == 0) + state_sync(state); + if (t % 10000 == 0) + update_interfaces(); + update(); + } + state_close(state); + return 0; +} diff --git a/bin/blocklistd.conf.5 b/bin/blocklistd.conf.5 new file mode 100644 index 000000000000..3b85fb889e32 --- /dev/null +++ b/bin/blocklistd.conf.5 @@ -0,0 +1,229 @@ +.\" $NetBSD: blacklistd.conf.5,v 1.7 2017/06/07 13:50:57 wiz 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 5, 2017 +.Dt BLACKLISTD.CONF 5 +.Os +.Sh NAME +.Nm blacklistd.conf +.Nd configuration file format for blacklistd +.Sh DESCRIPTION +The +.Nm +files contains configuration entries for +.Xr blacklistd 8 +in a fashion similar to +.Xr inetd.conf 5 . +Only one entry per line is permitted. +Every entry must have all fields populated. +Each field can be separated by a tab or a space. +Comments are denoted by a +.Dq # +at the beginning of a line. +.Pp +There are two kinds of configuration lines, +.Va local +and +.Va remote . +By default, configuration lines are +.Va local , +i.e. the address specified refers to the addresses on the local machine. +To switch to between +.Va local +and +.Va remote +configuration lines you can specify the stanzas: +.Dq [local] +and +.Dq [remote] . +.Pp +On +.Va local +and +.Va remote +lines +.Dq * +means use the default, or wildcard match. +In addition, for +.Va remote +lines +.Dq = +means use the values from the matched +.Va local +configuration line. +.Pp +The first four fields, +.Va location , +.Va type , +.Va proto , +and +.Va owner +are used to match the +.Va local +or +.Va remote +addresses, whereas the last 3 fields +.Va name , +.Va nfail , +and +.Va disable +are used to modify the filtering action. +.Pp +The first field denotes the +.Va location +as an address, mask, and port. +The syntax for the +.Va location +is: +.Bd -literal -offset indent + [
|][/][:] +.Ed +.Pp +The +.Dv address +can be an IPv4 address in numeric format, an IPv6 address +in numeric format and enclosed by square brackets, or an interface name. +Mask modifiers are not allowed on interfaces because interfaces +can have multiple addresses in different protocols where the mask has a different +size. +.Pp +The +.Dv mask +is always numeric, but the +.Dv port +can be either numeric or symbolic. +.Pp +The second field is the socket +.Va type : +.Dv stream , +.Dv dgram , +or numeric. +The third field is the +.Va prococol : +.Dv tcp , +.Dv udp , +.Dv tcp6 , +.Dv udp6 , +or numeric. +The fourth file is the effective user +.Va ( owner ) +of the daemon process reporting the event, +either as a username or a userid. +.Pp +The rest of the fields are controlling the behavior of the filter. +.Pp +The +.Va name +field, is the name of the packet filter rule to be used. +If the +.Va name +starts with a +.Dq - , +then the default rulename is prepended to the given name. +If the +.Dv name +contains a +.Dq / , +the remaining portion of the name is interpreted as the mask to be +applied to the address specified in the rule, causing a single rule violation to +block the entire subnet for the configured prefix. +.Pp +The +.Va nfail +field contains the number of failed attempts before access is blocked, +defaulting to +.Dq * +meaning never, and the last field +.Va disable +specifies the amount of time since the last access that the blocking +rule should be active, defaulting to +.Dq * +meaning forever. +The default unit for +.Va disable +is seconds, but one can specify suffixes for different units, such as +.Dq m +for minutes +.Dq h +for hours and +.Dq d +for days. +.Pp +Matching is done first by checking the +.Va local +rules individually, in the order of the most specific to the least specific. +If a match is found, then the +.Va remote +rules are applied. +The +.Va name , +.Va nfail , +and +.Va disable +fields can be altered by the +.Va remote +rule that matched. +.Pp +The +.Va remote +rules can be used for whitelisting specific addresses, changing the mask +size, the rule that the packet filter uses, the number of failed attempts, +or the block duration. +.Sh FILES +.Bl -tag -width /etc/blacklistd.conf -compact +.It Pa /etc/blacklistd.conf +Configuration file. +.El +.Sh EXAMPLES +.Bd -literal -offset 8n +# Block ssh, after 3 attempts for 6 hours on the bnx0 interface +[local] +# location type proto owner name nfail duration +bnx0:ssh * * * * 3 6h +[remote] +# Never block 1.2.3.4 +1.2.3.4:ssh * * * * * * +# For addresses coming from 8.8.0.0/16 block class C networks instead +# individual hosts, but keep the rest of the blocking parameters the same. +8.8.0.0/16:ssh * * * /24 = = +.Ed +.Sh SEE ALSO +.Xr blacklistctl 8 , +.Xr blacklistd 8 +.Sh HISTORY +.Nm +first appeared in +.Nx 7 . +.Fx +support for +.Nm +was implemented in +.Fx 11 . +.Sh AUTHORS +.An Christos Zoulas diff --git a/etc/blacklistd.conf b/etc/blacklistd.conf deleted file mode 100644 index f061b004ad36..000000000000 --- a/etc/blacklistd.conf +++ /dev/null @@ -1,14 +0,0 @@ -# Blacklist rule -# adr/mask:port type proto owner name nfail disable -[local] -ssh stream * * * 3 6h -ftp stream * * * 3 6h -domain * * named * 3 12h -#6161 stream tcp6 christos * 2 10m -* * * * * 3 60 - -# adr/mask:port type proto owner name nfail disable -[remote] -#129.168.0.0/16 * * * = * * -#6161 = = = =/24 = = -#* stream tcp * = = = diff --git a/etc/blocklistd.conf b/etc/blocklistd.conf new file mode 100644 index 000000000000..f061b004ad36 --- /dev/null +++ b/etc/blocklistd.conf @@ -0,0 +1,14 @@ +# Blacklist rule +# adr/mask:port type proto owner name nfail disable +[local] +ssh stream * * * 3 6h +ftp stream * * * 3 6h +domain * * named * 3 12h +#6161 stream tcp6 christos * 2 10m +* * * * * 3 60 + +# adr/mask:port type proto owner name nfail disable +[remote] +#129.168.0.0/16 * * * = * * +#6161 = = = =/24 = = +#* stream tcp * = = = diff --git a/etc/rc.d/blacklistd b/etc/rc.d/blacklistd deleted file mode 100644 index 278a6742e63c..000000000000 --- a/etc/rc.d/blacklistd +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh -# -# $NetBSD: blacklistd,v 1.2 2016/10/17 22:47:16 christos Exp $ -# - -# PROVIDE: blacklistd -# REQUIRE: npf -# BEFORE: SERVERS - -$_rc_subr_loaded . /etc/rc.subr - -name="blacklistd" -rcvar=$name -command="/sbin/${name}" -pidfile="/var/run/${name}.pid" -required_files="/etc/${name}.conf" -start_precmd="${name}_precmd" -extra_commands="reload" - -_sockfile="/var/run/${name}.sockets" -_sockname="blacklistd.sock" - -blacklistd_precmd() -{ - # Create default list of blacklistd sockets to watch - # - ( umask 022 ; > $_sockfile ) - - # Find /etc/rc.d scripts with "chrootdir" rcorder(8) keyword, - # and if $${app}_chrootdir is a directory, add appropriate - # blacklistd socket to list of sockets to watch. - # - for _lr in $(rcorder -k chrootdir /etc/rc.d/*); do - ( - _l=${_lr##*/} - load_rc_config ${_l} - eval _ldir=\$${_l}_chrootdir - if checkyesno $_l && [ -n "$_ldir" ]; then - echo "${_ldir}/var/run/${_sockname}" >> $_sockfile - fi - ) - done - - # If other sockets have been provided, change run_rc_command()'s - # internal copy of $blacklistd_flags to force use of specific - # blacklistd sockets. - # - if [ -s $_sockfile ]; then - echo "/var/run/${_sockname}" >> $_sockfile - rc_flags="-P $_sockfile $rc_flags" - fi - - return 0 -} - -load_rc_config $name -run_rc_command "$1" diff --git a/etc/rc.d/blocklistd b/etc/rc.d/blocklistd new file mode 100644 index 000000000000..278a6742e63c --- /dev/null +++ b/etc/rc.d/blocklistd @@ -0,0 +1,57 @@ +#!/bin/sh +# +# $NetBSD: blacklistd,v 1.2 2016/10/17 22:47:16 christos Exp $ +# + +# PROVIDE: blacklistd +# REQUIRE: npf +# BEFORE: SERVERS + +$_rc_subr_loaded . /etc/rc.subr + +name="blacklistd" +rcvar=$name +command="/sbin/${name}" +pidfile="/var/run/${name}.pid" +required_files="/etc/${name}.conf" +start_precmd="${name}_precmd" +extra_commands="reload" + +_sockfile="/var/run/${name}.sockets" +_sockname="blacklistd.sock" + +blacklistd_precmd() +{ + # Create default list of blacklistd sockets to watch + # + ( umask 022 ; > $_sockfile ) + + # Find /etc/rc.d scripts with "chrootdir" rcorder(8) keyword, + # and if $${app}_chrootdir is a directory, add appropriate + # blacklistd socket to list of sockets to watch. + # + for _lr in $(rcorder -k chrootdir /etc/rc.d/*); do + ( + _l=${_lr##*/} + load_rc_config ${_l} + eval _ldir=\$${_l}_chrootdir + if checkyesno $_l && [ -n "$_ldir" ]; then + echo "${_ldir}/var/run/${_sockname}" >> $_sockfile + fi + ) + done + + # If other sockets have been provided, change run_rc_command()'s + # internal copy of $blacklistd_flags to force use of specific + # blacklistd sockets. + # + if [ -s $_sockfile ]; then + echo "/var/run/${_sockname}" >> $_sockfile + rc_flags="-P $_sockfile $rc_flags" + fi + + return 0 +} + +load_rc_config $name +run_rc_command "$1" diff --git a/include/blacklist.h b/include/blacklist.h deleted file mode 100644 index 9ebe11b95e08..000000000000 --- a/include/blacklist.h +++ /dev/null @@ -1,46 +0,0 @@ -/* $NetBSD: blacklist.h,v 1.3 2015/01/23 18:48:56 christos Exp $ */ - -/*- - * Copyright (c) 2014 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. - */ -#ifndef _BLACKLIST_H -#define _BLACKLIST_H - -#include - -__BEGIN_DECLS -struct blacklist *blacklist_open(void); -void blacklist_close(struct blacklist *); -int blacklist(int, int, const char *); -int blacklist_r(struct blacklist *, int, int, const char *); -int blacklist_sa(int, int, const struct sockaddr *, socklen_t, const char *); -int blacklist_sa_r(struct blacklist *, int, int, - const struct sockaddr *, socklen_t, const char *); -__END_DECLS - -#endif /* _BLACKLIST_H */ diff --git a/include/blocklist.h b/include/blocklist.h new file mode 100644 index 000000000000..9ebe11b95e08 --- /dev/null +++ b/include/blocklist.h @@ -0,0 +1,46 @@ +/* $NetBSD: blacklist.h,v 1.3 2015/01/23 18:48:56 christos Exp $ */ + +/*- + * Copyright (c) 2014 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. + */ +#ifndef _BLACKLIST_H +#define _BLACKLIST_H + +#include + +__BEGIN_DECLS +struct blacklist *blacklist_open(void); +void blacklist_close(struct blacklist *); +int blacklist(int, int, const char *); +int blacklist_r(struct blacklist *, int, int, const char *); +int blacklist_sa(int, int, const struct sockaddr *, socklen_t, const char *); +int blacklist_sa_r(struct blacklist *, int, int, + const struct sockaddr *, socklen_t, const char *); +__END_DECLS + +#endif /* _BLACKLIST_H */ diff --git a/lib/blacklist.c b/lib/blacklist.c deleted file mode 100644 index b8a524ca301a..000000000000 --- a/lib/blacklist.c +++ /dev/null @@ -1,88 +0,0 @@ -/* $NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $ */ - -/*- - * Copyright (c) 2014 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 -__RCSID("$NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $"); - -#include -#include - -#include -#include -#include -#include -#include - -int -blacklist_sa(int action, int rfd, const struct sockaddr *sa, socklen_t salen, - const char *msg) -{ - struct blacklist *bl; - int rv; - if ((bl = blacklist_open()) == NULL) - return -1; - rv = blacklist_sa_r(bl, action, rfd, sa, salen, msg); - blacklist_close(bl); - return rv; -} - -int -blacklist_sa_r(struct blacklist *bl, int action, int rfd, - const struct sockaddr *sa, socklen_t slen, const char *msg) -{ - return bl_send(bl, action ? BL_ADD : BL_DELETE, rfd, sa, slen, msg); -} - -int -blacklist(int action, int rfd, const char *msg) -{ - return blacklist_sa(action, rfd, NULL, 0, msg); -} - -int -blacklist_r(struct blacklist *bl, int action, int rfd, const char *msg) -{ - return blacklist_sa_r(bl, action, rfd, NULL, 0, msg); -} - -struct blacklist * -blacklist_open(void) { - return bl_create(false, NULL, vsyslog); -} - -void -blacklist_close(struct blacklist *bl) -{ - bl_destroy(bl); -} diff --git a/lib/blocklist.c b/lib/blocklist.c new file mode 100644 index 000000000000..b8a524ca301a --- /dev/null +++ b/lib/blocklist.c @@ -0,0 +1,88 @@ +/* $NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $ */ + +/*- + * Copyright (c) 2014 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 +__RCSID("$NetBSD: blacklist.c,v 1.5 2015/01/22 16:19:53 christos Exp $"); + +#include +#include + +#include +#include +#include +#include +#include + +int +blacklist_sa(int action, int rfd, const struct sockaddr *sa, socklen_t salen, + const char *msg) +{ + struct blacklist *bl; + int rv; + if ((bl = blacklist_open()) == NULL) + return -1; + rv = blacklist_sa_r(bl, action, rfd, sa, salen, msg); + blacklist_close(bl); + return rv; +} + +int +blacklist_sa_r(struct blacklist *bl, int action, int rfd, + const struct sockaddr *sa, socklen_t slen, const char *msg) +{ + return bl_send(bl, action ? BL_ADD : BL_DELETE, rfd, sa, slen, msg); +} + +int +blacklist(int action, int rfd, const char *msg) +{ + return blacklist_sa(action, rfd, NULL, 0, msg); +} + +int +blacklist_r(struct blacklist *bl, int action, int rfd, const char *msg) +{ + return blacklist_sa_r(bl, action, rfd, NULL, 0, msg); +} + +struct blacklist * +blacklist_open(void) { + return bl_create(false, NULL, vsyslog); +} + +void +blacklist_close(struct blacklist *bl) +{ + bl_destroy(bl); +} diff --git a/lib/libblacklist.3 b/lib/libblacklist.3 deleted file mode 100644 index 77be80f89d4f..000000000000 --- a/lib/libblacklist.3 +++ /dev/null @@ -1,132 +0,0 @@ -.\" $NetBSD: libblacklist.3,v 1.8 2017/10/22 10:31:57 abhinav 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 January 22, 2015 -.Dt LIBBLACKLIST 3 -.Os -.Sh NAME -.Nm blacklist_open , -.Nm blacklist_close , -.Nm blacklist_r , -.Nm blacklist , -.Nm blacklist_sa , -.Nm blacklist_sa_r -.Nd Blacklistd notification library -.Sh LIBRARY -.Lb libblacklist -.Sh SYNOPSIS -.In blacklist.h -.Ft struct blacklist * -.Fn blacklist_open "void" -.Ft void -.Fn blacklist_close "struct blacklist *cookie" -.Ft int -.Fn blacklist "int action" "int fd" "const char *msg" -.Ft int -.Fn blacklist_r "struct blacklist *cookie" "int action" "int fd" "const char *msg" -.Ft int -.Fn blacklist_sa "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg" -.Ft int -.Fn blacklist_sa_r "struct blacklist *cookie" "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg" -.Sh DESCRIPTION -These functions can be used by daemons to notify -.Xr blacklistd 8 -about successful and failed remote connections so that blacklistd can -block or release port access to prevent Denial of Service attacks. -.Pp -The function -.Fn blacklist_open -creates the necessary state to communicate with -.Xr blacklistd 8 -and returns a pointer to it, or -.Dv NULL -on failure. -.Pp -The -.Fn blacklist_close -function frees all memory and resources used. -.Pp -The -.Fn blacklist -function sends a message to -.Xr blacklistd 8 , -with an -.Ar action -argument specifying -.Dv 1 -for a failed connection or -.Dv 0 -for a successful connection, -a file descriptor -.Ar fd -specifying the accepted file descriptor connected to the client, -and an optional message in the -.Ar msg -argument. -.Pp -The -.Fn blacklist_r -function is more efficient because it keeps the blacklist state around. -.Pp -The -.Fn blacklist_sa -and -.Fn blacklist_sa_r -functions can be used with unconnected sockets, where -.Xr getpeername 2 -will not work, the server will pass the peer name in the message. -.Pp -All functions log errors to -.Xr syslogd 8 . -.Sh RETURN VALUES -The function -.Fn blacklist_open -returns a cookie on success and -.Dv NULL -on failure setting -.Dv errno -to an appropriate value. -.Pp -The functions -.Fn blacklist , -.Fn blacklist_sa , -and -.Fn blacklist_sa_r -return -.Dv 0 -on success and -.Dv \-1 -on failure setting -.Dv errno -to an appropriate value. -.Sh SEE ALSO -.Xr blacklistd.conf 5 , -.Xr blacklistd 8 -.Sh AUTHORS -.An Christos Zoulas diff --git a/lib/libblocklist.3 b/lib/libblocklist.3 new file mode 100644 index 000000000000..77be80f89d4f --- /dev/null +++ b/lib/libblocklist.3 @@ -0,0 +1,132 @@ +.\" $NetBSD: libblacklist.3,v 1.8 2017/10/22 10:31:57 abhinav 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 January 22, 2015 +.Dt LIBBLACKLIST 3 +.Os +.Sh NAME +.Nm blacklist_open , +.Nm blacklist_close , +.Nm blacklist_r , +.Nm blacklist , +.Nm blacklist_sa , +.Nm blacklist_sa_r +.Nd Blacklistd notification library +.Sh LIBRARY +.Lb libblacklist +.Sh SYNOPSIS +.In blacklist.h +.Ft struct blacklist * +.Fn blacklist_open "void" +.Ft void +.Fn blacklist_close "struct blacklist *cookie" +.Ft int +.Fn blacklist "int action" "int fd" "const char *msg" +.Ft int +.Fn blacklist_r "struct blacklist *cookie" "int action" "int fd" "const char *msg" +.Ft int +.Fn blacklist_sa "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg" +.Ft int +.Fn blacklist_sa_r "struct blacklist *cookie" "int action" "int fd" "const struct sockaddr *sa" "socklen_t salen" "const char *msg" +.Sh DESCRIPTION +These functions can be used by daemons to notify +.Xr blacklistd 8 +about successful and failed remote connections so that blacklistd can +block or release port access to prevent Denial of Service attacks. +.Pp +The function +.Fn blacklist_open +creates the necessary state to communicate with +.Xr blacklistd 8 +and returns a pointer to it, or +.Dv NULL +on failure. +.Pp +The +.Fn blacklist_close +function frees all memory and resources used. +.Pp +The +.Fn blacklist +function sends a message to +.Xr blacklistd 8 , +with an +.Ar action +argument specifying +.Dv 1 +for a failed connection or +.Dv 0 +for a successful connection, +a file descriptor +.Ar fd +specifying the accepted file descriptor connected to the client, +and an optional message in the +.Ar msg +argument. +.Pp +The +.Fn blacklist_r +function is more efficient because it keeps the blacklist state around. +.Pp +The +.Fn blacklist_sa +and +.Fn blacklist_sa_r +functions can be used with unconnected sockets, where +.Xr getpeername 2 +will not work, the server will pass the peer name in the message. +.Pp +All functions log errors to +.Xr syslogd 8 . +.Sh RETURN VALUES +The function +.Fn blacklist_open +returns a cookie on success and +.Dv NULL +on failure setting +.Dv errno +to an appropriate value. +.Pp +The functions +.Fn blacklist , +.Fn blacklist_sa , +and +.Fn blacklist_sa_r +return +.Dv 0 +on success and +.Dv \-1 +on failure setting +.Dv errno +to an appropriate value. +.Sh SEE ALSO +.Xr blacklistd.conf 5 , +.Xr blacklistd 8 +.Sh AUTHORS +.An Christos Zoulas diff --git a/libexec/blacklistd-helper b/libexec/blacklistd-helper deleted file mode 100644 index 2d0a89e8fb0e..000000000000 --- a/libexec/blacklistd-helper +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/sh -#echo "run $@" 1>&2 -#set -x -# $1 command -# $2 rulename -# $3 protocol -# $4 address -# $5 mask -# $6 port -# $7 id - -pf= -if [ -f "/etc/ipfw-blacklist.rc" ]; then - pf="ipfw" - . /etc/ipfw-blacklist.rc - ipfw_offset=${ipfw_offset:-2000} -fi - -if [ -z "$pf" ]; then - for f in npf pf ipf; do - if [ -f "/etc/$f.conf" ]; then - pf="$f" - break - fi - done -fi - -if [ -z "$pf" ]; then - echo "$0: Unsupported packet filter" 1>&2 - exit 1 -fi - -if [ -n "$3" ]; then - proto="proto $3" -fi - -if [ -n "$6" ]; then - port="port $6" -fi - -addr="$4" -mask="$5" -case "$4" in -::ffff:*.*.*.*) - if [ "$5" = 128 ]; then - mask=32 - addr=${4#::ffff:} - fi;; -esac - -case "$1" in -add) - case "$pf" in - ipf) - /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 - echo block in quick $proto from $addr/$mask to \ - any port=$6 head port$6 | \ - /sbin/ipf -I -f - -s >/dev/null 2>&1 && echo OK - ;; - ipfw) - # use $ipfw_offset+$port for rule number - rule=$(($ipfw_offset + $6)) - tname="port$6" - /sbin/ipfw table $tname create type addr 2>/dev/null - /sbin/ipfw -q table $tname add "$addr/$mask" - # if rule number $rule does not already exist, create it - /sbin/ipfw show $rule >/dev/null 2>&1 || \ - /sbin/ipfw add $rule drop $3 from \ - table"("$tname")" to any dst-port $6 >/dev/null && \ - echo OK - ;; - npf) - /sbin/npfctl rule "$2" add block in final $proto from \ - "$addr/$mask" to any $port - ;; - pf) - # if the filtering rule does not exist, create it - /sbin/pfctl -a "$2/$6" -sr 2>/dev/null | \ - grep -q "" || \ - echo "block in quick $proto from to any $port" | \ - /sbin/pfctl -a "$2/$6" -f - - # insert $ip/$mask into per-protocol/port anchored table - /sbin/pfctl -a "$2/$6" -t "port$6" -T add "$addr/$mask" && \ - echo OK - ;; - esac - ;; -rem) - case "$pf" in - ipf) - /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 - echo block in quick $proto from $addr/$mask to \ - any port=$6 head port$6 | \ - /sbin/ipf -I -r -f - -s >/dev/null 2>&1 && echo OK - ;; - ipfw) - /sbin/ipfw table "port$6" delete "$addr/$mask" 2>/dev/null && \ - echo OK - ;; - npf) - /sbin/npfctl rule "$2" rem-id "$7" - ;; - pf) - /sbin/pfctl -a "$2/$6" -t "port$6" -T delete "$addr/$mask" && \ - echo OK - ;; - esac - ;; -flush) - case "$pf" in - ipf) - /sbin/ipf -Z -I -Fi -s > /dev/null && echo OK - ;; - ipfw) - /sbin/ipfw table "port$6" flush 2>/dev/null && echo OK - ;; - npf) - /sbin/npfctl rule "$2" flush - ;; - pf) - /sbin/pfctl -a "$2/$6" -t "port$6" -T flush && echo OK - ;; - esac - ;; -*) - echo "$0: Unknown command '$1'" 1>&2 - exit 1 - ;; -esac diff --git a/libexec/blocklistd-helper b/libexec/blocklistd-helper new file mode 100644 index 000000000000..2d0a89e8fb0e --- /dev/null +++ b/libexec/blocklistd-helper @@ -0,0 +1,129 @@ +#!/bin/sh +#echo "run $@" 1>&2 +#set -x +# $1 command +# $2 rulename +# $3 protocol +# $4 address +# $5 mask +# $6 port +# $7 id + +pf= +if [ -f "/etc/ipfw-blacklist.rc" ]; then + pf="ipfw" + . /etc/ipfw-blacklist.rc + ipfw_offset=${ipfw_offset:-2000} +fi + +if [ -z "$pf" ]; then + for f in npf pf ipf; do + if [ -f "/etc/$f.conf" ]; then + pf="$f" + break + fi + done +fi + +if [ -z "$pf" ]; then + echo "$0: Unsupported packet filter" 1>&2 + exit 1 +fi + +if [ -n "$3" ]; then + proto="proto $3" +fi + +if [ -n "$6" ]; then + port="port $6" +fi + +addr="$4" +mask="$5" +case "$4" in +::ffff:*.*.*.*) + if [ "$5" = 128 ]; then + mask=32 + addr=${4#::ffff:} + fi;; +esac + +case "$1" in +add) + case "$pf" in + ipf) + /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 + echo block in quick $proto from $addr/$mask to \ + any port=$6 head port$6 | \ + /sbin/ipf -I -f - -s >/dev/null 2>&1 && echo OK + ;; + ipfw) + # use $ipfw_offset+$port for rule number + rule=$(($ipfw_offset + $6)) + tname="port$6" + /sbin/ipfw table $tname create type addr 2>/dev/null + /sbin/ipfw -q table $tname add "$addr/$mask" + # if rule number $rule does not already exist, create it + /sbin/ipfw show $rule >/dev/null 2>&1 || \ + /sbin/ipfw add $rule drop $3 from \ + table"("$tname")" to any dst-port $6 >/dev/null && \ + echo OK + ;; + npf) + /sbin/npfctl rule "$2" add block in final $proto from \ + "$addr/$mask" to any $port + ;; + pf) + # if the filtering rule does not exist, create it + /sbin/pfctl -a "$2/$6" -sr 2>/dev/null | \ + grep -q "" || \ + echo "block in quick $proto from to any $port" | \ + /sbin/pfctl -a "$2/$6" -f - + # insert $ip/$mask into per-protocol/port anchored table + /sbin/pfctl -a "$2/$6" -t "port$6" -T add "$addr/$mask" && \ + echo OK + ;; + esac + ;; +rem) + case "$pf" in + ipf) + /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 + echo block in quick $proto from $addr/$mask to \ + any port=$6 head port$6 | \ + /sbin/ipf -I -r -f - -s >/dev/null 2>&1 && echo OK + ;; + ipfw) + /sbin/ipfw table "port$6" delete "$addr/$mask" 2>/dev/null && \ + echo OK + ;; + npf) + /sbin/npfctl rule "$2" rem-id "$7" + ;; + pf) + /sbin/pfctl -a "$2/$6" -t "port$6" -T delete "$addr/$mask" && \ + echo OK + ;; + esac + ;; +flush) + case "$pf" in + ipf) + /sbin/ipf -Z -I -Fi -s > /dev/null && echo OK + ;; + ipfw) + /sbin/ipfw table "port$6" flush 2>/dev/null && echo OK + ;; + npf) + /sbin/npfctl rule "$2" flush + ;; + pf) + /sbin/pfctl -a "$2/$6" -t "port$6" -T flush && echo OK + ;; + esac + ;; +*) + echo "$0: Unknown command '$1'" 1>&2 + exit 1 + ;; +esac -- cgit v1.2.3