Download raw body.
unwind: support wildcard in blacklist
On Mon, Jun 24, 2024 at 10:55:23PM +0100, Kirill A. Korinsky wrote:
> Florian, tech@,
>
> Here a diff which introduced support of wildcard inside unwind's domain
> blacklist. Wildcard supported only at begining and as '*' which should be
> followed by '.'.
>
> So, after that this two lines:
>
> google.com
> *.google.com
>
> blocks any requests to google.com and all its subdomains.
Please be aware that in DNS wildcards are already used and have a
somehat different than expected interpretation.
https://en.wikipedia.org/wiki/Wildcard_DNS_record
This means that this should be docuemnted extra carefully, or a
different syntax should be used that does not confuse DNS people.
-Otto
>
> The diff:
>
> diff --git sbin/unwind/frontend.c sbin/unwind/frontend.c
> index ccbc977eb73..32a83b56468 100644
> --- sbin/unwind/frontend.c
> +++ sbin/unwind/frontend.c
> @@ -118,6 +118,8 @@ TAILQ_HEAD(, pending_query) pending_queries;
> struct bl_node {
> RB_ENTRY(bl_node) entry;
> char *domain;
> + int len;
> + int wildcard;
> };
>
> __dead void frontend_shutdown(void);
> @@ -171,6 +173,18 @@ RB_GENERATE(bl_tree, bl_node, entry, bl_cmp)
> struct dns64_prefix *dns64_prefixes;
> int dns64_prefix_count;
>
> +static void
> +reverse(char* begin, char* end)
> +{
> + char t;
> + while (begin < --end) {
> + t = *begin;
> + *begin = *end;
> + *end = t;
> + ++begin;
> + }
> +}
> +
> void
> frontend_sig_handler(int sig, short event, void *bula)
> {
> @@ -790,6 +804,9 @@ handle_query(struct pending_query *pq)
> log_debug("%s: %s %s %s ?", ip_port((struct sockaddr *)&pq->from),
> dname, qclass_buf, qtype_buf);
>
> + find.len = strlen(dname);
> + find.wildcard = 0;
> + reverse(dname, dname + find.len);
> find.domain = dname;
> if (RB_FIND(bl_tree, &bl_head, &find) != NULL) {
> if (frontend_conf->blocklist_log)
> @@ -797,6 +814,7 @@ handle_query(struct pending_query *pq)
> error_answer(pq, LDNS_RCODE_REFUSED);
> goto send_answer;
> }
> + reverse(dname, dname + find.len);
>
> if (pq->qinfo.qtype == LDNS_RR_TYPE_AXFR || pq->qinfo.qtype ==
> LDNS_RR_TYPE_IXFR) {
> @@ -1541,7 +1559,7 @@ parse_blocklist(int fd)
> if (linelen >= 2 && line[linelen - 2] != '.')
> line[linelen - 1] = '.';
> else
> - line[linelen - 1] = '\0';
> + line[linelen-- - 1] = '\0';
> }
>
> bl_node = malloc(sizeof *bl_node);
> @@ -1549,6 +1567,15 @@ parse_blocklist(int fd)
> fatal("%s: malloc", __func__);
> if ((bl_node->domain = strdup(line)) == NULL)
> fatal("%s: strdup", __func__);
> + reverse(bl_node->domain, bl_node->domain + linelen);
> + if (linelen > 2 && line[0] == '*' && line[1] == '.') {
> + bl_node->wildcard = 1;
> + bl_node->domain[linelen - 1] = '\0';
> + bl_node->len = linelen - 1;
> + } else {
> + bl_node->wildcard = 0;
> + bl_node->len = linelen;
> + }
> if (RB_INSERT(bl_tree, &bl_head, bl_node) != NULL) {
> log_warnx("duplicate blocked domain \"%s\"", line);
> free(bl_node->domain);
> @@ -1563,7 +1590,12 @@ parse_blocklist(int fd)
>
> int
> bl_cmp(struct bl_node *e1, struct bl_node *e2) {
> - return (strcasecmp(e1->domain, e2->domain));
> + if (e1->wildcard == e2->wildcard)
> + return (strcasecmp(e1->domain, e2->domain));
> + else if (e1->wildcard)
> + return (strncasecmp(e1->domain, e2->domain, e1->len));
> + else /* e2->wildcard */
> + return (strncasecmp(e1->domain, e2->domain, e2->len));
> }
>
> void
>
>
> --
> wbr, Kirill
>
unwind: support wildcard in blacklist