-
-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Firewall: Add support for arbitrary rules for input, output and forward #12940
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Firewall: Add support for arbitrary rules for input, output and forward #12940
Conversation
By analyzing the blame information on this pull request, we identified @wkennington, @edolstra and @bluescreen303 to be potential reviewers |
b94da71
to
045f2f2
Compare
Thanks a lot for this! I'm willing to review & test this soon if nobody beats me to it. |
default = null; | ||
type = types.nullOr ( | ||
types.addCheck types.str ( | ||
v: v == "ACCEPT" || v == "DROP" || v == "REJECT" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not an enum here? Also, isn't LOG
an option sometimes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, enum sounds like the word I didn't remember when writing this ;-)
LOG
would be the action to just log, nothing else, right?
Also I think having DROP and REJECT both could be seen as superfluous as the actual action depends on the global rejectPackets
option. (Current difference between DROP and REJECT is that the first sends to nixos-fw-refuse while the later sends to nixos-fw-log-refuse.
Maybe these choices here shouldn't be these abstract names but the real chain names (without the nixos-fw-prefix)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, isn't LOG an option sometimes?
What would you think is better:
rule = [
{ fromInterface = "eth0"; target = "LOG"; log-prefix="bla: "; log-level = "info"; }
{ fromInterface = "eth0"; target = "ACCEPT"; }
];
with two rule-entries to explicitly LOG and ACCEPT the connection/packet? Or
rule = [
{ fromInterface = "eth0"; target = "ACCEPT"; log-prefix="bla: "; log-level = "info"; }
];
to have one rule-entry and create two iptables rules with log and accept implicit. Is there a need for logging without any special ACCEPT/DROP/REJECT handling?
I vote for transparent conversion of allowed ports into rules -- I like them for simplicity (and no need for one to understand iptables). |
11fa843
to
c1584d7
Compare
29a3f5d
to
4316c21
Compare
(triage) |
@grahamc security |
This extends the firewall to support arbitrary rules for the INPUT, OUTPUT and FORWARD chains. All the rules are placed in nixos-fw-[input|output|forward] chains. It also adds support to define the default policies of the chains. Logging works as special target. When hits for a rule should be logged, this rule has to be defined twice, once with the LOG target and once with the actual action. Or you just rely on logRejectedPackets. The old nixos-fw chain is deleted first. This is only really needed when switching to this new feature-branch and activiting the config the first time. But for this one case its needed as otherwise the accept and refuse chains can't be deleted. Also delete the invalid chain to allow reload to work. For debugging its now possible to run only the ipv6 tests or only the ipv4 tests. Maybe this should even be extracted into a parameter before including this in nixos.
4316c21
to
666b0b2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, thank you very much for the PR, it contains some awesome stuff (imho) 😄
However, imho it's a bit too late to get this right for 17.3
and would suggest to aim for 17.9
instead (unfortunately at least I don't have the time for a proper review atm and it's a pretty complex change anyway).
There is also an issue (and PR as I just noticed) for switching to nftables
and I'd personally aim for creating an abstraction layer (should require nixifying the rules, but even that's probably not enough...) so that we can use iptables
, nftables
, etc. as "back-ends" (I'll probably create an issue for that, but that has to wait for at least one weak as I don't have the time atm).
(Please note that the review is incomplete, just wanted to note some stuff until I or someone else has the time to do a proper review.)
FORWARD = "nixos-fw-forward"; | ||
PREROUTING = "PREROUTING"; | ||
POSTROUTING = "POSTROUTING"; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great if you could document these new rules at the beginning of the file.
getTargetForPolicy = policy: | ||
if policy == "ACCEPT" | ||
then "nixos-fw-accept" | ||
else "nixos-fw-refuse"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems a bit odd (without looking at the rest). If I hear policy I'd expect the following:
Only built-in (non-user-defined) chains can have policies, and neither built-in nor user-defined chains can be policy targets.
ip46tables -D INPUT -j nixos-fw-input 2> /dev/null || true | ||
ip46tables -D OUTPUT -j nixos-fw-output 2> /dev/null || true | ||
ip46tables -D FORWARD -j nixos-fw-forward 2> /dev/null || true | ||
for chain in nixos-fw nixos-fw-accept nixos-fw-input nixos-fw-output nixos-fw-forward nixos-fw-accept nixos-fw-log-refuse nixos-fw-refuse __invalid_chain__ FW_REFUSE; do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nixos-fw-accept
appears twice- You can drop
FW_REFUSE
(see 460b43d (was after your PR)) - I don't really like the following name:
__invalid_chain__
(that's just my personal opinion tho)
# Accept packets from established or related connections. | ||
ip46tables -A nixos-fw-input -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept | ||
ip46tables -A nixos-fw-forward -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept | ||
ip46tables -A nixos-fw-output -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't touch forward by default (probably set the policy to DROP
- but that could break some setups).
I assume new connections are handled below, if not we need the connection state NEW
as well.
input = mkOption { | ||
default = "DROP"; | ||
type = types.enum targetTypes; | ||
description = ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An empty description seems a bit odd, even if we probably don't need it.
''; | ||
}; | ||
|
||
networking.firewall.rules = mkOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nixifying the FW rules seems like a great idea (imho).
However #22586 does that as well (IIRC), i.e. we have to compare/merge them.
As this has been open for a year (and @kampfschlaefer would certainly like at least a resolution on this PR), ccould we put it in the 17.09 milestone? |
Please don't merge this - it conflict's with #22586 and there hasn't been any discussion yet! Just wanted to make sure anyone is aware of this as I can't see how we (currently) can merge them both. I encourage anyone to compare them and decide which one we use (or we could probably use parts from both). I don't really have much time ATM but I created the following issue to share some of my thought/ideas: #23181 |
This extends the firewall to support arbitrary rules for the INPUT, OUTPUT and
FORWARD chains. All the rules are placed in nixos-fw-[input|output|forward]
chains. It also adds support to define the default policies of the chains.
Logging works as special target. When hits for a rule should be logged, this
rule has to be defined twice, once with the LOG target and once with the actual
action. Or you just rely on logRejectedPackets.
The old nixos-fw chain is deleted first. This is only really needed when
switching to this new feature-branch and activiting the config the first time.
But for this one case its needed as otherwise the accept and refuse chains
can't be deleted. Also delete the invalid chain to allow reload to work.
For debugging its now possible to run only the ipv6 tests or only the ipv4
tests. Maybe this should even be extracted into a parameter before including
this in nixos.