diff --git a/CHANGELOG.md b/CHANGELOG.md index a023441..f84c629 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,13 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Changed -- Require Perl 5.12 - -### Fixed -- Fix warning when writing blocklist to stdout. -- Various script clean-ups - ## [0.2.0] - 2023-06-19 ### Added @@ -35,7 +28,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.1.0] - 2022-11-12 Initial published version - -[Unreleased]: https://codeberg.org/h3xx/you-dont-need-pihole/compare/v0.2.0...HEAD -[0.2.0]: https://codeberg.org/h3xx/you-dont-need-pihole/compare/v0.1.0...v0.2.0 -[0.1.0]: https://codeberg.org/h3xx/you-dont-need-pihole/releases/tag/v0.1.0 diff --git a/README.md b/README.md index a1b3029..8f9f2e1 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,7 @@ **Network-wide DNS blocking without extra hardware.** This project implements the ad-blocking functionality of a -[Pi-hole](https://pi-hole.net) without needing any extra hardware. All you need -is a Linux computer on your network. This might also work with a Mac OSX -computer, but I haven't tested it. +[Pi-hole](https://pi-hole.net) without needing any extra hardware. A Pi-hole is a [Raspberry Pi](https://www.raspberrypi.com/) based "black hole" for Internet advertisements. It works by intercepting and answering DNS queries @@ -24,20 +22,12 @@ You'll need `dnsmasq` installed for this. git clone --recursive https://codeberg.org/h3xx/you-dont-need-pihole.git /etc/you-dont-need-pihole ``` -2. Run `update.sh` to generate the initial blocklist: +2. Run `update.sh` to generate the blocklist. -```sh -/etc/you-dont-need-pihole/update.sh -``` +3. Update `dnsmasq.d/01-you-dont-need-pihole.conf`, replacing `/etc/you-dont-need-pihole` with wherever the root +of this project is installed to. -> [!IMPORTANT] -> If you didn't use `/etc/you-dont-need-pihole` as the installation directory, -> update `dnsmasq.d/01-you-dont-need-pihole.conf`, replacing -> `/etc/you-dont-need-pihole` with wherever the root of this project is -> installed to. - -4. Add You Don't Need Pi Hole's `dnsmasq.d` configuration directory path to - `dnsmasq.conf`: +4. Add the configuration directory to `dnsmasq.conf`: ```sh echo 'conf-dir=/etc/you-dont-need-pihole/dnsmasq.d' >> /etc/dnsmasq.conf @@ -46,32 +36,21 @@ echo 'conf-dir=/etc/you-dont-need-pihole/dnsmasq.d' >> /etc/dnsmasq.conf You can also copy or symlink `dnsmasq.d/01-you-dont-need-pihole.conf` if you need the config to live somewhere else. -5. Restart the `dnsmasq` service: +5. Restart the `dnsmasq` service. -```sh -# Debian & Ubuntu, RedHat & CentOS -service dnsmasq restart -``` +6. Make sure `53/udp` is unfirewalled. -6. Make sure `53/udp` is unfirewalled: +7. Go into your router settings and change the IP addressed provied via DHCP to + be your server's local IP address. [See this thread for a + walkthrough.](https://discourse.pi-hole.net/t/how-do-i-configure-my-devices-to-use-pi-hole-as-their-dns-server/245) -```sh -# Debian & Ubuntu, RedHat & CentOS -sudo firewall-cmd --add-port=53/udp --permanent -``` - -7. Go into your router settings and change the DNS IP address provided via your - router's DHCP responses to be your server's (i.e. the one with You Don't - Need Pi Hole) local IP address. - [See this thread for a walkthrough.](https://discourse.pi-hole.net/t/how-do-i-configure-my-devices-to-use-pi-hole-as-their-dns-server/245) - -8. Recommended: If you use the You Don't Need Pi Hole machine as a general - computer, configure it to use the local `dnsmasq` daemon for client DNS - queries. This is a good idea because it may save some network traffic +8. Recommended: Configure your local machine to use the local `dnsmasq` daemon + for client DNS queries, i.e. software running on the same server as + `dnsmasq`. This is a good idea because it may save some network traffic depending on how your router works. Worst case scenario, it'll do nothing. -If your OS uses `dhcpcd` for network configuration (Slackware), you can add -this line to your `/etc/dhcpcd.conf`: +If your OS uses `dhcpcd` for network configuration, you can add this line to your +`/etc/dhcpcd.conf` ``` static domain_name_servers=127.0.0.1 diff --git a/dev-t/doc-changelog-links.t b/dev-t/doc-changelog-links.t deleted file mode 100644 index 98d211b..0000000 --- a/dev-t/doc-changelog-links.t +++ /dev/null @@ -1,181 +0,0 @@ -#!perl -use 5.012; -use warnings FATAL => 'all'; - -use Test::More 'no_plan'; - -use FindBin qw//; -my $changelog = "$FindBin::Bin/../CHANGELOG.md"; -my $braced_inner_r = qr/(?:[^\]\\]|\\.)*/; -use constant PROJECT_GIT => 'https://codeberg.org/h3xx/you-dont-need-pihole'; - -SKIP: { - my $clh; - unless (open $clh, '<', $changelog) { - skip("failed to open changelog file to test: $!"); - } - my @cl_lines = <$clh>; - close $clh; - - ok(scalar @cl_lines, - 'changelog contains at least one line' - ); - - my %end_links = _link_references(@cl_lines); - my @reflinks = _ref_links(@cl_lines); - - my @unresolved = _unresolved_links(\%end_links, \@reflinks); - ok(!scalar @unresolved, ChangelogError->new('unresolved links', @unresolved)); - - my %unused_links = _unused_links(\%end_links, \@reflinks); - ok(!scalar %unused_links, ChangelogError->new('unused end links', values %unused_links)); - - my @incorrect_links = _incorrect_end_links(\%end_links, \@reflinks); - ok(!scalar @incorrect_links, ChangelogError->new('incorrect end links', @incorrect_links)); - -} - -sub _link_references { - my @lines = @_; - my $end_link_r = qr/^\s*\[(?$braced_inner_r)\]:\s*(?.*?)\s*$/; - my %end_links; - my $line_number = 0; - foreach my $line (@lines) { - ++$line_number; - if ($line =~ $end_link_r) { - $end_links{$+{key}} = { - line_number => $line_number, - url => $+{url}, - key => $+{key}, - }; - } - } - return %end_links; -} - -sub _ref_links { - my @lines = @_; - my $ref_link_r = qr/\[(?$braced_inner_r)\]\[(?$braced_inner_r)\]/; - # Make sure not to catch: - # - Normal links "[text](url)" - # - End links "[key]: url" - my $bare_ref_link_r = qr/\[(?$braced_inner_r)\](?!\s*[(:])/; - my @reflinks; - my $line_number = 0; - foreach my $line (@lines) { - ++$line_number; - if ($line =~ $ref_link_r) { - push @reflinks, { - line_number => $line_number, - text => $+{text}, - key => $+{key}, - }; - } elsif ($line =~ $bare_ref_link_r) { - push @reflinks, { - line_number => $line_number, - text => $+{textkey}, - key => $+{textkey}, - }; - } - } - return @reflinks; -} - -sub _unused_links { - my ($end_links, $reflinks) = @_; - # Make a copy, lest we destroy data - my %unused = %{$end_links}; - foreach my $link (@{$reflinks}) { - my $key = $link->{key}; - delete $unused{$key}; - } - return %unused; -} - -sub _unresolved_links { - my ($end_links, $reflinks) = @_; - my @unresolved; - foreach my $link (@{$reflinks}) { - my $key = $link->{key}; - unless (exists $end_links->{$key}) { - push @unresolved, $link; - } - } - return @unresolved; -} - -sub _incorrect_end_links { - my ($end_links, $reflinks) = @_; - my @versions_in_order; - my %versions_seen; - foreach my $link (@{$reflinks}) { - my $key = $link->{key}; - if (_is_version($key) && !exists $versions_seen{$key}) { - $versions_seen{$key} = 1; - push @versions_in_order, $key; - } - } - my %expected_links = ( - Unreleased => _make_tag_link("v$versions_in_order[0]", 'HEAD'), - $versions_in_order[-1] => _make_tag_link("v$versions_in_order[-1]"), - ); - foreach my $idx (0 .. ($#versions_in_order - 1)) { - my $this_version = $versions_in_order[$idx]; - my $last_version = $versions_in_order[$idx + 1]; - $expected_links{$this_version} = _make_tag_link("v$last_version", "v$this_version"); - } - - my @incorrect_links; - while (my ($key, $link) = each %{$end_links}) { - if (exists $expected_links{$key}) { - my $got = $link->{url}; - my $expected = $expected_links{$key}; - if ($got ne $expected) { - $link->{url_expected} = $expected; - push @incorrect_links, $link; - } - } - } - return @incorrect_links; -} - -sub _make_tag_link { - my ($before_tag, $after_tag) = @_; - unless (defined $after_tag) { - return sprintf '%s/releases/tag/%s', PROJECT_GIT, $before_tag; - } - return sprintf '%s/compare/%s...%s', PROJECT_GIT, $before_tag, $after_tag; -} - -sub _is_version { - my $ver = shift; - return $ver =~ /^[0-9.]+$/; -} - -package ChangelogError; -use 5.012; -use warnings FATAL => 'all'; -use overload '""' => '_as_string'; - -sub new { - my ($class, $name, @data) = @_; - return bless { - _name => $name, - _data => \@data, - }, $class; -} - -sub _as_string { - my $self = shift; - my @all = ($self->{_name}); - foreach my $datum (@{$self->{_data}}) { - my @out; - foreach my $key (qw/ line_number key text url url_expected /) { - if (defined $datum->{$key}) { - push @out, "$key: $datum->{$key}"; - } - } - push @all, '- ' . (join ', ', @out); - } - return join "\n", @all; -} diff --git a/make-block.pl b/make-block.pl index d53994d..c390910 100755 --- a/make-block.pl +++ b/make-block.pl @@ -16,7 +16,6 @@ use 5.012; use warnings; -use Carp qw/ croak /; use Getopt::Long qw/ GetOptions :config bundling no_getopt_compat no_ignore_case /; use FindBin qw//; @@ -24,26 +23,23 @@ my %domains; my $dupes = 0; my $skip = 0; my $removed_allowed = 0; - -sub _add_domain_list { +sub add_domain_list { my $file = shift; - foreach my $line (_read_stripped($file)) { + foreach my $line (read_stripped($file)) { my $domain = lc $line; if (defined $domains{$domain}) { ++$dupes; } $domains{$domain} = 1; } - return; } -sub _add_host_file { +sub add_host_file { my $file = shift; - foreach my $line (_read_stripped($file)) { + foreach my $line (read_stripped($file)) { my @parts = split /\s+/, $line; - if (@parts < 2) { - croak("Malformed line in $file: $line; @parts"); - } + die "Malformed line in $file: $line; @parts" + unless @parts > 1; if (lc $parts[0] eq lc $parts[1]) { ++$skip; next; @@ -58,30 +54,20 @@ sub _add_host_file { } $domains{$domain} = 1; } - return; } -sub _read_stripped { +sub read_stripped { my $file = shift; - my @stripped_lines; - my $add_stripped = sub { - my $line = shift; - chomp $line; - # Strip whitespace and comments - $line =~ s/^\s+|\s+$|\s*#.*$//; - if ($line) { - push @stripped_lines, $line; - } - }; - open my $fhi, '<', $file - or croak("Failed to open file $file for reading: $!"); + open my $fni, '<', $file + or die "Failed to open file $file for reading: $!"; - while (my $line = <$fhi>) { - $add_stripped->($line); - } - close $fhi; - return @stripped_lines; + map { + chomp; + # Strip whitespace and comments + s/^\s+|\s+$|\s*#.*$//; + $_ || () + } <$fni>; } MAIN: { @@ -101,36 +87,38 @@ MAIN: { my @allow_lists = glob "$workdir/allowlists/*.domains"; foreach my $listfile (@domain_lists) { - _add_domain_list($listfile); + add_domain_list($listfile); } foreach my $hostfile (@hosts_lists) { - _add_host_file($hostfile); + add_host_file($hostfile); } # Apply allowlists my @allow_domains; foreach my $allowlist (@allow_lists) { - push @allow_domains, _read_stripped($allowlist); + push @allow_domains, read_stripped($allowlist); } my $before = %domains; delete %domains{@allow_domains}; # Count number removed $removed_allowed = $before - %domains; - my @block_ip = sort split /\s+/, $block_ip; + my $written = 0; my $fho = \*STDOUT; if (defined $out && length $out) { open $fho, '>', $out - or croak("Failed to open file $out for writing: $!"); + or die "Failed to open file $out for writing: $!"; } - foreach my $domain (sort keys %domains) { - print $fho map { + my @block_ip = sort split /\s+/, $block_ip; + print $fho map { + ++$written; + my $domain = $_; + map { "$_ $domain\n" } @block_ip; - } - close $fho; + } sort keys %domains; - printf STDERR "%d domains written to %s from\n", (scalar %domains), $out // 'STDOUT'; + printf STDERR "%d domains written to %s from\n", $written, $out // 'STDOUT'; printf STDERR " - %d .domains files\n", (scalar @domain_lists); printf STDERR " - %d .hosts files\n", (scalar @hosts_lists); if ($dupes) { diff --git a/util/run-dev-tests.sh b/util/run-dev-tests.sh deleted file mode 100755 index 2e7568a..0000000 --- a/util/run-dev-tests.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -WORKDIR=${0%/*} -BASEDIR="$WORKDIR/.." -cd "$BASEDIR" || exit - -if ! prove 'dev-t'; then - printf 'Developer tests failed!\n' >&2 - exit 1 -fi