diff --git a/README.md b/README.md index c43c801..9117b25 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,14 @@ A custom `[section]` has the following options. We're calling them locals most o Subnets are unsupported, both as subnet masks (`142.251.36.195/255.255.255.248`) and in [CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) notation (`142.251.36.195/29`). Do not single- nor double-quote list entries. Do feel free to separate entries with comma-space instead of just a comma. + ``` + # Valid example: + addr = 2606:4700:20::681a:804, lowendtalk.com + + # Also valid (this is the default): + addr = + ``` + * `ports`, __*optional*__, defaults to `80, 443`: A comma-separated list of ports that should be accessible from `addr`. If empty `addr` may access all ports. See [iptables-extensions man page, section "multiport"](https://ipset.netfilter.org/iptables-extensions.man.html#lbBM) for syntax reference. All port-based rules use `iptables ... --match multiport` even if you're only allowing access to a single port. In essence construct your ports list with any combination of single ports (`80, 443, 8080`) and port ranges (`6660:7000, 61000:65535`). ``` @@ -189,10 +197,118 @@ A custom `[section]` has the following options. We're calling them locals most o * `state`, __*optional*__, defaults to `NEW`: Comma-separated list of connection tracking states against which a packet is matched. Most of the time your rules will want to use the default `NEW`. The final `DROP` rule present in the example `config.ini` file at [examples/config.ini.example](examples/config.ini.example) is one occasion where you'll want to deviate and unset `state` to an empty value. See ["state" extension man page in iptables docs](https://ipset.netfilter.org/iptables-extensions.man.html#lbCC) for reference. + ``` + # Valid example: + state = + ``` + * `do_ipv6`, __*optional*__, defaults to `false`: Decide if you want `firewalld` to generate `ip6tables` rules in addition to `iptables` rules. A default install of Docker Engine will have its IPv6 support disabled in `/etc/docker/daemon.json` in which case `ip6tables` will not have a `DOCKER-USER` or similar Docker-related chains. In this default setup having `update-firewall-source.py` generate an otherwise unused `DOCKER-USER` chain and adding rules to it clutters your rule set. Consider setting this to `true` if and when your Docker install uses IPv6. If this is `true` IPv6 addresses found or resolved in `addr` in a `[section]` will be discarded. + ``` + # Valid example: + do_ipv6 = true + ``` + +## iptables behind the scenes + +In an `iptables` rule set in the `filter` table by default you'll see something like this. We're only focusing on `INPUT` and `FORWARD` chains here as these are the ones relevant to Docker. + +``` +Chain INPUT (policy ACCEPT 140 packets, 10115 bytes) +num pkts bytes target prot opt in out source destination + +Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) +num pkts bytes target prot opt in out source destination + +... +``` + +Once you install a moderately modern Docker Engine it changes things up to this: + +``` +Chain INPUT (policy ACCEPT 1027 packets, 78370 bytes) +num pkts bytes target prot opt in out source destination + +Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) +num pkts bytes target prot opt in out source destination +1 0 0 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0 +2 0 0 DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0 +3 0 0 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED +4 0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0 +5 0 0 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0 +6 0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0 + +... + +Chain DOCKER-USER (1 references) +num pkts bytes target prot opt in out source destination +1 0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 +``` + +With UFS you're extending this into a configuration where UFS' `FILTERS` chain is called from both Docker's `DOCKER-USER` chain **_and_** the host OS `INPUT` chain. Ideally `FILTERS` ends with a `DROP` target to make sure nothing accesses your services that's not supposed to access them. + +``` +Chain INPUT (policy ACCEPT 56 packets, 4596 bytes) +num pkts bytes target prot opt in out source destination +1 2910 207K ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 +2 1309 111K FILTERS all -- * * 0.0.0.0/0 0.0.0.0/0 + +Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) +num pkts bytes target prot opt in out source destination +1 0 0 DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0 +2 0 0 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0 +3 0 0 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED +4 0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0 +5 0 0 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0 +6 0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0 + +... + +Chain FILTERS (2 references) +num pkts bytes target prot opt in out source destination +1 1267 107K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED +2 0 0 ACCEPT tcp -- * * 1.2.3.4 0.0.0.0/0 state NEW multiport dports 22,80,443 /* My home */ +3 1 162 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 /* deny-all */ + +Chain DOCKER-USER (1 references) +num pkts bytes target prot opt in out source destination +1 0 0 FILTERS all -- ens3 * 0.0.0.0/0 0.0.0.0/0 +2 0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 + +... +``` + +## Rule comments + +The `[section]` name is used as `ip(6)tables` rule comment. The `[section]` name is truncated to the first 256 characters to fit into an `ip(6)tables` comment if needed. + +Example: + +``` +[My home] +addr = some.dyndns.host.net +ports = 22, 80, 443 + +[deny-all] +target = DROP +addr = +ports = +proto = +state = +``` + +Results in `ip(6)tables` rules: + +``` +Chain FILTERS (2 references) +num pkts bytes target prot opt in out source destination +1 1267 107K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED +2 0 0 ACCEPT tcp -- * * 1.2.3.4 0.0.0.0/0 state NEW multiport dports 22,80,443 /* My home */ +3 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 /* deny-all */ +``` + # Development ## Conventional Commits