Bolt on for whonix_firewall - best place to put files?

I am working on a bolt on to whonix_firewall.

I am trying be consistent, and follow the whonix convention in /etc/whonix_firewall.d.

There are number of files possible, just like in /etc/whonix_firewall.d.

What would be whonix’s preference / convention be:

(1) Create /etc/whonix_firewall-post.d (or … suggestion?) and put files in there.

(2) Create files in /etc/whonix_firewall.d, but append '-post" (or … suggestion?) to the files, with an eye towards eventually modifying whonix_firewall to skip such files in its own processing?

Non-Qubes-Whonix:

We are currently using an /etc/network/if-pre-up.d/ hook.

https://github.com/Whonix/whonix-gw-firewall/blob/master/etc/network/if-pre-up.d/30_whonix_firewall

So any pre and post scripts could also be added to /etc/network/if-pre-up.d/?


Qubes-Whonix:

As of Whonix 12 uses https://github.com/Whonix/qubes-whonix/blob/master/lib/systemd/system/qubes-whonix-firewall.service. Could be extended with usual systemd drop-in (.d) files, ExecStartPre or ExecStartPost.


Future firewall loading:

Not that much related, but a bit… For Qubes generally I suggested to use netfilter-persistent. That may be perfectly suitable for distributions which would also allow chaining of iptables rules, pre and post.

broken /etc/resolv.conf, broken DNS resolution · Issue #1067 · QubesOS/qubes-issues · GitHub

