简介

基于iptables的内核通讯大杀器,使用nfnetlink协议与内核通信。

他可以通过iptables定义的规则去拦截相应的网络报文,他可以基于iptables前或者后去自定义拦截这些报文,也可以通过解析这些报文做一些审计之类的工作,也可以通过这些报文来形成一个阻断功能

NFQUEU 的源代码分为 nf_queuenfnetlink_queue 两部分。nf_queueiptables 的一部分,nfnetlink_queuenetfilter 的一个子模块。

nfnetlink_queuenf_queue 跟用户程序之间的桥梁,是基于 nfnetlink 的专门用于 NFQUEUE 的通信机制;而 nfnetlink 是一套基于 netlink的专门用于 netfilter 的通信机制。

安全性

nfqueue是一个队列,程序通过队列的形式来处理报文,默认这个队列的长度是1024,超出此队列的报文默认会丢弃,正常环境下,要控制好这些流量。在内核 3.6 之后,可以使用 --fail-open 选项将这默认丢包改为默认接收。在 /proc/net/netfilter/nfnetlink_queue 中可以看到丢包统计。

NFQUEUE 很容易地为任意入队的包做包重排序。然而,需要注意的是内核是使用链式列表来排队包的;所以,乱序判决会带来一定的损耗。

配置

按照iptables的四表五链配置规则即可

例如:

1
iptables -t raw -I PREROUTING -p tcp --syn -j NFQUEUE --queue-num=1 --queue-bypass
  • –queue-num 代表队列号
  • –queue-bypass 默认情况下,如果没有用户空间程序正在监听 NFQUEUE,那么将丢弃所有要排队的数据包。使用此选项时,NFQUEUE 规则的行为类似于 ACCEPT,数据包将转移到下一个表。但此规则要求 内核 >= 2.6.39,iptables >= 1.4.11

同时,为了防止丢包,也有负载均衡的配置

--queue-balance 是 NFQUEUE 选项,由 Florian Westphal 实现,实现了同一条 iptables 规则的网络包负载均衡到多个队列。用法非常简单。比如,负载均衡 INPUT 流量到 0-3 队列的规则如下,注意,负载均衡是基于流实现的(made with respect to the flow),一条流的所有网络包会发送到同一个队列。但此规则要求 Linux 内核 >= 2.6.31,iptables >= 1.4.5

1
iptables -A INPUT -j NFQUEUE --queue-balance 0:3

其他iptables配置可以参照 iptables 配置

代码参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
"fmt"
"os"
"github.com/subgraph/go-nfnetlink/nfqueue"
)

func main() {
q := nfqueue.NewNFQueue(1) // 此处参数1需要改为绑定的对列号
ps, err := q.Open()
if err != nil {
fmt.Printf("Error opening NFQueue: %v\n", err)
os.Exit(1)
}
defer q.Close()
fmt.Println("Start Listen ...")
for p := range ps {
fmt.Println(p.Packet.String())
err = p.Accept()
if err != nil {
fmt.Println(err)
}
}
}