7

I am using ansible to configure ufw on my DB servers to only let accept connections from certain servers connection to a specific port (lets say 1234).

When a server that used to have access is taken out of the pool, it might be forgotten to remove the access rule for that server.

My solution: When setting up the rules, I want to delete all rules for port 1234, and then recreate them with the servers from the current pool.

Unfortunately ufw delete requires to precisely specify the rule to be deleted (port,protocol, scr IP,...).

I tried a solution like ufw delete $(ufw status numbered | grep 1234 | <get all the numbers of the rules> ), but it got really ugly, really fast.

Is there a better way to delete all rules for a certain port?

7 Answers 7

9

There are two problems that need to be solved here:

  1. generate a list of ufw rule numbers which match a desired string.
  2. have the shell expand this list and tack it on the end of a sequence of 'ufw delete [rule number]' commands.

I think I have a solution for problem #1 via this one liner in bash:

ufw status numbered |(grep '80/tcp'|awk -F"[][]" '{print $2}')

The example above matches any firewall rule for the string '80/tcp' and prints just the rule number with the brackets stripped.

I have not solved problem #2 yet because as best I can tell, the 'ufw delete' command does not have a switch that suppresses the '(y|n)' confirmation prompt, thus foiling automation.

You can run the command below however and manually hammer out each rule deletion by hitting the 'y' key to confirm and then up arrow => enter to rinse and repeat

ufw delete $(ufw status numbered |(grep '80/tcp'|awk -F"[][]" '{print $2}'))
3
  • 1
    the 'ufw delete' command does not have a switch that suppresses the '(y|n)' confirmation prompt ... : As today, there is a way to solve #2: use ufw --force delete ....
    – lepe
    Commented Mar 2, 2016 at 3:57
  • 2
    You could also always use yes y | ufw delete ... Commented Nov 17, 2017 at 8:35
  • @JonathanY. that's very nice trick, ty. Commented Oct 4, 2020 at 3:31
6

I know this is very old question but google brought me here and the answers so far were helpful, so I wanted to share my full solution. The answer from @Seth got me most of the way there.

My goal is to remove all UFW rules allowing connections to the local MySQL server on port 3306. Here's what I used:

for NUM in $(ufw status numbered | grep 3306 | awk -F"[][]" '{print $2}' | tr --delete [:blank:] | sort -rn); do
    yes | ufw delete $NUM
done

The key to automating this is to delete rules in reverse order. When you delete from the end, the numbers above don't change.

When you run ufw status numbered you'll get output like this:

     To                         Action      From
     --                         ------      ----
[ 1] 22                         ALLOW IN    10.181.225.123
[ 2] 3306/tcp                   ALLOW IN    10.181.225.123
[ 3] 3306/tcp                   ALLOW IN    10.181.226.45
[ 4] 3306/tcp                   ALLOW IN    10.181.226.77
[ 5] 3306/tcp                   ALLOW IN    10.181.225.196
[ 6] 3306/tcp                   ALLOW IN    10.181.226.3
[ 7] Anywhere                   ALLOW IN    10.181.226.45
[ 8] 3306/tcp                   ALLOW IN    10.181.224.55
[ 9] 3306/tcp                   ALLOW IN    10.181.224.80
[10] 3306/tcp                   ALLOW IN    10.208.6.136
[11] 3306/tcp                   ALLOW IN    10.178.128.13

A few things to know:

  • The output from awk -F"[][]" '{print $2}' will include a leading space for numbers below 10, tr --delete [:blank:] will delete it
  • Once the leading spaces are deleted, sort -rn will sort the numbers in reverse numerical order.
  • I'm piping yes to ufw instead of using --force because I've got a very old ufw. If you've got a modern version, you can use --force.
1
  • Thank you! This has been extremely helpful. A potential bug is with the grep statement, if you are grepping for a port number < 256, you might end up matching a line that has an IP address with that number, and you'll end up deleting a line you didn't want to.
    – Rocklan
    Commented Sep 4, 2023 at 2:41
3

Most of the solutions here will delete the wrong rules because of UFW renumbering rules after deletion.

To workaround the new numbering after each deletion, we need to rerun the command and pick the first number then delete that rule and loop like this:

while true; do n=$(ufw status numbered | grep DENY | head -n 1 | awk -F"[][]" '{print $2}');[ "$n" != "" ] || break; yes | ufw delete $n; done;

2

If you need to wipe-out all your rules (not just specific ports):

ufw --force reset

(--force if you don't want to be prompted for confirmation)

0

Maybe needless to say: after each removal of a numbered ufw-item, all items following that item get renumbered. Therefore, this oneliner will delete the wrong items after the first deleted item:

#Wrong use of deleting multiple ufw-items:
for numb in $(ufw status numbered | grep DENY | cut -d" " -f1 | grep -o [[:digit:]]*); do ufw delete $numb; done

As long it is not possible to force-delete each item without a confirmation, I haven't found a better solution... yet ....

1
  • Adding to Xtophe's answer. You can force deletion without confirmation with (LC_ALL=C gives default linux language output) sudo LC_ALL=C ufw --force delete <row-number> Commented Jun 1, 2015 at 12:39
0

UFW (Uncomplicated Firewall) is a front-end for iptables. Just use iptables to block/remove ports in this case.

0

This will re-list,re-pick and delete the rules :

while true; do rule_number=$(ufw status numbered | awk '/(ALLOW|DENY) IN/ && $0 ~ /\<(3000)\>/{gsub(/[\[\]]/, ""); print $1; exit}'); if [ -z "$rule_number" ]; then break; else sudo yes | ufw delete $rule_number --force; fi; done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .