一、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
-
使用NFQUEUE改包
https://www.jianshu.com/p/ee728683a0ed
http://www.doc88.com/p-3744296686284.html
https://www.cnblogs.com/dpf-10/p/7899237.html -
参考
https://blog.csdn.net/wangzhen_csdn/article/details/83038122
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);联系在一起拉