In this article I will be mixing some ideas and concepts both of my own and I've seen in the web:
- git hooks to check content of new commit
- linux net namespaces to check if ruleset could load
- atomically replace a nftables ruleset
Mainly, getting nftables hooked in git is matter of combing these elements:
- a sudo security policy
- a git config and workflow to handle the checks and deployments
- a nftables workflow and ruleset architecture
We have a team of sysadmins who are working together to maintain a big ruleset (thousand of rules). Keeping track of changes is almost mandatory, and git does this thing very well.
Also, we want to prevent some human mistakes in terms of bad nftables syntax. In the devel world, this is equivalent to prevent developers to push code which fails to build from source. A basic QA.
If all is OK, replace the ruleset in an atomic way.
I assume this dirs scheme:
- the nftables ruleset is at
/etc/nftables.d
(don't touch this dir by hand!) - git repo in bare mode is at
/srv/git/nft-firewall.git
- sudoers policy is at
/etc/sudoers.d/nft-git
Create a git repo in bare mode somewhere, for example /srv/git/nft-firewall.git
(with git init --bare
).
Put update and post-receive hook scripts under /srv/git/nft-firewall.git/hooks/
with proper execs permissions.
The update hook will do the "QA" part when the user push changes from their local repos:
- Create a temp dir under /tmp
- Export the ruleset there (the new ruleset isn't in the filesystem yet, that's why git archive is used)
- Create a linux netnamespace
- Load the ruleset in the new network ns
- If the ruleset fails to load, reject the commit.
- If the ruleset loads, all is OK, do some cleanups and exit.
- The post-receive hook will run after the update hook, and takes care of the effective deployment of the just-changed ruleset:
- Checkout the git repo to /etc/nftables.d (this is, actually deploy the nftables config to the filesystem).
- Clean untracked files and dirs at /etc/nftables.d (don't touch this dir by hand!)
- Load the new ruleset.
nftables comes with a set of handy options which will permit you to organize the ruleset (thus, the firewall) in very flexible ways.
In this example, I use this layout:
/etc/nftables.d/ruleset.nft
(the main file)/etc/nftables.d/inet-filter-chain-input.nft
(filter rules in the input chain for the inet family)/etc/nftables.d/inet-filter-chain-forward.nft
(filter rules in the forward chain for the inet family)/etc/nftables.d/inet-filter-chain-output.nft
(filter rules in the output chain for the inet family)/etc/nftables.d/inet-filter-sets.nft
(data sets for the inet filter table)
So, we will be 'including' all the files from ruleset.nft
, plus flushing the previous ruleset.
In the other files, we only define each chain and rules. In the set file we define sets which are globals to be used by all rules in the inet filter table.
The nftables ruleset is meant to be loaded with 'nft -f ruleset.nft' which will perform an atomic replacement of the ruleset.
Before any other step, be sure you are following the security policy of your organization regarding this.
In order to allow all these operations with a unprivileged users (which BTW is modifying the ruleset via a remote git push), we need a concrete sudo policy.
Creating netnamespaces and modifying the nftables ruleset is a privileged operation.
My recomendation at this point is a sudoers file like the one you can find at the github repo.
The NOPASSWD
option is required for sudo to don't ask user password while in the git hooks.
You should take care also of standard unix users/groups layout. Give appropriate permissions to working dirs/scripts. For example, put your operators in a group git
, give the git bare repo group git
and give g+w.
A sys-admin team member could end in a workflow like this:
- Clone the nft-firewall.git repo
- Make changes to the ruleset (add a rule, replace other... whatever)
- Run some local tests (sure)
- Commit on your local repo
- Push to the git server
- The git server will run the hook scripts, testing and deploying the new ruleset
- Other sysadmin clones or pull the repo and go to step 2.
This was inspired by this blogpost by Vincent Bernat.
Check the nftables wiki.
Also, the official docs about git hooks.