內核模塊加載後不生效 (不 DROP)、無法卸載、無法獲取源 MAC (ethhdr 結構體變更)。
#include
#include
#include
#include
static unsigned int hook_func(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) {
if (!skb) return NF_ACCEPT;
// skb_mac_header 已由網卡驅動設置 (接收路徑)
// 發送路徑 (NF_INET_POST_ROUTING) 可能未推 MAC 頭,需 skb_push/skb_pull 處理
struct ethhdr *eth = eth_hdr(skb); // 等價於 (struct ethhdr *)skb_mac_header(skb)
if (!eth) return NF_ACCEPT;
// 打印源 MAC
printk(KERN_INFO "SRC MAC: %pM\n", eth->h_source); // %pM 內核格式化 MAC
// 示例:僅允許特定 MAC
u8 allowed_mac[6] = {0x11,0x22,0x33,0x44,0x55,0x66};
if (ether_addr_equal(eth->h_source, allowed_mac))
return NF_ACCEPT;
return NF_DROP;
}
NF_IP_PRI_FIRST 最高,但若有其他模塊 (如 docker/bridge) 同優先級順序不定。嘗試 NF_IP_PRI_FILTER - 1。NF_INET_POST_ROUTING 僅處理**本機發出**的包。若要攔截轉發包,用 NF_INET_FORWARD。printk 確認 hook_func 被調用,檢查 dmesg。hook_func **不能睡眠**,不能調用 msleep/mutex_lock/copy_to_user 等。/proc/net/nf_conntrack、lsmod 確認引用計數。rmmod -f (不安全,可能導致內核崩潰)。obj-m := arp_fw.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
net/netfilter/ 目錄下例程。eth_hdr(skb) 而非手動計算偏移。NF_INET_LOCAL_OUT 或更早點處理,或用 dev_queue_xmit_nit 旁路獲取。