Timotej Lazar
048195c45c
Before we relied on the combined data being present in ipsets.json when generating a new config, but ipsets.json is only updated through the form at /ipsets. So submitting any other form after changing NetBox definitions might crash when trying to find an entry from networks.json in ipsets.json. Now we introduce a helper functon to always read both files and combine the prefixes fron networks.json with ipsets.json. This way it is not necessary to save a new ipsets.json before other changes. Also don’t crash when enumerating networks for each VPN group.
54 lines
3.2 KiB
Markdown
54 lines
3.2 KiB
Markdown
# FRIwall
|
|
|
|
Web application for managing the main firewall at FRI.
|
|
|
|
## Operation
|
|
|
|
The firewall consists of two servers (or “bricks”) in active–backup configuration, using weighted BGP routes for failover. Traffic filtering and VPN are done with nftables and WireGuard. Both are configured exactly the same on both servers. The settings are managed with this application.
|
|
|
|
On each configuration change, a tarball of relevant files in `/etc` is generated and pushed via SSH to both nodes. This happens for instance each time an IP set or a forwarding rule is modified, or a VPN key is added or removed. Firewall nodes and the current configuration version for each are stored in `nodes.json`.
|
|
|
|
## Database
|
|
|
|
Application data is stored in a number of JSON files in the home directory of the user the application runs as. The `db` module defines utility functions to ensure consistency when manipulating data:
|
|
|
|
- `lock(name)` and `unlock(name)` acquire or release the lock for a given file or all files with no argument;
|
|
- `read(name)` and `write(name, data)` retrieve or store a dictionary in the given file, which should be locked;
|
|
- `load(name)` and `save(name, data)` do the same but lock the file first.
|
|
|
|
## IP sets
|
|
|
|
Names and IP prefixes for physical networks are configured in NetBox and stored in `networks.json`, which is never modified by the application. Custom IP sets used for forwarding rules may be defined at `/ipsets`, as well as NAT addresse and VPN access for all networks. These settings are stored in `ipsets.json`. To read and combine data from both files, the `ipsets.read` utility function should be used. Combined data may then be modified and written back to `ipsets.json`, as with all other files.
|
|
|
|
## Rules
|
|
|
|
Forwarding rules are configured at `/rules` and toggled at `/rules/manage`. Enabled rules are included directly in the nftables configuration. For each rule, one or more manager groups can be set; users in these AD groups may toggle the rule without admin access. This is used for instance to allow teachers to disable Internet access in classrooms.
|
|
|
|
## VPN
|
|
|
|
WireGuard is used for remote access. Domain users can self‐register new keys at `/vpn`. The key database `wireguard.json` is a dictionary of entries like
|
|
|
|
"10.0.0.26": {
|
|
"key": "ABC…XYZ=",
|
|
"ip6": "aaaa:bbbb:cccc:dddd:1a::/80",
|
|
"time": 1682166836.88937,
|
|
"name": "machine1",
|
|
"user": "user@domain"
|
|
}
|
|
|
|
IP addresses for new keys are assigned automatically from the subnets defined in `wg_net` and `wg_net6` settings. When generating firewall configuration, each IP is placed in the nftables sets based on its user’s group and settings in `ipsets.json`.
|
|
|
|
### Custom keys
|
|
|
|
Administrators can define custom keys with access to specified networks at `/vpn/custom`. These keys are used to connect machines into secure networks where users are not allowed to attach arbitrary devices themselves.
|
|
|
|
Custom keys are stored in the same database, but with a `networks` entry in place of `user`, for instance
|
|
|
|
"10.0.0.27": {
|
|
"key": "FOO…BAR=",
|
|
"ip6": "aaaa:bbbb:cccc:dddd:1b::/80",
|
|
"time": 1682166836.88937,
|
|
"name": "machine2",
|
|
"networks": ["net1", "net2"]
|
|
}
|