iptables 3: 动作MARK NFQUEUE

一、mark打标记

如何设置mark
iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 2
如何匹配mark
iptables -t mangle -A INPUT -m mark --mark 1
-m 即match匹配的意思。

mark的格式是–mark value[/mask],如上面的例子是没有掩码的,带掩码的例子如–mark 1/1。如果指定了掩码,就先把mark值和掩码取逻辑与,然后再和包的mark值比较。

二、NFQUEUE

  1. 使用NFQUEUE改包
    https://www.jianshu.com/p/ee728683a0ed
    http://www.doc88.com/p-3744296686284.html
    https://www.cnblogs.com/dpf-10/p/7899237.html

  2. 参考
    https://blog.csdn.net/wangzhen_csdn/article/details/83038122

  3. 更多函数介绍
    https://www.jianshu.com/p/23434149e3f0

nfqueue发送接收使用的fd都被封装在nfnl_open的返回值里。

nfqueue相关函数

1. nfnl_open

struct nfnl_handle *nfnl_open(void)
函数说明:
开启nfnetlink 处理程序
函数功能:
该函数创建一个nfnetlink 处理程序,此函数创建NFNETLink处理程序,这是需要建立的用户空间与NFNETLink系统之间的通信。
返回值:
成功 指向nfnl_handle structure的有效地址。
失败:NULL

2. nfq_unbind_pf nfq_bind_pf

int nfq_unbind_pf(struct nfq_handle *h, u_int16_t pf)
或者
int nfq_bind_pf(struct nfq_handle *h, u_int16_t pf)
函数说明:
解绑(绑定)nf_queue 队列
函数参数:
h:nfq_open()返回struct nfnl_handle结构的指针;
pf: 协议族 AF_BRIDGE:7多协议桥,AF_INET:2 路由模式
返回值:失败 : -1
 成功 :  0

3. nfq_create_queue

struct nfq_q_handle *nfq_create_queue(struct nfq_handle *h, u_int16_t num, nfq_callback *cb, void *data)

函数说明: 将此套接字绑定到特定的队列号.

函数参数:
h : nfq_open()返回struct nfnl_handle结构的指针;
num: 队列的序列号
cb : 数据包的处理函数(回调函数)
data: 自定义数据

返回值:
成功:struct nfq_q_handle 指针
失败 : null

4. nfq_set_mode

int nfq_set_mode(struct nfq_q_handle *qh,u_int8_t mode, u_int32_t range)

函数说明:
从netlink系统里设置copy数据的方式

函数参数:
qh: nfq_create_queue()函数的返回值
mode : copy 方式
NFQNL_COPY_NONE,
NFQNL_COPY_META,
NFQNL_COPY_PACKET,
range:copy 数据长度

返回值:
成功0
失败 -1

5. nfq_handle_packet

int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)

函数说明:
处理接收的数据

函数参数:
nfq_open()返回struct nfnl_handle结构的指针;
buf: 待处理的数据
len:数据长度

综上所述:
nf_queue仍然使用的netlink机制与内核之间进行通信,不同的是nf_queue根据不同的queue_num将数据包传递给不同的用户注册的回调函数。但是请注意,它们共用一个socket套接字

问题1:nfq_handle_packet()怎样和处理函数nfq_create_queue参数cb 建立起联系的?

struct nfq_q_handle
{
	struct nfq_q_handle *next;
	struct nfq_handle *h;
	u_int16_t id;
	nfq_callback *cb;
	void *data;
};

typedef int nfq_callback(struct nfq_q_handle *gh, struct nfgenmsg *nfmsg, struct nfq_data *nfad, void *data);

static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data)
{
	u_int32_t id = print_pkt(nfa);
	printf("entering callback\n");
	return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
}

struct nfq_q_handle *nfq_create_queue(struct nfq_handle *h, u_int16_t num, nfq_callback *cb, void *data)
{
	int ret;
	struct nfq_q_handle *qh;

	if (find_qh(h, num))
		return NULL; 
	qh = malloc(sizeof(*qh));
	memset(qh, 0, sizeof(*qh));
	qh->h = h;
	qh->id = num;
	qh->cb = cb;
	qh->data = data;
	ret = __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0);
	if (ret < 0) {
		nfq_errno = ret;
		free(qh);
		return NULL;
	}
	add_qh(qh);
	return qh;
}

//接收数据包
while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {
	printf("pkt received\n");
	nfq_handle_packet(h, buf, rv);
}

nfq_handle_packe://处理数据包函数
--> nfnl_handle_packet(h->nfnlh, buf, len);
--> __nfnl_handle_msg(h, nlh, rlen)

static int __nfnl_handle_msg(struct nfnl_handle *h, struct nlmsghdr *nlh, int len)
{
	struct nfnl_subsys_handle *ssh;
	。。。。。 

	ssh = &h->subsys[subsys_id];
	if (ssh->cb[type].attr_count) {
		if (ssh->cb[type].call)
		return ssh->cb[type].call(nlh, nfa, ssh->cb[type].data);
	}

	return 0;
} 

结构体定义:
struct nfnl_subsys_handle {
	struct nfnl_handle *nfnlh;
	u_int32_t subscriptions;
	u_int8_t subsys_id;
	u_int8_t cb_count;
	struct nfnl_callback *cb; /* array of callbacks */
};

struct nfnl_callback {
	int (*call)(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data);
	void *data;
	u_int16_t attr_count;
};

call:是一个函数指针(钩子) 

static struct nfnl_callback pkt_cb = {
	.call = &__nfq_rcv_pkt,
	.attr_count = NFQA_MAX,
}; 

函数的实现:
static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data)
{
	struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
	struct nfq_handle *h = data;
	u_int16_t queue_num = ntohs(nfmsg->res_id);
	struct nfq_q_handle *qh = find_qh(h, queue_num);
	struct nfq_data nfqa;

	if (!qh)
		return -ENODEV;

	if (!qh->cb)
		return -ENODEV;

	nfqa.data = nfa;

	return qh->cb(qh, nfmsg, &nfqa, qh->data);
}

就这样nfq_handle_packet(h, buf, rv)和qh = nfq_create_queue(h,  0, &cb, NULL);联系在一起拉

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值