LXD + Iptables + Fail2ban -> Blocking rules don't work

Hi,
I am running several websites in different containers / apache2 behind another container with nginx.
On the mainserver, I have several scripts that create Ipsets with blocking rules for certain IPs (country based and known offenders)

Currently, I am forwarding traffic through these rules in prerouting.

Chain PREROUTING
DNAT       tcp  --  anywhere             MYSERVERADDRESS  tcp dpt:http to:CONTAINERIP:80
DNAT       tcp  --  anywhere             MYSERVERADDRESS  tcp dpt:https to:CONTAINERIP:443

There is also an LXD Bridge which configures the following rules and one of the IPsets that should block the traffic.

Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:domain /* generated for LXD network lxd_bridge0 */
ACCEPT     udp  --  anywhere             anywhere             udp dpt:domain /* generated for LXD network lxd_bridge0 */
ACCEPT     udp  --  anywhere             anywhere             udp dpt:bootps /* generated for LXD network lxd_bridge0 */
REJECT     all  --  anywhere             anywhere             match-set f2b-fail2ban-A src reject-with icmp-port-unreachable
DROP       all  --  anywhere             anywhere             match-set IPSET_Block src

Here is what I observe:

  • My Ipset and fail2ban don’t seem to have an effect
  • It seems to me that the lxd bridge is not required (?) Or is it required for local networking?

What am I missing here? Should I reorder the rules for my blocking to be before the lxdbridge rules? can I delete the lxdbridge rules completely?

Additional info why I use NAT to forward traffic instead of the lxd bridge:
My reason for not using the lxd bridge for forwarding ports 443 and 80 was that I did not manage to make it work with nginx showing the source IP address in my logs.

Thank you very much for your input and helping me securing this :slight_smile:

Please can you show the output of lxc config show --expanded for one of your containers, and the output of lxc network ls.

Also, does fail2ban run on the host or in the container?

Hi Tomp, Thanks for the quick answer.
Fail2ban runs on my host.

sudo lxc config show --expanded nginx

prints

architecture: x86_64
config:
volatile.base_image: (…)
volatile.eth0.host_name: vethba502769
volatile.eth0.hwaddr: 00:16:3e:e7:bc:13
volatile.idmap.base: “0”
volatile.idmap.current: ‘[{“Isuid”:true,“Isgid”:false,“Hostid”:1000000,“Nsid”: 0,“Maprange”:1000000000},{“Isuid”:false,“Isgid”:true,“Hostid”:1000000,“Nsid”:0," Maprange":1000000000}]’
volatile.idmap.next: ‘[{“Isuid”:true,“Isgid”:false,“Hostid”:1000000,“Nsid”:0," Maprange":1000000000},{“Isuid”:false,“Isgid”:true,“Hostid”:1000000,“Nsid”:0,“Map range”:1000000000}]’
volatile.last_state.idmap: ‘[{“Isuid”:true,“Isgid”:false,“Hostid”:1000000,“Nsi d”:0,“Maprange”:1000000000},{“Isuid”:false,“Isgid”:true,“Hostid”:1000000,“Nsid”: 0,“Maprange”:1000000000}]’
volatile.last_state.power: RUNNING
devices:
eth0:
ipv4.address: INTERNALIP
name: eth0
nictype: bridged
parent: lxd_bridge0
type: nic
lxc_port_80:
connect: tcp:INTERNALIP:80
listen: tcp:0.0.0.0:80
type: proxy
lxc_proxy_port443:
connect: tcp:INTERNALIP:443
listen: tcp:0.0.0.0:443
type: proxy
root:
path: /
pool: lxd_storage_pool_01
type: disk
ephemeral: false
profiles:

  • default
    stateful: false
    description: “”

