How to UFW insert deny IPV6 address

How to UFW insert deny IPV6 address on Ubuntu 24.0? How can you UFW insert reject IPV6 address on Ubuntu?

This tutorial shows you how to insert a deny IPV6 rule or how to add ipv6 tcp/udp deny rule and provides scripts to easily insert the deny ipv6 rule to the top of the ufw rules above the allowed rules.

Yes you can insert an IPV6 rule into UFW but there it’s not as easy unless you know the upper most position of your IPV6 allow rules.

I have a written a script that you can execute from a shell a insert deny from an IPV6 address so that it’s above your IPV6 allow rules.

You will require shell access (SSH) and copy and past the following code into a script. I use this to deny pesty spammer / hackers that are using bad code (simple minded code) to pester your mail or http server.

I called my script by a simple name “ban” it contains 3 parts. Are you confused? Don’t be as I will explain each part.

You will need to create a BASH and a PHP script and an empty file with the extension “.dat”. I will explain what each does and the code to place into each.

Each file explained:

  • ban.dat will contain the IP address you ban
  • ban without extension is the BASH script. Without extension makes it easy to you to type on command line ./ban IP ADDRESS If you prefer you can call it ban.sh but you will have to from command line enter ban.sh IP address to ban.
  • ban.php This is the grunt that processes the IP address to ban and is called by the BASH script “ban”. It will allow you to easily insert both IPV4 and IPV6 addresses into UFW to ban.

The process: When you ban an ip like so ban xxx.xxx.xxx.xxx that address whether IPV4 or IPV6 will be inserted at the top of UFW rules (Top for IPV4 and top for IPV6). When added their IP is added to ban.dat file along with an expire time in Unix format like so xxx.xxx.xxx.xxx^EXPIRE-TIME. To remove those in the ban list you will issue the command php ban.php clean which will process those banned and any banned will be removed from the UFW ban when the expiry time elapses. You can automate the process using crontab by running it daily or as often as you want. I run mine daily, See and the end of this page my crontab examples as done on my 3 servers.

First: create the ban.dat file. From command line type echo “” > ban.dat and that will create the initial already banned ban.dat file than create the ban.log file echo “” > ban.log

Second: Create the BASH script called ban and past the following code into it.

#!/bin/bash
# This will accept up to 3 seperate IP addresses on the command line to pass to the ban.php script
# example: ban xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx
# would ban 3 IP is one go

# Change this to location of the ban.* files
PATH="/root"

echo "Adding IP: $1"

if [ "$2" != "" ]; then
echo "Adding $2"
/usr/bin/php $PATH/ban.php $2
fi

if [ "$3" != "" ]; then
echo "Adding $3"
/usr/bin/php $PATH/ban.php $3
fi

if [ "$4" != "" ]; then
echo "Adding $4"
/usr/bin/php $PATH/ban.php $4
fi

Third: Create the PHP script ban.php and past the following code

<?PHP
// Calling this like so: ban.php clean will remove expired banned
// You can call this directly: php ban.php XXX.xxx.xxx.xxx or use the bash script to call it ./ban XXX.XXX.XXX.XXX

// Change this to path/directory of the ban.* files
$PATH="/root";

// Change this to your time zone (Used for the logs)
date_default_timezone_set('Australia/Brisbane');

// In hours, how long to ban the IP address
$BanTime = 25;

$BanTime = 25 * 3600;

function Search($search, $string)
{
$position = strpos(strtolower($string), strtolower($search), 0);
if (is_numeric($position))
{
return true;
}
else
{
return false;
}
}


$BAN=$argv[1];
if($BAN == ""){
echo "Error: you didn't provide an IP to ban!";
exit();
}
$BANNED=[];
$log = fopen($PATH.'/ban.log', 'a');
$DUPLICATE="";
$lines = file($PATH.'/ban.dat');
foreach($lines as $line) {
$DUPLICATE = $DUPLICATE." ".$line;
}

