Ubuntu – Confused with ufw


I want ufw to block everything on my external interface (enp6s0) but allow everything on my internal ones (br0, tap0).

I had huge issues with this (ufw was blocking stuff on br0 even though I set up a rule to allow in on enevrything), so I set ufw to by default allow everything and then started adding exceptions for the interface I want blocked, like so:

ufw deny in on enp6s0 to any port 67 proto udp

I have a few of these for every port I don't want accessed from outside. But this solution makes me uneasy: basically I'm leaving everything open, just not listening on it. Sooner or later I'm going to forget to protect something.

So I went the other way around and wanted to create a set of rules which would allow certain ports but deny everything else, like so:

ufw insert 1 allow in on enp6s0 from any port ssh proto tcp
ufw insert 2 allow in on enp6s0 from any port http proto tcp
ufw insert 3 deny in on enp6s0 from any port 30:65535 proto tcp

The last command was intentionally leaving port 22 open so I could test effectiveness of the rules without risking losing my ssh connection to the server.

However, adding the deny rule immediately blocked the entire server. Everything, not just 30:65535. nmap thought it was down. Just by some huge luck, my existing ssh session remained active so I could delete the rule.

Now, I know I'm not some ufw guru or something, but this really came as (another) shock to me: it seems I have no idea about how it works.

Can anyone enlighten me on the deny rule? How I need to set it up?

Final edit:
It turned out that uninstalling & reinstalling ufw fixed the issues. It seems I messed up some setting at some point which caused all the unexplained behaviour.

Edit: my network config

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

# Our additions start here:
# tap interface (VMs will use this one)
auto tap0
iface tap0 inet manual
    pre-up ip tuntap add tap0 mode tap user root
    up ip link set dev tap0 up
    post-down ip link del dev tap0

# bridge
auto br0
iface br0 inet static
    bridge_ports tap0

iptables -S

-N ufw-after-forward
-N ufw-after-input
-N ufw-after-logging-forward
-N ufw-after-logging-input
-N ufw-after-logging-output
-N ufw-after-output
-N ufw-before-forward
-N ufw-before-input
-N ufw-before-logging-forward
-N ufw-before-logging-input
-N ufw-before-logging-output
-N ufw-before-output
-N ufw-logging-allow
-N ufw-logging-deny
-N ufw-not-local
-N ufw-reject-forward
-N ufw-reject-input
-N ufw-reject-output
-N ufw-skip-to-policy-forward
-N ufw-skip-to-policy-input
-N ufw-skip-to-policy-output
-N ufw-track-forward
-N ufw-track-input
-N ufw-track-output
-N ufw-user-forward
-N ufw-user-input
-N ufw-user-limit
-N ufw-user-limit-accept
-N ufw-user-logging-forward
-N ufw-user-logging-input
-N ufw-user-logging-output
-N ufw-user-output
-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 -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 FORWARD -i br0 -o enp6s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i enp6s0 -o br0 -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-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 4 -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 4 -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 -p udp -m udp --dport 5353 -j ACCEPT
-A ufw-before-input -d -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 ACCEPT
-A ufw-skip-to-policy-input -j ACCEPT
-A ufw-skip-to-policy-output -j ACCEPT
-A ufw-track-forward -p tcp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-track-forward -p udp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-track-input -p tcp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-track-input -p udp -m conntrack --ctstate NEW -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 -i enp6s0 -p tcp -m tcp --sport 22 -j ACCEPT
-A ufw-user-input -i enp6s0 -p tcp -m tcp --sport 80 -j ACCEPT
-A ufw-user-input -i enp6s0 -p tcp -m tcp --sport 443 -j ACCEPT
-A ufw-user-input -i enp6s0 -p tcp -m multiport --dports 2000:2100 -j DROP
-A ufw-user-input -i enp6s0 -p tcp -m tcp --dport 53 -j DROP
-A ufw-user-input -i enp6s0 -p udp -m udp --dport 53 -j DROP
-A ufw-user-input -i enp6s0 -p udp -m udp --dport 67 -j DROP
-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

Best Answer

You should reset ufw to defaults and start over:

sudo ufw reset

This will disable ufw and reset ufw to it's installation defaults which means to

- deny all incoming and
- allow all outgoing connections.

Then just add some rules to allow incoming connections for the applications you want to use:

sudo ufw allow ssh
sudo allow http

Now you can enable ufw

sudo ufw enable

Now ufw is running and configured to deny all incoming connections except connections to the ports needed for ssh and http. Outgoing connections are always allowed and this is normally desired.

You don't need to add a deny-rule for incoming connections like in your configuration:

deny in on enp6s0 from any port 30:65535 proto tcp`

This rule is unnecessary, incoming connections are denied by default.

If you want to configure the outgoing connections more restrictive, you can add deny-rules rather then defaulting outgoing connections to deny, it keeps rules simpler, mostly you want outgoing connections to be allowed. Deny-rules for outgoing connections would have to be designed carefully.

sudo ufw deny out 6773

for example would deny all outgoing connections on port 6773, any application that would need to use this port wouldn't be able to work properly anymore.


Using more than one interface makes things a bit more complicated. The defaults (deny in, allow out) apply to all interfaces,also rules which don't specify an interface will apply to all interfaces. You want your interfaces to behave different, so you have to add rules for each interface.

The rules in the section above need to be adapted to match your external interface (the rules in your question look like that).

Outgoing connections are allowed by default on all interfaces but not incoming connections, so you only need to add an allow in-rule for each internal interface:

sudo allow in on "interface" from any

Rules Order

Another important thing is the rules order. When a package arrives at the interface, ufw will check the rules,one by one. Whenever a rule matches the rule will be applied and the package denied, rejected or allowed. The rest of the rules which have not been checked at this moment are not used then. In your case I don't see much relevance of the rule order,but we always have to remind that rule order may matter.

Related Question