Simple script, allows to manage docker published ports in IPTABLES the same way as local published ports.
All filtering happens in mangle table: allowed, denied and rejected packets are marked. In INPUT and OUTPUT chains packets are accepted, dropped or rejected by flag set.
This makes setup simple, straightforward and easy to manage. See examples in iptables directory.
git clone https://github.com/freepaddler/ssdfw
sudo install -m 755 ssdfw/ssdfw.sh /usr/local/bin/ssdfw
sudo mkdir -p /etc/ssdfw/rules.d
sudo cp ssdfw/iptables/ssdfw.rules /etc/ssdfw/rules
sudo install -D -m 644 ssdfw/systemd/ssdfw.service /etc/systemd/system/ssdfw.servicePlace rules in:
/etc/ssdfw/rules/etc/ssdfw/rules.d/*.rules
If /etc/ssdfw does not exist, legacy paths are used instead:
/etc/iptables/ssdfw.rules/etc/iptables/ssdfw.d/*.rules
If no rule files are found in the selected location, rules are applied from script itself (yes, they may be also managed).
Run ssdfw.sh without args to apply rules. Script will try to use 'iptables-apply' (if found) to be failsafe.
Use ssdfw apply to apply rules directly without interactive iptables-apply prompts, for example from systemd.
Subcommands (1st arg):
applyapply rules directly, without iptables-apply promptsshowshow all ssdfw rules (iptables -S)listlist all ssdfw rules (iptables -L)flushdelete ssdfw rules, allow in and outflush_iptablesdelete all iptables rules, allow in and out
Find rules examples in iptables directory.
Since ssdfw.sh is just a shell script, working with iptables, then most directives are just vars and functions declared in script itself.
You can easily use original iptables commands to add custom rules.
Add DNAT rules
-
table: nat
-
chain: PREROUTING
-
directive
$nat_into add rule to the section -
targets:
- any IPTABLES supported targets (commonly DNAT)
Filters traffic to host itself (including DNATed ports for docker). Use instead of filter INPUT
- table: mangle
- chain: PREROUTING
- directive
$into add rule to the section - first match target applied (allow, deny, reject, ignore)
- custom targets:
- check-state: special directive, MUST exist in
INsection at least once- it ACCEPTs ESTABLISHED and RELATED packets
- it checks packet destination, if destination is not host itself, then IN processing stops and packet enters IP FORWARD section
- allow = ACCEPT
- deny = DROP
- reject = REJECT (with-reset for tcp)
- ignore = leave chain without allow/deny decision
- skip: skip next matching rule for this packet
- check-state: special directive, MUST exist in
skip target allows to mark packet to skip next matching rule. designed to be used for straightforward exclusion. The example below excludes 10.0.12/0 and 10.1.2.3 from dropping by deny -d 10/8 rule.
$in -j skip -d 10.0.12/0
$in -j skip -d 10.1.2.3
$in -j deny -d 10/8ssdfw creates a filter table sshguard chain and hooks it into INPUT before accepting packets marked as allowed. Do not add sshguard to $in; $in rules are added to the mangle table. Just allow SSH in the IN section:
$in -j allow -p tcp --dport 22If sshguard is installed and manages the sshguard chain, it will be applied by the built-in INPUT hook.
Filters forwarded traffic (not dedicated to host itself), excluding DNATed ports (docker). Use instead of filter FORWARD
- table: mangle
- chain: FORWARD
- directive
$fwdto add rule to the section - first match target applied (allow, deny, reject, ignore)
- custom targets:
- check_fwd_state: optional directive, put it before forward allow/deny rules to ACCEPT ESTABLISHED and RELATED packets
- allow = ACCEPT
- deny = DROP
- reject = REJECT (with-reset for tcp)
- ignore = leave chain without allow/deny decision
- skip: skip next matching rule for this packet
check_fwd_state is not added automatically. DNATed/docker traffic that was already decided in the IN section is protected by built-in rules before user $fwd rules are evaluated.
Filter host outgoing traffic
-
table: filter
-
chain: OUTPUT
-
directive
$outto add rule to the section -
targets:
- any IPTABLES supported targets (ACCEPT, DROP...)
Manage SNAT and MASQUERADING
-
table: nat
-
chain: POSTROUTING
-
directive
$nat_into add rule to the section -
targets:
- any IPTABLES supported targets (SNAT, MASQUERADE)
I don't deal much with ipv6, that's why script does nothing with it. But some may use no_ipv6 directive
no_ipv6DROP all ipv6 traffic, allowing onlylointerfaceno_ipv6 --allow-outadditionally allows any outgoing traffic
- works with bridged docker interfaces (docker+, br-+)
- docker swarm mode is not tested
apk add iptables
ssdfw.sh
rc-service iptables save
rc-service ip6tables save
rc-update add iptables
rc-update add ip6tables
rc-service iptables start
rc-service ip6tables startsudo apt install iptables
sudo install -D -m 644 ssdfw/systemd/ssdfw.service /etc/systemd/system/ssdfw.service
sudo systemctl daemon-reload
sudo systemctl enable --now ssdfw.service
systemctl status ssdfw.serviceiptables-persistent is not required for ssdfw. The systemd unit applies the rule files at boot with ssdfw apply, so /etc/ssdfw/rules and /etc/ssdfw/rules.d/*.rules remain the source of truth instead of an iptables-save snapshot. Legacy /etc/iptables/ssdfw.rules and /etc/iptables/ssdfw.d/*.rules are used only when /etc/ssdfw does not exist.
After changing rule files, run sudo systemctl reload ssdfw.service to apply them again.