📄 netlink.htm
字号:
length:0 over:0 crc:0 frame:0 fifo:0 missed:0
发送信息:
发送报文:73 字节:5105
errors:0 dropped:0
aborted:0 carrier:0 fifo:0 heartbeat:0 window:0
获取到设备[2]信息
设备类型:以太网
设备状态: UP BROADCAST RUNNING MULTICAST
设备名称:eth0
MAC地址:0:e0:4c:68:17:e2
广播MAC地址:ff:ff:ff:ff:ff:ff
设备MTU:1500
设备队列:pfifo_fast
接收信息:
接收报文:23942563 字节:2498812213
errors:0 dropped:0 multicast:0 collisions:0
length:0 over:0 crc:0 frame:0 fifo:0 missed:0
发送信息:
发送报文:26027259 字节:782054736
errors:0 dropped:0
aborted:0 carrier:0 fifo:0 heartbeat:0 window:0
获取到设备[3]信息
设备类型:以太网
设备状态: UP BROADCAST RUNNING MULTICAST
设备名称:eth1
MAC地址:0:11:5b:16:ac:52
广播MAC地址:ff:ff:ff:ff:ff:ff
设备MTU:1500
设备队列:pfifo_fast
接收信息:
接收报文:28576652 字节:97399242
errors:0 dropped:0 multicast:0 collisions:0
length:0 over:0 crc:0 frame:0 fifo:0 missed:0
发送信息:
发送报文:22489921 字节:2255181112
errors:0 dropped:0
aborted:0 carrier:0 fifo:0 heartbeat:0 window:0
获取到设备[4]信息
设备类型:PPP拨号
设备状态: UP POINTOPOINT RUNNING NOARP MULTICAST
设备名称:ppp0
设备MTU:1492
设备队列:pfifo_fast
接收信息:
接收报文:25021013 字节:3614587231
errors:0 dropped:0 multicast:0 collisions:0
length:0 over:0 crc:0 frame:0 fifo:0 missed:0
发送信息:
发送报文:22442439 字节:1757067695
errors:0 dropped:0
aborted:0 carrier:0 fifo:0 heartbeat:0 window:0
</pre>
<h1><li><a id="NETLINK_SKIP协议介绍">NETLINK_SKIP 协议介绍</a></li></h1>
<h1>TODO:还没有找到资料</h1>
<h1><li><a id="NETLINK_USERSOCK协议介绍">NETLINK_USERSOCK协议介绍</a></li></h1>
<h1>TODO:还没有找到资料</h1>
<h1><li><a id="NETLINK_FIREWALL协议介绍">NETLINK_FIREWALL 协议介绍</a></li></h1>
<p style="text-indent:30px;line-height:25px;">FIREWALL协议一般主要是用于netfilter的包过虑机制中,我们通过使用iptables的-j QUEUE机制将报文进行队列排队,然后就从用户层来进行报文的接收或者拒绝操作。对于FIREWALL协议,支持的消息类型有三种分别是:
<ul>
<ol>IPQM_MODE</ol> 设置内核模式
<ol>IPQM_VERDICT</ol> 控制内核报文下一步骤
<ol>IPQM_PACKET</ol> 报文为从内核接收到
</ul>
<p style="text-indent:30px;line-height:25px;">当消息类型为IPQM_PACKET,表示报文是从内核到用户的。从内核到用户的报文格式为nlmsghdr头加上一个ipq_packet_msg数据报文。其中ipq_packet_msg的结构定义为:
<pre style="border:1px solid blue">
<font color="#ffff00"><b> 1</b></font> <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> </b></font>
<font color="#ffff00"><b> 2</b></font> <font color="#00ffff"><b> * 从内核发送到用户的消息格式</b></font>
<font color="#ffff00"><b> 3</b></font> <font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b> 4</b></font> <font color="#00ff00"><b>typedef</b></font> <font color="#00ff00"><b>struct</b></font> ipq_packet_msg {
<font color="#ffff00"><b> 5</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>long</b></font> packet_id; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 报文ID号 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b> 6</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>long</b></font> mark; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> MARK标记 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b> 7</b></font> <font color="#00ff00"><b>long</b></font> timestamp_sec; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 到达时间(秒) </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b> 8</b></font> <font color="#00ff00"><b>long</b></font> timestamp_usec; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 到达时间(微秒) </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b> 9</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>int</b></font> hook; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 钩子位置 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>10</b></font> <font color="#00ff00"><b>char</b></font> indev_name[IFNAMSIZ]; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 进入接口 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>11</b></font> <font color="#00ff00"><b>char</b></font> outdev_name[IFNAMSIZ]; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 出去接口 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>12</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>short</b></font> hw_protocol; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 硬件协议 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>13</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>short</b></font> hw_type; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 硬件类型 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>14</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>char</b></font> hw_addrlen; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 硬件地址长度 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>15</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>char</b></font> hw_addr[<font color="#ff40ff"><b>8</b></font>]; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 硬件地址 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>16</b></font> <font color="#00ff00"><b>size_t</b></font> data_len; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 数据长度 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>17</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>char</b></font> payload[<font color="#ff40ff"><b>0</b></font>]; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 数据起始位置 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>18</b></font> } ipq_packet_msg_t;
</pre>
<p style="text-indent:30px;line-height:25px;">当消息类型为IPQM_MODE,表示报文是从用户到内核,用户请求内核完成某项操作。请求报文的格式为nlmsghdr头加上一个ipq_mode_msg数据报文。其中ipq_mode_msg的结构定义为:
<pre style="border:1px solid blue">
<font color="#ffff00"><b>21</b></font> <font color="#00ffff"><b> * 从用户到内核的消息</b></font>
<font color="#ffff00"><b>22</b></font> <font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>23</b></font> <font color="#00ff00"><b>typedef</b></font> <font color="#00ff00"><b>struct</b></font> ipq_mode_msg {
<font color="#ffff00"><b>24</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>char</b></font> value; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 要求操作指令 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>25</b></font> <font color="#00ff00"><b>size_t</b></font> range; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 数据范围 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>26</b></font> } ipq_mode_msg_t;
</pre>
其中value的合法取值为:
<ul>
<li>IPQ_COPY_NONE</li> 取消从内核传送报文到用户
<li>IPQ_COPY_META</li> 只从内核拷贝基本数据到用户
<li>IPQ_COPY_PACKET</li> 除了拷贝基本数据外还拷贝报文数据,这个时候从内核出来的报文中payload指向数据的地址。
</ul>
range在value为IPQ_COPY_PACKET时候指定我们希望从内核拷贝多少的数据出来。
<p style="text-indent:30px;line-height:25px;">当消息类型为IPQM_VERDICT,表示报文是从用户到内核,用户指定内核完成某项操作。请求报文的格式为nlmsghdr头加上一个ipq_mode_verdict数据报文。其中ipq_mode_verdict的结构定义为:
<pre style="border:1px solid blue">
<font color="#ffff00"><b>28</b></font> <font color="#00ffff"><b>/*</b></font>
<font color="#ffff00"><b>29</b></font> <font color="#00ffff"><b> * 从用户到内核的消息</b></font>
<font color="#ffff00"><b>30</b></font> <font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>31</b></font> <font color="#00ff00"><b>typedef</b></font> <font color="#00ff00"><b>struct</b></font> ipq_verdict_msg {
<font color="#ffff00"><b>32</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>int</b></font> value; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 控制操作模式 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>33</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>long</b></font> id; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 要求操作的报文ID </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>34</b></font> <font color="#00ff00"><b>size_t</b></font> data_len; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 数据长度 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>35</b></font> <font color="#00ff00"><b>unsigned</b></font> <font color="#00ff00"><b>char</b></font> payload[<font color="#ff40ff"><b>0</b></font>]; <font color="#00ffff"><b>/*</b></font><font color="#00ffff"><b> 数据的长度 </b></font><font color="#00ffff"><b>*/</b></font>
<font color="#ffff00"><b>36</b></font> } ipq_verdict_msg_t;
</pre>
<p style="text-indent:30px;line-height:25px;">其中value的取值为NF_ACCEPT表示要求内核接受这个报文,NF_DROP表示丢弃这个报文,其余我们不关心的取值有NF_STOLEN, NF_QUEUE, NF_REPEAT等。下面是一个实际的例子:
<pre style="border:1px solid blue">
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><unistd.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><stdlib.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><stdio.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><string.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><errno.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><time.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><asm/types.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><sys/types.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><sys/socket.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><linux/netlink.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><linux/netfilter.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><linux/netfilter_ipv4/ip_queue.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><netinet/ether.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><linux/netfilter_ipv4.h></b></font>
<font color="#8080ff"><b>#include </b></font><font color="#ff40ff"><b><signal.h></b></font>
<font color="#00ff00"><b>static</b></font> <font color="#00ff00"><b>volatile</b></font> <font color="#00ff00"><b>int</b></font> gnContinue = <font color="#ff40ff"><b>1</b></font>;
<font color="#00ff00"><b>static</b></font> <font color="#00ff00"><b>void</b></font> in_catch_sig(<font color="#00ff00"><b>int</b></font> nSig)
{
gnContinue = <font color="#ff40ff"><b>0</b></font>;
}
<font color="#00ff00"><b>int</b></font> main(<font color="#00ff00"><b>int</b></font> argc, <font color="#00ff00"><b>char</b></font> *argv[])
{
<font color="#00ff00"><b>int</b></font> nSocket, nLen;
<font color="#00ff00"><b>struct</b></font> sockaddr_nl struAddr;
<font color="#00ff00"><b>struct</b></font> nlmsghdr *pstruNL;
<font color="#00ff00"><b>struct</b></font> ipq_packet_msg *pstruPacketMsg;
<font color="#00ff00"><b>char</b></font> szBuffer[<font color="#ff40ff"><b>4096</b></font>];
<font color="#00ff00"><b>struct</b></font> tm struTmNow;
<font color="#00ff00"><b>struct</b></font> sigaction struAct;
<font color="#00ff00"><b>struct</b></font> {
<font color="#00ff00"><b>struct</b></font> nlmsghdr head;
<font color="#00ff00"><b>union</b></font>{
<font color="#00ff00"><b>struct</b></font> ipq_mode_msg mode;
<font color="#00ff00"><b>struct</b></font> ipq_verdict_msg verdict;
}body;
} struReq;
<font color="#00ffff"><b>/*</b></font>
<font color="#00ffff"><b> * 创建SOCKET</b></font>
<font color="#00ffff"><b> </b></font><font color="#00ffff"><b>*/</b></font>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -