From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <development+bounces-469-archive=lists.ipfire.org@lists.ipfire.org> Received: from mail02.haj.ipfire.org (localhost [127.0.0.1]) by mail02.haj.ipfire.org (Postfix) with ESMTP id 4b3CJJ13xFz3375 for <archive@lists.ipfire.org>; Thu, 22 May 2025 15:44:00 +0000 (UTC) Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) client-signature RSA-PSS (4096 bits)) (Client CN "mail01.haj.ipfire.org", Issuer "R10" (verified OK)) by mail02.haj.ipfire.org (Postfix) with ESMTPS id 4b3CJD17nxz32f1 for <development@lists.ipfire.org>; Thu, 22 May 2025 15:43:56 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail01.ipfire.org (Postfix) with ESMTPSA id 4b3CJC3ySVzGc; Thu, 22 May 2025 15:43:55 +0000 (UTC) DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=ipfire.org; s=202003ed25519; t=1747928635; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kukaq62tyLLUoSZdXIgFmVw5/8T4KJRKbWVU5/jtcMg=; b=evHL9kpn8l68bUXj6spXKWV3LSMd3907xJ0HBn2KET1u5sZYQ6KSL0B7BoWQqxrBS2Ppot b7dpOuCKYJzZg8BQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ipfire.org; s=202003rsa; t=1747928635; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kukaq62tyLLUoSZdXIgFmVw5/8T4KJRKbWVU5/jtcMg=; b=s5FLc3XsUc0dpgLoRsLEEFjHq6F9qdxyZB9ghfcdmBrz+AmD/aAoaMLsPlqLI8izi4JVEK lOYONeM12QwLXk2UbV+nCFhrIN78ZifaqlDbk0+v7IpC8A1EL7BQdwcRWqPqYAotMAor45 ab7NMk6hcw5zNYJQn3Ztn0ZK30/CY0xEdM7wwl0MkVGhECOK/5xa4Prfsh8j7Gx9VnKBZw tOTFRdnjsCY6CwnlMItsnFh6Ta4+QkZQ/3lwCwxuYzH3yw8m/BxWQj3D0fJNXA45DOzY01 QEYomVQPVESxD2Sm/bExoFtxnkK8/wZjyXKJ6dJzSq4fNIAJx9dt9ZG+bdW+Pg== Content-Type: text/plain; charset=utf-8 Precedence: list List-Id: <development.lists.ipfire.org> List-Subscribe: <https://lists.ipfire.org/>, <mailto:development+subscribe@lists.ipfire.org?subject=subscribe> List-Unsubscribe: <https://lists.ipfire.org/>, <mailto:development+unsubscribe@lists.ipfire.org?subject=unsubscribe> List-Post: <mailto:development@lists.ipfire.org> List-Help: <mailto:development+help@lists.ipfire.org?subject=help> Sender: <development@lists.ipfire.org> Mail-Followup-To: <development@lists.ipfire.org> Mime-Version: 1.0 Subject: Re: [PATCH] RPZ: update code to include WEBGUI and additional languages From: Michael Tremer <michael.tremer@ipfire.org> In-Reply-To: <em5b48e622-ea4f-4528-b509-17b70627e6d2@e4a72e70.com> Date: Thu, 22 May 2025 16:43:55 +0100 Cc: Bernhard Bitsch <bbitsch@ipfire.org>, "IPFire: Development-List" <development@lists.ipfire.org> Content-Transfer-Encoding: quoted-printable Message-Id: <0261B2EC-034E-4231-B105-DEFB8091BF07@ipfire.org> References: <20250206163522.2363178-1-jon.murphy@ipfire.org> <A0568469-68D8-4C26-9154-E9961F4AAA60@ipfire.org> <ED243073-E39A-47BA-BBF0-728A13C439BF@ipfire.org> <FEF2E201-5067-429B-A829-A472354FF615@ipfire.org> <C28A0D7E-6C16-4F6F-9366-A8498F40631E@ipfire.org> <8b594873-86ca-46b9-bb4b-94fd6b0239b1@ipfire.org> <A1492735-FF13-4F2B-8F5B-0800FB1D669F@ipfire.org> <d970c80d-2c13-4f71-9b0f-356a0f3013c6@ipfire.org> <9A0DBDA4-75B0-40D2-AE06-78D9BA5EE7D3@ipfire.org> <afcb2a99-1281-43e3-bd3d-d915024683f6@ipfire.org> <89101199-33D1-40AC-8CCE-DD97583129F2@ipfire.org> <em3ba7826f-2bff-4c2c-bf92-b540b8864013@78ba6e0b.com> <8703C3D8-C30C-4A56-9F30-7B90BB1E3027@ipfire.org> <502fa002-d6da-45d6-9b3e-d4130e59f50a@ipfire.org> <64617942-44E2-4E7B-A8AB-D5C22F94F68B@ipfire.org> <em524a73af-b1c4-46a3-b1bf-bdfbec02d48a@78ba6e0b.com> <8D5093D0-A699-4C4E-AEA3-185AD323EF67@ipfire.org> <em1522345b-bb45-442c-a981-51662434afab@78ba6e0b.com> <9221F825-15BB-484C-A921-118C7F3266AC@ipfire.org> <em2b6fdf23-3c41-4448-b79e-c3d052f06d31@78ba6e0b.com> <BAA426BB-19B8-45FF-BF7D-4D7D41E64DCF@ipfire.org> <emdb723861-7930-453c-b27c-15857af4618d@6c678a4d.com> <ACCBF35D-C5C8-471F-AFE8-77EC4D752D5D@ipfire.org> <em5b48e622-ea4f-4528-b509-17b70627e6d2@e4a72e70.com> To: Jon Murphy <jon.murphy@ipfire.org> I stated that before. I need to block adult websites. > On 22 May 2025, at 16:42, Jon Murphy <jon.murphy@ipfire.org> wrote: >=20 > Now I am curious! What is your use-case? Tell me more... >=20 >=20 > ------ Original Message ------ > =46rom "Michael Tremer" <michael.tremer@ipfire.org> > To "Jon Murphy" <jon.murphy@ipfire.org> > Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire: Development-List" = <development@lists.ipfire.org> > Date 5/22/2025 10:40:38=E2=80=AFAM > Subject Re: [PATCH] RPZ: update code to include WEBGUI and additional = languages >=20 >> Hello Jon, >>=20 >> I have not been spending on time on this at all since we talked last. >>=20 >> I don=E2=80=99t need Unbound to download any files for my use-case = either. >>=20 >> -Michael >>=20 >>> On 20 May 2025, at 17:30, Jon Murphy <jon.murphy@ipfire.org> wrote: >>>=20 >>> Michael, >>>=20 >>> Were you able to debug RPZ and get Unbound to download `.rpz` files? >>>=20 >>>=20 >>> Jon >>>=20 >>>=20 >>>=20 >>> ------ Original Message ------ >>> =46rom "Michael Tremer" <michael.tremer@ipfire.org> >>> To "Jon Murphy" <jon.murphy@ipfire.org> >>> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire: = Development-List" <development@lists.ipfire.org> >>> Date 3/24/2025 9:43:37=E2=80=AFAM >>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and = additional languages >>>=20 >>>> Yes, I don=E2=80=99t need any debugging of this... >>>>=20 >>>>> On 24 Mar 2025, at 14:42, Jon Murphy <jon.murphy@ipfire.org> = wrote: >>>>>=20 >>>>> Is there a: >>>>>=20 >>>>> server: >>>>> module-config: "respip validator iterator" >>>>>=20 >>>>> In your RPZ set-up? >>>>>=20 >>>>>=20 >>>>> ------ Original Message ------ >>>>> =46rom "Michael Tremer" <michael.tremer@ipfire.org> >>>>> To "Jon Murphy" <jon.murphy@ipfire.org> >>>>> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire: = Development-List" <development@lists.ipfire.org> >>>>> Date 3/24/2025 9:40:15=E2=80=AFAM >>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and = additional languages >>>>>=20 >>>>>> Because it is not doing it on my system... >>>>>>=20 >>>>>>> On 24 Mar 2025, at 14:38, Jon Murphy <jon.murphy@ipfire.org> = wrote: >>>>>>>=20 >>>>>>> Actually it did. >>>>>>>=20 >>>>>>> Why do you think Unbound did not? >>>>>>>=20 >>>>>>>=20 >>>>>>> ------ Original Message ------ >>>>>>> =46rom "Michael Tremer" <michael.tremer@ipfire.org> >>>>>>> To "Jon Murphy" <jon.murphy@ipfire.org> >>>>>>> Cc "Bernhard Bitsch" <bbitsch@ipfire.org>; "IPFire: = Development-List" <development@lists.ipfire.org> >>>>>>> Date 3/24/2025 9:36:53=E2=80=AFAM >>>>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and = additional languages >>>>>>>=20 >>>>>>>> Unbound did not put those there... >>>>>>>>=20 >>>>>>>>> On 24 Mar 2025, at 14:33, Jon Murphy <jon.murphy@ipfire.org> = wrote: >>>>>>>>>=20 >>>>>>>>>=20 >>>>>>>>>=20 >>>>>>>>> And where are these stored? >>>>>>>>>=20 >>>>>>>>> In `/etc/unbound/zonefiles`: >>>>>>>>>=20 >>>>>>>>>=20 >>>>>>>>> [root@ipfire ~] # ls -al /etc/unbound/zonefiles >>>>>>>>> total 20664 >>>>>>>>> drwxr-xr-x 2 nobody nobody 4096 Mar 24 04:40 . >>>>>>>>> drwxr-xr-x 4 root root 4096 Mar 19 16:24 .. >>>>>>>>> -rw-r--r-- 1 nobody nobody 3999087 Mar 23 15:11 adhocSB.rpz >>>>>>>>> -rw-r--r-- 1 nobody nobody 1411 Mar 23 14:23 allow.rpz >>>>>>>>> -rw-r--r-- 1 nobody nobody 25355 Mar 24 04:40 = AmazonTrkrHZ.rpz >>>>>>>>> -rw-r--r-- 1 nobody nobody 7241 Mar 24 04:40 = AppleTrkrHZ.rpz >>>>>>>>> -rw-r--r-- 1 nobody nobody 178 Mar 23 14:23 block.rpz >>>>>>>>> -rw-r--r-- 1 nobody nobody 78496 Mar 24 04:40 = DOHblockHZ.rpz >>>>>>>>> -rw-r--r-- 1 nobody nobody 16983551 Mar 24 04:40 = MxProPlusHZ.rpz >>>>>>>>> -rw-r--r-- 1 nobody nobody 2893 Mar 24 04:40 tldHZ.rpz >>>>>>>>> -rw-r--r-- 1 nobody nobody 29419 Mar 24 04:40 WinTrkrHZ.rpz >>>>>>>>> [root@ipfire ~] # >>>>>>>>>=20 >>>>>>>>>=20 >>>>>>>>>=20 >>>>>>>>> ------ Original Message ------ >>>>>>>>> =46rom "Michael Tremer" <michael.tremer@ipfire.org> >>>>>>>>> To "Bernhard Bitsch" <bbitsch@ipfire.org> >>>>>>>>> Cc development@lists.ipfire.org >>>>>>>>> Date 3/24/2025 9:25:40=E2=80=AFAM >>>>>>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and = additional languages >>>>>>>>>=20 >>>>>>>>>> Hello, >>>>>>>>>>=20 >>>>>>>>>>>=20 >>>>>>>>>>> On 24 Mar 2025, at 13:33, Bernhard Bitsch = <bbitsch@ipfire.org> wrote: >>>>>>>>>>> Am 24.03.2025 um 11:17 schrieb Michael Tremer: >>>>>>>>>>>>=20 >>>>>>>>>>>>=20 >>>>>>>>>>>> Hello Jon, >>>>>>>>>>>>>=20 >>>>>>>>>>>>>=20 >>>>>>>>>>>>> On 24 Mar 2025, at 00:00, Jon Murphy = <jon.murphy@ipfire.org> wrote: >>>>>>>>>>>>> Michael, >>>>>>>>>>>>> FYI - I was wrong Unbound RPZ is _not_ watching the = serial number, it is watching the "refresh", the number after the serial = number. >>>>>>>>>>>>=20 >>>>>>>>>>>> Refresh just tells the client how often to check for an = update. >>>>>>>>>>>> If that is actually being set by the list publisher, then = we have another problem here, because they could put some insanely low = value there and we would then DDoS their infrastructure. I think we = should keep it like we have it in other places that we control how often = we want to check or pull for updates. >>>>>>>>>>>>=20 >>>>>>>>>>> You are right. But an extra update process wastes = additional processor time. The update mechanism of unbound does the = check for update ( however it is realized ) nevertheless. >>>>>>>>>>=20 >>>>>>>>>> Yes, doing more things needs resources. But we are not = seriously considering whether an IPFire system has enough resources to = perform the download of a text file, or are we? >>>>>>>>>>=20 >>>>>>>>>>>=20 >>>>>>>>>>>>> I understand that you don=E2=80=99t speak C, but you got = the information from somewhere. Documentation maybe? Since that is out = of date very often I like to consult the code. >>>>>>>>>>>>> =46rom testing. Downloading rpz files using rpz unbound, = and watching what happens. If the rpz file is setup for "once per day" = refresh, then it only downloads one time. >>>>>>>>>>>>> However that won=E2=80=99t solve our problem . . . and = having no cache. >>>>>>>>>>>>> In `/etc/unbound/tuning.conf` there is `rrset-cache-size: = 128m`. Are you referring to a different cache. >>>>>>>>>>>>=20 >>>>>>>>>>>> Naturally unbound is loading the zone into its memory which = we generally call cache. >>>>>>>>>>>> When I say cache I am thinking about persistent data = storage across multiple restarts of Unbound. If I am downloading 100 MiB = of RPZ lists (which is presumably still on the lower end) and I reboot = my firewall, I do not want to download the same data again. We can only = ever download a list *once* unless we are 100% certain that it has = changed. Then we can download it once again. >>>>>>>>>>>=20 >>>>>>>>>>> The RPZ lists are stored in files in persistent storage. = Unbound creates the internal cache from these. >>>>>>>>>>=20 >>>>>>>>>> And where are these stored? >>>>>>>>>>=20 >>>>>>>>>>>=20 >>>>>>>>>>>>> Maybe we need to implement both? >>>>>>>>>>>>> Yes. There are very few AXFR list (I think only four were = found). And many more HTTPS rpz files. >>>>>>>>>>>>> Jon >>>>>>>>>>>>> ------ Original Message ------ >>>>>>>>>>>>> =46rom "Michael Tremer" <michael.tremer@ipfire.org> >>>>>>>>>>>>> To "Jon Murphy" <jon.murphy@ipfire.org> >>>>>>>>>>>>> Cc "IPFire: Development-List" = <development@lists.ipfire.org> >>>>>>>>>>>>> Date 3/20/2025 11:26:43=E2=80=AFAM >>>>>>>>>>>>> Subject Re: [PATCH] RPZ: update code to include WEBGUI and = additional languages >>>>>>>>>>>>>=20 >>>>>>>>>>>>>>=20 >>>>>>>>>>>>>> Hello Jon, >>>>>>>>>>>>>> Please don=E2=80=99t forget to Cc the list... >>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>> On 19 Mar 2025, at 18:27, Jon Murphy = <jon.murphy@ipfire.org> wrote: >>>>>>>>>>>>>>> Michael, >>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>> Where in the code is this implemented? I cannot find = anything like this: >>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>> Keep in mind I am not a "C" person. Maybe in this = section?: >>>>>>>>>>>>>>> = https://git.ipfire.org/?p=3Dthirdparty/unbound.git;a=3Dblob;f=3Dservices/a= uthzone.c;hb=3D30b9cb5f813003d0a2b1c2e678652396615b1b7d#l5875 >>>>>>>>>>>>>>=20 >>>>>>>>>>>>>> This where the AXFR response is being handled when doing = a DNS zone transfer. This code is not being called when performing a = HTTP download. >>>>>>>>>>>>>> I understand that you don=E2=80=99t speak C, but you got = the information from somewhere. Documentation maybe? Since that is out = of date very often I like to consult the code. >>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>> =E2=80=94 >>>>>>>>>>>>>>> When I was just learning about RPZ I created a separate = RPZ file for testing. When I changed the SOA line with a new serial = number, the RPZ file download would happen in about 5 minutes. >>>>>>>>>>>>>>> https://people.ipfire.org/~jon/sblack-adhoc.rpz >>>>>>>>>>>>>>=20 >>>>>>>>>>>>>> It might well be that the file is not being reloaded if = the download matches the content that unbound already has. That would of = course save some resources. >>>>>>>>>>>>>> However that won=E2=80=99t solve our problem with = redundant downloads and having no cache. >>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>> That is how I found out the SOA line is watched for a = serial number change. >>>>>>>>>>>>>>> I=E2=80=99ll reconfirm my findings. >>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>> The second reason is that we have a lot of firewalls = out there. Not all of them will enable this feature and all of the = lists, but even if it is a good chunk, we will generate terabytes of = traffic which put load on the infrastructure and will cost money. It = simply is not what we want to do, regardless of self-hosting those lists = and pulling them from somewhere else. >>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>> So I understand, are you thinking of hosting RPZ AXFR = (DNS zone transfer) on IPFire infrastructure? >>>>>>>>>>>>>>=20 >>>>>>>>>>>>>> No, I don=E2=80=99t think that we can generally do this. = The biggest problem is licensing as we cannot take anyones content and = host it ourselves. We would re-distribute those lists and that will only = work with permission of the publishers. I assume that would be too much = work to actually get some useful content out there. We might limit = ourselves to only those lists that are under a very permissive license. = Nobody wants that. >>>>>>>>>>>>>> =46rom a technical point of view, DNS over TCP might not = be very nice in terms of forging the transfer and so we would need TLS = as well=E2=80=A6 It should work, but even if we would be able to = encourage other people to publish their lists I doubt they would = implement DNS over TLS for authoritative DNS. That standard is in very = early stages as well. >>>>>>>>>>>>>> As far as I can see, those vendors who offer a list as a = commercial product are using DNS to distribute it (e.g. Spamhaus). Those = people who have made this all a hobby are throwing the lists onto GitHub = and let them handle the traffic. >>>>>>>>>>>>>> Maybe we need to implement both? >>>>>>>>>>>>>> -Michael >>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>> Jon >>>>>>>>>>>>>>> On 3/19/25 5:35 AM, Michael Tremer wrote: >>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>> Hello Jon, >>>>>>>>>>>>>>>> Where in the code is this implemented? I cannot find = anything like this: >>>>>>>>>>>>>>>> Unbound loads the entire file into memory and then = starts parsing it. The only special treatment there is is to check = whether the first line is a valid zone entry. It does not even have to = be a SOA record. >>>>>>>>>>>>>>>> = https://git.ipfire.org/?p=3Dthirdparty/unbound.git;a=3Dblob;f=3Dservices/a= uthzone.c;hb=3D30b9cb5f813003d0a2b1c2e678652396615b1b7d#l1188 >>>>>>>>>>>>>>>> I am also concerned that Unbound will not be able to = support an upstream proxy for any downloads. The caching situation is = also unclear for me, so I believe that we will be looking at writing a = custom downloader that implements all these things. >>>>>>>>>>>>>>>> -Michael >>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>> On 19 Mar 2025, at 02:58, Jon Murphy = <jon.murphy@ipfire.org> wrote: >>>>>>>>>>>>>>>>> Michael, >>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>> The emphasis is on the repeated downloads of the = same list. That is >>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>> =E2=80=8B> what cannot happen. >>>>>>>>>>>>>>>>> The Unbound RPZ code, as installed within IPFire, = watches for a change >>>>>>>>>>>>>>>>> =E2=80=8Bin the SOA line of each RPZ file. This is an = example of the first few >>>>>>>>>>>>>>>>> =E2=80=8Blines for every RPZ file. >>>>>>>>>>>>>>>>> $TTL 300 >>>>>>>>>>>>>>>>> @ SOA localhost. root.localhost. 1742298960 43200 3600 = 86400 300 >>>>>>>>>>>>>>>>> NS localhost. >>>>>>>>>>>>>>>>> ; >>>>>>>>>>>>>>>>> ; Title: HaGeZi's Pop-Up Ads DNS Blocklist >>>>>>>>>>>>>>>>> ; Description: Blocks annoying and malicious pop-up = ads. >>>>>>>>>>>>>>>>> If the SOA serial number changes (e.g. the = 1742298960), then Unbound RPZ >>>>>>>>>>>>>>>>> =E2=80=8Bcode does its thing and downloads. Otherwise = there is no download. >>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>> So there has to be a way to ensure that we won=E2=80=99= t download a list again >>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>> =E2=80=8B> unless it has actually changed. >>>>>>>>>>>>>>>>> This should do what you want but I may be missing your = point. >>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>> DNS has a builtin functionality called AXFR. It = simply does the job >>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>> =E2=80=8B> for you. I was just wondering whether that = was not being used. >>>>>>>>>>>>>>>>> I need to read about AXFR/IXFR and learn a little = more. >>>>>>>>>>>>>>>>> Jon >>>>>>>>>>>>>>>>> On 3/17/25 5:35 AM, Michael Tremer wrote: >>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>> Good Morning Jon, >>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>> On 16 Mar 2025, at 17:00, Jon Murphy = <jon.murphy@ipfire.org> wrote: >>>>>>>>>>>>>>>>>>> Michael, >>>>>>>>>>>>>>>>>>> I was reading through you response again an I want = to understand this post: >>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>> I have also stated that we cannot download any = lists over HTTPS again and again and again. The implementation that we = have here seems to exactly do that and therefore I think that my = feedback has been dismissed entirely. >>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>> So if RPZ doesn't use HTTPS, what is it using? I am = missing a key point here. >>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>> The emphasis is on the repeated downloads of the = same list. That is what cannot happen. >>>>>>>>>>>>>>>>>> Although it might not affect a lot of people in our = general user-base, there are some that have a metered connection and = will pay for data by volume. Some of the lists I looked at are just = under 20 MiB. Therefore we need to keep any traffic down to a minimum. = The second reason is that we have a lot of firewalls out there. Not all = of them will enable this feature and all of the lists, but even if it is = a good chunk, we will generate terabytes of traffic which put load on = the infrastructure and will cost money. It simply is not what we want to = do, regardless of self-hosting those lists and pulling them from = somewhere else. >>>>>>>>>>>>>>>>>> So there has to be a way to ensure that we won=E2=80=99= t download a list again unless it has actually changed. >>>>>>>>>>>>>>>>>> DNS has a builtin functionality called AXFR. It = simply does the job for you. I was just wondering whether that was not = being used. >>>>>>>>>>>>>>>>>> HTTPS is an option because that is simply what we use = elsewhere, but extra functionality will have to be built for it. >>>>>>>>>>>>>>>>>> -Michael >>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>> Jon >>>>>>>>>>>>>>>>>>> On 2/13/25 3:34 PM, jon wrote: >>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>> Michael, >>>>>>>>>>>>>>>>>>>> I=E2=80=99ve read through your comments a few times = and I ended up with many more questions. >>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> What I rather mean is that it has never been = added as a topic on the agenda and it has not been pitched by yourself. >>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>> To me the efforts to get new code accepted seem to = have changed and it seemed easier in the past. In the past I made the = Core Team aware via the Dev Mailing List and wrote a simple two or three = paragraphs of "What is it? / What is the value? / Here is the code" >>>>>>>>>>>>>>>>>>>> So in an effort to move forward: How exactly is = something presented to the Core Team? >>>>>>>>>>>>>>>>>>>> Is there an example of a recent effort that was = presented that I can see as a sample? (This type of info can also be = added to the Wiki) >>>>>>>>>>>>>>>>>>>> I understand you want it this way, but I don=E2=80=99= t know what exactly is needed. Please be specific. >>>>>>>>>>>>>>>>>>>> Jon >>>>>>>>>>>>>>>>>>>> PS - I am not ignoring your other comments, I am = just trying to move forward and keep things simple. >>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> On Feb 8, 2025, at 1:27=E2=80=AFPM, Michael = Tremer <michael.tremer@ipfire.org> wrote: >>>>>>>>>>>>>>>>>>>>> Hello Jon, >>>>>>>>>>>>>>>>>>>>> Thanks for your reply. And good that you are = copying everyone into this conversation. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> On 8 Feb 2025, at 18:41, jon = <jon.murphy@ipfire.org> wrote: >>>>>>>>>>>>>>>>>>>>>> Michael, >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> I think I have covered this all at lengths = before that this project has been started as a separate effort >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> Yes, this has been a separate effort (a very = public separate effort). Yes, as you pointed this out early on with the = "proof-of-concept" and then my request for people to help test RPZ. = Nothing was hidden. >>>>>>>>>>>>>>>>>>>>>> This was done because you (and maybe others) did = not have the time and I wanted to help and because I needed assistance = with RPZ. I tried my best to do this without bothering you. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> I don=E2=80=99t that it is accurate that nobody = wanted to help on this. The list was always open - although not every = email has been replied to swiftly it is also your responsibility to = raise a question again if it was missed. People here have open ears. >>>>>>>>>>>>>>>>>>>>> It was also stated on this very list on in our = documentation that working on something without involving the core team = is a risky undertaking. Of course IPFire is free software and so = everyone is free to fork if they wish to do so. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> and as far as I am aware none of the other team = members has been involved. This has not been discussed either on this = list, on our calls. >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> You were aware many steps along the way. See = your email on July 28, 2024, August 15, 2024, September 30, 2024, = December 23, 2024, and January 16. My attempts to get the team involved = were met with "things are busy" and sometimes silence. (Yes, I get it, = people are busy.) >>>>>>>>>>>>>>>>>>>>>> You and Adolf, Leo, Erik and Bernhard have been = aware since the beginning. You mention you were aware of the = "proof-of-concept". If you include those beginning posts, since Sep = 2023. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> Yes, I am aware of a proof-of-concept that I have = been running myself for a long time. I am also aware of the efforts that = you have been taking. >>>>>>>>>>>>>>>>>>>>> Yet I don=E2=80=99t think there has ever been any = joint effort, or am I seeing that wrong? >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> This has not been discussed . . . on our calls. >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> On the July 28th you stated: >>>>>>>>>>>>>>>>>>>>>> "We have talked about RPZ many times on the = monthly call since the URL filter feature is falling more and more out = of fashion. I think there is also many posts about this on the forum." >>>>>>>>>>>>>>>>>>>>>> Please don=E2=80=99t insult me again by stating = "you know what I mean". >>>>>>>>>>>>>>>>>>>>>> And it has been discussed but not documented in = the Monthly Meeting notes. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> I am not at all insulting you. I don=E2=80=99t = want to take this down to a personal level at all. This is a public = mailing list and people who read this don=E2=80=99t need to listen to an = argument we are having. They are here for the tech inside IPFire. >>>>>>>>>>>>>>>>>>>>> When I wrote that it has not been discussed that = does not mean that we have not been touching on the topic. We have been = talking about lots of things on the calls, the weather, politics, how = our pets are. None of that makes it to the logs. What I rather mean is = that it has never been added as a topic on the agenda and it has not = been pitched by yourself. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> Instead there has been a separate conversation = on the forum with the occasional dip here to the list. But that was not = a regular two-way conversation. >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> Regular conversation on the Dev Mailing list is = many times met with silence. I get it, people are busy. >>>>>>>>>>>>>>>>>>>>>> And regular two-way conversation doesn=E2=80=99t = happen on the list. At least not with me. I=E2=80=99d be happy to point = out the posts that were met with silence. >>>>>>>>>>>>>>>>>>>>>> Again, I get it, people are busy. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> And you think my emails are not being met with = silence? This has nothing to do with this specific topic. This has = something to do with how occupied people are and how engaged they are on = certain topics. Not everyone is involved in all the things and simply = will ignore emails simply based on their subject line. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> But the "dip here to the list" were my attempts = to get a conversation started. As I said, many time met with silence. >>>>>>>>>>>>>>>>>>>>>> The only place I was not met with silence was on = the Community. You have a great group of people in the Community. It is = a shame you don=E2=80=99t want to have others help. It would reduce your = workload. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> You should stop making statements that are not = true. Who doesn=E2=80=99t want anyone to help? >>>>>>>>>>>>>>>>>>>>> Not having this conversation on a Saturday evening = would reduce my workload. At least it would free up time for something = else. Helping with the things that are already on the go would reduce = the workload of the entire team. Starting one thing at a time and = finishing it is a lot better to manage than starting a hundred things = and not even finish one. I can tell you that I already have a hundred = things on the go. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> Therefore, what am I supposed to do with this = email? >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> To me it is beyond obvious=E2=80=A6 >>>>>>>>>>>>>>>>>>>>>> If it isn=E2=80=99t what you want, then guide me = with how to do this the correct way. And be specific. I am trying to = help. I am trying to make things better. I am trying to do things the = right way. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> To me it isn=E2=80=99t. This is yet another = project that has been dumped to the list like so many before and later = on everyone has left to have the team deal with the rest. >>>>>>>>>>>>>>>>>>>>> It is a huge patch set. You explained what the = vision is, but that is about it. There is no chance this will continue = if this disagreement isn=E2=80=99t solved first. I didn=E2=80=99t even = look at the code. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> I don=E2=80=99t want to merge code that I = don=E2=80=99t agree with. >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> I asked multiple times if you "agreed with the = concept" and again, met with silence. Yes I get it, people are busy. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> Having support for RPZ? Yes, it was definitely on = the roadmap. That I agree with. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> So many fundamental things that I have been = raising have either not been discussed or outright dismissed. >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> You mentioned this a in the past, but for some = reason you do not disclose what I dismissed. Why do you continue to make = this harder, wouldn=E2=80=99t it not be easier to tell me what I have = dismissed? >>>>>>>>>>>>>>>>>>>>>> I have sent multiple emails trying to answer your = concerns and comments. On July 28, Aug 14, Aug 22, Aug 23, Sep 30, etc. >>>>>>>>>>>>>>>>>>>>>> I=E2=80=99ve gone through all of the questions = you asked and I cannot find a "dismissed" item. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> Maybe I need to be *more clear*. I feel humoured = by this. >>>>>>>>>>>>>>>>>>>>> It is late on a Saturday and I want my dinner = soon, but certainly I have stated that this should never be an add-on = considering it is supposed to replace URL Filter. We should never allow = people to add their own sources. I have also stated that we cannot = download any lists over HTTPS again and again and again. The = implementation that we have here seems to exactly do that and therefore = I think that my feedback has been dismissed entirely. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> I don=E2=80=99t want to merge code that has no = future inside IPFire as there is no constructive conversation with the = maintainers of it. >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> The maintainers of Unbound and/or RPZ? >>>>>>>>>>>>>>>>>>>>>> The maintainers of Hagezi list, the threatfox = list, the urlhaus list, etc.? >>>>>>>>>>>>>>>>>>>>>> What else? The maintainers or the RPZ scripts? = That is me. Let=E2=80=99s talk! >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> You. I don=E2=80=99t care much about the = providers of the lists. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> See, this is where it gets confusing. There are = hundreds of open source packages as part of IPFire. Pick the last five = years of items added to the IPFire build. You're telling me you have = "constructive conversation with the maintainers" of all of the added = packages? >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> They publish their software and they don=E2=80=99t = care whether I am pulling it or not. They publish it with the commitment = to maintain it - sometimes for better and sometimes for worse. >>>>>>>>>>>>>>>>>>>>> You care about me pulling your code and I don=E2=80=99= t know whether you would commit to maintain this. >>>>>>>>>>>>>>>>>>>>> These two are very different cases. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> Pick the IP Blocklists list (i.e., 3CORESEC, = ABUSECH, DSHIELD, SPAMHAUS, etc.) or the Suricata lists = (i.e.,Emergingthreats.net <http://emergingthreats.net/>,Abuse.ch = <http://abuse.ch/>, etc.). So you=E2=80=99ve have "constructive = conversation with the maintainers"? >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> Yes, occasionally I have phone calls with a few = of these providers. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> Having been trying for a long time to make you = aware of this, nothing of this should come as a surprise. >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> Ha! Yes a surprise. In the beginning you seemed = interested as IPFire needed a replacement for URL Filter. You asked good = questions about the lists picked, asked for the value to the users, etc. = And I answered the best I could. >>>>>>>>>>>>>>>>>>>>>> You even asked: =E2=80=9CWhy is this realised as = an add-on and not part of the core system?=E2=80=9D from your Jul 28, = 2024 email. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> Ah, so, why is the patch creating an add-on? Not = that I am saying that what I say is law, but it has not been challenged = either. If my input is being ignored, why should I put this to the top = of my list of priorities? I am not disappointed about this, just trying = to be very good with my time. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> And on January 16, 2025 I wrote a message = looking for help. And you were kind to respond quickly. So in three = weeks time, since the kind response, something has changed. You went = from supportive to "this". >>>>>>>>>>>>>>>>>>>>>> So yes, I am surprised. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> Well, maybe I should not have replied to that = email. It was clear that you were on some path that was not right, but = you were not interested before in finding the right path from the = beginning. >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> Please consider if that can be changed and if = there is a path forward with this. >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> Be more specific, what has to change? What = exactly did I dismiss? >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>> Dismissal is just my assumption. I don=E2=80=99t = know what you actually did with my feedback. I can only see the end = product that does not seem contain much of it. Repeatedly I have been = pointing out that we should think before we build. I am sure a lot of = hours have now gone into some code that simply does not satisfy me. And = I am not not talking about the code itself, what it does is what I = don=E2=80=99t think is right for us. >>>>>>>>>>>>>>>>>>>>> The process is very clear for me that we should = first of all think whether we want a certain feature now. Then there = should be a clear roadmap for everyone to follow; tasks can be split-up = as we go and hopefully then have something that is maintainable, = interesting for our users and even would do us proud. This is how this = should work. >>>>>>>>>>>>>>>>>>>>> So, what has to change? I don=E2=80=99t think with = shouting at each other, throwing patches around and making me generally = unhappy is a good start. >>>>>>>>>>>>>>>>>>>>> -Michael >>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> Jon >>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>> On Feb 6, 2025, at 2:13=E2=80=AFPM, Michael = Tremer <michael.tremer@ipfire.org> wrote: >>>>>>>>>>>>>>>>>>>>>>> Hello Jon, >>>>>>>>>>>>>>>>>>>>>>> Well, here we are again with another patch = regarding this feature. >>>>>>>>>>>>>>>>>>>>>>> I cannot quite see from your email what the = question is, but if this is a request to have this merged into IPFire, I = am once again sorry to disappoint you. >>>>>>>>>>>>>>>>>>>>>>> I think I have covered this all at lengths = before that this project has been started as a separate effort and as = far as I am aware none of the other team members has been involved. This = has not been discussed either on this list, on our calls. Instead there = has been a separate conversation on the forum with the occasional dip = here to the list. But that was not a regular two-way conversation. = Therefore, what am I supposed to do with this email? >>>>>>>>>>>>>>>>>>>>>>> I don=E2=80=99t want to merge code that I = don=E2=80=99t agree with. So many fundamental things that I have been = raising have either not been discussed or outright dismissed. >>>>>>>>>>>>>>>>>>>>>>> I don=E2=80=99t want to merge code that has no = future inside IPFire as there is no constructive conversation with the = maintainers of it. >>>>>>>>>>>>>>>>>>>>>>> Having been trying for a long time to make you = aware of this, nothing of this should come as a surprise. >>>>>>>>>>>>>>>>>>>>>>> Please consider if that can be changed and if = there is a path forward with this. >>>>>>>>>>>>>>>>>>>>>>> All the best, >>>>>>>>>>>>>>>>>>>>>>> -Michael >>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>>>> On 6 Feb 2025, at 16:35, Jon Murphy = <jon.murphy@ipfire.org> wrote: >>>>>>>>>>>>>>>>>>>>>>>> What is it? >>>>>>>>>>>>>>>>>>>>>>>> Response Policy Zone (RPZ) is a mechanism to = define local policies in a >>>>>>>>>>>>>>>>>>>>>>>> standardized way and load those policies from = external sources. >>>>>>>>>>>>>>>>>>>>>>>> Bottom line: RPZ allows admins to easily block = access to websites via DNS lookup. >>>>>>>>>>>>>>>>>>>>>>>> RPZ can block websites via categories. Examples = include: fake websites, annoying >>>>>>>>>>>>>>>>>>>>>>>> pop-up ads, newly registered domains, DoH = bypass sites, bad "host" services, >>>>>>>>>>>>>>>>>>>>>>>> maliscious top level domains (e.g., *.zip, = *.mov), piracy, gambling, pornography, >>>>>>>>>>>>>>>>>>>>>>>> and more. RPZ lists come from various RPZ = providers and their available >>>>>>>>>>>>>>>>>>>>>>>> catagories. >>>>>>>>>>>>>>>>>>>>>>>> This RPZ add-on enables the RPZ functionality = by adding a couple lines in a >>>>>>>>>>>>>>>>>>>>>>>> configuration file. This add-on simply adds = configuration files and adds >>>>>>>>>>>>>>>>>>>>>>>> scripts (config, metrics and sleep) to make RPZ = easier for the admin to use. >>>>>>>>>>>>>>>>>>>>>>>> The RPZ scripts include additional languages: = German, Spanish, French, Turkish, >>>>>>>>>>>>>>>>>>>>>>>> and Italian. >>>>>>>>>>>>>>>>>>>>>>>> RPZ itself was release in 2010 and has been = part of the IPFire build since ~2015. >>>>>>>>>>>>>>>>>>>>>>>> Why is it needed? What is its value? >>>>>>>>>>>>>>>>>>>>>>>> - The RPZ concept places this filtering into = IPFire, our internet access >>>>>>>>>>>>>>>>>>>>>>>> gateway, which is (should be) solely used as = DNS source of the internal network. >>>>>>>>>>>>>>>>>>>>>>>> - As most sites use HTTPS it makes it difficult = to filter traffic with URL >>>>>>>>>>>>>>>>>>>>>>>> Filter without also properly configuring = conventional (non-transparent) >>>>>>>>>>>>>>>>>>>>>>>> mode on the proxy. RPZ is a nice replacement = for the URL Filter. >>>>>>>>>>>>>>>>>>>>>>>> - No need to install and maintain an additional = device like PiHole or AdBlock >>>>>>>>>>>>>>>>>>>>>>>> browser extensions on multiple user devices. >>>>>>>>>>>>>>>>>>>>>>>> - This is an additional layer of protection for = users. Less worry someone will >>>>>>>>>>>>>>>>>>>>>>>> click on something that gets them into trouble. = And, saying this with emphasis, >>>>>>>>>>>>>>>>>>>>>>>> the ability to do it in one place! >>>>>>>>>>>>>>>>>>>>>>>> - Blocked sites save on unneeded traffic and = can lessen the threat of malware >>>>>>>>>>>>>>>>>>>>>>>> in advertisements >>>>>>>>>>>>>>>>>>>>>>>> - Logging allows the admin to see the site = blocked and take actions >>>>>>>>>>>>>>>>>>>>>>>> - RPZ will be used at the home, home-office = (work from home), schools, >>>>>>>>>>>>>>>>>>>>>>>> ministerial, and at the office. Device counts = are small (2-6) to medium (~80) >>>>>>>>>>>>>>>>>>>>>>>> to mediam-large (200+). >>>>>>>>>>>>>>>>>>>>>>>> - RPZ can block ads, popups, phishing, = scammers, spyware, malware, annoying >>>>>>>>>>>>>>>>>>>>>>>> popups, NSFW links, DOH servers, and the usual = internet trash. >>>>>>>>>>>>>>>>>>>>>>>> ------------------------------ >>>>>>>>>>>>>>>>>>>>>>>> Change Log for RPZ add-on >>>>>>>>>>>>>>>>>>>>>>>> rpz-1.0.0-18 on 2025-02-05 >>>>>>>>>>>>>>>>>>>>>>>> - Build for approval & release as IPFire add-on >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.18-18.ipfire on 2025-02-01 >>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: added a mod key to force a = unbound restart >>>>>>>>>>>>>>>>>>>>>>>> rpz-config and rpz-make: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: added action for unbound restart = `rpz-config unbound-restart` >>>>>>>>>>>>>>>>>>>>>>>> rpz-metrics: >>>>>>>>>>>>>>>>>>>>>>>> - simple reformatting >>>>>>>>>>>>>>>>>>>>>>>> - rename far right column from "last update" to = "last download" >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.17-17.ipfire on 2024-12-09 >>>>>>>>>>>>>>>>>>>>>>>> rpz-make >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected validation regex for = wildcards like: `*.domain.com` >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.16-16.ipfire on 2024-11-18 >>>>>>>>>>>>>>>>>>>>>>>> rpz-make >>>>>>>>>>>>>>>>>>>>>>>> - new feature: updated validation regex >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: moved validation to beginning of = process. Now we validate before >>>>>>>>>>>>>>>>>>>>>>>> creating config files. >>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: use CSS color variables of the = main ipfire theme >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: empty zonefile remarks were stored = as =E2=80=9Cundef=E2=80=9D and caused a warning >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: HTML textarea removes the first = empty line in a custom list >>>>>>>>>>>>>>>>>>>>>>>> - thank you Leo! >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.15-15.ipfire on 2024-11-04 >>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file for = Turkish (thank you Peppe) >>>>>>>>>>>>>>>>>>>>>>>> rpz-make >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected empty allow/block list = issue. An empty allow/block list >>>>>>>>>>>>>>>>>>>>>>>> will now remove contents of allow/block.rpz = files and remove unneeded >>>>>>>>>>>>>>>>>>>>>>>> allow/block.conf file. (thank you iptom) >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.14-14.ipfire on 2024-10-29 >>>>>>>>>>>>>>>>>>>>>>>> rpz-config: >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: correct missing rpz extension. = `rpz-config list` displayed URL >>>>>>>>>>>>>>>>>>>>>>>> incorrectly (thank you Bernhard) >>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi: >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: remove extra `"` in language files = (thank you Bernhard) >>>>>>>>>>>>>>>>>>>>>>>> - new feature: slightly dim "apply" button when = not enabled >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.13-13.ipfire on 2024-10-27 >>>>>>>>>>>>>>>>>>>>>>>> - skipped >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.12-12.ipfire on 2024-10-21 >>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file for = French (thank you gw-ipfire) >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.11-11.ipfire on 2024-10-18 >>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file for = Italian (thank you umberto) >>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file for = Spanish (thank you Roberto) >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.10-10.ipfire on 2024-10-15 >>>>>>>>>>>>>>>>>>>>>>>> rpz-make: >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected validation error for a = custom list entry (thank you siosios) >>>>>>>>>>>>>>>>>>>>>>>> - e.g., `*.cloudflare-dns.com` >>>>>>>>>>>>>>>>>>>>>>>> install.sh: >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: add chown to correct user created = files >>>>>>>>>>>>>>>>>>>>>>>> update.sh: >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: add chown to correct user created = files (thank you siosios) >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.9-9.ipfire on 2024-10-08 >>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new language file for = German (thank you Leo) >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: add missing "rpz exitcode 110" >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected missing RPZ menu item at = menu > IPFire >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.8-8.ipfire on 2024-10-04 >>>>>>>>>>>>>>>>>>>>>>>> - skipped >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> rpz-beta-0.1.7-7.ipfire on 2024-10-03 >>>>>>>>>>>>>>>>>>>>>>>> All: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: includes beta version numbers = for pakfire package, >>>>>>>>>>>>>>>>>>>>>>>> instead of only `rpz-1.0.0-1.ipfire`, for each = release. >>>>>>>>>>>>>>>>>>>>>>>> rpz.cgi: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: added new WebGUI at `rpz.cgi` >>>>>>>>>>>>>>>>>>>>>>>> - a BIG thank you to Leo Hofmann for all of his = work creating the webgui!! >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected missing RPZ menu item at = menu > IPFire >>>>>>>>>>>>>>>>>>>>>>>> rpz-make: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: validate entries in allowlist = and blocklist >>>>>>>>>>>>>>>>>>>>>>>> - new feature: add "no-reload" option for = WebGUI >>>>>>>>>>>>>>>>>>>>>>>> rpz-metrics: >>>>>>>>>>>>>>>>>>>>>>>> - new feature: info can be sorted by name, by = hit count, by line count, by >>>>>>>>>>>>>>>>>>>>>>>> "enabled" list or all lists >>>>>>>>>>>>>>>>>>>>>>>> backups: >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: include all files in = `/var/ipfire/dns/rpz` directory in backup >>>>>>>>>>>>>>>>>>>>>>>> update.sh: >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: corrected ownership for = `/var/ipfire/dns/rpz` directory during an >>>>>>>>>>>>>>>>>>>>>>>> update >>>>>>>>>>>>>>>>>>>>>>>> Build: >>>>>>>>>>>>>>>>>>>>>>>> - bug fix: `block.rpz.conf` and `block.rpz` = from build. Files to be created >>>>>>>>>>>>>>>>>>>>>>>> by `rpz-make` >>>>>>>>>>>>>>>>>>>>>>>> WebGUI and German language file >>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Leo-Andres Hofmann = <hofmann@leo-andres.de> >>>>>>>>>>>>>>>>>>>>>>>> Spanish language file >>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Roberto Pe=C3=B1a >>>>>>>>>>>>>>>>>>>>>>>> Italian language file >>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Umberto Parma >>>>>>>>>>>>>>>>>>>>>>>> French language file >>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: gw-ipfire >>>>>>>>>>>>>>>>>>>>>>>> Turkish language file >>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Peppe Tech >>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Bernhard Bitsch = <bbitsch@ipfire.org> >>>>>>>>>>>>>>>>>>>>>>>> Contribution-by: Erik Kapfer = <erik.kapfer@ipfire.org> >>>>>>>>>>>>>>>>>>>>>>>> Signed-off-by: Jon Murphy = <jon.murphy@ipfire.org >>>>>>>>>>>>>>>>>>>>>>>> --- >>>>>>>>>>>>>>>>>>>>>>>> config/backup/includes/rpz | 4 + >>>>>>>>>>>>>>>>>>>>>>>> config/cfgroot/manualpages | 1 + >>>>>>>>>>>>>>>>>>>>>>>> config/menu/EX-rpz.menu | 6 + >>>>>>>>>>>>>>>>>>>>>>>> config/rootfiles/common/configroot | 1 + >>>>>>>>>>>>>>>>>>>>>>>> config/rootfiles/common/web-user-interface | 1 = + >>>>>>>>>>>>>>>>>>>>>>>> config/rootfiles/packages/rpz | 20 + >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/00-rpz.conf | 10 + >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-config | 130 +++ >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-functions | 85 ++ >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-make | 203 +++++ >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-metrics | 170 ++++ >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz-sleep | 58 ++ >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.de.pl | 30 + >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.en.pl | 30 + >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.es.pl | 30 + >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.fr.pl | 30 + >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.it.pl | 30 + >>>>>>>>>>>>>>>>>>>>>>>> config/rpz/rpz.tr.pl | 30 + >>>>>>>>>>>>>>>>>>>>>>>> html/cgi-bin/rpz.cgi | 923 = +++++++++++++++++++++ >>>>>>>>>>>>>>>>>>>>>>>> lfs/rpz | 96 +++ >>>>>>>>>>>>>>>>>>>>>>>> make.sh | 3 +- >>>>>>>>>>>>>>>>>>>>>>>> src/paks/rpz/install.sh | 36 + >>>>>>>>>>>>>>>>>>>>>>>> src/paks/rpz/uninstall.sh | 38 + >>>>>>>>>>>>>>>>>>>>>>>> src/paks/rpz/update.sh | 52 ++ >>>>>>>>>>>>>>>>>>>>>>>> 24 files changed, 2016 insertions(+), 1 = deletion(-) >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/backup/includes/rpz >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/menu/EX-rpz.menu >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 = config/rootfiles/packages/rpz >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/00-rpz.conf >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz-config >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz-functions >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz-make >>>>>>>>>>>>>>>>>>>>>>>> create mode 100755 config/rpz/rpz-metrics >>>>>>>>>>>>>>>>>>>>>>>> create mode 100755 config/rpz/rpz-sleep >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.de.pl >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.en.pl >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.es.pl >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.fr.pl >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.it.pl >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 config/rpz/rpz.tr.pl >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 html/cgi-bin/rpz.cgi >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 lfs/rpz >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 src/paks/rpz/install.sh >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 src/paks/rpz/uninstall.sh >>>>>>>>>>>>>>>>>>>>>>>> create mode 100644 src/paks/rpz/update.sh >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/backup/includes/rpz = b/config/backup/includes/rpz >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..36513e494 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/backup/includes/rpz >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,4 @@ >>>>>>>>>>>>>>>>>>>>>>>> +/var/ipfire/dns/rpz/* >>>>>>>>>>>>>>>>>>>>>>>> +/etc/unbound/zonefiles/allow.rpz >>>>>>>>>>>>>>>>>>>>>>>> +/etc/unbound/zonefiles/block.rpz >>>>>>>>>>>>>>>>>>>>>>>> +/etc/unbound/local.d/*rpz.conf >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/cfgroot/manualpages = b/config/cfgroot/manualpages >>>>>>>>>>>>>>>>>>>>>>>> index 1f7e01efc..d3a48c633 100644 >>>>>>>>>>>>>>>>>>>>>>>> --- a/config/cfgroot/manualpages >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/cfgroot/manualpages >>>>>>>>>>>>>>>>>>>>>>>> @@ -70,6 +70,7 @@ = pakfire.cgi=3Dconfiguration/ipfire/pakfire >>>>>>>>>>>>>>>>>>>>>>>> wlanap.cgi=3Daddons/wireless >>>>>>>>>>>>>>>>>>>>>>>> tor.cgi=3Daddons/tor >>>>>>>>>>>>>>>>>>>>>>>> samba.cgi=3Daddons/samba >>>>>>>>>>>>>>>>>>>>>>>> +rpz.cgi=3Daddons/rpz >>>>>>>>>>>>>>>>>>>>>>>> # Logs menu >>>>>>>>>>>>>>>>>>>>>>>> logs.cgi/summary.dat=3Dconfiguration/logs/summary= >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/menu/EX-rpz.menu = b/config/menu/EX-rpz.menu >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..2f4daf410 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/menu/EX-rpz.menu >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,6 @@ >>>>>>>>>>>>>>>>>>>>>>>> +$subipfire->{'20.rpz'} =3D { >>>>>>>>>>>>>>>>>>>>>>>> + 'caption' =3D> $Lang::tr{'rpz'}, >>>>>>>>>>>>>>>>>>>>>>>> + 'uri' =3D> '/cgi-bin/rpz.cgi', >>>>>>>>>>>>>>>>>>>>>>>> + 'title' =3D> "RPZ", >>>>>>>>>>>>>>>>>>>>>>>> + 'enabled' =3D> 1, >>>>>>>>>>>>>>>>>>>>>>>> +}; >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rootfiles/common/configroot = b/config/rootfiles/common/configroot >>>>>>>>>>>>>>>>>>>>>>>> index 9839eee45..b30d6aae4 100644 >>>>>>>>>>>>>>>>>>>>>>>> --- a/config/rootfiles/common/configroot >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rootfiles/common/configroot >>>>>>>>>>>>>>>>>>>>>>>> @@ -120,6 +120,7 @@ = var/ipfire/menu.d/70-log.menu >>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-apcupsd.menu >>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-guardian.menu >>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-mympd.menu >>>>>>>>>>>>>>>>>>>>>>>> +#var/ipfire/menu.d/EX-rpz.menu >>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-samba.menu >>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-tor.menu >>>>>>>>>>>>>>>>>>>>>>>> #var/ipfire/menu.d/EX-transmission.menu >>>>>>>>>>>>>>>>>>>>>>>> diff --git = a/config/rootfiles/common/web-user-interface = b/config/rootfiles/common/web-user-interface >>>>>>>>>>>>>>>>>>>>>>>> index 816241dae..e00464076 100644 >>>>>>>>>>>>>>>>>>>>>>>> --- = a/config/rootfiles/common/web-user-interface >>>>>>>>>>>>>>>>>>>>>>>> +++ = b/config/rootfiles/common/web-user-interface >>>>>>>>>>>>>>>>>>>>>>>> @@ -69,6 +69,7 @@ = srv/web/ipfire/cgi-bin/proxy.cgi >>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/qos.cgi >>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/remote.cgi >>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/routing.cgi >>>>>>>>>>>>>>>>>>>>>>>> +#srv/web/ipfire/cgi-bin/rpz.cgi >>>>>>>>>>>>>>>>>>>>>>>> #srv/web/ipfire/cgi-bin/samba.cgi >>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/services.cgi >>>>>>>>>>>>>>>>>>>>>>>> srv/web/ipfire/cgi-bin/shutdown.cgi >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rootfiles/packages/rpz = b/config/rootfiles/packages/rpz >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..1c8663049 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rootfiles/packages/rpz >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,20 @@ >>>>>>>>>>>>>>>>>>>>>>>> +etc/unbound/local.d/00-rpz.conf >>>>>>>>>>>>>>>>>>>>>>>> +etc/unbound/zonefiles >>>>>>>>>>>>>>>>>>>>>>>> +etc/unbound/zonefiles/allow.rpz >>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-config >>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-functions >>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-make >>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-metrics >>>>>>>>>>>>>>>>>>>>>>>> +usr/sbin/rpz-sleep >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.de.pl >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.en.pl >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.es.pl >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.fr.pl >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.it.pl >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/addon-lang/rpz.tr.pl >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/backup/addons/includes/rpz >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/dns/rpz >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/dns/rpz/allowlist >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/dns/rpz/blocklist >>>>>>>>>>>>>>>>>>>>>>>> +var/ipfire/menu.d/EX-rpz.menu >>>>>>>>>>>>>>>>>>>>>>>> +srv/web/ipfire/cgi-bin/rpz.cgi >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/00-rpz.conf = b/config/rpz/00-rpz.conf >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..f005a4f2e >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/00-rpz.conf >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,10 @@ >>>>>>>>>>>>>>>>>>>>>>>> +server: >>>>>>>>>>>>>>>>>>>>>>>> + module-config: "respip validator iterator" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +rpz: >>>>>>>>>>>>>>>>>>>>>>>> + name: allow.rpz >>>>>>>>>>>>>>>>>>>>>>>> + zonefile: /etc/unbound/zonefiles/allow.rpz >>>>>>>>>>>>>>>>>>>>>>>> + rpz-action-override: passthru >>>>>>>>>>>>>>>>>>>>>>>> + rpz-log: yes >>>>>>>>>>>>>>>>>>>>>>>> + rpz-log-name: allow >>>>>>>>>>>>>>>>>>>>>>>> + rpz-signal-nxdomain-ra: yes >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-config = b/config/rpz/rpz-config >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..c72d50f9b >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-config >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,130 @@ >>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024-2025 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +version=3D"2025-01-11 - v44" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +############### Functions ############### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +source /usr/sbin/rpz-functions >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +############### Main ############### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +tagName=3D"unbound" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +rpzAction=3D"${1}" # input RPZ action >>>>>>>>>>>>>>>>>>>>>>>> +rpzName=3D"${2}" # input RPZ name >>>>>>>>>>>>>>>>>>>>>>>> +rpzURL=3D"${3}" # input RPZ URL >>>>>>>>>>>>>>>>>>>>>>>> +rpzOption1=3D"${4}" # input RPZ option #1 >>>>>>>>>>>>>>>>>>>>>>>> +rpzOption2=3D"${5}" # input RPZ option #2 >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> = +rpzConfig=3D"/etc/unbound/local.d/${rpzName}.rpz.conf" # output zone = conf file >>>>>>>>>>>>>>>>>>>>>>>> = +rpzFile=3D"/etc/unbound/zonefiles/${rpzName}.rpz" # output for RPZ file >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +rpzLog=3D"yes" # log default is yes >>>>>>>>>>>>>>>>>>>>>>>> +ucReload=3D"yes" # reload default is yes >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +while [[ $# -gt 0 ]] ; do >>>>>>>>>>>>>>>>>>>>>>>> + case "$1" in >>>>>>>>>>>>>>>>>>>>>>>> + --no-log ) rpzLog=3D"no" ;; >>>>>>>>>>>>>>>>>>>>>>>> + --no-reload ) ucReload=3D"no" ; = checkConf=3D"no" ;; >>>>>>>>>>>>>>>>>>>>>>>> + esac >>>>>>>>>>>>>>>>>>>>>>>> + shift # Shift after checking all the cases to = get next option >>>>>>>>>>>>>>>>>>>>>>>> +done >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +case "${rpzAction}" in >>>>>>>>>>>>>>>>>>>>>>>> + # add new rpz list >>>>>>>>>>>>>>>>>>>>>>>> + add ) >>>>>>>>>>>>>>>>>>>>>>>> + check_name "${rpzName}" # is this a valid = name? >>>>>>>>>>>>>>>>>>>>>>>> + # does this config already exist? If yes, = then exit >>>>>>>>>>>>>>>>>>>>>>>> + if [[ -f "${rpzConfig}" ]] ; then >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: duplicate - ${rpzConfig} = already exists. exit" >>>>>>>>>>>>>>>>>>>>>>>> + exit 104 >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # is this a valid URL? >>>>>>>>>>>>>>>>>>>>>>>> + = regex=3D'^https://[-[:alnum:]\+&@#/%?=3D~_|!:,.;]*[-[:alnum:]\+&@#/%=3D~_|= ]' >>>>>>>>>>>>>>>>>>>>>>>> + if ! [[ "${rpzURL}" =3D~ $regex ]] ; then >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: the URL is not valid: = \"${rpzURL}\". exit." >>>>>>>>>>>>>>>>>>>>>>>> + exit 105 >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # create the zone config file >>>>>>>>>>>>>>>>>>>>>>>> + { >>>>>>>>>>>>>>>>>>>>>>>> + echo "rpz:" >>>>>>>>>>>>>>>>>>>>>>>> + echo " name: ${rpzName}.rpz" >>>>>>>>>>>>>>>>>>>>>>>> + echo " zonefile: ${rpzFile}" >>>>>>>>>>>>>>>>>>>>>>>> + echo " url: ${rpzURL}" >>>>>>>>>>>>>>>>>>>>>>>> + echo " rpz-action-override: nxdomain" >>>>>>>>>>>>>>>>>>>>>>>> + echo " rpz-log: ${rpzLog}" >>>>>>>>>>>>>>>>>>>>>>>> + echo " rpz-log-name: ${rpzName}" >>>>>>>>>>>>>>>>>>>>>>>> + echo " rpz-signal-nxdomain-ra: yes" >>>>>>>>>>>>>>>>>>>>>>>> + } > "${rpzConfig}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # set-up zonefile >>>>>>>>>>>>>>>>>>>>>>>> + # create an empty rpz file if it does not = exist >>>>>>>>>>>>>>>>>>>>>>>> + if [[ ! -f "${rpzFile}" ]] ; then >>>>>>>>>>>>>>>>>>>>>>>> + touch "${rpzFile}" >>>>>>>>>>>>>>>>>>>>>>>> + # unbound requires these settings for rpz = files >>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${rpzFile}" "${rpzConfig}" >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # trash config file & rpz file >>>>>>>>>>>>>>>>>>>>>>>> + remove ) >>>>>>>>>>>>>>>>>>>>>>>> + if ! [[ -f "${rpzConfig}" ]] ; then >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: cannot remove = ${rpzConfig}, does not exist. exit" >>>>>>>>>>>>>>>>>>>>>>>> + exit 106 >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: remove config file & rpz = file \"${rpzName}\"" >>>>>>>>>>>>>>>>>>>>>>>> + rm "${rpzConfig}" >>>>>>>>>>>>>>>>>>>>>>>> + rm "${rpzFile}" >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + reload ) >>>>>>>>>>>>>>>>>>>>>>>> + check_unbound_conf "${checkConf}" >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + list ) >>>>>>>>>>>>>>>>>>>>>>>> + awk -F':' '/^\s*name:/{ = gsub(/[[:blank:]]|\.rpz/, "",$2) ; NAME=3D$2 } \ >>>>>>>>>>>>>>>>>>>>>>>> + /^\s*url:/{ gsub(/[[:blank:]]/, "") ; print = NAME"=3D"$2":"$3} ' \ >>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/local.d/*rpz.conf >>>>>>>>>>>>>>>>>>>>>>>> + exit >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + unbound-restart ) >>>>>>>>>>>>>>>>>>>>>>>> + check_unbound_conf "${checkConf}" >>>>>>>>>>>>>>>>>>>>>>>> + unbound_restart >>>>>>>>>>>>>>>>>>>>>>>> + exit >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + * ) >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: missing or incorrect = parameter" >>>>>>>>>>>>>>>>>>>>>>>> + printf "Usage: $(basename "$0") <ACTION> = <NAME> <URL> <OPTION> <OPTION>\n" >>>>>>>>>>>>>>>>>>>>>>>> + printf "Version: ${version}\n" >>>>>>>>>>>>>>>>>>>>>>>> + exit 108 >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +esac >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +unbound_control_reload "${ucReload}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +exit >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-functions = b/config/rpz/rpz-functions >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..ace1d2690 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-functions >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,85 @@ >>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +version=3D"2024-12-10 - v02" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +############### Functions ############### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +msg_log () { >>>>>>>>>>>>>>>>>>>>>>>> + logger --tag "${tagName}" "$*" >>>>>>>>>>>>>>>>>>>>>>>> + if tty --silent ; then >>>>>>>>>>>>>>>>>>>>>>>> + echo "${tagName}:" "$*" >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# check for a valid name >>>>>>>>>>>>>>>>>>>>>>>> +check_name () { >>>>>>>>>>>>>>>>>>>>>>>> + local theName=3D"${1}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + regex=3D'^[a-zA-Z0-9_]+$' # no dash or plus, = alpha numeric only >>>>>>>>>>>>>>>>>>>>>>>> + regex1=3D'^(allow|block)$' # allow and block = are reserved NAMEs >>>>>>>>>>>>>>>>>>>>>>>> + if [[ ! "${theName}" =3D~ $regex ]] || [[ = "${theName}" =3D~ $regex1 ]] ; then >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: the NAME is not valid: = \"${theName}\". exit." >>>>>>>>>>>>>>>>>>>>>>>> + exit 101 >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +set_permissions () { >>>>>>>>>>>>>>>>>>>>>>>> + chown nobody:nobody "$@" >>>>>>>>>>>>>>>>>>>>>>>> + chmod 644 "$@" >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +check_unbound_conf () { >>>>>>>>>>>>>>>>>>>>>>>> + local thecheckConf=3D"${1:-yes}" # check = config default is yes >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # check the above config files >>>>>>>>>>>>>>>>>>>>>>>> + if [[ "${thecheckConf}" =3D=3D yes ]] ; then >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: check for errors with = \"unbound-checkconf\"" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + if ! unbound-checkconf ; then >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: unbound-checkconf found = invalid configuration." >>>>>>>>>>>>>>>>>>>>>>>> + msg_log \ >>>>>>>>>>>>>>>>>>>>>>>> + "error: rpz: In Terminal run the command = \"unbound-checkconf\" for more information. exit." >>>>>>>>>>>>>>>>>>>>>>>> + exit 102 >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +unbound_control_reload () { >>>>>>>>>>>>>>>>>>>>>>>> + local theReload=3D"${1:-yes}" # reload = default is yes >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + if [[ "${theReload}" =3D=3D yes ]] ; then >>>>>>>>>>>>>>>>>>>>>>>> + # reload due to the changes >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: run \"unbound-control = reload\"" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + if ! unbound-control reload ; then >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: unbound-control reload. = exit." >>>>>>>>>>>>>>>>>>>>>>>> + exit 109 >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +unbound_restart () { >>>>>>>>>>>>>>>>>>>>>>>> + # restart due to the changes >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: run \"unbound restart\"" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + /usr/local/bin/unboundctrl restart >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-make = b/config/rpz/rpz-make >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..927d55170 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-make >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,203 @@ >>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024-2025 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +version=3D"2025-01-11 - v14" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +############### Functions ############### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +source /usr/sbin/rpz-functions >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# create the config file for allow >>>>>>>>>>>>>>>>>>>>>>>> +make_allow_config () { >>>>>>>>>>>>>>>>>>>>>>>> + local theLog=3D"${1:-yes}" # log default ON >>>>>>>>>>>>>>>>>>>>>>>> + local = theConfig=3D"/etc/unbound/local.d/00-rpz.conf" # output zone conf file >>>>>>>>>>>>>>>>>>>>>>>> + local theList=3D"/var/ipfire/dns/rpz/allowlist"= # input custom list of domains >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: make config file = \"00-rpz.conf\"" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + echo "server: >>>>>>>>>>>>>>>>>>>>>>>> + module-config: \"respip validator iterator\"" = > "${theConfig}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # does allow list exist? >>>>>>>>>>>>>>>>>>>>>>>> + if [[ -s "${theList}" ]] && grep -q . = "${theList}" ; then >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + echo "rpz: >>>>>>>>>>>>>>>>>>>>>>>> + name: allow.rpz >>>>>>>>>>>>>>>>>>>>>>>> + zonefile: /etc/unbound/zonefiles/allow.rpz >>>>>>>>>>>>>>>>>>>>>>>> + rpz-action-override: passthru >>>>>>>>>>>>>>>>>>>>>>>> + rpz-log: ${theLog} >>>>>>>>>>>>>>>>>>>>>>>> + rpz-log-name: allow >>>>>>>>>>>>>>>>>>>>>>>> + rpz-signal-nxdomain-ra: yes" >> = "${theConfig}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # set-up zonefile - unbound requires these = settings for rpz files >>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${theConfig}" >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# create the config file for block >>>>>>>>>>>>>>>>>>>>>>>> +make_block_config () { >>>>>>>>>>>>>>>>>>>>>>>> + local theLog=3D"${1:-yes}" # log default ON >>>>>>>>>>>>>>>>>>>>>>>> + local = theConfig=3D"/etc/unbound/local.d/block.rpz.conf" # output zone conf = file >>>>>>>>>>>>>>>>>>>>>>>> + local theList=3D"/var/ipfire/dns/rpz/blocklist"= # input custom list of domains >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: make config file = \"block.rpz.conf\"" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # does block list exist? >>>>>>>>>>>>>>>>>>>>>>>> + if [[ -s "${theList}" ]] && grep -q . = "${theList}" ; then >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + echo "rpz: >>>>>>>>>>>>>>>>>>>>>>>> + name: block.rpz >>>>>>>>>>>>>>>>>>>>>>>> + zonefile: /etc/unbound/zonefiles/block.rpz >>>>>>>>>>>>>>>>>>>>>>>> + rpz-action-override: nxdomain >>>>>>>>>>>>>>>>>>>>>>>> + rpz-log: ${theLog} >>>>>>>>>>>>>>>>>>>>>>>> + rpz-log-name: block >>>>>>>>>>>>>>>>>>>>>>>> + rpz-signal-nxdomain-ra: yes" > "${theConfig}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # set-up zonefile - unbound requires these = settings for rpz files >>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${theConfig}" >>>>>>>>>>>>>>>>>>>>>>>> + else >>>>>>>>>>>>>>>>>>>>>>>> + # no - trash the config file >>>>>>>>>>>>>>>>>>>>>>>> + rm --verbose = /etc/unbound/local.d/block.rpz.conf >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# create an RPZ file for allow or block >>>>>>>>>>>>>>>>>>>>>>>> +make_rpz_file () { >>>>>>>>>>>>>>>>>>>>>>>> + local theName=3D"${1}" # allow or block >>>>>>>>>>>>>>>>>>>>>>>> + local theAction=3D'.' # the default is = nxdomain or block >>>>>>>>>>>>>>>>>>>>>>>> + local actionList >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + local = theList=3D"/var/ipfire/dns/rpz/${theName}list" # input custom list of = domains >>>>>>>>>>>>>>>>>>>>>>>> + local = theZonefile=3D"/etc/unbound/zonefiles/${theName}.rpz" # output file for = RPZ >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # does a list exist? >>>>>>>>>>>>>>>>>>>>>>>> + if [[ -s "${theList}" ]] && grep -q . = "${theList}" ; then >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # for allow set to passthru >>>>>>>>>>>>>>>>>>>>>>>> + [[ "${theName}" =3D=3D allow ]] && = theAction=3D'rpz-passthru.' >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # drop any extra "blanks" and add "CNAME <RPZ = action>." to each line >>>>>>>>>>>>>>>>>>>>>>>> + actionList=3D$( awk '{$1=3D$1};1' = "${theList}" | >>>>>>>>>>>>>>>>>>>>>>>> + sed "/^[^;].*[[:alnum:]]/ s|$| CNAME = ${theAction}|" ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: create zonefile for = \"${theName}list\"" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +echo "; Name: ${theName} list >>>>>>>>>>>>>>>>>>>>>>>> +; Last modified: $(date "+%Y-%m-%d at %H.%M.%S = %Z") >>>>>>>>>>>>>>>>>>>>>>>> +; >>>>>>>>>>>>>>>>>>>>>>>> +; domains with actions list >>>>>>>>>>>>>>>>>>>>>>>> +; >>>>>>>>>>>>>>>>>>>>>>>> +${actionList}" > "${theZonefile}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # set-up zonefile - unbound requires these = settings for rpz files >>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${theZonefile}" >>>>>>>>>>>>>>>>>>>>>>>> + # set-up allow/block list files >>>>>>>>>>>>>>>>>>>>>>>> + set_permissions "${theList}" >>>>>>>>>>>>>>>>>>>>>>>> + else >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "info: rpz: the ${theList} is empty." >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + rm --verbose "${theZonefile}" # trash the RPZ = file >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# check if allow/block list is valid >>>>>>>>>>>>>>>>>>>>>>>> +validate_list () { >>>>>>>>>>>>>>>>>>>>>>>> + local theName=3D"${1}" # allow or block >>>>>>>>>>>>>>>>>>>>>>>> + local = theList=3D"/var/ipfire/dns/rpz/${theName}list" # input custom list of = domains >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # remove good: >>>>>>>>>>>>>>>>>>>>>>>> + # - properly formated domain names with or = without leading wildcard >>>>>>>>>>>>>>>>>>>>>>>> + # - properly formated top level domain (TLD) = names with wildcard >>>>>>>>>>>>>>>>>>>>>>>> + # - blank lines and comment lines >>>>>>>>>>>>>>>>>>>>>>>> + # remaining lines are considered "bad" >>>>>>>>>>>>>>>>>>>>>>>> + bad_lines=3D$( sed --regexp-extended \ >>>>>>>>>>>>>>>>>>>>>>>> + = '/^(\*\.)?([a-zA-Z0-9](([a-zA-Z0-9\-]){0,61}[a-zA-Z0-9])?\.)+([a-zA-Z]{2,}= |xn--[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])$/d ; >>>>>>>>>>>>>>>>>>>>>>>> + /^(\*\.)([a-z]{2,61}|xn--[a-z0-9]{1,60})$/d ; >>>>>>>>>>>>>>>>>>>>>>>> + /^$/d ; /^;/d' "${theList}" ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + if [[ ! -z "${bad_lines}" ]] ; then >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: invalid line(s) in = ${theList}." >>>>>>>>>>>>>>>>>>>>>>>> + printf "%s\n" "bad line(s): ${bad_lines}" >>>>>>>>>>>>>>>>>>>>>>>> + exit 110 >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +############### Main ############### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +tagName=3D"unbound" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +rpzName=3D"${1}" # input RPZ name >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +rpzLog=3D"yes" # log default is yes >>>>>>>>>>>>>>>>>>>>>>>> +ucReload=3D"yes" # reload default is yes >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +while [[ $# -gt 0 ]] ; do >>>>>>>>>>>>>>>>>>>>>>>> + case "$1" in >>>>>>>>>>>>>>>>>>>>>>>> + --no-log ) rpzLog=3D"no" ;; >>>>>>>>>>>>>>>>>>>>>>>> + --no-reload ) ucReload=3D"no" ; = checkConf=3D"no" ;; >>>>>>>>>>>>>>>>>>>>>>>> + esac >>>>>>>>>>>>>>>>>>>>>>>> + shift # Shift after checking all the cases to = get next option >>>>>>>>>>>>>>>>>>>>>>>> +done >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +case "${rpzName}" in >>>>>>>>>>>>>>>>>>>>>>>> + # make a new allow or block rpz file >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + allow ) >>>>>>>>>>>>>>>>>>>>>>>> + validate_list 'allow' # is the allowlist = valid? >>>>>>>>>>>>>>>>>>>>>>>> + make_allow_config "${rpzLog}" >>>>>>>>>>>>>>>>>>>>>>>> + make_rpz_file 'allow' >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + allowblock ) >>>>>>>>>>>>>>>>>>>>>>>> + validate_list 'allow' # is the list valid? >>>>>>>>>>>>>>>>>>>>>>>> + make_allow_config "${rpzLog}" >>>>>>>>>>>>>>>>>>>>>>>> + make_rpz_file 'allow' >>>>>>>>>>>>>>>>>>>>>>>> + ;& >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + block ) >>>>>>>>>>>>>>>>>>>>>>>> + validate_list 'block' # is the blocklist = valid? >>>>>>>>>>>>>>>>>>>>>>>> + make_block_config "${rpzLog}" >>>>>>>>>>>>>>>>>>>>>>>> + make_rpz_file 'block' >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + reload ) >>>>>>>>>>>>>>>>>>>>>>>> + check_unbound_conf "${checkConf}" >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + unbound-restart ) >>>>>>>>>>>>>>>>>>>>>>>> + check_unbound_conf "${checkConf}" >>>>>>>>>>>>>>>>>>>>>>>> + unbound_restart >>>>>>>>>>>>>>>>>>>>>>>> + exit >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + * ) >>>>>>>>>>>>>>>>>>>>>>>> + msg_log "error: rpz: missing or incorrect = parameter" >>>>>>>>>>>>>>>>>>>>>>>> + printf "Usage: $(basename "$0") <NAME> = <OPTION> <OPTION>\n" >>>>>>>>>>>>>>>>>>>>>>>> + printf "Version: ${version}\n" >>>>>>>>>>>>>>>>>>>>>>>> + exit 108 >>>>>>>>>>>>>>>>>>>>>>>> + ;; >>>>>>>>>>>>>>>>>>>>>>>> +esac >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +unbound_control_reload "${ucReload}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +exit >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-metrics = b/config/rpz/rpz-metrics >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100755 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..4d43e1629 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-metrics >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,170 @@ >>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +version=3D"2025-01-20 - v25" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +############### Main ############### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +weeks=3D"2" # default to two message logs >>>>>>>>>>>>>>>>>>>>>>>> +sortBy=3D"name" # default "by name" >>>>>>>>>>>>>>>>>>>>>>>> +rpzActive=3D"enabled" # default "enabled only" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +while [[ $# -gt 0 ]] ; do >>>>>>>>>>>>>>>>>>>>>>>> + case "$1" in >>>>>>>>>>>>>>>>>>>>>>>> + --by-names | --by-name | name ) sortBy=3D"name"= ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + --by-hits | --by-hit | hits | hit ) = sortBy=3D"hit" ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + --by-lines | --by-line | lines | line ) = sortBy=3D"line" ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + --by-effect ) sortBy=3D"effect" ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + --enabled-only ) rpzActive=3D"enabled" ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + --active-all | --all | all ) rpzActive=3D"all" = ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + [0-9] | [0-9][0-9] ) weeks=3D$1 ;; >>>>>>>>>>>>>>>>>>>>>>>> + esac >>>>>>>>>>>>>>>>>>>>>>>> + shift # Shift after checking all the cases to = get next option >>>>>>>>>>>>>>>>>>>>>>>> +done >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# get the list of message logs for N weeks >>>>>>>>>>>>>>>>>>>>>>>> +messageLogs=3D$( find /var/log/messages* -type = f | sort --version-sort | >>>>>>>>>>>>>>>>>>>>>>>> + head -"${weeks}" ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# get the list of RPZ names & counts from the = message log(s) >>>>>>>>>>>>>>>>>>>>>>>> +rpzNameCount=3D$( for logf in ${messageLogs} ; = do >>>>>>>>>>>>>>>>>>>>>>>> + zgrep --text --fixed-strings 'info: rpz: = applied' "${logf}" | >>>>>>>>>>>>>>>>>>>>>>>> + awk '$10 ~ /\[\w*]/ { print $10 }' ; >>>>>>>>>>>>>>>>>>>>>>>> + done | sort | uniq --count ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# flip results and remove brackets `[` and `]` >>>>>>>>>>>>>>>>>>>>>>>> +rpzNameCount=3D$( echo "${rpzNameCount}" | >>>>>>>>>>>>>>>>>>>>>>>> + awk '{ print $2, $1 }' | >>>>>>>>>>>>>>>>>>>>>>>> + sed --regexp-extended 's|^\[(.*)\]|\1|' ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# grab only names >>>>>>>>>>>>>>>>>>>>>>>> +rpzNames=3D$( echo "${rpzNameCount}" | awk '{ = print $1 }' ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# get list of RPZ files >>>>>>>>>>>>>>>>>>>>>>>> +rpzFileList=3D$( find /etc/unbound/zonefiles = -type f -iname "*.rpz" ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# get basename of those files >>>>>>>>>>>>>>>>>>>>>>>> +rpzBaseNames=3D$( echo "${rpzFileList}" | >>>>>>>>>>>>>>>>>>>>>>>> + sed 's|/etc/unbound/zonefiles/||g ; = s|\.rpz||g ;' ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# add to rpzNames >>>>>>>>>>>>>>>>>>>>>>>> +rpzNames=3D"${rpzNames}"$'\n'"${rpzBaseNames}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# drop duplicate names >>>>>>>>>>>>>>>>>>>>>>>> +rpzNames=3D$( echo "${rpzNames}" | sort = --unique ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# get line count for each RPZ >>>>>>>>>>>>>>>>>>>>>>>> +lineCount=3D$( echo "${rpzFileList}" | xargs = wc -l ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# get comment line count and blank line count = for each RPZ >>>>>>>>>>>>>>>>>>>>>>>> +commentCount=3D$( echo "${rpzFileList}" | = xargs grep --count -e "^$" -e "^;" ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# get modified date each RPZ >>>>>>>>>>>>>>>>>>>>>>>> +modDateList=3D$( echo "${rpzFileList}" | xargs = stat -c '%.10y %n' ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +ucListAuthZones=3D$( unbound-control = list_auth_zones ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# get width of RPZ names >>>>>>>>>>>>>>>>>>>>>>>> +pWidth=3D$( echo "${rpzNames}" | awk '{ print = $1" " }' | wc -L ) >>>>>>>>>>>>>>>>>>>>>>>> +pFormat=3D"%-${pWidth}s %-8s %-8s %8s %12s = %12s\n" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# print title line >>>>>>>>>>>>>>>>>>>>>>>> +printf "${pFormat}" "name" "hits" "active" = "lines" " hits/line" "last download" >>>>>>>>>>>>>>>>>>>>>>>> +printf -- "--------------" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +theResults=3D"" >>>>>>>>>>>>>>>>>>>>>>>> +totalLines=3D0 >>>>>>>>>>>>>>>>>>>>>>>> +totalHits=3D0 >>>>>>>>>>>>>>>>>>>>>>>> +while read -r theName >>>>>>>>>>>>>>>>>>>>>>>> +do >>>>>>>>>>>>>>>>>>>>>>>> + printf -- "--" # pretend progress bar >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # is this RPZ list active? >>>>>>>>>>>>>>>>>>>>>>>> + theActive=3D"disabled" >>>>>>>>>>>>>>>>>>>>>>>> + if grep --quiet "^${theName}\.rpz" <<< = "${ucListAuthZones}" >>>>>>>>>>>>>>>>>>>>>>>> + then >>>>>>>>>>>>>>>>>>>>>>>> + theActive=3D"enabled" >>>>>>>>>>>>>>>>>>>>>>>> + else >>>>>>>>>>>>>>>>>>>>>>>> + [[ "${rpzActive}" =3D=3D enabled ]] && = continue >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # get hit count >>>>>>>>>>>>>>>>>>>>>>>> + theHits=3D"0" >>>>>>>>>>>>>>>>>>>>>>>> + if output=3D$( grep "^${theName}\s" <<< = "${rpzNameCount}" ) ; then >>>>>>>>>>>>>>>>>>>>>>>> + theHits=3D$( echo "${output}" | awk '{ print = $2 }' ) >>>>>>>>>>>>>>>>>>>>>>>> + totalHits=3D$(( totalHits + theHits )) >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # get line count >>>>>>>>>>>>>>>>>>>>>>>> + theLines=3D"n/a" >>>>>>>>>>>>>>>>>>>>>>>> + hitsPerLine=3D"0" >>>>>>>>>>>>>>>>>>>>>>>> + if output=3D$( grep --fixed-strings = "/${theName}.rpz" <<< "${lineCount}" ) ; then >>>>>>>>>>>>>>>>>>>>>>>> + theLines=3D$( echo "${output}" | awk '{ print = $1 }' ) >>>>>>>>>>>>>>>>>>>>>>>> + totalLines=3D$(( totalLines + theLines )) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + if [[ "${theLines}" -gt 2 ]] ; then >>>>>>>>>>>>>>>>>>>>>>>> + hitsPerLine=3D$(( 100 * theHits / theLines )) >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # get modification date >>>>>>>>>>>>>>>>>>>>>>>> + theModDate=3D"n/a" >>>>>>>>>>>>>>>>>>>>>>>> + if output=3D$( grep --fixed-strings = "/${theName}.rpz" <<< "${modDateList}" ) ; then >>>>>>>>>>>>>>>>>>>>>>>> + theModDate=3D$( echo "${output}" | awk '{ = print $1 }' ) >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # add to results list >>>>>>>>>>>>>>>>>>>>>>>> + theResults+=3D"${theName} ${theHits} = ${theActive} ${theLines} ${hitsPerLine} ${theModDate}"$'\n' >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +done <<< "${rpzNames}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +case "${sortBy}" in >>>>>>>>>>>>>>>>>>>>>>>> + # sort by "active" then by "name" >>>>>>>>>>>>>>>>>>>>>>>> + name) sortArg=3D(-k3,3r -k1,1) ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # sort by "active" then by "hits" then by = "name" >>>>>>>>>>>>>>>>>>>>>>>> + hit) sortArg=3D(-k3,3r -k2,2nr -k1,1) ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # sort by "active" then by "lines" then by = "name" >>>>>>>>>>>>>>>>>>>>>>>> + line) sortArg=3D(-k3,3r -k4,4nr -k1,1) ;; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # sort by "active" then by "effect" then by = "name" >>>>>>>>>>>>>>>>>>>>>>>> + effect) sortArg=3D(-k3,3r -k5,5nr -k1,1) ;; >>>>>>>>>>>>>>>>>>>>>>>> +esac >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +printf -- "--------------\n" >>>>>>>>>>>>>>>>>>>>>>>> +# remove blank lines, sort, print as columns >>>>>>>>>>>>>>>>>>>>>>>> +echo "${theResults}" | >>>>>>>>>>>>>>>>>>>>>>>> + awk '!/^[[:space:]]*$/' | >>>>>>>>>>>>>>>>>>>>>>>> + sort "${sortArg[@]}" | >>>>>>>>>>>>>>>>>>>>>>>> + awk --assign=3Dwidth=3D"${pWidth}" \ >>>>>>>>>>>>>>>>>>>>>>>> + '{ printf "%-*s %-8s %-8s %8s %10s %% = %12s\n", width, $1, $2, $3, $4, $5, $6 }' >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +printf "${pFormat}" "" "=3D=3D=3D=3D=3D=3D=3D" = "" "=3D=3D=3D=3D=3D=3D=3D=3D" "" "" >>>>>>>>>>>>>>>>>>>>>>>> +printf "${pFormat}" "Totals -->" = "${totalHits}" "" "${totalLines}" "" "" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +exit >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz-sleep = b/config/rpz/rpz-sleep >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100755 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..dd3603599 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz-sleep >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,58 @@ >>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +version=3D"2024-08-16" # v05 >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +############### Functions ############### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# send message to message log >>>>>>>>>>>>>>>>>>>>>>>> +msg_log () { >>>>>>>>>>>>>>>>>>>>>>>> + logger --tag "${tagName}" "$*" >>>>>>>>>>>>>>>>>>>>>>>> + if tty --silent ; then >>>>>>>>>>>>>>>>>>>>>>>> + echo "${tagName}:" "$*" >>>>>>>>>>>>>>>>>>>>>>>> + fi >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +############### Main ############### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +tagName=3D"unbound" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +sleepTime=3D"${1:-5m}" # default to sleep for = 5m (5 minutes) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +zoneList=3D$( unbound-control list_auth_zones = | awk '{print $1}' ) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +for zone in ${zoneList} ; do >>>>>>>>>>>>>>>>>>>>>>>> + printf "disable ${zone}\t" >>>>>>>>>>>>>>>>>>>>>>>> + unbound-control rpz_disable "${zone}" >>>>>>>>>>>>>>>>>>>>>>>> +done >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +msg_log "info: rpz: disabled all zones for = ${sleepTime}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +sleep "${sleepTime}" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +for zone in ${zoneList} ; do >>>>>>>>>>>>>>>>>>>>>>>> + printf "enable ${zone}\t" >>>>>>>>>>>>>>>>>>>>>>>> + unbound-control rpz_enable "${zone}" >>>>>>>>>>>>>>>>>>>>>>>> +done >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +msg_log "info: rpz: enabled all zones" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +exit >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.de.pl = b/config/rpz/rpz.de.pl >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..3770c6bb0 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.de.pl >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@ >>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ) add-on >>>>>>>>>>>>>>>>>>>>>>>> +%tr =3D (%tr, >>>>>>>>>>>>>>>>>>>>>>>> +'rpz' =3D> 'Response Policy Zones (RPZ)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' =3D> '=C3=9Cbernehmen', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' =3D> 'Benutzerdefinierte = Allowlist aktivieren:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' =3D> 'Zugelassene Domains = (eine pro Zeile)<br>Beispiel: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' =3D> 'Benutzerdefinierte = Allowlist', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' =3D> 'Benutzerdefinierte = Blocklist aktivieren:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' =3D> 'Gesperrte Domains = (eine pro Zeile)<br>Beispiel: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' =3D> 'Benutzerdefinierte = Blocklist', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' =3D> 'Benutzerdefinierte Listen', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' =3D> 'Der Name enth=C3=A4lt = unzul=C3=A4ssige Zeichen', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' =3D> 'unbound-checkconf hat = eine fehlerhafte Konfiguration ermittelt. F=C3=BChren Sie das Kommando = unbound-checkconf auf der Konsole aus, um weitere Informationen zu = erhalten.', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' =3D> 'Die = benutzerdefinierte Allow-/Blocklist ist leer', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' =3D> 'Ein Eintrag mit = identischem Namen existiert bereits', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' =3D> 'Die URL ist = ung=C3=BCltig', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' =3D> 'Eintrag kann nicht = entfernt werden, der Name existiert nicht', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' =3D> 'Der Name ist = ung=C3=BCltig - nur "allow" oder "block" m=C3=B6glich', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' =3D> 'Fehlende oder = inkorrekte Parameter', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' =3D> 'unbound-control = reload ist fehlgeschlagen', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' =3D> 'Die = benutzerdefinierte Allow-/Blocklist enth=C3=A4lt unzul=C3=A4ssige = Eintr=C3=A4ge', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' =3D> 'Die Anmerkung = enth=C3=A4lt unzul=C3=A4ssige Zeichen', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' =3D> 'Ung=C3=BCltiger = Eintrag in der benutzerdefinierten Allowlist, Zeile ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' =3D> 'Ung=C3=BCltiger = Eintrag in der benutzerdefinierten Blocklist, Zeile ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' =3D> 'Ausgew=C3=A4hlter = Eintrag existiert nicht: ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' =3D> 'Zonendatei-Eintrag = bearbeiten', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' =3D> '(importiert aus = rpz-config)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' =3D> 'Erlaubte Zeichen = sind a-z, A-Z, 0-9 und Unterstriche', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' =3D> 'Zonendateien', >>>>>>>>>>>>>>>>>>>>>>>> +); >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.en.pl = b/config/rpz/rpz.en.pl >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..0720a8940 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.en.pl >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@ >>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ) add-on >>>>>>>>>>>>>>>>>>>>>>>> +%tr =3D (%tr, >>>>>>>>>>>>>>>>>>>>>>>> +'rpz' =3D> 'Response Policy Zones (RPZ)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' =3D> 'Apply', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' =3D> 'Enable custom = allowlist:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' =3D> 'Allowed domains (one = per line)<br>Example: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' =3D> 'Custom allowlist', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' =3D> 'Enable custom = blocklist:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' =3D> 'Blocked domains (one = per line)<br>Example: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' =3D> 'Custom blocklist', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' =3D> 'Custom lists', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' =3D> 'the NAME is not = valid', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' =3D> 'unbound-checkconf = found invalid configuration. In the Terminal run the command = unbound-checkconf for more information', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' =3D> 'the allow/block list = is empty', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' =3D> 'duplicate - NAME = already exists', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' =3D> 'the URL is not = valid', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' =3D> 'cannot remove the = NAME does not exist', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' =3D> 'the NAME is not valid = - "allow" or "block" only', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' =3D> 'missing or incorrect = parameter', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' =3D> 'unbound-control = reload failed', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' =3D> 'custom = Allowlist/Blocklist contains invalid entries', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' =3D> 'the REMARK is not = valid', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' =3D> 'invalid entry in = allowlist, line ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' =3D> 'invalid entry in = blocklist, line ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' =3D> 'Selected entry does = not exist: ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' =3D> 'Edit zonefiles entry', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' =3D> '(imported from = rpz-config)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' =3D> 'Valid characters = are a-z, A-Z, 0-9 and underscore.', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' =3D> 'Zonefiles', >>>>>>>>>>>>>>>>>>>>>>>> +); >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.es.pl = b/config/rpz/rpz.es.pl >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..98628e4aa >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.es.pl >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@ >>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ) add-on >>>>>>>>>>>>>>>>>>>>>>>> +%tr =3D (%tr, >>>>>>>>>>>>>>>>>>>>>>>> +'rpz' =3D> 'Zonas de pol=C3=ADtica de = respuesta (RPZ)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' =3D> 'Aplicar', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' =3D> 'Habilitar la lista = blanca personalizada:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' =3D> 'Dominio permitido = (uno por l=C3=ADnea)<br>Ejemplo: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' =3D> 'Lista blanca = personalizada', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' =3D> 'Habilitar la lista = negra personalizada:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' =3D> 'Dominio bloqueado = (uno por l=C3=ADnea)<br>Ejemplo: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' =3D> 'Lista negra = personalizada', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' =3D> 'Lista personalizada', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' =3D> 'El NOMBRE no es = v=C3=A1lido', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' =3D> 'unbound-checkconf ha = encontrado una configuraci=C3=B3n no v=C3=A1lida. Desde Terminal, = ejecute el comando unbound-checkconf para mayor informaci=C3=B3n', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' =3D> 'La lista de = permitidos/bloqueados est=C3=A1 vac=C3=ADa', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' =3D> 'duplicado - NOMBRE ya = existe', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' =3D> 'la URL no es = v=C3=A1lida', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' =3D> 'no es posible = eliminar el NOMBRE que no existe', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' =3D> 'el NOMBRE no es = v=C3=A1lido - s=C3=B3lo "permitir" o "bloquear"', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' =3D> 'par=C3=A1metro = faltante o incorrecto', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' =3D> 'Error al recargar = unbound-control', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' =3D> 'la Lista blanca/Lista = negra personalizada contiene entradas no v=C3=A1lidas', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' =3D> 'el COMENTARIO no es = v=C3=A1lido', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' =3D> 'entrada no v=C3=A1lida = en la lista blanca, l=C3=ADnea ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' =3D> 'entrada no v=C3=A1lida = en la lista negra, l=C3=ADnea ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' =3D> 'La entrada = seleccionada no existe: ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' =3D> 'Editar la entrada de = archivos de zona', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' =3D> '(importado de = rpz-config)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' =3D> 'Los caracteres = v=C3=A1lidos son a-z, A-Z, 0-9 y gui=C3=B3n bajo', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' =3D> 'Archivos de zona', >>>>>>>>>>>>>>>>>>>>>>>> +); >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.fr.pl = b/config/rpz/rpz.fr.pl >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..f35f3c2d0 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.fr.pl >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@ >>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ) add-on >>>>>>>>>>>>>>>>>>>>>>>> +%tr =3D (%tr, >>>>>>>>>>>>>>>>>>>>>>>> +'rpz' =3D> 'Response Policy Zones (RPZ)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' =3D> 'Appliquer', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' =3D> 'Activer la liste = d\'autorisations personnalis=C3=A9e:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' =3D> 'Domaines autoris=C3=A9= s (un par ligne)<br>Example: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' =3D> 'Liste d\'autorisations = personnalis=C3=A9e', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' =3D> 'Activer la liste = de blocage personnalis=C3=A9e:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' =3D> 'Domaines bloqu=C3=A9s = (un par ligne)<br>Example: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' =3D> 'liste de blocage = personnalis=C3=A9', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' =3D> 'Listes personnalis=C3=A9es', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' =3D> 'le NOM n\'est pas = valide', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' =3D> 'unbound-checkconf = configuration non valide trouv=C3=A9e. Dans le terminal, ex=C3=A9cutez = la commande unbound-checkconf pour plus d\'informations', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' =3D> 'la liste = autoriser/bloquer est vide', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' =3D> 'le NOM existe = d=C3=A9j=C3=A0', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' =3D> 'L\'URL n\'est pas = valide', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' =3D> 'impossible de = supprimer le NOM n\'existe pas', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' =3D> 'le NOM n\'est pas = valide - =C2=AB autoriser =C2=BB ou =C2=AB bloquer =C2=BB seulement', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' =3D> 'param=C3=A8tre = manquant ou incorrect', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' =3D> 'unbound-control = rechargement =C3=A9chou=C3=A9', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' =3D> 'la liste = autoriser/bloquer contient des entr=C3=A9es non valides', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' =3D> 'la REMARQUE n\'est = pas valable', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' =3D> 'entr=C3=A9e non = valide dans la liste d\'autorisation, ligne ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' =3D> 'entr=C3=A9e non = valide dans la liste de blocs, ligne ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' =3D> 'L\'entr=C3=A9e = s=C3=A9lectionn=C3=A9e n\'existe pas: ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' =3D> 'Modifier l\'entr=C3=A9e = Fichiers Zone', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' =3D> '(import=C3=A9 de = rpz-config)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' =3D> 'Les caract=C3=A8res = valides sont a-z, A-Z, 0-9 et soulignement.', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' =3D> 'Fichiers Zone', >>>>>>>>>>>>>>>>>>>>>>>> +); >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.it.pl = b/config/rpz/rpz.it.pl >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..ee81605c9 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.it.pl >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@ >>>>>>>>>>>>>>>>>>>>>>>> +# Added for Response Policy Zone (RPZ) add-on >>>>>>>>>>>>>>>>>>>>>>>> +%tr =3D (%tr, >>>>>>>>>>>>>>>>>>>>>>>> +'rpz' =3D> 'Response Policy Zones (RPZ)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' =3D> 'Applica', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' =3D> 'Abilita la = Whitelist personalizzata:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' =3D> 'Domini consentiti = (uno per riga)<br>Esempio: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' =3D> 'Whitelist = personalizzata', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' =3D> 'Abilita la = Blacklist personalizzata:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' =3D> 'Domini bloccati (uno = per riga)<br>Esempio: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' =3D> 'Blacklist = personalizzata', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' =3D> 'Liste personalizzate', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' =3D> 'il NOME non =C3=A8 = valido', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' =3D> 'unbound-checkconf ha = trovato una configurazione non valida. Dal Terminale esegui il comando = unbound-checkconf per maggiori informazioni', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' =3D> 'l\'elenco = consentiti/bloccati =C3=A8 vuoto', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' =3D> 'duplicato - NAME = esiste di gi=C3=A0', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' =3D> 'l\'URL non =C3=A8 = valido', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' =3D> 'non =C3=A8 possibile = rimuovere il NOME non esiste', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' =3D> 'il NOME non =C3=A8 = valido - solo "consenti" o "blocca"', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' =3D> 'parametro mancante o = non corretto', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' =3D> 'ricaricamento del = controllo non associato non riuscito', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' =3D> 'la = Whitelist/Blacklist personalizzata contiene voci non valide', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' =3D> 'l"OSSERVAZIONE non =C3=A8= valida', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' =3D> 'voce non valida nella = Whitelist, riga ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' =3D> 'voce non valida nella = Blacklist, riga ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' =3D> 'La voce selezionata = non esiste: ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' =3D> 'Modifica la voce dei = file di zona', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' =3D> '(importato da = rpz-config)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' =3D> 'I caratteri validi = sono a-z, A-Z, 0-9 e trattino basso', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' =3D> 'Zonefiles', >>>>>>>>>>>>>>>>>>>>>>>> +); >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/config/rpz/rpz.tr.pl = b/config/rpz/rpz.tr.pl >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..00226e192 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/config/rpz/rpz.tr.pl >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,30 @@ >>>>>>>>>>>>>>>>>>>>>>>> +# I=EF=BF=BDin eklendi Ayriyeten Response = Policy Zone (RPZ) >>>>>>>>>>>>>>>>>>>>>>>> +%tr =3D (%tr, >>>>>>>>>>>>>>>>>>>>>>>> +'rpz' =3D> 'Response Policy Zones (RPZ)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz apply' =3D> 'Uygulamak', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow enable' =3D> '=EF=BF=BDzel = Etkinlestir allowlist:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow info' =3D> 'Izin verilmis = domains (satir basina bir)<br>=EF=BF=BDrnegin: domain.com, = *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl allow' =3D> 'Etkinlestir allowlist', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block enable' =3D> '=EF=BF=BDzel = Etkinlestir blocklist:', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block info' =3D> 'Engellenmis domains = (satir basina bir)<br>=EF=BF=BDrnegin: domain.com, *.domain.com', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl block' =3D> 'Engellenmis blocklist', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz cl' =3D> 'Engellenmis lists', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 101' =3D> 'NAME ge=EF=BF=BDerli = degil', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 102' =3D> 'unbound-checkconf = ge=EF=BF=BDersiz yapilandirma bulundu. Terminalde daha fazla bilgi = i=EF=BF=BDin Unbound-checkConf komutunu =EF=BF=BDalistirin', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 103' =3D> 'allow/block liste = bos', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 104' =3D> 'kopyalamak - NAME = zaten var', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 105' =3D> 'URL ge=EF=BF=BDerli = degil', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 106' =3D> '=EF=BF=BDikarilamiyor = NAME yok', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 107' =3D> 'NAME ge=EF=BF=BDerli = degil - "allow" veya "block" yalniz', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 108' =3D> 'Parametre eksik veya = yanlis', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 109' =3D> 'unbound-control = basarisiz', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 110' =3D> 'Engellenmis = Allowlist/Blocklist ge=EF=BF=BDersiz girisler i=EF=BF=BDerir', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 201' =3D> 'REMARK ge=EF=BF=BDerli = degil', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 202' =3D> 'Ge=EF=BF=BDersiz = giris allowlist, line ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 203' =3D> 'Ge=EF=BF=BDersiz = giris blocklist, line ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz exitcode 204' =3D> 'Se=EF=BF=BDilen giris = yok: ', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf editor' =3D> 'yazimlamak zonefiles = giris', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf imported' =3D> '(ithal edildi = rpz-config)', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf remark info' =3D> 'Ge=EF=BF=BDerli = karakterler a-z, A-Z, 0-9ve alt=EF=BF=BDst.', >>>>>>>>>>>>>>>>>>>>>>>> +'rpz zf' =3D> 'Zonefiles', >>>>>>>>>>>>>>>>>>>>>>>> +); >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/html/cgi-bin/rpz.cgi = b/html/cgi-bin/rpz.cgi >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..a821c92ac >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/html/cgi-bin/rpz.cgi >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,923 @@ >>>>>>>>>>>>>>>>>>>>>>>> +#!/usr/bin/perl >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2005-2024 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +use strict; >>>>>>>>>>>>>>>>>>>>>>>> +use Scalar::Util qw(looks_like_number); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# debugging >>>>>>>>>>>>>>>>>>>>>>>> +#use warnings; >>>>>>>>>>>>>>>>>>>>>>>> +#use CGI::Carp 'fatalsToBrowser'; >>>>>>>>>>>>>>>>>>>>>>>> +#use Data::Dumper; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +require '/var/ipfire/general-functions.pl'; >>>>>>>>>>>>>>>>>>>>>>>> +require "${General::swroot}/lang.pl"; >>>>>>>>>>>>>>>>>>>>>>>> +require "${General::swroot}/header.pl"; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +###--- Extra HTML ---### >>>>>>>>>>>>>>>>>>>>>>>> +my $extraHead =3D <<END >>>>>>>>>>>>>>>>>>>>>>>> +<style> >>>>>>>>>>>>>>>>>>>>>>>> + /* alternating row background */ >>>>>>>>>>>>>>>>>>>>>>>> + .tbl tr:nth-child(2n+2) { >>>>>>>>>>>>>>>>>>>>>>>> + background-color: var(--color-light-grey); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + .tbl tr:nth-child(2n+3) { >>>>>>>>>>>>>>>>>>>>>>>> + background-color: var(--color-grey); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + /* text styles */ >>>>>>>>>>>>>>>>>>>>>>>> + .tbl th:not(:last-child) { >>>>>>>>>>>>>>>>>>>>>>>> + text-align: left; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + div.right { >>>>>>>>>>>>>>>>>>>>>>>> + text-align: right; >>>>>>>>>>>>>>>>>>>>>>>> + margin-top: 0.5em; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + /* customlist input */ >>>>>>>>>>>>>>>>>>>>>>>> + textarea.domainlist { >>>>>>>>>>>>>>>>>>>>>>>> + margin: 0.5em 0; >>>>>>>>>>>>>>>>>>>>>>>> + resize: vertical; >>>>>>>>>>>>>>>>>>>>>>>> + min-height: 10em; >>>>>>>>>>>>>>>>>>>>>>>> + overflow: auto; >>>>>>>>>>>>>>>>>>>>>>>> + white-space: pre; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + button[type=3Dsubmit]:disabled { >>>>>>>>>>>>>>>>>>>>>>>> + opacity: 0.6; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> +</style> >>>>>>>>>>>>>>>>>>>>>>>> +END >>>>>>>>>>>>>>>>>>>>>>>> +; >>>>>>>>>>>>>>>>>>>>>>>> +###--- End of extra HTML ---### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +### Settings ### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Request DNS service reload after = configuration change >>>>>>>>>>>>>>>>>>>>>>>> +my $RPZ_RELOAD_FLAG =3D = "${General::swroot}/dns/rpz/reload.flag"; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Configuration file for all available = zonefiles >>>>>>>>>>>>>>>>>>>>>>>> +# Format: index, name (unique), enabled = (on/off), URL, remark >>>>>>>>>>>>>>>>>>>>>>>> +my $ZONEFILES_CONF =3D = "${General::swroot}/dns/rpz/zonefiles.conf"; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Configuration file for custom lists >>>>>>>>>>>>>>>>>>>>>>>> +# IDs: 0=3Dallowlist, 1=3Dblocklist, 2=3Doptions= (allow/block enabled) >>>>>>>>>>>>>>>>>>>>>>>> +my $CUSTOMLISTS_CONF =3D = "${General::swroot}/dns/rpz/customlists.conf"; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Export custom lists to rpz-config >>>>>>>>>>>>>>>>>>>>>>>> +my $RPZ_ALLOWLIST =3D = "${General::swroot}/dns/rpz/allowlist"; >>>>>>>>>>>>>>>>>>>>>>>> +my $RPZ_BLOCKLIST =3D = "${General::swroot}/dns/rpz/blocklist"; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +### Preparation ### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Create missing config files >>>>>>>>>>>>>>>>>>>>>>>> +unless(-f $ZONEFILES_CONF) { = &General::system('touch', "$ZONEFILES_CONF"); } >>>>>>>>>>>>>>>>>>>>>>>> +unless(-f $CUSTOMLISTS_CONF) { = &General::system('touch', "$CUSTOMLISTS_CONF"); } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +## Global gui data >>>>>>>>>>>>>>>>>>>>>>>> +my $errormessage =3D ""; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +## Global configuration data >>>>>>>>>>>>>>>>>>>>>>>> +my %zonefiles =3D (); >>>>>>>>>>>>>>>>>>>>>>>> +my %customlists =3D (); >>>>>>>>>>>>>>>>>>>>>>>> +&_zonefiles_load(); >>>>>>>>>>>>>>>>>>>>>>>> +&_customlists_load(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +## Global CGI form data >>>>>>>>>>>>>>>>>>>>>>>> +my %cgiparams =3D (); >>>>>>>>>>>>>>>>>>>>>>>> +&Header::getcgihash(\%cgiparams); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +my $action =3D $cgiparams{'ACTION'} // 'NONE'; >>>>>>>>>>>>>>>>>>>>>>>> +my $action_key =3D $cgiparams{'KEY'} // ''; # = entry being edited, empty =3D none/new >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +###--- Process form actions ---### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Zonefiles action: Check whether the = requested entry exists >>>>>>>>>>>>>>>>>>>>>>>> +if((substr($action, 0, 3) eq 'ZF_') && = ($action_key)) { >>>>>>>>>>>>>>>>>>>>>>>> + unless(defined $zonefiles{$action_key}) { >>>>>>>>>>>>>>>>>>>>>>>> + $errormessage =3D &_rpz_error_tr(204, = $action_key); >>>>>>>>>>>>>>>>>>>>>>>> + $action =3D 'NONE'; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +## Perform actions >>>>>>>>>>>>>>>>>>>>>>>> +if($action eq 'ZF_SAVE') { ## Save new or = modified zonefiles entry >>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_zf_save()) { >>>>>>>>>>>>>>>>>>>>>>>> + $action =3D 'NONE'; # success, return to main = page >>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect(); >>>>>>>>>>>>>>>>>>>>>>>> + } else { >>>>>>>>>>>>>>>>>>>>>>>> + $action =3D 'ZF_EDIT'; # error occured, keep = editing >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'ZF_TOGGLE') { ## Toggle = on/off >>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_zf_toggle()) { >>>>>>>>>>>>>>>>>>>>>>>> + $action =3D 'NONE'; >>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'ZF_REMOVE') { ## Remove = entry >>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_zf_remove()) { >>>>>>>>>>>>>>>>>>>>>>>> + $action =3D 'NONE'; >>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'CL_SAVE') { ## Save custom = lists >>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_cl_save()) { >>>>>>>>>>>>>>>>>>>>>>>> + $action =3D 'NONE'; >>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'RPZ_RELOAD') { ## Reload = dns configuration >>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_rpz_reload()) { >>>>>>>>>>>>>>>>>>>>>>>> + $action =3D 'NONE'; >>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +} elsif($action eq 'UNB_RESTART') { ## Restart = unbound service >>>>>>>>>>>>>>>>>>>>>>>> + if(&_action_unb_restart()) { >>>>>>>>>>>>>>>>>>>>>>>> + $action =3D 'NONE'; >>>>>>>>>>>>>>>>>>>>>>>> + &_http_prg_redirect(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +###--- Start GUI ---### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +## Start http output >>>>>>>>>>>>>>>>>>>>>>>> +&Header::showhttpheaders(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Start HTML >>>>>>>>>>>>>>>>>>>>>>>> +&Header::openpage($Lang::tr{'rpz'}, 1, = $extraHead); >>>>>>>>>>>>>>>>>>>>>>>> +&Header::openbigbox('100%', 'left', ''); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Show error messages >>>>>>>>>>>>>>>>>>>>>>>> +if($errormessage) { >>>>>>>>>>>>>>>>>>>>>>>> + &_print_message($errormessage); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Handle zonefile add/edit mode >>>>>>>>>>>>>>>>>>>>>>>> +if($action eq "ZF_EDIT") { >>>>>>>>>>>>>>>>>>>>>>>> + &_print_zonefile_editor(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Finalize page and exit cleanly >>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebigbox(); >>>>>>>>>>>>>>>>>>>>>>>> + &Header::closepage(); >>>>>>>>>>>>>>>>>>>>>>>> + exit(0); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Show gui elements >>>>>>>>>>>>>>>>>>>>>>>> +&_print_zonefiles(); >>>>>>>>>>>>>>>>>>>>>>>> +&_print_customlists(); >>>>>>>>>>>>>>>>>>>>>>>> +&_print_gui_extras(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +&Header::closebigbox(); >>>>>>>>>>>>>>>>>>>>>>>> +&Header::closepage(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +###--- End of GUI ---### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal configuration file functions = ---### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Load all available zonefiles from rpz-config = and the internal configuration >>>>>>>>>>>>>>>>>>>>>>>> +sub _zonefiles_load { >>>>>>>>>>>>>>>>>>>>>>>> + # Clean start >>>>>>>>>>>>>>>>>>>>>>>> + %zonefiles =3D (); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Source 1: Get the currently enabled = zonefiles from rpz-config (expected format [name]=3D[URL]) >>>>>>>>>>>>>>>>>>>>>>>> + my @enabled_files =3D = &General::system_output('/usr/sbin/rpz-config', 'list'); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + foreach my $row (@enabled_files) { >>>>>>>>>>>>>>>>>>>>>>>> + chomp($row); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Use regex instead of split() to skip = non-matching lines >>>>>>>>>>>>>>>>>>>>>>>> + next unless($row =3D~ /^(\w+)=3D(.+)$/); >>>>>>>>>>>>>>>>>>>>>>>> + my ($name, $url) =3D ($1, $2); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Unique names are already guaranteed by = rpz-config >>>>>>>>>>>>>>>>>>>>>>>> + if(&_rpz_validate_zonefile($name, $url, '', = 0) =3D=3D 0) { >>>>>>>>>>>>>>>>>>>>>>>> + # Populate global data hash, mark all found = entries as enabled >>>>>>>>>>>>>>>>>>>>>>>> + my %entry =3D ('enabled' =3D> 'on', >>>>>>>>>>>>>>>>>>>>>>>> + 'url' =3D> $url, >>>>>>>>>>>>>>>>>>>>>>>> + 'remark' =3D> $Lang::tr{'rpz zf imported'}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name} =3D \%entry; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Source 2: Get additional data and disabled = entries from configuration file >>>>>>>>>>>>>>>>>>>>>>>> + my %configured_files =3D (); >>>>>>>>>>>>>>>>>>>>>>>> + &General::readhasharray($ZONEFILES_CONF, = \%configured_files); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + foreach my $row (values (%configured_files)) = { >>>>>>>>>>>>>>>>>>>>>>>> + my ($name, $enabled, $url, $remark) =3D = @$row; >>>>>>>>>>>>>>>>>>>>>>>> + $remark //=3D ""; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + next unless($name); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Check whether this row belongs to an entry = already imported from rpz-config >>>>>>>>>>>>>>>>>>>>>>>> + if(defined $zonefiles{$name}) { >>>>>>>>>>>>>>>>>>>>>>>> + # Existing entry, only merge additional data >>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name}{'remark'} =3D $remark; >>>>>>>>>>>>>>>>>>>>>>>> + } else { >>>>>>>>>>>>>>>>>>>>>>>> + # Skip entry if it is marked as enabled but = not found by rpz-config. It was then deleted manually >>>>>>>>>>>>>>>>>>>>>>>> + if($enabled ne 'on') { >>>>>>>>>>>>>>>>>>>>>>>> + # Populate global data hash >>>>>>>>>>>>>>>>>>>>>>>> + my %entry =3D ('enabled' =3D> 'off', >>>>>>>>>>>>>>>>>>>>>>>> + 'url' =3D> $url // "", >>>>>>>>>>>>>>>>>>>>>>>> + 'remark' =3D> $remark); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name} =3D \%entry; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Save internal zonefiles configuration >>>>>>>>>>>>>>>>>>>>>>>> +sub _zonefiles_save_conf { >>>>>>>>>>>>>>>>>>>>>>>> + my $index =3D 0; >>>>>>>>>>>>>>>>>>>>>>>> + my %export =3D (); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Loop trough all zonefiles and create = "hasharray" type export >>>>>>>>>>>>>>>>>>>>>>>> + foreach my $name (keys %zonefiles) { >>>>>>>>>>>>>>>>>>>>>>>> + my @entry =3D ($name, >>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name}{'enabled'}, >>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name}{'url'}, >>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name}{'remark'}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + $export{$index++} =3D \@entry; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + &General::writehasharray($ZONEFILES_CONF, = \%export); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Load custom lists from rpz-config and the = internal configuration >>>>>>>>>>>>>>>>>>>>>>>> +sub _customlists_load { >>>>>>>>>>>>>>>>>>>>>>>> + # Clean start >>>>>>>>>>>>>>>>>>>>>>>> + %customlists =3D (); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Load configuration file >>>>>>>>>>>>>>>>>>>>>>>> + my %lists_conf =3D (); >>>>>>>>>>>>>>>>>>>>>>>> + &General::readhasharray($CUSTOMLISTS_CONF, = \%lists_conf); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Get list options, enabled by default to = start import >>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'allow'}{'enabled'} =3D = $lists_conf{2}[0] // 'on'; >>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'block'}{'enabled'} =3D = $lists_conf{2}[1] // 'on'; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Import enabled list from rpz-config, = otherwise retrieve stored or empty list from configuration file >>>>>>>>>>>>>>>>>>>>>>>> + if($customlists{'allow'}{'enabled'} eq 'on') = { >>>>>>>>>>>>>>>>>>>>>>>> + &_customlist_import('allow', $RPZ_ALLOWLIST); >>>>>>>>>>>>>>>>>>>>>>>> + } else { >>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'allow'}{'list'} =3D = $lists_conf{0} // []; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + if($customlists{'block'}{'enabled'} eq 'on') = { >>>>>>>>>>>>>>>>>>>>>>>> + &_customlist_import('block', $RPZ_BLOCKLIST); >>>>>>>>>>>>>>>>>>>>>>>> + } else { >>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'block'}{'list'} =3D = $lists_conf{1} // []; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Save internal custom lists configuration >>>>>>>>>>>>>>>>>>>>>>>> +sub _customlists_save_conf { >>>>>>>>>>>>>>>>>>>>>>>> + my %export =3D (); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Match IDs with import function >>>>>>>>>>>>>>>>>>>>>>>> + $export{0} =3D $customlists{'allow'}{'list'}; >>>>>>>>>>>>>>>>>>>>>>>> + $export{1} =3D $customlists{'block'}{'list'}; >>>>>>>>>>>>>>>>>>>>>>>> + $export{2} =3D = [$customlists{'allow'}{'enabled'}, $customlists{'block'}{'enabled'}]; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + &General::writehasharray($CUSTOMLISTS_CONF, = \%export); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Import a custom list from plain file, = returns empty list if file is missing >>>>>>>>>>>>>>>>>>>>>>>> +sub _customlist_import { >>>>>>>>>>>>>>>>>>>>>>>> + my ($listname, $filename) =3D @_; >>>>>>>>>>>>>>>>>>>>>>>> + my @list =3D (); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # File exists, load and check all lines >>>>>>>>>>>>>>>>>>>>>>>> + if(-f $filename) { >>>>>>>>>>>>>>>>>>>>>>>> + open(my $FH, '<', $filename) or die "Can't = read $filename: $!"; >>>>>>>>>>>>>>>>>>>>>>>> + while(my $line =3D <$FH>) { >>>>>>>>>>>>>>>>>>>>>>>> + chomp($line); >>>>>>>>>>>>>>>>>>>>>>>> + push(@list, $line); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + close($FH); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Clean up imported data >>>>>>>>>>>>>>>>>>>>>>>> + &_rpz_validate_customlist(\@list, 1); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + $customlists{$listname}{'list'} =3D \@list; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Export a custom list to plain file or clear = file if list is disabled >>>>>>>>>>>>>>>>>>>>>>>> +sub _customlist_export { >>>>>>>>>>>>>>>>>>>>>>>> + my ($listname, $filename) =3D @_; >>>>>>>>>>>>>>>>>>>>>>>> + return unless(defined = $customlists{$listname}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Write enabled domain list to file, = otherwise save empty file >>>>>>>>>>>>>>>>>>>>>>>> + open(my $FH, '>', $filename) or die "Can't = write $filename: $!"; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + if($customlists{$listname}{'enabled'} eq = 'on') { >>>>>>>>>>>>>>>>>>>>>>>> + foreach my $line = (@{$customlists{$listname}{'list'}}) { >>>>>>>>>>>>>>>>>>>>>>>> + print $FH "$line\n"; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } else { >>>>>>>>>>>>>>>>>>>>>>>> + print $FH "; Note: This list is currently = disabled by $ENV{'SCRIPT_NAME'}\n"; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + close($FH); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal gui functions ---### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Show simple message box >>>>>>>>>>>>>>>>>>>>>>>> +sub _print_message { >>>>>>>>>>>>>>>>>>>>>>>> + my ($message, $title) =3D @_; >>>>>>>>>>>>>>>>>>>>>>>> + $title ||=3D $Lang::tr{'error messages'}; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + &Header::openbox('100%', 'left', $title); >>>>>>>>>>>>>>>>>>>>>>>> + print "<span>$message</span>"; >>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebox(); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Show all zone files and related gui elements >>>>>>>>>>>>>>>>>>>>>>>> +sub _print_zonefiles { >>>>>>>>>>>>>>>>>>>>>>>> + &Header::openbox('100%', 'left', = $Lang::tr{'rpz zf'}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + print <<END >>>>>>>>>>>>>>>>>>>>>>>> +<table class=3D"tbl" width=3D"100%"> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <th>$Lang::tr{'name'}</th> >>>>>>>>>>>>>>>>>>>>>>>> + <th>URL</th> >>>>>>>>>>>>>>>>>>>>>>>> + <th>$Lang::tr{'remark'}</th> >>>>>>>>>>>>>>>>>>>>>>>> + <th colspan=3D"3">$Lang::tr{'action'}</th> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> +END >>>>>>>>>>>>>>>>>>>>>>>> +; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Sort zonefiles by name and loop trough all = entries >>>>>>>>>>>>>>>>>>>>>>>> + foreach my $name (sort keys %zonefiles) { >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Toggle button label translation >>>>>>>>>>>>>>>>>>>>>>>> + my $toggle_tr =3D = ($zonefiles{$name}{'enabled'} eq 'on') ? $Lang::tr{'click to disable'} : = $Lang::tr{'click to enable'}; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + print <<END >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td>$name</td> >>>>>>>>>>>>>>>>>>>>>>>> + <td>$zonefiles{$name}{'url'}</td> >>>>>>>>>>>>>>>>>>>>>>>> + <td>$zonefiles{$name}{'remark'}</td> >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + <td align=3D"center" width=3D"5%"> >>>>>>>>>>>>>>>>>>>>>>>> + <form method=3D"post" = action=3D"$ENV{'SCRIPT_NAME'}"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"hidden" name=3D"KEY" = value=3D"$name"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"hidden" name=3D"ACTION" = value=3D"ZF_TOGGLE"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"image" = src=3D"/images/$zonefiles{$name}{'enabled'}.gif" title=3D"$toggle_tr" = alt=3D"$toggle_tr"> >>>>>>>>>>>>>>>>>>>>>>>> + </form> >>>>>>>>>>>>>>>>>>>>>>>> + </td> >>>>>>>>>>>>>>>>>>>>>>>> + <td align=3D"center" width=3D"5%"> >>>>>>>>>>>>>>>>>>>>>>>> + <form method=3D"post" = action=3D"$ENV{'SCRIPT_NAME'}"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"hidden" name=3D"KEY" = value=3D"$name"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"hidden" name=3D"ACTION" = value=3D"ZF_EDIT"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"image" src=3D"/images/edit.gif" = title=3D"$Lang::tr{'edit'}" alt=3D"$Lang::tr{'edit'}"> >>>>>>>>>>>>>>>>>>>>>>>> + </form> >>>>>>>>>>>>>>>>>>>>>>>> + </td> >>>>>>>>>>>>>>>>>>>>>>>> + <td align=3D"center" width=3D"5%"> >>>>>>>>>>>>>>>>>>>>>>>> + <form method=3D"post" = action=3D"$ENV{'SCRIPT_NAME'}"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"hidden" name=3D"KEY" = value=3D"$name"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"hidden" name=3D"ACTION" = value=3D"ZF_REMOVE"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"image" = src=3D"/images/delete.gif" title=3D"$Lang::tr{'remove'}" = alt=3D"$Lang::tr{'remove'}"> >>>>>>>>>>>>>>>>>>>>>>>> + </form> >>>>>>>>>>>>>>>>>>>>>>>> + </td> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> +END >>>>>>>>>>>>>>>>>>>>>>>> +; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Disable reload button if not needed >>>>>>>>>>>>>>>>>>>>>>>> + my $reload_state =3D &_rpz_needs_reload() ? = "" : " disabled"; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + print <<END >>>>>>>>>>>>>>>>>>>>>>>> +</table> >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +<div class=3D"right"> >>>>>>>>>>>>>>>>>>>>>>>> + <form method=3D"post" = action=3D"$ENV{'SCRIPT_NAME'}"> >>>>>>>>>>>>>>>>>>>>>>>> + <input type=3D"hidden" name=3D"KEY" value=3D"">= >>>>>>>>>>>>>>>>>>>>>>>> + <button type=3D"submit" name=3D"ACTION" = value=3D"ZF_EDIT">$Lang::tr{'add'}</button> >>>>>>>>>>>>>>>>>>>>>>>> + <button type=3D"submit" name=3D"ACTION" = value=3D"RPZ_RELOAD" class=3D"commit"$reload_state>$Lang::tr{'rpz = apply'}</button> >>>>>>>>>>>>>>>>>>>>>>>> + </form> >>>>>>>>>>>>>>>>>>>>>>>> +</div> >>>>>>>>>>>>>>>>>>>>>>>> +END >>>>>>>>>>>>>>>>>>>>>>>> +; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebox(); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Show zonefiles entry editor >>>>>>>>>>>>>>>>>>>>>>>> +sub _print_zonefile_editor { >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Key specified: Edit existing entry >>>>>>>>>>>>>>>>>>>>>>>> + if(($action_key) && (defined = $zonefiles{$action_key})) { >>>>>>>>>>>>>>>>>>>>>>>> + # Load data to be edited, but don't override = already present values (allows user to edit after error) >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_NAME'} //=3D $action_key; >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_URL'} //=3D = $zonefiles{$action_key}{'url'}; >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_REMARK'} //=3D = $zonefiles{$action_key}{'remark'}; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Fallback to empty form >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_NAME'} //=3D ""; >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_URL'} //=3D ""; >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ZF_REMARK'} //=3D ""; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + &Header::openbox('100%', 'left', = $Lang::tr{'rpz zf editor'}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + print <<END >>>>>>>>>>>>>>>>>>>>>>>> +<form method=3D"post" = action=3D"$ENV{'SCRIPT_NAME'}"> >>>>>>>>>>>>>>>>>>>>>>>> +<input type=3D"hidden" name=3D"KEY" = value=3D"$action_key"> >>>>>>>>>>>>>>>>>>>>>>>> +<table width=3D"100%"> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td width=3D"20%">$Lang::tr{'name'}: <img = src=3D"/blob.gif" alt=3D"*"></td> >>>>>>>>>>>>>>>>>>>>>>>> + <td><input type=3D"text" name=3D"ZF_NAME" = value=3D"$cgiparams{'ZF_NAME'}" size=3D"40" maxlength=3D"32" = title=3D"$Lang::tr{'rpz zf remark info'}" pattern=3D"[a-zA-Z0-9_]{1,32}" = required></td> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td width=3D"20%">URL: <img = src=3D"/blob.gif" alt=3D"*"></td> >>>>>>>>>>>>>>>>>>>>>>>> + <td><input type=3D"url" name=3D"ZF_URL" = value=3D"$cgiparams{'ZF_URL'}" size=3D"40" maxlength=3D"128" = required></td> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td width=3D"20%">$Lang::tr{'remark'}:</td> >>>>>>>>>>>>>>>>>>>>>>>> + <td><input type=3D"text" name=3D"ZF_REMARK" = value=3D"$cgiparams{'ZF_REMARK'}" size=3D"40" maxlength=3D"32"></td> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td colspan=3D"2"><hr></td> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td width=3D"55%"><img src=3D"/blob.gif" = alt=3D"*"> $Lang::tr{'required field'}</td> >>>>>>>>>>>>>>>>>>>>>>>> + <td align=3D"right"><button type=3D"submit" = name=3D"ACTION" value=3D"ZF_SAVE">$Lang::tr{'save'}</button></td> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> +</table> >>>>>>>>>>>>>>>>>>>>>>>> +</form> >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +<div class=3D"right"> >>>>>>>>>>>>>>>>>>>>>>>> + <form method=3D"post" = action=3D"$ENV{'SCRIPT_NAME'}"> >>>>>>>>>>>>>>>>>>>>>>>> + <button type=3D"submit" name=3D"ACTION" = value=3D"NONE">$Lang::tr{'back'}</button> >>>>>>>>>>>>>>>>>>>>>>>> + </form> >>>>>>>>>>>>>>>>>>>>>>>> +</div> >>>>>>>>>>>>>>>>>>>>>>>> +END >>>>>>>>>>>>>>>>>>>>>>>> +; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebox(); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Show custom allow/block files and related = gui elements >>>>>>>>>>>>>>>>>>>>>>>> +sub _print_customlists { >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Load lists from config, unless they are = currently being edited >>>>>>>>>>>>>>>>>>>>>>>> + if($action ne 'CL_SAVE') { >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ALLOW_LIST'} =3D join("\n", = @{$customlists{'allow'}{'list'}}); >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'BLOCK_LIST'} =3D join("\n", = @{$customlists{'block'}{'list'}}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ALLOW_ENABLED'} =3D = ($customlists{'allow'}{'enabled'} eq 'on') ? 'on' : undef; >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'BLOCK_ENABLED'} =3D = ($customlists{'block'}{'enabled'} eq 'on') ? 'on' : undef; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Fallback to empty form >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'ALLOW_LIST'} //=3D ""; >>>>>>>>>>>>>>>>>>>>>>>> + $cgiparams{'BLOCK_LIST'} //=3D ""; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # HTML checkboxes, unchecked =3D no or undef = value in POST data >>>>>>>>>>>>>>>>>>>>>>>> + my %checked =3D (); >>>>>>>>>>>>>>>>>>>>>>>> + $checked{'ALLOW_ENABLED'} =3D (defined = $cgiparams{'ALLOW_ENABLED'}) ? " checked" : ""; >>>>>>>>>>>>>>>>>>>>>>>> + $checked{'BLOCK_ENABLED'} =3D (defined = $cgiparams{'BLOCK_ENABLED'}) ? " checked" : ""; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Disable reload button if not needed >>>>>>>>>>>>>>>>>>>>>>>> + my $reload_state =3D &_rpz_needs_reload() ? = "" : " disabled"; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + &Header::openbox('100%', 'left', = $Lang::tr{'rpz cl'}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + print <<END >>>>>>>>>>>>>>>>>>>>>>>> +<form method=3D"post" = action=3D"$ENV{'SCRIPT_NAME'}"> >>>>>>>>>>>>>>>>>>>>>>>> +<table width=3D"100%"> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td colspan=3D"2"><b>$Lang::tr{'rpz cl = allow'}</b><br>$Lang::tr{'rpz cl allow info'}</td> >>>>>>>>>>>>>>>>>>>>>>>> + <td colspan=3D"2"><b>$Lang::tr{'rpz cl = block'}</b><br>$Lang::tr{'rpz cl block info'}</td> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td colspan=3D"2"><textarea name=3D"ALLOW_LIST"= class=3D"domainlist" cols=3D"45"> >>>>>>>>>>>>>>>>>>>>>>>> +$cgiparams{'ALLOW_LIST'}</textarea></td> >>>>>>>>>>>>>>>>>>>>>>>> + <td colspan=3D"2"><textarea name=3D"BLOCK_LIST"= class=3D"domainlist" cols=3D"45"> >>>>>>>>>>>>>>>>>>>>>>>> +$cgiparams{'BLOCK_LIST'}</textarea></td> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td><label for=3D"allow_enabled">$Lang::tr{'rpz= cl allow enable'}</label></td> >>>>>>>>>>>>>>>>>>>>>>>> + <td width=3D"15%"><input type=3D"checkbox" = name=3D"ALLOW_ENABLED" id=3D"allow_enabled"$checked{'ALLOW_ENABLED'}></td>= >>>>>>>>>>>>>>>>>>>>>>>> + <td><label for=3D"block_enabled">$Lang::tr{'rpz= cl block enable'}</label></td> >>>>>>>>>>>>>>>>>>>>>>>> + <td width=3D"15%"><input type=3D"checkbox" = name=3D"BLOCK_ENABLED" id=3D"block_enabled"$checked{'BLOCK_ENABLED'}></td>= >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td colspan=3D"4"><hr></td> >>>>>>>>>>>>>>>>>>>>>>>> + </tr> >>>>>>>>>>>>>>>>>>>>>>>> + <tr> >>>>>>>>>>>>>>>>>>>>>>>> + <td align=3D"right" colspan=3D"4"> >>>>>>>>>>>>>>>>>>>>>>>> + <button type=3D"submit" name=3D"ACTION" = value=3D"CL_SAVE">$Lang::tr{'save'}</button> >>>>>>>>>>>>>>>>>>>>>>>> + <button type=3D"submit" name=3D"ACTION" = value=3D"RPZ_RELOAD" class=3D"commit"$reload_state>$Lang::tr{'rpz = apply'}</button> >>>>>>>>>>>>>>>>>>>>>>>> + </td> >>>>>>>>>>>>>>>>>>>>>>>> +</table> >>>>>>>>>>>>>>>>>>>>>>>> +</form> >>>>>>>>>>>>>>>>>>>>>>>> +END >>>>>>>>>>>>>>>>>>>>>>>> +; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + &Header::closebox(); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Output javascript and extra gui elements >>>>>>>>>>>>>>>>>>>>>>>> +sub _print_gui_extras { >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Apply/Restart button modifier key handler >>>>>>>>>>>>>>>>>>>>>>>> + if(&_rpz_needs_reload()) { >>>>>>>>>>>>>>>>>>>>>>>> + print <<END >>>>>>>>>>>>>>>>>>>>>>>> +<script> >>>>>>>>>>>>>>>>>>>>>>>> + // Commit modifier key handler >>>>>>>>>>>>>>>>>>>>>>>> + (function(jq, document) { >>>>>>>>>>>>>>>>>>>>>>>> + var keyEventsOn =3D false; // Keyboard events = attached >>>>>>>>>>>>>>>>>>>>>>>> + var keyModify =3D false; // Modifier key = pressed >>>>>>>>>>>>>>>>>>>>>>>> + var mouseHover =3D false; // Mouse over = commit button >>>>>>>>>>>>>>>>>>>>>>>> + var btnModified =3D false; // Button modified = to "Restart" >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + // Document-level key events, enable only = while cursor is over button >>>>>>>>>>>>>>>>>>>>>>>> + function attachKeyEvents() { >>>>>>>>>>>>>>>>>>>>>>>> + if(keyEventsOn) { >>>>>>>>>>>>>>>>>>>>>>>> + return; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + keyEventsOn =3D true; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + jq(document).on("keydown.rpz", = function(event) { >>>>>>>>>>>>>>>>>>>>>>>> + if((!keyModify) && event.shiftKey) { >>>>>>>>>>>>>>>>>>>>>>>> + keyModify =3D true; >>>>>>>>>>>>>>>>>>>>>>>> + handleModify(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + }); >>>>>>>>>>>>>>>>>>>>>>>> + jq(document).on("keyup.rpz", function(event) = { >>>>>>>>>>>>>>>>>>>>>>>> + if(keyModify && (!event.shiftKey)) { >>>>>>>>>>>>>>>>>>>>>>>> + keyModify =3D false; >>>>>>>>>>>>>>>>>>>>>>>> + handleModify(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + }); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + function removeKeyEvents() { >>>>>>>>>>>>>>>>>>>>>>>> + keyModify =3D false; >>>>>>>>>>>>>>>>>>>>>>>> + if(keyEventsOn) { >>>>>>>>>>>>>>>>>>>>>>>> + jq(document).off("keydown.rpz keyup.rpz"); >>>>>>>>>>>>>>>>>>>>>>>> + keyEventsOn =3D false; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + // Attach mouse hover events to commit = buttons >>>>>>>>>>>>>>>>>>>>>>>> + function attachMouseEvents() { >>>>>>>>>>>>>>>>>>>>>>>> + jq("button.commit").on("mouseenter", = function(event) { >>>>>>>>>>>>>>>>>>>>>>>> + if(!mouseHover) { >>>>>>>>>>>>>>>>>>>>>>>> + mouseHover =3D true; >>>>>>>>>>>>>>>>>>>>>>>> + attachKeyEvents(); >>>>>>>>>>>>>>>>>>>>>>>> + // Handle already pressed key >>>>>>>>>>>>>>>>>>>>>>>> + keyModify =3D !!(event.shiftKey); >>>>>>>>>>>>>>>>>>>>>>>> + handleModify(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + }); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + // Cursor moved away: Disable key listener to = minimize events >>>>>>>>>>>>>>>>>>>>>>>> + jq("button.commit").on("mouseleave", = function() { >>>>>>>>>>>>>>>>>>>>>>>> + if(mouseHover) { >>>>>>>>>>>>>>>>>>>>>>>> + mouseHover =3D false; >>>>>>>>>>>>>>>>>>>>>>>> + removeKeyEvents(); >>>>>>>>>>>>>>>>>>>>>>>> + handleModify(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + }); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + // Modify commit button >>>>>>>>>>>>>>>>>>>>>>>> + function handleModify() { >>>>>>>>>>>>>>>>>>>>>>>> + let modify =3D mouseHover && keyModify; >>>>>>>>>>>>>>>>>>>>>>>> + if(btnModified !=3D modify) { >>>>>>>>>>>>>>>>>>>>>>>> + if(modify) { >>>>>>>>>>>>>>>>>>>>>>>> + = jq("button.commit").text("$Lang::tr{'restart'}").val("UNB_RESTART"); >>>>>>>>>>>>>>>>>>>>>>>> + } else { >>>>>>>>>>>>>>>>>>>>>>>> + jq("button.commit").text("$Lang::tr{'rpz = apply'}").val("RPZ_RELOAD"); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + btnModified =3D modify; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + // jQuery DOM ready >>>>>>>>>>>>>>>>>>>>>>>> + jq(function() { >>>>>>>>>>>>>>>>>>>>>>>> + attachMouseEvents(); >>>>>>>>>>>>>>>>>>>>>>>> + }); >>>>>>>>>>>>>>>>>>>>>>>> + })(jQuery, document); >>>>>>>>>>>>>>>>>>>>>>>> +</script> >>>>>>>>>>>>>>>>>>>>>>>> +END >>>>>>>>>>>>>>>>>>>>>>>> +; >>>>>>>>>>>>>>>>>>>>>>>> + } # End of modifier key handler >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal action processing functions = ---### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Toggle zonefile on/off >>>>>>>>>>>>>>>>>>>>>>>> +sub _action_zf_toggle { >>>>>>>>>>>>>>>>>>>>>>>> + return unless(defined = $zonefiles{$action_key}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + my $result =3D 0; >>>>>>>>>>>>>>>>>>>>>>>> + my $enabled =3D = $zonefiles{$action_key}{'enabled'}; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Perform toggle action >>>>>>>>>>>>>>>>>>>>>>>> + if($enabled eq 'on') { >>>>>>>>>>>>>>>>>>>>>>>> + $enabled =3D 'off'; >>>>>>>>>>>>>>>>>>>>>>>> + $result =3D = &General::system('/usr/sbin/rpz-config', 'remove', $action_key, = '--no-reload'); >>>>>>>>>>>>>>>>>>>>>>>> + } else { >>>>>>>>>>>>>>>>>>>>>>>> + $enabled =3D 'on'; >>>>>>>>>>>>>>>>>>>>>>>> + $result =3D = &General::system('/usr/sbin/rpz-config', 'add', $action_key, = $zonefiles{$action_key}{'url'}, '--no-reload'); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Check for errors, request service reload on = success >>>>>>>>>>>>>>>>>>>>>>>> + return unless &_rpz_check_result($result, 1); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Save changes >>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$action_key}{'enabled'} =3D = $enabled; >>>>>>>>>>>>>>>>>>>>>>>> + &_zonefiles_save_conf(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 1; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Remove zonefile >>>>>>>>>>>>>>>>>>>>>>>> +sub _action_zf_remove { >>>>>>>>>>>>>>>>>>>>>>>> + return unless(defined = $zonefiles{$action_key}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Remove from rpz-config if currently active >>>>>>>>>>>>>>>>>>>>>>>> + if($zonefiles{$action_key}{'enabled'} eq = 'on') { >>>>>>>>>>>>>>>>>>>>>>>> + my $result =3D = &General::system('/usr/sbin/rpz-config', 'remove', $action_key, = '--no-reload'); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Check for errors, request service reload on = success >>>>>>>>>>>>>>>>>>>>>>>> + return unless &_rpz_check_result($result, 1); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Remove from data hash and save changes >>>>>>>>>>>>>>>>>>>>>>>> + delete $zonefiles{$action_key}; >>>>>>>>>>>>>>>>>>>>>>>> + &_zonefiles_save_conf(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Clear action_key, as the entry is now = removed entirely >>>>>>>>>>>>>>>>>>>>>>>> + $action_key =3D ""; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 1; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Create or update zonefile entry >>>>>>>>>>>>>>>>>>>>>>>> +# Returns undef if gui needs to stay in editor = mode >>>>>>>>>>>>>>>>>>>>>>>> +sub _action_zf_save { >>>>>>>>>>>>>>>>>>>>>>>> + my $result =3D 0; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + my $name =3D $cgiparams{'ZF_NAME'} // ""; >>>>>>>>>>>>>>>>>>>>>>>> + my $url =3D $cgiparams{'ZF_URL'} // ""; >>>>>>>>>>>>>>>>>>>>>>>> + my $remark =3D $cgiparams{'ZF_REMARK'} // ""; >>>>>>>>>>>>>>>>>>>>>>>> + my $enabled =3D 'on'; # Enable new entries by = default >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Note on variables: >>>>>>>>>>>>>>>>>>>>>>>> + # name =3D unique key, will be used to = address the entry >>>>>>>>>>>>>>>>>>>>>>>> + # action_key =3D name of the entry being = edited, empty for new entry >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Only check for unique name if it changed >>>>>>>>>>>>>>>>>>>>>>>> + # (this also checks new entries because the = action_key is empty in this case) >>>>>>>>>>>>>>>>>>>>>>>> + $result =3D &_rpz_validate_zonefile($name, = $url, $remark, (lc($name) ne lc($action_key))); >>>>>>>>>>>>>>>>>>>>>>>> + return unless &_rpz_check_result($result, 0); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Edit existing entry: Determine what was = changed >>>>>>>>>>>>>>>>>>>>>>>> + if(($action_key) && (defined = $zonefiles{$action_key})) { >>>>>>>>>>>>>>>>>>>>>>>> + # Name und URL remain unchanged, only save = remark and finish >>>>>>>>>>>>>>>>>>>>>>>> + if(($name eq $action_key) && ($url eq = $zonefiles{$action_key}{'url'})) { >>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$action_key}{'remark'} =3D = $remark; >>>>>>>>>>>>>>>>>>>>>>>> + &_zonefiles_save_conf(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 1; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Entry was changed and needs to be = recreated, preserve status >>>>>>>>>>>>>>>>>>>>>>>> + $enabled =3D = $zonefiles{$action_key}{'enabled'}; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Remove from rpz-config >>>>>>>>>>>>>>>>>>>>>>>> + return unless &_action_zf_remove(); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Add new entry to rpz-config >>>>>>>>>>>>>>>>>>>>>>>> + if($enabled eq 'on') { >>>>>>>>>>>>>>>>>>>>>>>> + $result =3D = &General::system('/usr/sbin/rpz-config', 'add', $name, $url, = '--no-reload'); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Check for errors, request service reload on = success >>>>>>>>>>>>>>>>>>>>>>>> + return unless &_rpz_check_result($result, 1); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Add to global data hash and save changes >>>>>>>>>>>>>>>>>>>>>>>> + my %entry =3D ('enabled' =3D> $enabled, >>>>>>>>>>>>>>>>>>>>>>>> + 'url' =3D> $url, >>>>>>>>>>>>>>>>>>>>>>>> + 'remark' =3D> $remark); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + $zonefiles{$name} =3D \%entry; >>>>>>>>>>>>>>>>>>>>>>>> + &_zonefiles_save_conf(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 1; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Save custom lists >>>>>>>>>>>>>>>>>>>>>>>> +sub _action_cl_save { >>>>>>>>>>>>>>>>>>>>>>>> + return unless((defined = $cgiparams{'ALLOW_LIST'}) && (defined $cgiparams{'BLOCK_LIST'})); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + my $result =3D 0; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + my @allowlist =3D split(/\R/, = $cgiparams{'ALLOW_LIST'}); >>>>>>>>>>>>>>>>>>>>>>>> + my @blocklist =3D split(/\R/, = $cgiparams{'BLOCK_LIST'}); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Validate lists >>>>>>>>>>>>>>>>>>>>>>>> + $result =3D = &_rpz_validate_customlist(\@allowlist); >>>>>>>>>>>>>>>>>>>>>>>> + if($result !=3D 0) { >>>>>>>>>>>>>>>>>>>>>>>> + $errormessage =3D &_rpz_error_tr(202, = $result); >>>>>>>>>>>>>>>>>>>>>>>> + return; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + $result =3D = &_rpz_validate_customlist(\@blocklist); >>>>>>>>>>>>>>>>>>>>>>>> + if($result !=3D 0) { >>>>>>>>>>>>>>>>>>>>>>>> + $errormessage =3D &_rpz_error_tr(203, = $result); >>>>>>>>>>>>>>>>>>>>>>>> + return; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Add to global data hash and save changes >>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'allow'}{'list'} =3D = \@allowlist; >>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'block'}{'list'} =3D = \@blocklist; >>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'allow'}{'enabled'} =3D (defined = $cgiparams{'ALLOW_ENABLED'}) ? 'on' : 'off'; >>>>>>>>>>>>>>>>>>>>>>>> + $customlists{'block'}{'enabled'} =3D (defined = $cgiparams{'BLOCK_ENABLED'}) ? 'on' : 'off'; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + &_customlists_save_conf(); >>>>>>>>>>>>>>>>>>>>>>>> + &_customlist_export('allow', $RPZ_ALLOWLIST); >>>>>>>>>>>>>>>>>>>>>>>> + &_customlist_export('block', $RPZ_BLOCKLIST); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Make new lists, request service reload on = success >>>>>>>>>>>>>>>>>>>>>>>> + $result =3D = &General::system('/usr/sbin/rpz-make', 'allowblock', '--no-reload'); >>>>>>>>>>>>>>>>>>>>>>>> + return unless &_rpz_check_result($result, 1); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 1; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Trigger rpz-config reload >>>>>>>>>>>>>>>>>>>>>>>> +sub _action_rpz_reload { >>>>>>>>>>>>>>>>>>>>>>>> + return 1 unless &_rpz_needs_reload(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Immediately clear flag to prevent multiple = reloads >>>>>>>>>>>>>>>>>>>>>>>> + if(-f $RPZ_RELOAD_FLAG) { >>>>>>>>>>>>>>>>>>>>>>>> + unlink($RPZ_RELOAD_FLAG) or die "Can't remove = $RPZ_RELOAD_FLAG: $!"; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Perform reload, recreate reload flag on = error to enable retry >>>>>>>>>>>>>>>>>>>>>>>> + my $result =3D = &General::system('/usr/sbin/rpz-config', 'reload'); >>>>>>>>>>>>>>>>>>>>>>>> + if(not &_rpz_check_result($result, 0)) { >>>>>>>>>>>>>>>>>>>>>>>> + &General::system('touch', = "$RPZ_RELOAD_FLAG"); >>>>>>>>>>>>>>>>>>>>>>>> + return; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 1; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Trigger unbound restart >>>>>>>>>>>>>>>>>>>>>>>> +sub _action_unb_restart { >>>>>>>>>>>>>>>>>>>>>>>> + return 1 unless &_rpz_needs_reload(); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Immediately clear flag to prevent multiple = restarts >>>>>>>>>>>>>>>>>>>>>>>> + if(-f $RPZ_RELOAD_FLAG) { >>>>>>>>>>>>>>>>>>>>>>>> + unlink($RPZ_RELOAD_FLAG) or die "Can't remove = $RPZ_RELOAD_FLAG: $!"; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Perform restart, unboundctrl always exits = zero >>>>>>>>>>>>>>>>>>>>>>>> + = &General::system('/usr/local/bin/unboundctrl', 'restart'); >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 1; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal rpz-config functions ---### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Translate rpz-config exitcodes and messages >>>>>>>>>>>>>>>>>>>>>>>> +# 100-199: rpz-config, 200-299: webgui >>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_error_tr { >>>>>>>>>>>>>>>>>>>>>>>> + my ($error, $append) =3D @_; >>>>>>>>>>>>>>>>>>>>>>>> + $append //=3D ''; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Translate numeric exit codes >>>>>>>>>>>>>>>>>>>>>>>> + if(looks_like_number($error)) { >>>>>>>>>>>>>>>>>>>>>>>> + if(defined $Lang::tr{"rpz exitcode $error"}) = { >>>>>>>>>>>>>>>>>>>>>>>> + $error =3D $Lang::tr{"rpz exitcode $error"}; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return "RPZ $Lang::tr{'error'}: $error" . = &Header::escape($append); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Check result of rpz-config system call, = request reload on success >>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_check_result { >>>>>>>>>>>>>>>>>>>>>>>> + my ($result, $request_reload) =3D @_; >>>>>>>>>>>>>>>>>>>>>>>> + $request_reload //=3D 0; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # exitcode 0 =3D success >>>>>>>>>>>>>>>>>>>>>>>> + if($result !=3D 0) { >>>>>>>>>>>>>>>>>>>>>>>> + $errormessage =3D &_rpz_error_tr($result); >>>>>>>>>>>>>>>>>>>>>>>> + return; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Set reload flag >>>>>>>>>>>>>>>>>>>>>>>> + if($request_reload) { >>>>>>>>>>>>>>>>>>>>>>>> + &General::system('touch', = "$RPZ_RELOAD_FLAG"); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 1; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Test whether reload flag is set >>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_needs_reload { >>>>>>>>>>>>>>>>>>>>>>>> + return (-f $RPZ_RELOAD_FLAG); >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Validate a zonefile entry, returns = rpz-config exitcode on failure. Use _rpz_check_result to verify. >>>>>>>>>>>>>>>>>>>>>>>> +# unique =3D check for unique name >>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_validate_zonefile { >>>>>>>>>>>>>>>>>>>>>>>> + my ($name, $url, $remark, $unique) =3D @_; >>>>>>>>>>>>>>>>>>>>>>>> + $unique //=3D 1; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + unless($name =3D~ /^[a-zA-Z0-9_]{1,32}$/) { >>>>>>>>>>>>>>>>>>>>>>>> + return 101; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + unless($url =3D~ = /^[\w+\.:;\/\\&@#%?=3D\-~|!]{1,128}$/) { >>>>>>>>>>>>>>>>>>>>>>>> + return 105; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + unless($remark =3D~ /^[\w = \-()\.:;*\/\\?!&=3D]{0,32}$/) { >>>>>>>>>>>>>>>>>>>>>>>> + return 201; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Check against already existing names >>>>>>>>>>>>>>>>>>>>>>>> + if($unique) { >>>>>>>>>>>>>>>>>>>>>>>> + foreach my $existing (keys %zonefiles) { >>>>>>>>>>>>>>>>>>>>>>>> + if(lc($name) eq lc($existing)) { >>>>>>>>>>>>>>>>>>>>>>>> + return 104; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 0; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Validate a custom list, returns number of = rejected line on failure. Check for non-zero results. >>>>>>>>>>>>>>>>>>>>>>>> +# listref =3D array reference, cleanup =3D = remove invalid entries instead of returning an error >>>>>>>>>>>>>>>>>>>>>>>> +sub _rpz_validate_customlist { >>>>>>>>>>>>>>>>>>>>>>>> + my ($listref, $cleanup) =3D @_; >>>>>>>>>>>>>>>>>>>>>>>> + $cleanup //=3D 0; >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + foreach my $index (reverse 0..$#{$listref}) { >>>>>>>>>>>>>>>>>>>>>>>> + my $row =3D @$listref[$index]; >>>>>>>>>>>>>>>>>>>>>>>> + next unless($row); # Skip/allow empty lines >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Reject/remove everything besides wildcard = domains and remarks >>>>>>>>>>>>>>>>>>>>>>>> + if((not = &General::validwildcarddomainname($row)) && (not $row =3D~ /^;[\w = \-()\.:;*\/\\?!&=3D]*$/)) { >>>>>>>>>>>>>>>>>>>>>>>> + unless($cleanup) { >>>>>>>>>>>>>>>>>>>>>>>> + # +1 for user friendly line number and to = ensure non-zero exitcode >>>>>>>>>>>>>>>>>>>>>>>> + return $index + 1; >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Remove current row >>>>>>>>>>>>>>>>>>>>>>>> + splice(@$listref, $index, 1); >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + } >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + return 0; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +###--- Internal misc functions ---### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Send HTTP 303 redirect headers for = post/request/get pattern >>>>>>>>>>>>>>>>>>>>>>>> +# (Must be sent before calling = &Header::showhttpheaders()) >>>>>>>>>>>>>>>>>>>>>>>> +sub _http_prg_redirect { >>>>>>>>>>>>>>>>>>>>>>>> + my $location =3D = "https://$ENV{'SERVER_NAME'}:$ENV{'SERVER_PORT'}$ENV{'SCRIPT_NAME'}"; >>>>>>>>>>>>>>>>>>>>>>>> + print "Status: 303 See Other\n"; >>>>>>>>>>>>>>>>>>>>>>>> + print "Location: $location\n"; >>>>>>>>>>>>>>>>>>>>>>>> +} >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/lfs/rpz b/lfs/rpz >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..7ddbc38e5 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/lfs/rpz >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,96 @@ >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# Definitions >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +include Config >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +SUMMARY =3D response policy zone - RPZ = reputation system for unbound DNS >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +VER =3D 1.0.0 >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +THISAPP =3D rpz-$(VER) >>>>>>>>>>>>>>>>>>>>>>>> +DIR_APP =3D $(DIR_SRC)/$(THISAPP) >>>>>>>>>>>>>>>>>>>>>>>> +TARGET =3D $(DIR_INFO)/$(THISAPP) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +PROG =3D rpz >>>>>>>>>>>>>>>>>>>>>>>> +PAK_VER =3D 18 >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +DEPS =3D >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +SERVICES =3D >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# Top-level Rules >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +install : $(TARGET) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +check : >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +download : >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +b2 : >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +dist: >>>>>>>>>>>>>>>>>>>>>>>> + @$(PAK) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# Installation Details >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +$(TARGET) : >>>>>>>>>>>>>>>>>>>>>>>> + @$(PREBUILD) >>>>>>>>>>>>>>>>>>>>>>>> + @rm -rf $(DIR_APP) >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # RPZ scripts >>>>>>>>>>>>>>>>>>>>>>>> + install --verbose --mode=3D755 \ >>>>>>>>>>>>>>>>>>>>>>>> + = $(DIR_CONF)/rpz/{rpz-config,rpz-metrics,rpz-sleep,rpz-make,rpz-functions} = \ >>>>>>>>>>>>>>>>>>>>>>>> + --target-directory=3D/usr/sbin >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # RPZ config files >>>>>>>>>>>>>>>>>>>>>>>> + mkdir -pv /etc/unbound/local.d >>>>>>>>>>>>>>>>>>>>>>>> + install --verbose --mode=3D644 --owner=3Dnobody= --group=3Dnobody \ >>>>>>>>>>>>>>>>>>>>>>>> + $(DIR_CONF)/rpz/00-rpz.conf \ >>>>>>>>>>>>>>>>>>>>>>>> + --target-directory=3D/etc/unbound/local.d >>>>>>>>>>>>>>>>>>>>>>>> + chown --verbose --recursive nobody:nobody = /etc/unbound/local.d >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # RPZ custom list files for allow and block >>>>>>>>>>>>>>>>>>>>>>>> + mkdir -pv /var/ipfire/dns/rpz >>>>>>>>>>>>>>>>>>>>>>>> + touch = /var/ipfire/dns/rpz/{allowlist,blocklist} >>>>>>>>>>>>>>>>>>>>>>>> + chown --verbose --recursive nobody:nobody = /var/ipfire/dns/rpz >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # RPZ zone files >>>>>>>>>>>>>>>>>>>>>>>> + # create empty RPZ config file to avoid a = unbound config error >>>>>>>>>>>>>>>>>>>>>>>> + mkdir -pv /etc/unbound/zonefiles >>>>>>>>>>>>>>>>>>>>>>>> + touch /etc/unbound/zonefiles/allow.rpz >>>>>>>>>>>>>>>>>>>>>>>> + chown --verbose --recursive nobody:nobody = /etc/unbound/zonefiles >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Install addon-specific language-files >>>>>>>>>>>>>>>>>>>>>>>> + install --verbose --mode=3D004 = $(DIR_CONF)/rpz/rpz.*.pl \ >>>>>>>>>>>>>>>>>>>>>>>> + --target-directory=3D/var/ipfire/addon-lang >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + # Install backup definition >>>>>>>>>>>>>>>>>>>>>>>> + cp -vf $(DIR_CONF)/backup/includes/rpz = /var/ipfire/backup/addons/includes/rpz >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> + @rm -rf $(DIR_APP) >>>>>>>>>>>>>>>>>>>>>>>> + @$(POSTBUILD) >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/make.sh b/make.sh >>>>>>>>>>>>>>>>>>>>>>>> index 827ea9e77..a77535b13 100755 >>>>>>>>>>>>>>>>>>>>>>>> --- a/make.sh >>>>>>>>>>>>>>>>>>>>>>>> +++ b/make.sh >>>>>>>>>>>>>>>>>>>>>>>> @@ -390,7 +390,7 @@ prepareenv() { >>>>>>>>>>>>>>>>>>>>>>>> if [ "${free_space}" -lt "${required_space}" ]; = then >>>>>>>>>>>>>>>>>>>>>>>> # Add any consumed space >>>>>>>>>>>>>>>>>>>>>>>> while read -r consumed_space path; do >>>>>>>>>>>>>>>>>>>>>>>> - (( free_space +=3D consumed_space / 1024 / = 1024 )) >>>>>>>>>>>>>>>>>>>>>>>> + (( free_space +=3D consumed_space / 1024 / = 1024 )) >>>>>>>>>>>>>>>>>>>>>>>> done <<< "$(du --summarize --bytes = "${BUILD_DIR}" "${IMAGES_DIR}" "${LOG_DIR}" 2>/dev/null)" >>>>>>>>>>>>>>>>>>>>>>>> fi >>>>>>>>>>>>>>>>>>>>>>>> @@ -2087,6 +2087,7 @@ build_system() { >>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 btrfs-progs >>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 inotify-tools >>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 grub-btrfs >>>>>>>>>>>>>>>>>>>>>>>> + lfsmake2 rpz >>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 linux >>>>>>>>>>>>>>>>>>>>>>>> lfsmake2 rtl8812au >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/src/paks/rpz/install.sh = b/src/paks/rpz/install.sh >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..ef99bf742 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/src/paks/rpz/install.sh >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,36 @@ >>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# >>>>>>>>>>>>>>>>>>>>>>>> +. /opt/pakfire/lib/functions.sh >>>>>>>>>>>>>>>>>>>>>>>> +extract_files >>>>>>>>>>>>>>>>>>>>>>>> +restore_backup ${NAME} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# fix user created files >>>>>>>>>>>>>>>>>>>>>>>> +chown --verbose --recursive nobody:nobody \ >>>>>>>>>>>>>>>>>>>>>>>> + /var/ipfire/dns/rpz \ >>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/zonefiles \ >>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/local.d >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Update Language cache >>>>>>>>>>>>>>>>>>>>>>>> +/usr/local/bin/update-lang-cache >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# restart unbound to load config file >>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound restart >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/src/paks/rpz/uninstall.sh = b/src/paks/rpz/uninstall.sh >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..e11427df3 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/src/paks/rpz/uninstall.sh >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,38 @@ >>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# >>>>>>>>>>>>>>>>>>>>>>>> +. /opt/pakfire/lib/functions.sh >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# stop unbound to delete RPZ conf file >>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound stop >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +make_backup ${NAME} >>>>>>>>>>>>>>>>>>>>>>>> +remove_files >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# delete rpz config files. Otherwise unbound = will throw error: >>>>>>>>>>>>>>>>>>>>>>>> +# "[1723428668] unbound-control[17117:0] = error: connect: Connection refused for 127.0.0.1 port 8953" >>>>>>>>>>>>>>>>>>>>>>>> +/bin/rm --verbose --force = /etc/unbound/local.d/*.rpz.conf >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Update Language cache >>>>>>>>>>>>>>>>>>>>>>>> +/usr/local/bin/update-lang-cache >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# start unbound to load unbound config file >>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound start >>>>>>>>>>>>>>>>>>>>>>>> diff --git a/src/paks/rpz/update.sh = b/src/paks/rpz/update.sh >>>>>>>>>>>>>>>>>>>>>>>> new file mode 100644 >>>>>>>>>>>>>>>>>>>>>>>> index 000000000..9bc340bc6 >>>>>>>>>>>>>>>>>>>>>>>> --- /dev/null >>>>>>>>>>>>>>>>>>>>>>>> +++ b/src/paks/rpz/update.sh >>>>>>>>>>>>>>>>>>>>>>>> @@ -0,0 +1,52 @@ >>>>>>>>>>>>>>>>>>>>>>>> +#!/bin/bash >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# IPFire.org - A linux based firewall # >>>>>>>>>>>>>>>>>>>>>>>> +# Copyright (C) 2024 IPFire Team = <info@ipfire.org> # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is free software: you can = redistribute it and/or modify # >>>>>>>>>>>>>>>>>>>>>>>> +# it under the terms of the GNU General Public = License as published by # >>>>>>>>>>>>>>>>>>>>>>>> +# the Free Software Foundation, either version = 3 of the License, or # >>>>>>>>>>>>>>>>>>>>>>>> +# (at your option) any later version. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# This program is distributed in the hope that = it will be useful, # >>>>>>>>>>>>>>>>>>>>>>>> +# but WITHOUT ANY WARRANTY; without even the = implied warranty of # >>>>>>>>>>>>>>>>>>>>>>>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR = PURPOSE. See the # >>>>>>>>>>>>>>>>>>>>>>>> +# GNU General Public License for more details. = # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> +# You should have received a copy of the GNU = General Public License # >>>>>>>>>>>>>>>>>>>>>>>> +# along with this program. If not, see = <http://www.gnu.org/licenses/>. # >>>>>>>>>>>>>>>>>>>>>>>> +# # >>>>>>>>>>>>>>>>>>>>>>>> = +#########################################################################= ###### >>>>>>>>>>>>>>>>>>>>>>>> +# >>>>>>>>>>>>>>>>>>>>>>>> +. /opt/pakfire/lib/functions.sh >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# from update.sh >>>>>>>>>>>>>>>>>>>>>>>> +extract_backup_includes >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# stop unbound to delete RPZ conf file >>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound stop >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# from uninstall.sh >>>>>>>>>>>>>>>>>>>>>>>> +make_backup ${NAME} >>>>>>>>>>>>>>>>>>>>>>>> +remove_files >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# delete rpz config files. Otherwise unbound = will throw error: >>>>>>>>>>>>>>>>>>>>>>>> +# "unbound-control[nn:0] error: connect: = Connection refused for 127.0.0.1 port 8953" >>>>>>>>>>>>>>>>>>>>>>>> +/bin/rm --verbose --force = /etc/unbound/local.d/*.rpz.conf >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# from install.sh >>>>>>>>>>>>>>>>>>>>>>>> +extract_files >>>>>>>>>>>>>>>>>>>>>>>> +restore_backup ${NAME} >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# fix user created files >>>>>>>>>>>>>>>>>>>>>>>> +chown --verbose --recursive nobody:nobody \ >>>>>>>>>>>>>>>>>>>>>>>> + /var/ipfire/dns/rpz \ >>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/zonefiles \ >>>>>>>>>>>>>>>>>>>>>>>> + /etc/unbound/local.d >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# Update Language cache >>>>>>>>>>>>>>>>>>>>>>>> +/usr/local/bin/update-lang-cache >>>>>>>>>>>>>>>>>>>>>>>> + >>>>>>>>>>>>>>>>>>>>>>>> +# restart unbound to load config files >>>>>>>>>>>>>>>>>>>>>>>> +/etc/init.d/unbound start >>>>>>>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>>>>>>>> 2.39.5 >>>>>>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>>>> Jon >>>>>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>>>>>> Jon Murphy >>>>>>>>>>>>>>>>>>>>>> jon.murphy@ipfire.org >>>>>>>>>>>>>>>>>>>>=20 >>>>>>>>>>>>>>>>>>>> Jon >>>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>>>> Jon Murphy >>>>>>>>>>>>>>>>>>>> jon.murphy@ipfire.org >>>>>>>>=20 >>>>>>>>=20 >>>>>>>>=20 >>>>>>=20 >>>>>>=20 >>>>=20 >>>>=20 >>>=20 >>=20 >>=20