Although I recommended against using iptables-persistent as a distribution. That may be more appropriate for sysadmins. But caused an issue for distributions (removed iptables-persistent from Depends to improve usablity by adrelanos · Pull Request #2 · QubesOS/qubes-core-agent-linux · GitHub).

This would make the setups more uniform and chaining iptables rules with pre and post scripts would be simpler.


//cc @HulaHoop

I don’t expect that to be the case, as the files/rules will need the env. vars that whonix_firewall sets up. Thus it seems simplest to have whonix_firewall ultimately source the files, as it does so currently for the contents of whonix_firewall.d. (Thus my question of preference, different .d directory, or differentiating filenames within the current .d directory.)

I can see your point, though. However, I don’t expect there’s interest in splitting out whonix_firewall to call something like whonix_firewall_setenv.

Without such, any bolt on would break at a whonix_firewall change, creating a perpetual maintenance cycle.

[The intent is to impact the current iptables rules to the least extent possible - there is serious protection and thinking behind them to be leveraged.]

Suggestions?

I have been wondering for some time now if the firewall script should be split. A lot sections are being used by multiple packages, whonix-gw-firewall, whonix-ws-firewall and vpn-firewall. Eventually further in future (corridor-gateway to be created one day)…

  • error_handler
  • source config folder
  • IPv4 DEFAULTS
  • IPv4 PREPARATIONS
  • IPv4 DROP INVALID INCOMING PACKAGES
  • IPv4 FORWARD
  • IPv6
  • more minor stuff (iptables_cmd, ip6tables_cmd)

Converted to shell functions. And added to anon-shared-helper-scripts.

The risk of changing firewall rules while refactoring is minimal because it can be verified:

However, the goal is to make the firewall scripts easier to read. Not more difficult to audit. I am not sure which style (all in one file vs split) makes it simpler at this point.

//cc @marmarek

Hmmm.

Let alone, split as separate scripts, or as separate files sourced by separate scripts.

Moreover, what is really being talked about is system configuration values. (And are environment variables really the best way to declare them - since even exporting them would only impact in line calls. Programs needing those values outside of that chain don’t get them.) [Not professing one or the other here, merely noting that I see the conundrum.]

In the mean time, what would be preferred - modifying whonix_firewall to ignore files suffixed with ‘-post’?

[quote=“Patrick, post:4, topic:2222”]
The risk of changing firewall rules while refactoring is minimal because it can be verified:[/quote]

Not so sure that’s true - at development time, yes. At run time, most anything could get their fingers in there. Isn’t this really suggesting some form of iptables intended / current diff run called by whonixcheck?

[quote]
www.whonix.org

Dev/Firewall Refactoring

How to refactor Whonix’s firewall.[/quote]

I don’t think I’m well following that article / its intent.

It reads more like a iptable verification process than a refactoring. Am I missing something?
(never mind, why not just use iptables-save | cut {something or other}. In either case a post-run munging to minimize diff hits is going to be needed.)

Does ‘Dev/Firewall Refactoring’ need to itself be refactored to individually thread the items (you so excellently) note?

I would source them. Not call as separate scripts. Easier with shared variables.

We should not mix up the config folder /etc/whonix_firewall.d with other possible future folders for dispatching pre or post hooks. That would be non-standard. We being the only ones doing that.


The following gives maximum ability to add pre/post hooks everywhere.

funct1() {
...
}
funct2() {
...
}
funct3() {
...
}
main() {
   funct1
   funct2
   funct3
}

...source some .d folder(s)...

main "$@"

When sourcing of a .d folder is done early, it allows to overwrite any shell function. Including the main function to change ordering what is run and when.

genmkfile has a mechanism to automatically run funcname_pre and functname_post functions - if they have been declared in a .d folder. So you can have pre and/or post actions for any shell function that is run anyhow. And if that is not enough, you can also re-implement / overwrite the whole default shell function.

genmkfile/usr/share/genmkfile/make-helper.bsh at bbe8e989a29f1620a71e13b2ed6717ceb09d8825 · Kicksecure/genmkfile · GitHub

If this is still too unclear, I can try implementing a pseudo example script called “super-flexible” which shows as far as I can imagine how far hooking can go.


The other question with firewall code injection, pre/post hooks is when to dispatch them? When you want to dispatch them depends on what you actually want to implement.

For example obviously running the hook after $iptables_cmd -A INPUT -j DROP would not allow you to modify the input chain. (Unless doing trickery that would look awful.) On the other hand, do you want your hook dispatched before or after $iptables_cmd -t nat -A PREROUTING -i "$int_if_item" -p udp --dport 53 -j REDIRECT --to-ports "$DNS_PORT_WORKSTATION"? Again it depends on what you want to implement.

It feels easy enough, for example, to split out env. var setting within whonix_firewall to something like /etc/whonix_firewall.d/10_setenvvars, but I don’t grok enough of whonix to be confident that doing so is appropriate / consistent / desired. e.g. The multiple scripts you note would need to understand that pinned down filename.

Let alone, each script would have to duplicate that a var exists / is set. Each var dev. change would need reflection in each script dependent upon the file.

I can work on this if desired, but these feel like global whonix environment settings, of which the whonix_firewall particulars are but a subset. Is this even a reasonable mechanism to perpetuate?

(Again, I’m not arguing, nor arguing one way or another. I don’t profess to know.)

Dev/Firewall Refactoring - Kicksecure purpose is only a description on how to ease development.

Let’s say the line was

$iptables_cmd -A INPUT -j DROP;

And I want to change it to.

$iptables_cmd -A INPUT -j DROP

Or the whole thing gets converted into a shell function. (Just a demonstrative example.)

Then the intent of the firewall script change was not to change actual iptables rules. It was code refactoring only. And to make sure it was only code refactoring and no actual iptables chain change, the above instructions should work. So when adding some new hook code theoretically or when splitting the firewall script into multiple files or whatever it is easy to verify, that only the layout was changed, not the actual iptables chain. It does not go beyond that. No leak testing etc. However, it’s sane to have an iptables dump of Whonix 12 and then compare it with Whonix 13 etc.

[quote=“Patrick, post:8, topic:2222”]
If this is still too unclear, I can try implementing a pseudo example script called “super-flexible” which shows as far as I can imagine how far hooking can go.[/quote]

No, by including the example you did, I get a glimpse of what you’re saying - and can appreciate it. Refinement / specifics can come if/should such be considered for acceptance.

Yep. Thus the next step after the file location would be a whonix_firewall change to call them (at the end).

Yep. That’s why I expect to propose whonix_firewall changes to set such rules in env. vars.

e.g.
IPT_FILT_INP_LASTRULE=‘INPUT -j DROP’
$iptables_cmd -A $IPT_FILT_INP_LASTRULE

And scripts can:
$iptables_cmd -D $IPT_FILT_INP_LASTRULE
$iptables_cmd -A {other good stuff}
$iptables_cmd -A $IPT_FILT_INP_LASTRULE

You are suggesting…

  • set all rules as env vars first
  • allow overwriting with a .d folder that gets sourced
  • $env_var_1, $env_var_2 (more pretty names) etc. below?

I guess that would be super difficult to read if we did that for each and every time executing $iptables_cmd.

AGREED. And not something I would want to suggest. Simpler is better. (Mind you, I find whonix_firewall pretty easy to read as it stands now. So not sure about others looking for simpler. But I do take your points of multiple callers, and the value of functions().)

The idea of a bolt on (addon?), optionally chosen / added functionality, is to leave the base strictly alone / completely transparent to those who didn’t take specific steps to enable that functionality. While enabling those who do choose to choose the option, to be able to do so.

Unfortunately, inherent to such a facility is being able to leverage the good stuff that is already there (e.g. env. vars like INT_IF), and hooks for calls to such if present. Which is to say, changes to current scripts. (That null out if the option not chosen.)

Thus, I take your point, and agree, that a separate .d directory is the correct answer, rather that inserting changes into current, to segregate such off, and have the least impact upon base, possible.

In that case I would have a simpler and more readable implementation in mind. Before the reject iptables rule… If function whonix_firewall_input_hook_end exists, execute it. (Open for better function name.)

if [ "$(type -t whonix_firewall_input_hook_end)" = "function" ]; then
   whonix_firewall_input_hook_end
fi

That way you could ship a file /etc/whonix_firewall.d/40_something.conf:

whonix_firewall_input_hook_end() {
   ... your stuff ...
}

allow overwriting with a .d folder that gets sourced

Ah. OK, I get you now - initial sourcing picks up function definitions (but not execution thereof) at that time.

However, this feels overly complex. I’m not saying unnecessarily so, I wouldn’t know - the more I look the more I realize how many larger concerns are in play (e.g. qubes vs whonix, poking at the packages you noted, debian + lintian), the more expensive it appears gazing into the contributing room from the doorway. And the less inclined I am to cross that threshold. (No doubt, after several years of contributing, looking back on that comment will feel very newbie and wasn’t really something all that intimidating. Not so much so, today, though.)

Here, in this complexity, not doing as you suggest feels like it brings: prove {this} out {fini}, next then prove {that} out {fini}. vs the complexity, inserting many little bits in many places, and having to prove the whole out every time. i.e. Every time one turns around there’s another new entire ecosystem to grok before one can begin to think about where they’re trying to go. (I’m not saying this isn’t inherent / inevitable, merely daunting.)

Hmmm. This doesn’t handle the case of multiple addons. Unless it is the responsibility of each function declarer to chain to the next. Or leads to what essentially become callbacks.

Arrays, instead?

func mypostcallstuff() {
mystuff;
}

hook_end_funcs += mypostcallstuff();

foreach hook_end_funcs call hook_end_funcs(@);

[Pardon the really bad pseudo-code.]

  • problem, something developed later wants to insert itself earlier in the chain, the running of which breaks something developed earlier but now called later. (Perhaps this is an inevitable Catch 22.)

Is there a separate forum / wiki / phabircator (?) area where this discussion should be moved to / is already ongoing?

In the mean time, see next messages, trying to keep discussion points / threads here separate.

[quote=“Patrick, post:4, topic:2222, full:true”]
I have been wondering for some time now if the firewall script should be split. A lot sections are being used by multiple packages, whonix-gw-firewall, whonix-ws-firewall and vpn-firewall.[/quote]

I was startled some while back when I realized that, e.g. whonix-gw-firewall and whonix-ws-firewall, did not ‘source’ a common bit of code across both.

From comments here, it seems that such is desirable. How to go about getting from current to there?

So, the article is really just expressing the desire for a iptables sanity check process.

I expect I can come up with such - I’ve already gone almost blind trying to sanity check scripts, and verify pre- and post- script iptables impact.

However, I’ve no idea where / how to plug the right things to the right places in the whonix git. i.e. Inherently, it feels like such a facility would get incorporated into whonixcheck (much like the extra / unwanted package checks). However, if one chooses to use an ‘addon’, ‘good’ [Warn?Diff:NotDiff] becomes a moving target I don’t see how to incorporate. Never mind where/how to incorporate such into whonixcheck at all, and a default inclination to keep my sticky fingers out of it entirely.

Dev/Firewall Refactoring does not need to go into whonixcheck. It’s a lot simpler process than you might think.

  1. developer stores an iptables rules dump
  2. developer does some refactoring in the firewall script
  3. developer stores another iptables rules dump
  4. diff the dumps

Or…

  1. developer stores an iptables rules dump of Whonix 12
  2. developer stores another iptables rules dump of Whonix 13
  3. diff the dumps

It’s so simple it may even go without saying as an implicit expectation when making changes.

I take your point, but I’m not so sure.

[At the least, presumably one would want to call such as part of the build process. iptables rule changes possibly inadvertently killing connectivity isn’t something you want to leave to ‘hope the developer ran this check’. Oops, they forgot.]

Many things post-installation can munge on iptables, deliberately such as ufw, pgl, or any other firewall, or inadvertently (and hidden) by accident or nefariousness. Since, for example, I don’t run qubes, I have no way to check qubes impact. One after installation insertion of -j ACCEPT would seriously endanger ones objective in choosing whonix.

In any case, where to plug in any results? The wiki item, then transform / transmit to {destination} when such becomes apparent?

It could be part of the build process by policy. I.e. running a test suite, which we don’t have. But not part of the image build script, because it runs in chroot and we don’t want to modify the build system iptables rules.

Anyhow. It’s a separate discussion that deserves a separate topic. For refactoring whonix firewall script (move to functions or similar), Dev/Firewall Refactoring really is enough.

Also whonixcheck (which is somewhat a replacement for the lack of test suite) could indeed be useful to check if the loaded iptables rules match a hardcoded iptables dump. Yes, with additional firewalll add-ons that would be hard. Then these firewall add-ons could ship a dump that also gets verified. (iptables-dumps.d folder checked by whonixcheck or so.) But then multiple firewall add-ons gets hard. Mutliple firewall add-ons and dumping, that kind of flexibility might be stretching what the Whonix project may be able to implement. That is more like an iptables super flexibility project. Lots of work to do. Also deserves additional thread.

OK. Thank you.

Except … I still don’t fathom a wiki page (sans talk pages) serving such a purpose. Is there a wiki page around that shows such use?