if($BAN == "clean") {
echo "Checking for expired UFW deny IP \n";
$lines = file($PATH.'/ban.dat');
if($lines==0) exit();
$count = 0;
foreach($lines as $line) {
$count += 1;
$TEMP = explode('^',trim($line),2);
if(time() > $TEMP[1]) {
shell_exec("/usr/sbin/ufw delete deny from ".$TEMP[0]);
fwrite($log,date("Y-m-d h:i A")." Removed banned: ".$TEMP[0]."\n");
} else array_push($BANNED,trim($line));
}
$count = count($BANNED);
if($count == 0) exit();

$out = fopen($PATH.'/ban.dat', 'w');
for($a=0;$a<$count;$a++) {
fwrite($out, $BANNED[$a]."\r\n");
}
fclose($out);
fclose($log);
exit();
}

$position = strpos($DUPLICATE, $BAN, 0);
if (is_numeric($position))
{
echo $BAN." Already banned"."\r\n";
exit();
}

///////// This is to process IPV6 insert at top of the IPV6 entries
// This rountine simply locates the insert point for IPV6
// It's the same as using insert 1 on IPV4 which does not work on IPV6

$insert = 1;
// The Search() is used to determine if an IPV4 or IPV6 address
if( Search(":",$BAN) ) {
$index=-3;$insert=0;
shell_exec("/usr/sbin/ufw status numbered > ".$PATH."/ban.ufw");
$lines = file($PATH.'/ban.ufw');
foreach($lines as $line) {
if($insert == 0 && Search("(v6)",$line)) {
$insert = $index;
}
$index++;
}
}

///////// END process IPV6 insert

$RESULT=shell_exec("/usr/sbin/ufw insert ".$insert." deny log from ".$BAN." comment \"Banned by ME\"");
if($RESULT == $BAN." Already banned"){
echo $RESULT."\n";
exit();
}
$out = fopen($PATH.'/ban.dat', 'a');
$data = $BAN."^".(time()+$BanTime)."\n";
fwrite($out, $data);
fclose($out);
fwrite($log,date("Y-m-d H:i")." Added ".$BAN." to UFW by ME"."\n");
fclose($log);

?>

After creating the files you should do:
chmod 700 ban.php (Execute/Read/Write) for you
chmod 700 ban.sh (Execute/Read/Write) for you
chmod 600 ban.dat (Read/Write) for you
chmod 600 ban.log (Read/Write) for you

Each time you ban someone it will be recorded in the ban.log.
If you crontab ban.php clean the remove of IP from ban and UFW will also be recorded

Crontab examples to run the clean the ban list

Edit your crontab.
crontab -e
Past the code and it will run ban.php clean every hour to remove expired banned from those you used ban.php to ban with.

0 * * * * /usr/sbin/php /root/ban.php clean >/dev/null 2>&1

The above crontab will execute the php script hourly to remove from UFW (uncomplicated firewall) those you previously banned after expire time elapses.

Don’t forget to change the path/directory’s to match the location of where you created the ban.php file(s) etc. (I like using root) can be dangerous as I once found out when I in error deleted the entire server excluding the protected directories. Thank goodness for my moto – backup, backup and backup and you can never do too many backups!

The trailing >/dev/null 2>&1 tells crontab not to send you an email. Obviously you can have crontab process it daily or every minute. That’s entirely up to you. How do you stop crontab from sending emails on some tasks? Place a trailing >/dev/null 2>&1 on the end of the job.

Trivial tip

How to find the path a program uses on Ubuntu? Many jobs like my scripts and crontab need you to include the path of something you want to run. You just cant put php job.php you have to tell crontab where the PHP is located.

If you don’t know the path for a program just type on command line which php or which postfix or which apache2 and which will displays the full path.

Don’t have which installed! Easy, on Ubuntu just do an: apt install which. Which will be your best friend for ever on Ubuntu!