Various Changes

Signed-off-by: MOVZX <movzx@yahoo.com>
This commit is contained in:
2025-08-29 17:36:45 +07:00
parent 7e5158dc51
commit 53b40c0329
10 changed files with 352 additions and 18 deletions

View File

@@ -1,5 +0,0 @@
#!/bin/env bash
ETH=enp11s0
/usr/sbin/ip link set dev $ETH xdp obj xdp_packet_filter.o sec packet_filter

4
blocked_ips.conf Normal file
View File

@@ -0,0 +1,4 @@
57.141.2.0/24
139.59.224.0/20
178.156.172.0/24
141.148.153.0/24

214
blokir.sh Executable file
View File

@@ -0,0 +1,214 @@
#!/usr/bin/env bash
#
# blokir.sh manage IPv4 prefixes in the “blocked_ips” LPM-trie map
#
# sudo ./blokir.sh # help
# sudo ./blokir.sh 1.2.3.4/24 … # add
# sudo ./blokir.sh unblock … # delete exact prefix(es)
# sudo ./blokir.sh reset # flush whole map
# sudo ./blokir.sh export [f] # print or save list
#
set -euo pipefail
###############################################################################
# 1. Locate the map automatically
###############################################################################
MAP_NAME=${MAP_NAME:-blocked_ips} # change if you used another name
detect_map_id() {
local id=""
if command -v jq >/dev/null; then
id=$(bpftool -j map show | jq -r --arg n "$MAP_NAME" \
'.[]|select(.name==$n)|.id' | head -n1)
fi
if [[ -z $id ]]; then # plain-text fallback
id=$(bpftool -p map show |
awk -v n="$MAP_NAME" '$4==n{split($1,a,":");print a[1];exit}')
fi
[[ -z $id ]] && {
echo "‼︎ map \"$MAP_NAME\" not found." >&2
exit 1
}
echo "$id"
}
MAP_ID=$(detect_map_id)
###############################################################################
# 2. Helpers
###############################################################################
usage() {
cat <<EOF
Usage:
$0 reset
$0 unblock <ip|cidr> [..]
$0 import [file]
$0 export [file]
$0 <ip|cidr> [..] (add)
$0 show
$0 (help)
EOF
}
# dotted IP + plen → key-bytes "xx xx …"
gen_key_bytes() {
local ip=$1 plen=$2
IFS=. read -r o1 o2 o3 o4 <<<"$ip"
printf '%02x %02x %02x %02x %02x %02x %02x %02x' \
$((plen & 255)) 0 0 0 "$o1" "$o2" "$o3" "$o4"
}
mask_ip() { # → network/0-host bits
local ip=$1 plen=$2
IFS=. read -r a b c d <<<"$ip"
local v=$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))
local m=$((plen == 0 ? 0 : (0xFFFFFFFF << (32 - plen)) & 0xFFFFFFFF))
v=$((v & m))
printf '%d.%d.%d.%d' $((v >> 24 & 255)) $((v >> 16 & 255)) $((v >> 8 & 255)) $((v & 255))
}
import_prefixes() {
local file="$1"
[[ -r "$file" ]] || {
echo "‼︎ Cannot read file: $file" >&2
exit 1
}
echo "📥 Importing from $file"
while IFS= read -r line || [[ -n "$line" ]]; do
[[ -z "$line" || "$line" =~ ^# ]] && continue # skip empty lines and comments
insert_prefix "$line"
done <"$file"
show_map
}
parse_cidr() { # validate → "ip plen"
local cidr="$1" ip plen
ip=${cidr%%/*}
plen=${cidr#*/}
[[ $ip == $plen ]] && plen=32
[[ $plen =~ ^[0-9]+$ && plen -le 32 ]] || return 1
if ! [[ $ip =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then return 1; fi
IFS=. read -r a b c d <<<"$ip"
for o in $a $b $c $d; do ((o > 255)) && return 1; done
echo "$ip $plen"
}
###############################################################################
# 3. Map-byte helpers (used by add/del/export)
###############################################################################
list_keys() { # stdout: "xx xx …" (8-byte key)
if command -v jq >/dev/null; then
bpftool -j map dump id "$MAP_ID" |
jq -r '.[]|.key|join(" ")'
else
bpftool -p map dump id "$MAP_ID" |
awk '/^key:/{for(i=2;i<=NF;i++)printf $i" ";print ""}'
fi
}
bytes_to_prefix() { # arg: "xx xx …" → "IP/len"
read -ra b <<<"$1" # eight bytes
local plen=$((16#${b[0]#0x})) # byte-0 = prefix length
local o1=$((16#${b[4]#0x}))
local o2=$((16#${b[5]#0x}))
local o3=$((16#${b[6]#0x}))
local o4=$((16#${b[7]#0x}))
echo "$o1.$o2.$o3.$o4/$plen"
}
###############################################################################
# 4. Core operations
###############################################################################
insert_prefix() {
local parsed
parsed=$(parse_cidr "$1") || {
echo "‼︎ Bad CIDR: $1" >&2
return 1
}
set -- $parsed
local ip=$1 plen=$2
local net=$(mask_ip "$ip" "$plen")
local k=$(gen_key_bytes "$net" "$plen")
echo " $net/$plen"
bpftool map update id "$MAP_ID" key hex $k value hex 01
}
delete_prefix() {
local parsed
parsed=$(parse_cidr "$1") || {
echo "‼︎ Bad CIDR: $1" >&2
return 1
}
set -- $parsed
local ip=$1 plen=$2
local net=$(mask_ip "$ip" "$plen")
local k=$(gen_key_bytes "$net" "$plen")
echo " $net/$plen"
bpftool map delete id "$MAP_ID" key hex $k 2>/dev/null || echo " (not present)"
}
flush_map() {
echo "🗑 Flushing…"
list_keys | while read -r k; do bpftool map delete id "$MAP_ID" key hex $k 2>/dev/null || true; done
}
export_map() { # [outfile]
local out=${1:-}
local lines=""
while read -r k; do
[[ -z $k ]] && continue
lines+=$(bytes_to_prefix "$k")$'\n'
done < <(list_keys)
if [[ -n $out ]]; then
printf '%s' "$lines" >"$out"
echo "📤 List written to $out"
else printf '%s' "$lines"; fi
}
show_map() {
echo -e "\n📋 Current prefixes:"
export_map
echo -e "\n"
}
###############################################################################
# 5. CLI
###############################################################################
(($# == 0)) && {
usage
exit 0
}
case "$1" in
reset)
flush_map
show_map
;;
unblock)
shift
(($# == 0)) && {
usage
exit 1
}
for p in "$@"; do delete_prefix "$p"; done
show_map
;;
import)
shift
[[ $# -ne 1 ]] && {
usage
exit 1
}
import_prefixes "$1"
;;
export)
shift
export_map "${1:-}"
;;
show)
show_map
;;
-h | --help | help) usage ;;
*)
for p in "$@"; do insert_prefix "$p"; done
show_map
;;
esac

View File

@@ -1,5 +1,3 @@
#!/bin/env bash
rm xdp_packet_filter.o
clang -O2 -g -Wall -target bpf -c xdp_packet_filter.c -o xdp_packet_filter.o

View File

@@ -1,5 +0,0 @@
#!/bin/env bash
ETH=enp11s0
/usr/sbin/ip link set dev $ETH xdp off

View File

@@ -32,10 +32,34 @@
20, 21, 22, 23, 25, 53, 67, 68, 69, 110, 111, 135, \
137, 138, 139, 143, 389, 445, 465, 546, 873, 993, 995, \
1080, 1433, 1435, 1900, 2049, 3306, 3389, 5353, 5432, \
5900, 5901, 5902, 6667 \
5900, 5901, 5902, 6667, 8006 \
}
#define DEBUG
#define LOCAL_ADDRESS 0x00000000
#define LOCAL_BROADCAST 0xFFFFFFFF
#define INTERVAL 1000000000 // 1 detik dalam nano detik
#define DEBUG 1
struct
{
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint(max_entries, 1);
__type(key, __u32);
__type(value, __u64);
} rate_limit_map SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_LPM_TRIE);
__uint(max_entries, 1024);
__type(key, struct {
__u32 prefixlen;
__u32 addr;
});
__type(value, __u8);
__uint(map_flags, BPF_F_NO_PREALLOC);
} blocked_ips SEC(".maps");
/**
* Fungsi untuk memeriksa apakah port tujuan terdaftar
@@ -61,6 +85,64 @@ static inline int periksa_port_tujuan(unsigned short port)
return 0; // Aman
}
/**
* Fungsi untuk memeriksa apakah sudah lewat dari interval rate limit.
*
* @param ip_klien: Alamat IP pengirim yang akan diperiksa.
*
* @return:
* 1 jika sudah melewati interval (tipe int),
* 0 jika belum melewati interval (tipe int).
*/
static inline int cek_rate_limit(__u32 ip_klien)
{
__u64 current_time = bpf_ktime_get_ns();
__u64 *val = bpf_map_lookup_elem(&rate_limit_map, &ip_klien);
if (val)
{
if (current_time - *val < INTERVAL)
return 0; // Belum melewati interval, drop paket
}
__u64 new_val = current_time;
bpf_map_update_elem(&rate_limit_map, &ip_klien, &new_val, BPF_ANY);
return 1; // Sudah melewati interval, izinkan paket
}
static inline int is_ip_blocked(__u32 ip)
{
struct {
__u32 prefixlen;
__u32 addr;
} key;
// Try /32 match first
key.prefixlen = 32;
key.addr = ip;
if (bpf_map_lookup_elem(&blocked_ips, &key))
return 1;
// Try /24 match
key.prefixlen = 24;
key.addr = ip & bpf_htonl(0xFFFFFF00);
if (bpf_map_lookup_elem(&blocked_ips, &key))
return 1;
// Try /20 match
key.prefixlen = 20;
key.addr = ip & bpf_htonl(0xFFFFF000);
if (bpf_map_lookup_elem(&blocked_ips, &key))
return 1;
return 0;
}
/**
* Program filtrasi paket XDP untuk memblokir paket berdasarkan port tujuan.
*
@@ -108,26 +190,53 @@ SEC("packet_filter") int xdp_packet_filter(struct xdp_md *ctx)
__u32 ip_klien = ip->saddr;
__u32 ip_tujuan = ip->daddr;
if (bpf_htonl(LOCAL_ADDRESS) == ip_klien || bpf_htonl(LOCAL_BROADCAST) == ip_tujuan)
return XDP_PASS;
// Header transport (TCP/UDP)
__u8 protocol = ip->protocol;
void *trans_hdr = (void *)(ip + 1);
__u16 dest_port;
__u16 dest_port = 0;
if (is_ip_blocked(ip_klien)) {
#ifdef DEBUG
bpf_printk("[DROP][IP]: %pI4 -> %pI4", &ip_klien, &ip_tujuan);
#endif
return XDP_DROP;
}
// TCP
if (protocol == IPPROTO_TCP)
{
if (trans_hdr + sizeof(struct tcphdr) > data_end)
return XDP_DROP;
dest_port = ((struct tcphdr *)trans_hdr)->dest;
}
// UDP
else if (protocol == IPPROTO_UDP)
{
if (trans_hdr + sizeof(struct udphdr) > data_end)
return XDP_DROP;
dest_port = ((struct udphdr *)trans_hdr)->dest;
}
else
// ICMP
else if (protocol == IPPROTO_ICMP)
{
return XDP_PASS;
if (trans_hdr + sizeof(struct icmphdr) > data_end)
return XDP_DROP;
if (!cek_rate_limit(ip_klien))
{
#ifdef DEBUG
bpf_printk("[DROP][ICMP]: %pI4 -> %pI4", &ip_klien, &ip_tujuan);
#endif
return XDP_DROP;
}
}
// Cek daftar blokir port
@@ -144,4 +253,4 @@ SEC("packet_filter") int xdp_packet_filter(struct xdp_md *ctx)
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";
char _license[] SEC("license") = "GPL";

5
xload Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/env bash
/usr/sbin/ip link set dev "$1" xdp obj /root/xdp_packet_filter.o sec packet_filter
/usr/sbin/xdp-loader status

3
xlog Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/env bash
cat /sys/kernel/debug/tracing/trace_pipe

6
xreload Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/env bash
/usr/sbin/ip link set dev "$1" xdp off
/usr/sbin/ip link set dev "$1" xdp obj /root/xdp_packet_filter.o sec packet_filter
/usr/sbin/xdp-loader status

5
xunload Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/env bash
/usr/sbin/ip link set dev "$1" xdp off
/usr/sbin/xdp-loader status