A sidenote: You might wonder why I also configured a proxy device for the ports I already forward by NAT. The reason is that I have an internal python script checking these websites by their domain name and the request did not function without the bridged ports (I assume this is because they also work on the loopback (?).

+-------------+----------+---------+----------------+---------------------------+-------------+---------+
|    NAME     |   TYPE   | MANAGED |      IPV4      |           IPV6            | DESCRIPTION | USED BY |
+-------------+----------+---------+----------------+---------------------------+-------------+---------+
| eth0        | physical | NO      |                |                           |             | 0       |
+-------------+----------+---------+----------------+---------------------------+-------------+---------+
| lxd_bridge0 | bridge   | YES     | INTERNALIP/24 | IN:TER:NAL::4566::1/64 |             | 16      |
+-------------+----------+---------+----------------+---------------------------+-------------+---------+

I’m still a bit confused to be honest.

Which logs does fail2ban monitor to add rules to the host’s firewall?

And are you seeing fail2ban successfully add IPs to the set?

I’m also confused why you have proxy device setup, but are using (presumably manually added) NAT rules, when the proxy device itself can operate in nat=true mode so it would add its own NAT rules.

I’m not sure what the internal python script you refer to does, and why this wasn’t working.

With the info so far I’m struggling to come up with a suggestion on how to proceed. However my general recommendation would be to remove your manually added NAT rules, and use the proxy device in nat=true mode. Then the external IP will be passed into your containers, and then hopefully fail2ban will see the correct IP.

Also worth noting, if you are using NAT mode (either manually or via nat=true on the proxy device), then if fail2ban on the host is adding rules to the INPUT firewall chain, then these are not going to match because DNAT will pass these rules through the FORWARD chain in iptables (this is why when using the proxy device in NAT mode we enable bridge iptables filtering and hairpin mode see https://github.com/lxc/lxd/blob/master/lxd/device/proxy.go#L407-L454).

Hi tomp,

Thanks for your answer. Let me be a bit clearer about it.

Thanks for pointing out that fail2ban is not using the forwarding chain, i oversaw that point.
Let’s break the problem down nevertheless and ignore fail2ban for now, because also the other rules don’t block requests.

I use the manually filled ipset COLLECTED_manually in both chains FORWARD and INPUT configured as shown below.

The problem: If I add an IP to this set, it does not get blocked either.
I assume that this is somehow due to the rules generated for the bridge?

In addition to your suggestion to use the bridge in nat mode (which I failed to do so far, I will look into this again to make it work with nginx),
my question is: Should my DROP rule for the set COLLECTED_manually be before the bridge rules to work?
I understood so far, that as soon as a rule in iptables gets matched and has the target “ACCEPT” the following rules are not treated anymore?
I guess I overall am not entirely understanding what the rules for the lxc-bridge do.

Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:domain /* generated for LXD network lxd_bridge0 */
ACCEPT     udp  --  anywhere             anywhere             udp dpt:domain /* generated for LXD network lxd_bridge0 */
ACCEPT     udp  --  anywhere             anywhere             udp dpt:bootps /* generated for LXD network lxd_bridge0 */
REJECT     all  --  anywhere             anywhere             match-set f2b-SOMESET src reject-with icmp-port-unreachable
DROP       all  --  anywhere             anywhere             match-set COLLECTED_manually src

and in the forward chain:

Chain FORWARD (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             /* generated for LXD network lxd_bridge0 */
ACCEPT     all  --  anywhere             anywhere             /* generated for LXD network lxd_bridge0 */
DROP       all  --  anywhere             anywhere             match-set COLLECTED_manually src

My NAT PREROUTING rules are:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       tcp  --  anywhere             localhost     tcp dpt:https to:INTERNAL_nginx_IP:443
...[some other rules]...
DNAT       tcp  --  anywhere             PUBLICSERVER  tcp dpt:http to:INTERNAL_nginx_IP:80
DNAT       tcp  --  anywhere             PUBLICSERVER  tcp dpt:https to:INTERNAL_nginx_IP:443

I hope that my question is clearer now and thank you a lot for your help.

Best,

Florian

The ordering in relation to the LXD rules added shouldn’t matter as they are only targeting DNS and DHCP packets, so they won’t be matching for HTTP/HTTPS traffic. Nor do they affect any interfaces apart from lxdbr0.

Perhaps your system is not configured to pass bridge traffic through iptables at all, please show the output of:

sudo sysctl -a | grep net.bridge.bridge-nf-call

Hi Tomp,
The command as shown prints nothing.

However sysctl -a has the following values:

net.ipv4.conf.lxd_bridge0.accept_local = 0
net.ipv4.conf.lxd_bridge0.accept_redirects = 0
net.ipv4.conf.lxd_bridge0.accept_source_route = 0
net.ipv4.conf.lxd_bridge0.arp_accept = 0
net.ipv4.conf.lxd_bridge0.arp_announce = 0
net.ipv4.conf.lxd_bridge0.arp_filter = 0
net.ipv4.conf.lxd_bridge0.arp_ignore = 0
net.ipv4.conf.lxd_bridge0.arp_notify = 0
net.ipv4.conf.lxd_bridge0.bc_forwarding = 0
net.ipv4.conf.lxd_bridge0.bootp_relay = 0
net.ipv4.conf.lxd_bridge0.disable_policy = 0
net.ipv4.conf.lxd_bridge0.disable_xfrm = 0
net.ipv4.conf.lxd_bridge0.drop_gratuitous_arp = 0
net.ipv4.conf.lxd_bridge0.drop_unicast_in_l2_multicast = 0
net.ipv4.conf.lxd_bridge0.force_igmp_version = 0
net.ipv4.conf.lxd_bridge0.forwarding = 1
net.ipv4.conf.lxd_bridge0.igmpv2_unsolicited_report_interval = 10000
net.ipv4.conf.lxd_bridge0.igmpv3_unsolicited_report_interval = 1000
net.ipv4.conf.lxd_bridge0.ignore_routes_with_linkdown = 0
net.ipv4.conf.lxd_bridge0.log_martians = 0
net.ipv4.conf.lxd_bridge0.mc_forwarding = 0
net.ipv4.conf.lxd_bridge0.medium_id = 0
net.ipv4.conf.lxd_bridge0.promote_secondaries = 1
net.ipv4.conf.lxd_bridge0.proxy_arp = 0
net.ipv4.conf.lxd_bridge0.proxy_arp_pvlan = 0
net.ipv4.conf.lxd_bridge0.route_localnet = 0
net.ipv4.conf.lxd_bridge0.rp_filter = 1
net.ipv4.conf.lxd_bridge0.secure_redirects = 1
net.ipv4.conf.lxd_bridge0.send_redirects = 0
net.ipv4.conf.lxd_bridge0.shared_media = 1
net.ipv4.conf.lxd_bridge0.src_valid_mark = 0
net.ipv4.conf.lxd_bridge0.tag = 0
net.ipv4.neigh.lxd_bridge0.anycast_delay = 100
net.ipv4.neigh.lxd_bridge0.app_solicit = 0
net.ipv4.neigh.lxd_bridge0.base_reachable_time_ms = 30000
net.ipv4.neigh.lxd_bridge0.delay_first_probe_time = 5
net.ipv4.neigh.lxd_bridge0.gc_stale_time = 60
net.ipv4.neigh.lxd_bridge0.locktime = 100
net.ipv4.neigh.lxd_bridge0.mcast_resolicit = 0
net.ipv4.neigh.lxd_bridge0.mcast_solicit = 3
net.ipv4.neigh.lxd_bridge0.proxy_delay = 80
net.ipv4.neigh.lxd_bridge0.proxy_qlen = 64
net.ipv4.neigh.lxd_bridge0.retrans_time_ms = 1000
net.ipv4.neigh.lxd_bridge0.ucast_solicit = 3
net.ipv4.neigh.lxd_bridge0.unres_qlen = 101
net.ipv4.neigh.lxd_bridge0.unres_qlen_bytes = 212992
net.ipv6.conf.lxd_bridge0.accept_dad = 0
net.ipv6.conf.lxd_bridge0.accept_ra = 2

In that case you are missing the br_netfilter kernel module.

modprobe br_netfilter

1 Like

Chapeau for that quick analysis.

Here’s the printout:

net.bridge.bridge-nf-call-arptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

Great, so now try your firewall rules.

Same result if I try to open a website with a blocked IP in the set COLLECTED_manually, it still goes through.
(as of your earlier post passing through PREROUTING and then FORWARD, which has two rules ACCEPT for the lxd bridge.
Just to see what happens, I temporarily moved the subsequent blocking rule (DROP ALL if in set COLLECTED_mailserver) before the LXD bridge generated rules. That effectively blocked the traffic.

Maybe to precise, the set works for other ports that are not forwarded to the lxd bridge and not in the PREROUTING rules, so it must somewhat be related to the bridge and prerouting.

So thats in encouraging if the br_netfilter module is now loaded, have you tried moving your IP set ruless above the LXD rules in the FORWARD chain (as those should be taking effect now).

If so then you could disable LXD’s firewall rules using lxc network set lxdbr0 ipv4.firewall=false and then manually add the INPUT rules for DNS and DHCP.

Ok, just making sure that I understand everything correctly.
1.) move my own iptable rules BEFORE the lxd bridge rules for input and forward
2.) disable LXD firewall
3.) add Iptable rules for DNS and DHCP. (I would appreciate further infos on this, sorry the ignorance) would your suggestion mean:

iptables -A INPUT -p udp -i eth0 --dport 67 -j ACCEPT
iptables -A INPUT -p udp --sport 53 -j ACCEPT

I will do some tests tonight and post the result. Thank you for your help.

Disabling LXD firewall will remove those rules entirely from the FORWARD chain.

Before doing that, if you save a copy of the rules LXD adds (using something like iptables-save ) to and then reproduce those manually, then you can have more control over the firewalling.

Otherwise your default policy of DROP on the INPUT chain will break DHCP and DNS for your containers.

Hi Thomas,
Thanks for all the hints.
Here’s what I did and what I observe:
I added these rules:

/usr/sbin/iptables  -A INPUT -j ACCEPT -p TCP --dport domain -m comment --comment "man generated for LXD bridge"
/usr/sbin/iptables  -A INPUT -j ACCEPT -p UDP --dport domain -m comment --comment "man generated for LXD bridge"
/usr/sbin/iptables  -A INPUT -j ACCEPT -p UDP --dport bootps -m comment --comment "man generated for LXD bridge"

/usr/sbin/iptables  -A OUTPUT -j ACCEPT -p TCP --sport domain -m comment --comment "man generated for LXD bridge"
/usr/sbin/iptables  -A OUTPUT -j ACCEPT -p UDP --sport domain -m comment --comment "man generated for LXD bridge"
/usr/sbin/iptables  -A OUTPUT -j ACCEPT -p UDP --sport bootps -m comment --comment "man generated for LXD bridge"

/usr/sbin/iptables  -A FORWARD -j ACCEPT -m comment --comment "man generated for LXD bridge"

/usr/sbin/iptables  -t nat -A POSTROUTING -s INTERNALIP/24 ! -d INTERNALIP/24 -m comment --comment "man generated for LXD bridge" -j MASQUERADE    

I modified fail2ban such that it creates a rule for the FORWARD chain.
That now seems all to work as expected.

Unfortunately my ufw firewall now seems to block traffic that it should not block. (I assume this is maybe a question I should not ask here anymore, but I do it in the continuity of this post)

[UFW BLOCK] IN=lxd_bridge0 OUT=lxd_bridge0 PHYSIN=vethba502769 PHYSOUT=vethc923101b MAC=... SRC=IP_1_internal DST=IP_2_internal  LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=48020 DF PROTO=TCP SPT=34518 DPT=80 WINDOW=64240 RES=0x00 SYN URGP=0

ufw is set to block by default with exceptions on IPv6 and IPv4 for port 80 like:

To                         Action      From
--                         ------      ----
80/tcp                     ALLOW       Anywhere

note that this a port that is passing through PREROUTING in order to be passed to lxd.
my iptables rules from ufw are:

CHAIN INPUT:

ufw-before-logging-input  all  --  anywhere             anywhere
ufw-before-input  all  --  anywhere             anywhere
ufw-after-input  all  --  anywhere             anywhere
ufw-after-logging-input  all  --  anywhere             anywhere
ufw-reject-input  all  --  anywhere             anywhere
ufw-track-input  all  --  anywhere             anywhere

CHAIN FORWARD:

ufw-before-logging-forward  all  --  anywhere             anywhere
ufw-before-forward  all  --  anywhere             anywhere
ufw-after-forward  all  --  anywhere             anywhere
ufw-after-logging-forward  all  --  anywhere             anywhere
ufw-reject-forward  all  --  anywhere             anywhere
ufw-track-forward  all  --  anywhere             anywhere

THe new rules for the lxd bridge come after that. In case you see the error quicker than me I’d be happy to learn.

Thank you,

Flo

You should also add the interface selector flags to your manual lxd firewall rules otherwise they may allow some external inbound traffic. The output of iptables-save would have had interface selectors on them.

As for ufw I’ll take a look.

Please can you renable the lxd firewall option, remove your manual ones and leave ufw enabled and show output of ‘iptables-save’ as ufw just adds iptables rules afaik.

Just did that, so back to initial status gives:

# Generated by iptables-save v1.8.4 on Mon Oct 12 22:28:18 2020
*nat
:PREROUTING ACCEPT [33:9050]
:INPUT ACCEPT [25:8650]
:OUTPUT ACCEPT [8:1339]
:POSTROUTING ACCEPT [59:3867]
-A PREROUTING -d 127.0.0.1/32 -i lo -p tcp -m tcp --dport 443 -j DNAT --to-destination INTERNIP:443
-A PREROUTING -d 173.212.223.15/32 -i eth0 -p tcp -m tcp --dport 443 -j DNAT --to-destination INTERNIP:443
-A OUTPUT -d 127.0.0.1/32 -p tcp -m tcp --dport 443 -j DNAT --to-destination INTERNIP:443
-A POSTROUTING -s INTERNAL/24 ! -d INTERNAL/24 -m comment --comment "generated for LXD network lxd_bridge0" -j MASQUERADE
COMMIT
# Completed on Mon Oct 12 22:28:18 2020
# Generated by iptables-save v1.8.4 on Mon Oct 12 22:28:18 2020
*mangle
:PREROUTING ACCEPT [2698:3167761]
:INPUT ACCEPT [2541:3160153]
:FORWARD ACCEPT [157:7608]
:OUTPUT ACCEPT [2413:140128]
:POSTROUTING ACCEPT [2570:147736]
-A POSTROUTING -o lxd_bridge0 -p udp -m udp --dport 68 -m comment --comment "generated for LXD network lxd_bridge0" -j CHECKSUM --checksum-fill
COMMIT
# Completed on Mon Oct 12 22:28:18 2020
# Generated by iptables-save v1.8.4 on Mon Oct 12 22:28:18 2020
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:ufw-after-forward - [0:0]
:ufw-after-input - [0:0]
:ufw-after-logging-forward - [0:0]
:ufw-after-logging-input - [0:0]
:ufw-after-logging-output - [0:0]
:ufw-after-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-before-input - [0:0]
:ufw-before-logging-forward - [0:0]
:ufw-before-logging-input - [0:0]
:ufw-before-logging-output - [0:0]
:ufw-before-output - [0:0]
:ufw-logging-allow - [0:0]
:ufw-logging-deny - [0:0]
:ufw-not-local - [0:0]
:ufw-reject-forward - [0:0]
:ufw-reject-input - [0:0]
:ufw-reject-output - [0:0]
:ufw-skip-to-policy-forward - [0:0]
:ufw-skip-to-policy-input - [0:0]
:ufw-skip-to-policy-output - [0:0]
:ufw-track-forward - [0:0]
:ufw-track-input - [0:0]
:ufw-track-output - [0:0]
:ufw-user-forward - [0:0]
:ufw-user-input - [0:0]
:ufw-user-limit - [0:0]
:ufw-user-limit-accept - [0:0]
:ufw-user-logging-forward - [0:0]
:ufw-user-logging-input - [0:0]
:ufw-user-logging-output - [0:0]
:ufw-user-output - [0:0]
-A INPUT -m set --match-set COLLECTED_manually src -j DROP
-A INPUT -m set --match-set Blocked_Countries src -j DROP
-A INPUT -i lxd_bridge0 -p tcp -m tcp --dport 53 -m comment --comment "generated for LXD network lxd_bridge0" -j ACCEPT
-A INPUT -i lxd_bridge0 -p udp -m udp --dport 53 -m comment --comment "generated for LXD network lxd_bridge0" -j ACCEPT
-A INPUT -i lxd_bridge0 -p udp -m udp --dport 67 -m comment --comment "generated for LXD network lxd_bridge0" -j ACCEPT
-A INPUT -m set --match-set f2b-Portscanner src -j REJECT --reject-with icmp-port-unreachable
-A INPUT -j ufw-before-logging-input
-A INPUT -j ufw-before-input
-A INPUT -j ufw-after-input
-A INPUT -j ufw-after-logging-input
-A INPUT -j ufw-reject-input
-A INPUT -j ufw-track-input
-A FORWARD -m set --match-set COLLECTED_manually src -j DROP
-A FORWARD -o lxd_bridge0 -m comment --comment "generated for LXD network lxd_bridge0" -j ACCEPT
-A FORWARD -i lxd_bridge0 -m comment --comment "generated for LXD network lxd_bridge0" -j ACCEPT
-A FORWARD -m set --match-set f2b-Portscanner src -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -j ufw-before-logging-forward
-A FORWARD -j ufw-before-forward
-A FORWARD -j ufw-after-forward
-A FORWARD -j ufw-after-logging-forward
-A FORWARD -j ufw-reject-forward
-A FORWARD -j ufw-track-forward
-A OUTPUT -o lxd_bridge0 -p tcp -m tcp --sport 53 -m comment --comment "generated for LXD network lxd_bridge0" -j ACCEPT
-A OUTPUT -o lxd_bridge0 -p udp -m udp --sport 53 -m comment --comment "generated for LXD network lxd_bridge0" -j ACCEPT
-A OUTPUT -o lxd_bridge0 -p udp -m udp --sport 67 -m comment --comment "generated for LXD network lxd_bridge0" -j ACCEPT
-A OUTPUT -j ufw-before-logging-output
-A OUTPUT -j ufw-before-output
-A OUTPUT -j ufw-after-output
-A OUTPUT -j ufw-after-logging-output
-A OUTPUT -j ufw-reject-output
-A OUTPUT -j ufw-track-output
-A ufw-after-input -p udp -m udp --dport 137 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 138 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp --dport 139 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp --dport 445 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 67 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 68 -j ufw-skip-to-policy-input
-A ufw-after-input -m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input
-A ufw-after-logging-forward -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-after-logging-input -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A ufw-before-forward -j ufw-user-forward
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP
-A ufw-before-input -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A ufw-before-input -p udp -m udp --sport 67 --dport 68 -j ACCEPT
-A ufw-before-input -j ufw-not-local
-A ufw-before-input -d 224.0.0.251/32 -p udp -m udp --dport 5353 -j ACCEPT
-A ufw-before-input -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT
-A ufw-before-input -j ufw-user-input
-A ufw-before-output -o lo -j ACCEPT
-A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -j ufw-user-output
-A ufw-logging-allow -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW ALLOW] "
-A ufw-logging-deny -m conntrack --ctstate INVALID -m limit --limit 3/min --limit-burst 10 -j RETURN
-A ufw-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP
-A ufw-skip-to-policy-forward -j DROP
-A ufw-skip-to-policy-input -j DROP
-A ufw-skip-to-policy-output -j ACCEPT
-A ufw-track-output -p tcp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-track-output -p udp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 80 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 443 -j ACCEPT
-A ufw-user-input -s INTERNALIP/24 -j ACCEPT
-A ufw-user-limit -m limit --limit 3/min -j LOG --log-prefix "[UFW LIMIT BLOCK] "
-A ufw-user-limit -j REJECT --reject-with icmp-port-unreachable
-A ufw-user-limit-accept -j ACCEPT
COMMIT
# Completed on Mon Oct 12 22:28:18 2020

Hi Thomas,

Thank you again for all your insights. It now works the way I expect it to.
After the restart, the lxd_bridge0 rules ended up at the end (just before the firewall) which makes fail2ban work (I modified the action.d configfile such that it added a rule to the chain FORWARD) and my own ipset.

I would close the topic now if you don’t have an opposing view.

Thanks a lot for helping and sharing your knowledge.

Flo

1 Like