Velvet Star Monitor

Standout celebrity highlights with iconic style.

updates

Iptables bash script

Writer Andrew Henderson

I currently have a script that adds rules to the firewall table based on a selection criterion between two files.

FILE 1 keys.txt

<string>
<string>
..
..

FILE 2 hellos.txt

<string> <ipaddress> <ipaddress>
<string> <ipaddress> <ipaddress>
..
..

My script matches a string from file 2 with a string from file 1. If a match exists, then it adds the firewall rule for the ipaddress following the string match.

The script is as follows -

#!/bin/bash
while true
do
#Match a string from both the files and print the ipaddress to a file
word=$(awk 'FNR==NR{a[$1];next}($1 in a){print}' keys.txt hellos.txt | awk -v OFS=' ' '{ print $2, $3 }') >address.txt
#Remove duplicates for the ipaddress file
awk '!a[$0]++' address.txt > address_improved.txt
#Add firewall rule from new file.
filename=address_improved.txt
while read -r a b
do "/sbin/iptables" -I FORWARD 1 -m physdev --physdev-is-bridged --physdev-in enxa0cec80f92bd --physdev-out eno1 -s $a -d $b -j ACCEPT
done < "$filename"
sleep 0.01
#Run while loop again because the files are changing constantly
done

How can I improve this script such that I do not add duplicate firewall rules everytime the while loop executes. I tried to add the -C (check) option but it does not work for me. I just get a bad rule output.

3

1 Answer

Match a string from both the files and print the ipaddress to a file

Instead execute: (after following instructions)

ipset add allowed_hosts <ip> <ip>

(will not allow duplicates automatically)

Sets up ipset to be ready: (adjust maxelem to your liking)

ipset create allowed_hosts hash:net,net family inet hashsize 262144 maxelem 333000 counters comment

Your new rule:

 "/sbin/iptables" -I INPUT 1 -m conntrack -j ACCEPT --ctstate RELATED,ESTABLISHED "/sbin/iptables" -I INPUT 2 -m physdev --physdev-is-bridged --physdev-in enxa0cec80f92bd --physdev-out eno1 -m set --match-set allowed_hosts src,dst -j ACCEPT "/sbin/iptables" -I INPUT 3 -m physdev --physdev-is-bridged --physdev-in enxa0cec80f92bd --physdev-out eno1 -m u32 --u32 "0>>22&0x3C@ 12>>26&0x3C@ 0 & 0xFF000000=0x17000000" -j DROP "/sbin/iptables" -I FORWARD 1 -m conntrack -j ACCEPT --ctstate RELATED,ESTABLISHED "/sbin/iptables" -I FORWARD 2 -m physdev --physdev-is-bridged --physdev-in enxa0cec80f92bd --physdev-out eno1 -m set --match-set allowed_hosts src,dst -j ACCEPT "/sbin/iptables" -I FORWARD 3 -m physdev --physdev-is-bridged --physdev-in enxa0cec80f92bd --physdev-out eno1 -m u32 --u32 "0>>22&0x3C@ 12>>26&0x3C@ 0 & 0xFF000000=0x17000000" -j DROP

Now your new loop:

while read -r a b
do "/sbin/ipset" -! add allowed_hosts $a,$b
done < "$filename"

If you ever need to save the ipset table say for a reboot.

ipset save >ipset.txt

or

ipset save -f ipset.txt

bulk import, including autocreate from save.

ipset restore -f ipset.txt

It will be way more efficient as you don't need to keep changing iptables.

this single line might do away with everything but the loop

word=$(awk 'FNR==NR{a[$1];next}($1 in a){print}' keys.txt hellos.txt | awk -v OFS=' ' '{ print $2,$3 }') |xargs -n1 ipset -! add allowed_hosts

The xargs -n1 repeats the command for each line from stdin. the -! hide the duplicate entries alert. The output from the stdin is automatically appended so it isn't mentioned.

You will still need 1 iptables entry and the ipset mentioned above.

11

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy