Files
bpfire/src/initscripts/system/ddos
Vincent Li 3579fd95a1 xdp-dns: attach xdp-dns prog to green0 interface
To block or rate limit DNS query from green
network client, the xdp-dns program should
be attached to green0 interface to scan the
DNS query. attach to red0 interface only get
the DNS response packet from red0(WAN), not
matching the DNS query we want.

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
2024-09-09 00:32:30 +00:00

200 lines
6.6 KiB
Bash
Executable File

#!/bin/sh
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2007-2022 IPFire Team <info@ipfire.org> #
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
###############################################################################
. /etc/sysconfig/rc
. $rc_functions
eval $(/usr/local/bin/readhash /var/ipfire/ddos/settings)
eval $(/usr/local/bin/readhash /var/ipfire/ddos/udp-ddos-settings)
eval $(/usr/local/bin/readhash /var/ipfire/ddos/dns-ddos-settings)
get_ports () {
# Define an empty variable to store the output
local output=""
local ddos_port_file="$1"
# Read the input file line by line
while IFS= read -r line; do
# Check if the line contains '=on'
if [[ "$line" == [0-9]*"=on" ]]; then
# Extract the service/port number
service=$(echo "$line" | cut -d'=' -f1)
# Append the service/port number to the output string
output="$output$service,"
fi
done < $ddos_port_file
# Remove the trailing comma from the output string
output="${output%,}"
echo $output
}
load_syncookie () {
sysctl -w net.ipv4.tcp_syncookies=2
sysctl -w net.ipv4.tcp_timestamps=1
sysctl -w net.netfilter.nf_conntrack_tcp_loose=0
/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
xdp_synproxy --prog $prog_id --ports="$tcp_ports"
else
xdp-loader load red0 /usr/lib/bpf/xdp_synproxy.bpf.o
if [ $? -ge 1 ]; then
boot_mesg "Native mode not supported, try SKB"
xdp-loader load red0 -m skb /usr/lib/bpf/xdp_synproxy.bpf.o
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
xdp_synproxy --prog $prog_id --ports="$tcp_ports"
else
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
xdp_synproxy --prog $prog_id --ports="$tcp_ports"
fi
fi
}
load_xdpudp () {
/usr/sbin/xdp-loader status red0 | grep 'xdp_udp'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
xdp-udp --prog $prog_id --ports="$udp_ports"
else
xdp-loader load red0 -P 90 -p /sys/fs/bpf/xdp-udp -n xdp_udp /usr/lib/bpf/xdp_udp.bpf.o
if [ $? -ge 1 ]; then
boot_mesg "Native mode not supported, try SKB"
xdp-loader load red0 -m skb -P 90 -p /sys/fs/bpf/xdp-udp -n xdp_udp /usr/lib/bpf/xdp_udp.bpf.o
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
xdp-udp --prog $prog_id --ports="$udp_ports"
else
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
xdp-udp --prog $prog_id --ports="$udp_ports"
fi
fi
}
load_xdpdns () {
/usr/sbin/xdp-loader status green0 | grep 'xdp_dns'
if [ $? -ne 0 ]; then
xdp-loader load green0 -P 80 -p /sys/fs/bpf/xdp-dns -n xdp_dns /usr/lib/bpf/xdp_dnsrrl.bpf.o
if [ $? -ge 1 ]; then
boot_mesg "Native mode not supported, try SKB"
xdp-loader load green0 -m skb -P 80 -p /sys/fs/bpf/xdp-dns -n xdp_dns /usr/lib/bpf/xdp_dnsrrl.bpf.o
fi
fi
}
unload_syncookie () {
sysctl -w net.ipv4.tcp_syncookies=1
/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
/usr/sbin/xdp-loader unload -i $prog_id red0
else
boot_mesg "Error syncookie_xdp not loaded!"
fi
}
unload_xdpudp () {
/usr/sbin/xdp-loader status red0 | grep 'xdp_udp'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
/usr/sbin/xdp-loader unload -i $prog_id red0
/bin/rm -rf /sys/fs/bpf/xdp-udp
else
boot_mesg "Error xdp_udp not loaded!"
fi
}
unload_xdpdns () {
/usr/sbin/xdp-loader status green0 | grep 'xdp_dns'
if [ $? -eq 0 ]; then
prog_id=$(xdp-loader status green0 | grep 'xdp_dns' | awk '{print $4}')
/usr/sbin/xdp-loader unload -i $prog_id green0
else
boot_mesg "Error xdp_dns not loaded!"
fi
}
set_ratelimit () {
local rate=$1
local map=$2
hex=$(printf '%08x' "$rate") # Convert decimal to hexadecimal
bytes=$(echo "$hex" | fold -w2 | tac) # Split the hexadecimal into pairs of bytes and reverse the order
hex_le=$(echo "$bytes" | sed 's/^/0x/' | tr '\n' ' ') # Add prefix "0x" to each byte and concatenate them
bpftool map update name $map key hex 00 00 00 00 value $hex_le
}
tcp_ports="$(get_ports /var/ipfire/ddos/settings)"
udp_ports="$(get_ports /var/ipfire/ddos/udp-ddos-settings)"
case "$1" in
start)
if [ ! -e /var/ipfire/red/active ]; then
boot_mesg " ERROR! Red0 interface not online!"
echo_warning
exit 1
fi
boot_mesg -n "Starting ddos..."
if [ "$ENABLE_DDOS" == "on" ]; then
load_syncookie
fi
if [ "$ENABLE_UDP_DDOS" == "on" ]; then
load_xdpudp
fi
if [ "$ENABLE_DNS_DDOS" == "on" ]; then
load_xdpdns
fi
;;
stop)
boot_mesg "Stopping ddos..."
if [ "$ENABLE_DDOS" == "off" ]; then
unload_syncookie
fi
if [ "$ENABLE_UDP_DDOS" == "off" ]; then
unload_xdpudp
if [ -n "$UDP_RATELIMIT" ]; then
set_ratelimit $UDP_RATELIMIT "xdp_udp.data"
fi
fi
if [ "$ENABLE_DNS_DDOS" == "off" ]; then
unload_xdpdns
if [ -n "$DNS_RATELIMIT" ]; then
set_ratelimit $DNS_RATELIMIT "xdp_dnsr.data"
fi
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
status)
/usr/sbin/xdp-loader status red0
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac